Алексей Маркин рабочий журнал

ищет по заголовкам и тексту записей и заметок

запись 3 сентября 2026 г. · 5 мин
Все статьи

Регрессии в промптах: сравнивать надо свойства, а не текст

Промпт — это код, у которого по умолчанию нет ни тестов, ни диффа. Разбираю, почему обычное сравнение ответов не работает и что класть в журнал прогона вместо него.

Промпт живёт в репозитории как строка. У строки есть история изменений, но нет ничего из того, что делает код кодом: ни тестов, ни способа увидеть, что именно сломала правка.

Первая мысль — сделать дифф ответов: прогнать до и после, сравнить. Мысль правильная ровно до момента, когда вы это попробуете.

Почему дифф ответов не работает

Прогоните один и тот же промпт дважды, ничего не меняя. Ответы разойдутся: переставлены абзацы, другой синоним, лишняя запятая. Побитового повтора не даёт даже нулевая температура, и причин тому несколько — от порядка суммирования чисел с плавающей точкой до состава пакета, в который попал ваш запрос на стороне провайдера.

Значит, обычный текстовый дифф покажет расхождения всегда. Прогон до правки и прогон после будут отличаться, даже если правки не было. Такой инструмент бесполезен: он не различает шум и сигнал, а значит не различает ничего.

Вывод неприятный, но он же и открывает выход: сравнивать надо не текст ответа, а его проверяемые свойства.

Свойство вместо текста

Свойство — это утверждение об ответе, которое проверяется программой и не зависит от формулировки.

Плохой критерийСвойство, которое его заменяет
ответ совпадает с эталоннымответ разбирается как JSON по схеме
ответ выглядит правильнымполе amount совпадает с ожидаемым числом
модель не выдумала датузначение date присутствует в исходном тексте
ответ по делуупомянут хотя бы один из ключевых терминов
ответ не слишком длинныйдлина в пределах заданного диапазона
формат не сломалсянет текста до первой открывающей скобки

Свойства скучны, и в этом их достоинство: они дают бинарный исход, устойчивый к перефразированию. А бинарный исход на фиксированном наборе примеров — это ровно то, что можно сравнить между прогонами и посчитать статистически.

Здесь стоит остановиться на частой ошибке. Соблазн — попросить оценку у другой модели и сравнивать её баллы. Это не свойство: у модели нет устойчивой шкалы, её оценка сама плавает от прогона к прогону, и вы меняете один источник шума на другой, только менее прозрачный.

ТЕКСТ ОТВЕТАпрогон 1прогон 2различия есть всегдадаже без единой правкиСВОЙСТВА ОТВЕТАсхема: дасумма: 4200дата: из текстасхема: дасумма: 4200дата: из текстасовпадают, пока промпт тот жерасхождение = сигнал
рис. 1 Что сравнивать между прогонами. Слева — величина, которая меняется сама по себе. Справа — та, которая меняется только от правки.

Что класть в журнал прогона

Свойства дают сигнал, но без контекста сигнал бесполезен: через неделю вы увидите, что стало хуже, и не сможете сказать, от чего.

Минимальный набор полей, который окупается почти сразу:

  • хеш промпта — не текст, а именно хеш: он влезает в таблицу и мгновенно отвечает на вопрос «промпт вообще менялся?»;
  • идентификатор модели с версией — не «claude», а полная строка; провайдеры обновляют модели под тем же именем, и это самая коварная из причин, потому что в вашем репозитории не изменилось ничего;
  • параметры сэмплирования — температура, top-p, лимит токенов;
  • идентификатор примера — чтобы сравнение было парным;
  • результат по каждому свойству — булево, а не текст;
  • сырой ответ — целиком, для разбора руками;
  • число токенов на входе и выходе — стоимость это тоже регрессия;
  • время до первого токена и до последнего.

Половина этих полей нужна не для метрики, а для ответа на вопрос «что изменилось». Самое частое объяснение внезапной просадки — не ваша правка, а обновление модели на стороне провайдера, и без записанной версии доказать это невозможно.

Порог, за которым это окупается

Признак простой и проверяется без раздумий: если вы боитесь трогать промпт — обвязка уже нужна.

Страх правки означает, что стоимость проверки выше стоимости изменения. В коде это состояние называют отсутствием тестов, и лечат одинаково.

До этого порога — если промпт правится раз в месяц и результат читает живой человек — вся описанная машинерия избыточна.

Условие несогласия

Всё написанное относится к промптам, результат которых уходит в код. Для черновиков, разовых задач и текстов, которые человек всё равно перепишет, свойства бессмысленны: единственное осмысленное свойство там — «мне нравится», а оно не проверяется программой.

Граница та же, что и везде в этой теме: кто следующий читатель ответа.

Чего я делать не стал бы

Не стал бы хранить только последний прогон. Ценность журнала появляется на третьем-четвёртом, когда становится видно тренд, а не точка.

Не стал бы прогонять весь набор на каждое сохранение файла. Это дорого и приучает игнорировать результат. Прогон перед слиянием ветки — достаточно.

Не стал бы делать свойства слишком строгими. Проверка «ответ содержит ровно эту фразу» сломается от синонима и приучит вас чинить тест, а не систему; проверка «упомянут срок возврата» переживёт перефразирование.

Открытый вопрос

Свойства хорошо ловят то, что вы уже придумали проверять. Регрессия, которая не попала ни в одно свойство, невидима полностью — и вероятность такого тем выше, чем дольше набор не обновлялся. Формального способа оценить эту слепоту у меня нет: чтобы измерить, чего не хватает в проверках, нужно знать, чего именно, а это и есть исходный вопрос.