TL;DR
Когда просишь LLM написать код и добавляешь в промпт тест-примеры (входы и ожидаемые выходы), модель не всегда реально «понимает» через них задачу. Иногда она честно разбирает логику тестов и пишет правильный код, а иногда просто реагирует на тесты как на дополнительный шум в тексте — и со стороны это выглядит одинаково хорошо, пока не подменишь тесты на неправильные или вообще чужие.
Главная боль: на простых, типовых задачах тесты в промпте реально поднимают точность генерации кода заметно. А на сложных, нестандартных задачах эффект нестабильный и слабый — иногда тесты из совсем другой задачи работают не хуже правильных тестов для этой. Модель на трудных задачах не отличает полезный пример от случайного текста, хотя внутри неё «сигналы» меняются сильно в обоих случаях.
Вывод простой: тесты в промпте — это не гарантированная спецификация, которую модель честно исполняет, а скорее подсказка, которая работает надёжно только когда задача похожа на то, что модель уже видела много раз. На сложных задачах не надейся, что тест-кейсы «спасут» алгоритм — важнее подробное текстовое описание, и тесты никогда не должны его заменять.
Схема принципа
ШАГ 1: Оцени задачу → типовая/частая (парсер, сортировка, форматирование) или нестандартная/сложная (кастомная бизнес-логика, редкий алгоритм)
ШАГ 2: Если типовая → добавь 2-3 примера "вход → выход" в промпт → заметный рост точности
ШАГ 3: Если нестандартная → не жди чуда от тестов → делай упор на подробное словесное описание правил, границ, особых случаев
ШАГ 4: Всегда сохраняй текстовое описание задачи рядом с тестами → без него точность резко падает
ШАГ 5: Не закидывай много тестов "на всякий случай" → после 2-3 примеров эффект перестаёт расти
Пример применения
Задача: Ты ведёшь маленький интернет-магазин и просишь ChatGPT написать функцию расчёта скидки: для новых клиентов — 5%, для тех кто покупал больше 10 раз — 15%, но если сумма заказа меньше 500 рублей, скидка не действует, а в праздники (список дат) скидка удваивается, но не больше 30%.
Это не типовая задача (кастомная бизнес-логика с исключениями) — значит тесты не спасут, если описание нечёткое.
Промпт:
Напиши функцию на Python calculate_discount(customer, order_sum, date), которая рассчитывает скидку по правилам:
- Новый клиент (меньше 1 покупки в истории): скидка 5%
- Клиент с более чем 10 покупками: скидка 15%
- Если сумма заказа меньше 500 рублей — скидка не применяется вообще, независимо от статуса клиента
- Если дата входит в список праздников [8 марта, 23 февраля, 31 декабря] — скидка умножается на 2, но итоговая скидка не может превышать 30%
- Если клиент подходит под несколько условий одновременно — действует наибольшая скидка из применимых
Вот примеры для проверки логики (используй их, но помни: они не покрывают все пограничные случаи — подумай сам, что может пойти не так):
customer.purchases=0, order_sum=1000, date="обычный день" → скидка 5%
customer.purchases=15, order_sum=1000, date="8 марта" → скидка 30% (15% × 2, но капнуто на 30%)
customer.purchases=15, order_sum=400, date="8 марта" → скидка 0% (сумма меньше 500)
Перед финальным ответом проверь: проходит ли твоё решение все три примера, и учтён ли случай когда клиент новый И заказ в праздник.
Результат: Модель напишет функцию с условной логикой, учитывающей порядок правил (сначала проверка минимальной суммы, потом статус клиента, потом праздничный множитель с капом). Благодаря явному описанию правил, а не только тестам, модель не будет угадывать логику по 3 примерам — она получит полную спецификацию, а тесты послужат проверкой, а не единственным источником смысла.
Почему это работает
Слабость LLM: модель не умеет достоверно отличать «этот тест содержит важный смысл, который нужно разобрать» от «это просто ещё один кусок текста в промпте». На сложных задачах, где модель не уверена в алгоритме, любой добавленный текст — даже тест из совсем другой задачи — может сдвинуть генерацию, но не обязательно в правильную сторону.
Сильная сторона LLM: на частых, типовых паттернах (стандартные функции сортировки, парсинга, форматирования) модель отлично использует тесты как уточнение — они помогают увидеть недостающие детали формата, граничные случаи, которые не были явно описаны словами.
Как применять: добавляй тесты когда задача похожа на то, что модель "видела" тысячи раз в обучении. Если задача нестандартная — не экономь на текстовом описании в надежде, что тесты сами всё объяснят. И всегда проверяй код сам — большой сдвиг в «уверенности» модели (внутренние изменения) не значит, что она поняла задачу правильно.
Ограничения
⚠️ Ненадёжность на сложных задачах: на нестандартных, редких алгоритмах добавление правильных тестов может помочь не больше, чем добавление тестов из совсем другой задачи. Модель не гарантированно использует смысл тестов.
⚠️ Тесты не заменяют описание: если убрать текстовое описание задачи и оставить только тесты, точность падает резко и сильно — тесты работают только вместе с полной спецификацией.
⚠️ Больше тестов не значит лучше: эффект от добавления тестов быстро выходит на плато после 2-3 примеров, а иногда даже снижается — не нужно перегружать промпт тестами «на всякий случай».
⚠️ Неправильные тесты почти не хуже правильных: на части задач тесты с перепутанными ожидаемыми результатами работали почти так же, как правильные — значит нельзя слепо доверять, что «раз я дал тесты, модель точно поняла логику».
Как исследовали
Исследователи взяли две модели для генерации кода (Qwen2.5-Coder-7B и более сильную Qwen3.6-27B) и прогнали их через три набора задач разной сложности: простые типовые задачи (MBPP+), задачи среднего уровня, которые модель уже решает хорошо (HumanEval+), и свежие сложные задачи с LeetCode и AtCoder (LiveCodeBench). Для каждой задачи сравнили шесть вариантов промпта: без тестов, с правильными тестами, с тестами где перепутаны ожидаемые результаты, с тестами из другой задачи, только с тестами без описания задачи, и с искусственно сгенерированными тестами от более мощной модели.
Дополнительно заглянули «внутрь» модели — замерили, как меняются внутренние численные представления текста при разных вариантах промпта, чтобы понять: реагирует модель на смысл тестов или просто на то, что текст стал другим. Оказалось, что даже бессмысленные (нерелевантные) тесты сильно меняют эти внутренние сигналы — иногда даже сильнее, чем правильные тесты — но это не приводит к более верному коду. Это и есть главный неожиданный вывод: большой внутренний «отклик» модели на промпт не означает, что она разобралась в задаче лучше.
