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

Почему релиз ломает то, что вчера работало
Новый релиз может заметно поменять поведение системы, даже если команда правит "всего лишь" промпт или переключает модель. Тот же запрос начинает звучать другим тоном, меняет длину ответа, порядок шагов или уровень уверенности. Вчера модель честно писала "не знаю", а сегодня уверенно выдумывает ответ.
В LLM-продуктах это особенно заметно. Интерфейс остаётся тем же, API не меняется, а поведение уже другое. Для пользователя это выглядит как случайная нестабильность: вчера бот правильно заполнял заявку, а сегодня путает поля или просит лишние данные.
Ручная проверка такие сбои часто пропускает. Обычно люди смотрят на 10-20 знакомых примеров, где и так всё должно работать, и быстро успокаиваются. Но тихая регрессия прячется в редких формулировках, длинных диалогах, спорных кейсах и ответах, которые на вид нормальные, но уже ломают бизнес-логику.
Проблема в том, что часть ошибок не выглядит ошибкой с первого чтения. Ответ может быть вежливым и гладким, но при этом перепутать сумму, дату или имя клиента, пропустить обязательное предупреждение, сломать JSON для следующего шага или дать слишком уверенный ответ без опоры на факты.
Пользователь замечает такое сразу. Бот отвечает дольше обычного, повторяет вопрос, уходит в сторону, не соблюдает стиль бренда или внезапно просит данные, которые раньше не требовал. В банке, ритейле или медицине это быстро превращается в жалобу, повторное обращение и ручную работу оператора.
Поэтому проверку перед релизом обычно строят не вокруг "идеального" ответа, а вокруг сравнения с прошлой версией. Идеал часто спорный. Два сильных ревьюера могут по-разному оценить один и тот же ответ. А вот ухудшение относительно того, что уже работало в продакшене, заметить проще и полезнее.
Если старая версия решала 92 из 100 типовых запросов, новая должна быть не красивее на демо, а как минимум не хуже на тех же данных. Такой подход быстро отрезвляет. Он помогает ловить не абстрактное "качество модели", а конкретные регрессии: где стало медленнее, дороже, длиннее, неточнее или рискованнее для бизнеса.
С чего начать
Не начинайте с метрик и таблиц. Сначала команда должна в одном предложении описать, что именно меняется. Например: "Меняем модель ответа в чате поддержки банка, не трогая интерфейс и промпт". Этого часто достаточно, чтобы сузить проверку и убрать лишние споры.
Такая формулировка сразу задаёт рамки. Вы не оцениваете весь продукт. Вы проверяете конкретное изменение и его последствия.
Если релиз идёт через единый шлюз вроде AI Router, сценарий тоже лучше назвать прямо: команда переводит часть трафика на другую модель через тот же OpenAI-совместимый эндпоинт и хочет понять, не просели ли факты, тон и задержка. Это уже рабочая постановка задачи.
Кто отвечает за проверку
У первой проверки почти всегда одна и та же проблема: все участвуют, но никто не отвечает за результат до конца. Лучше закрепить роли заранее. Один человек ведёт золотой набор, один запускает тесты и следит за повторяемостью, ещё один принимает решение по релизу. Иногда это два человека, а не три. Это нормально. Плохо, когда владелец набора меняет примеры в последний момент, а решение о выкладке принимает команда, которая не видела деталей.
После ролей запишите риски. Не десять и не двадцать. Для первого прохода хватит 3-5 пунктов, которые реально могут сорвать релиз. Обычно список быстро становится понятным: модель путает факты, пишет слишком свободно для банковского тона, ломает формат ответа или отвечает медленнее допустимого времени.
Риски лучше формулировать как проверяемые ожидания. Не "качество может ухудшиться", а "доля фактических ошибок не должна вырасти" или "ответ в JSON не должен ломаться". Тогда решение можно принять без длинного созвона.
Что остановит релиз
До запуска договоритесь, при каком результате команда говорит "стоп". Иначе торг начнётся уже после цифр.
Обычно хватает нескольких простых правил:
- любая просадка по критичным фактам останавливает релиз;
- сбой формата выше согласованного порога останавливает релиз;
- рост задержки выше лимита отправляет релиз на доработку;
- спорные случаи в тот же день уходят человеку, который принимает финальное решение.
Если эти правила записаны заранее, отчёт потом читают за десять минут, а не разбирают полдня.
Как собрать золотой набор
Золотой набор лучше собирать не из придуманных промптов, а из того, что люди уже пишут в продукте. Берите запросы из логов, переписок с поддержкой и разборов инцидентов. Именно такие примеры быстро показывают, где модель путается, молчит или отвечает слишком уверенно.
Для первой версии не нужен огромный архив. Часто хватает 150-300 примеров, если они хорошо покрывают реальные сценарии. Если вы работаете в банке, телекоме или healthcare, сразу маскируйте PII: имена, номера, адреса, счета, телефоны.
Потом набор нужно почистить. Уберите дубликаты, почти одинаковые формулировки и шум, который ничего не проверяет. Если десять пользователей спросили одно и то же разными словами, оставьте два-три варианта. Этого достаточно.
Дальше разложите примеры по сценариям и сложности. Иначе весь набор забьют частые простые запросы, а сложные случаи пропадут. В практике обычно нужны четыре группы: бытовые вопросы, многошаговые сценарии с длинным контекстом, неоднозначные запросы, где модель должна уточнить вопрос, и редкие, но рискованные кейсы.
Редкие и неудобные примеры дают много пользы. Добавьте опечатки, смешение русского и английского, обрывки фраз, злые сообщения, очень длинные вопросы и запросы без нужных данных. Если модель работает в поддержке, включите случаи, где пользователь просит то, чего система делать не должна.
У каждого примера должно быть не только поле "правильный ответ". Намного полезнее зафиксировать, что именно вы ждёте. Для одной задачи нужен точный эталонный текст. Для другой важнее правила оценки: модель не выдумывает факты, отвечает в нужном тоне, задаёт уточняющий вопрос, не раскрывает личные данные и не обещает недоступное действие.
Минимум для каждой записи простой: сам запрос, сценарий, уровень сложности, ожидаемый ответ или короткий рубрикатор и пометка, почему пример попал в набор.
Относитесь к золотому набору как к живому рабочему артефакту. После каждого сбоя в проде добавляйте новый пример в тот же день, а не "когда-нибудь потом". Через несколько релизов такой набор начнёт ловить проблемы раньше, чем их заметят пользователи.
Какие метрики выбрать
Если в отчёте 12 чисел, команда не запомнит ни одного. Для релиза обычно хватает 2-4 метрик, которые отвечают на обычные вопросы о результате.
Хорошая базовая рамка такая: верно ли модель решила задачу, дала ли полный ответ, не нарушила ли правила безопасности и уложилась ли в нужное время ответа. Эти четыре метрики понятны и продакту, и разработчику, и руководителю, который откроет отчёт на десять минут перед выкладкой.
Для каждой метрики нужен простой способ подсчёта. "Верно" можно считать как долю ответов, где модель попала в ожидаемый смысл. "Полно" - как долю ответов со всеми обязательными полями или пунктами. "Безопасно" - как долю ответов без утечки персональных данных, опасных советов и обхода ограничений. "Быстро" - как p95 по времени ответа или долю запросов, уложившихся в лимит.
Пороги лучше задавать в двух слоях. Сначала по всему золотому набору. Потом по тем группам, где ошибка особенно дорогая: длинные диалоги, смешанные языки, юридические формулировки, ответы в JSON, запросы с PII. Общий проходной балл может быть таким: точность не ниже 92%, полнота не ниже 90%, безопасность 99,5%, p95 не выше 4 секунд. Но для группы с обязательным JSON разумно требовать 99% попадания в формат, даже если общий результат выше.
Отдельно считайте неудачные режимы. Иначе они потеряются внутри средней оценки. В верхнюю часть отчёта лучше сразу вынести отказы без причины, пустые ответы, выход за формат, тайм-ауты и ошибки провайдера.
Это не шум, а прямой риск для релиза. Если модель стала чуть точнее, но доля пустых ответов выросла с 0,2% до 3%, выпускать её рано. То же самое с форматом: для команды, которая меняет модель за одним OpenAI-совместимым эндпоинтом, сломанный JSON часто больнее, чем небольшая просадка по качеству текста.
Хорошие метрики не пытаются описать всё. Они быстро показывают, стало лучше или хуже, и подсказывают, где разбирать руками.
Как прогнать кандидата
Сравнение ломается в тот момент, когда команда меняет сразу всё: модель, системный промпт, температуру и даже тестовый набор. На один прогон лучше брать одного кандидата и одни и те же условия. Иначе вы не поймёте, что именно дало прирост или просадку.
Сначала зафиксируйте условия запуска. Набор примеров, параметры генерации, формат входа и постобработку нельзя менять по ходу проверки. Если трафик идёт через AI Router, имеет смысл явно сохранить model id, system prompt, temperature, max tokens и другие настройки, которые могут сдвинуть результат даже при той же задаче.
Дальше процесс обычно выглядит так:
- Берёте базовую версию из продакшена и нового кандидата.
- Прогоняете обе версии на одном и том же золотом наборе в одинаковом порядке.
- Сохраняете по каждому примеру не только итоговую оценку, но и сам ответ, latency, тайм-ауты и цену запроса, если стоимость важна для релиза.
- Складываете результаты в одну таблицу, где каждая строка - это один тест, а столбцы показывают базу, кандидата и разницу.
- Размечаете падения по типам: фактическая ошибка, отказ, лишняя многословность, плохой формат, нарушение политики, рост времени ответа.
Среднее число почти всегда прячет неприятные вещи. Общий score может вырасти на 2%, потому что FAQ начал отвечать быстрее, но в кредитных заявках модель стала чаще путать срок и ставку. Формально среднее лучше. Для банка это всё равно плохой релиз.
Поэтому после общей сводки разрежьте результаты по сегментам. Смотрите отдельно длинные и короткие запросы, диалоги с историей, случаи с PII, сложные инструкции и редкие сценарии. Один провалившийся сегмент часто важнее аккуратного роста по остальным.
Потом откройте 10-20 худших примеров руками. Автоматика здесь не спасает полностью. Люди быстро видят то, чего не ловит таблица: ответ стал уклончивым, тон съехал, формат вроде правильный, но оператору неудобно с ним работать.
Нормальный итог прогона звучит не как "модель стала лучше", а как короткий вывод: где кандидат выиграл, где проиграл, сколько это стоит и какие тесты блокируют выкладку прямо сейчас.
Пример: обновление чат-бота банка
Банк решил обновить системный промпт у чат-бота поддержки. Цель была ясной: сделать ответы короче, строже по тону и реже уводить клиента в общие советы вместо прямого ответа.
На общей сводке всё выглядело спокойно. Средняя оценка почти не сдвинулась. Если смотреть только на итоговый балл, релиз можно было легко пропустить дальше.
Проблема всплыла после разбивки по типам вопросов. На запросах про комиссии новая версия ошибалась чаще. Бот путал условия или отвечал слишком общо, когда клиент спрашивал про перевод, снятие наличных или обслуживание карты.
Что нашёл золотой набор
Набор не состоял только из коротких и чистых вопросов. В нём были длинные сообщения в стиле живого чата, где клиент сразу писал про карту, тариф, лимиты и просил сравнить два случая в одном сообщении. Туда же попали вопросы по старым тарифам, которые всё ещё встречаются в поддержке.
Именно на этих примерах новый промпт начал сбоить. Он чаще терял одну из частей длинного запроса и уверенно отвечал по текущим условиям там, где клиент спрашивал про старый тариф. Ошибка не выглядела грубой, но клиент всё равно получал неверную информацию и шёл жаловаться оператору.
Команда быстро увидела, зачем вообще нужна такая проверка. Не ради красивого среднего числа, а ради поиска узких провалов, которые больно бьют по продукту. В отчёте не было сотни строк. Там была короткая сводка: общий результат старой и новой версии, сегменты с просадкой, 14 проблемных примеров и решение - блокировать релиз или править промпт.
В этом случае релиз остановили, поправили инструкцию для ответов по комиссиям и заново прогнали проблемные сегменты вместе с полным набором. Это заняло меньше времени, чем разбирать жалобы после выкладки.
Где команды чаще ошибаются
Большинство провалов в проверке идут не от слабых метрик, а от плохой дисциплины. Схема может выглядеть аккуратно, а результат всё равно даёт ложное спокойствие.
Первая частая ошибка - золотой набор собирают из удачных примеров. Туда попадают хорошие диалоги из демо, чистые запросы без опечаток и короткие задачи, где модель и так показывает себя неплохо. Потом релиз выходит, и пользователи приносят всё, чего в наборе не было: длинный контекст, смесь русского и казахского, злые формулировки, спорные запросы и старые баги. Если сложных случаев мало, общий балл почти всегда выглядит лучше реальности.
Вторая ошибка - менять сразу всё. Команда берёт новую модель, переписывает системный промпт, правит правила оценки и заодно обновляет ретривер. После этого уже никто не понимает, что помогло, а что сломало ответы. На один цикл лучше менять один крупный слой и не трогать остальное.
Третья ошибка - смотреть только на средний балл. Среднее удобно для слайда, но оно скрывает неприятные провалы. Модель может прибавить 4% в целом и при этом заметно хуже отвечать на жалобы, запросы с персональными данными или длинные многоходовые диалоги. Если вы используете маршрутизацию между моделями, полезно смотреть не только общий результат, но и срезы по типам задач и маршрутам.
Ещё одна проблема - известные сбои не помечают отдельно. В итоге старые баги снова всплывают в каждом прогоне, смешиваются с новыми регрессиями и размывают приоритеты. Намного проще держать для них отдельный тег: "известно", "допустимо до релиза" или "блокер".
И, наконец, отчёт часто пишут так, будто его будут изучать полдня. На деле у команды есть десять минут. За это время человек должен понять, что изменили, где стало лучше, где появилась просадка и выпускать ли релиз сейчас.
Быстрый чек перед выкладкой
Перед выкладкой не нужен новый большой прогон. Нужен короткий контрольный проход, который команда делает одинаково каждый раз.
Сначала проверьте сам набор. В нём должны быть не только сценарии под новую функцию, но и старые случаи, на которых продукт держится каждый день. Если бот научился лучше объяснять новый кредитный продукт, но стал хуже отвечать про блокировку карты, релиз выпускать рано.
Потом откройте пороги. Их записывают до тестов, а не после просмотра результатов. Иначе команда почти всегда начинает торговаться с цифрами. Если заранее написано, что точность в критичных сценариях не падает ниже 97%, спорить уже не о чем.
Удобно, когда всё лежит в одном месте: ответы кандидата, ответы прошлой версии, автоматические оценки, ручные пометки, версия промпта и версия модели. Одна таблица или один дашборд лучше пяти разрозненных файлов. Если проверка идёт через AI Router, аудит-логи помогают быстро сверить параметры запуска и не спорить о том, какая именно конфигурация попала в прогон.
Финальный чек занимает десять минут, если в нём есть пять вещей: обновлённый набор, заранее зафиксированные пороги качества и стоимости, все ответы и оценки в одном месте, ручной просмотр худших кейсов и один человек, который принимает итоговое решение.
Ручной просмотр обязателен. Средняя оценка может выглядеть спокойно, пока внизу списка лежат два провала в юридическом дисклеймере, один опасный совет клиенту и пара сломанных ответов на казахском языке. Именно такие случаи потом доезжают до поддержки.
Финальная запись по релизу должна быть короткой. Часто хватает трёх строк: что улучшилось, где есть просадка и кто принял решение. Если просадка вышла за порог, кандидата не обсуждают бесконечно. Его чинят или откатывают.
Что должно быть в отчёте
Отчёт после прогона отвечает на один вопрос: релиз можно выкатывать или нет. В первом абзаце напишите, что именно команда поменяла, на каком наборе это проверила и чем всё закончилось - прошёл кандидат порог или дал регрессию.
На первой странице обычно достаточно трёх чисел:
- общий результат по всему золотому набору;
- результат по сложным группам, где модель ошибается чаще;
- число регрессий относительно текущей версии.
Рядом с цифрами дайте короткий комментарий. Например: "Общий score вырос на 1,8%, но в сценариях с длинным контекстом нашли 12 новых ошибок". Такая строка экономит время и не прячет плохие новости в таблицах.
После сводки добавьте 5-10 примеров, которые реально влияют на решение. Не нужно набивать отчёт десятками похожих кейсов. Гораздо полезнее показать случаи, где ошибка дорогая для бизнеса: неверный ответ по тарифу, пропуск запрета, путаница в суммах или уверенный вымысел в ответе клиенту.
Хороший пример выглядит просто: вход, ответ старой версии, ответ новой версии и короткая пометка ревьюера. Если новый вариант стал хуже в одном редком тесте, но сильно лучше в двадцати частых, это видно сразу. Если он ломает сценарий для VIP-клиентов банка, это тоже видно сразу.
Шаблон отчёта лучше не менять от релиза к релизу. Обычно хватает четырёх блоков: что изменили, три главных числа, примеры, которые повлияли на решение, и вердикт - выпускать, чинить или отправлять на повторный прогон.
Что делать после отчёта
После отчёта нужен явный следующий шаг. Если релиз прошёл, зафиксируйте этот прогон как новую базовую точку сравнения. Если не прошёл, отправляйте в работу только те ошибки, которые реально сдвинут решение на следующем прогоне.
Для команд, которые сравнивают несколько моделей через один совместимый endpoint, удобно держать запуск и логи в одном месте. В AI Router можно опираться на единый API и аудит-логи, чтобы сверять кандидатов по одинаковым условиям, а не спорить по памяти или по разным выгрузкам. Это особенно полезно, когда один и тот же тест гоняют по нескольким провайдерам.
Сама идея простая: не пытайтесь измерить всё. Дайте команде набор, которому она доверяет, несколько понятных метрик и короткий отчёт, который можно прочитать за десять минут. Этого уже достаточно, чтобы ловить регрессии до того, как их поймают пользователи.