Eval как release-критерий: как ловить agent drift до прода, а не после
AI-фича, одобренная на тех же входах, что и питч, ломается в проде на длинном хвосте реальных случаев. Eval-harness делает набор проверок критерием релиза и гоняет фичу против этого хвоста: regression из прошлых инцидентов, distribution-diff и human spot-check — до деплоя, а не после инцидента.
Проблема
AI-фича, которая работает на демо, ломается в проде непредсказуемо и необъяснимо. Большинство команд узнают это после релиза. Причина — «demo grade»: eval, который одобрил фичу, использовал те же входы, что и питч. Курированный датасет, контролируемые условия. Длинный хвост реального трафика никогда не прогонялся.
Методика
Сделать качество AI-вывода release-критерием, а не ретроспективной находкой. Минимальный eval при релизе — три слоя.
-
1. Layer 1 — Regression (non-negotiable).
Фиксированный набор reference-кейсов с известным ожидаемым выводом:
edge-кейсы прошлых инцидентов, кейсы из демо (которым одобряли фичу),
минимум один adversarial-вход на тип вывода (prompt injection, пустой,
malformed). Любой новый фейл блокирует релиз.
# cases/rag-stale-corpus.yaml id: rag-stale-corpus origin: incident-2026-03 # RAG галлюцинировал на полном корпусе input: query: "действующая ставка по тарифу X" expected: must_contain: - "актуальный документ" must_not_contain: - "status: archived" retrieved_chunks: min_count: 1 must_contain: - "active" must_not_contain: - "archived" pass_criteria: - no_archived_docs - answer_groundedКейс рождается из инцидента (
origin) — это и отличает regression set от demo-датасета: входы взяты из того, что уже ломалось в проде. -
2. Layer 2 — Distribution check (RAG/классификаторы).
20–50 свежих реальных входов через новую версию. Проверка не на «идеал», а на
diff против снапшота прошлого релиза:
распределение длины/формата, изменение retrieved-чанков, сдвиг confidence
(сдвиг к краям = хрупкость).
Механика — не статтест, а пороги на сводных статистиках против снапшота:
# layers/distribution.py LENGTH_DRIFT_THRESHOLD = 0.30 # rel-change среднего > 30% → флаг CONFIDENCE_STD_DRIFT_THRESHOLD = 0.20 # рост std confidence > 20% → хрупкость std_growth = (current_std - baseline_std) / baseline_std if std_growth > CONFIDENCE_STD_DRIFT_THRESHOLD: flags.append(f"confidence std grew {std_growth:.1%} — fragility signal") # сдвиг среднего confidence к краям [<0.35 | >0.85] при движении > 0.15 edge_shift = abs(current["confidence_mean"] - baseline_mean) if edge_shift > 0.15 and (mean < 0.35 or mean > 0.85): flags.append("confidence mean shifted toward edges")Почему пороги, а не KS/PSI: на 20–50 сэмплах двухвыборочный Колмогоров-Смирнов недомощен и даёт ложные тревоги; пороги на
mean/pstdev— дешёвый гейт для такого N. Плата — не ловятся изменения формы (бимодальность, утолщение хвоста): грубые сдвиги среднего/разброса видны, тонкие — нет. Путь апгрейда, когда набор растёт: PSI или two-sample KS на распределениях длины и confidence. - 3. Layer 3 — Human spot-check. Обязателен перед первым проддеплоем нового вида вывода: доменный человек читает 10–20 реальных выводов с конкретными вопросами (нет ли данных, к которым модель не должна иметь доступ; счёл бы эксперт это корректным; нет ли adversarial-эксплуатации).
- 4. Owner. Один человек подписывает sign-off. Если перед релизом нельзя назвать владельца — это уже первый тревожный признак.
Артефакт
Минимальный harness под этот чеклист: Python-скрипт, который прогоняет regression set против snapshot и сравнивает distribution (Layer 1 + Layer 2). Система под тест подключается через тонкий адаптер — harness не знает про модель, только про контракт:
# adapter.run(input) -> {"output": str, "chunks": list, "confidence": float}
response = adapter.run(raw_input)
Wiring как release-gate — через exit-коды, чтобы CI мог блокировать мёрж:
python run_eval.py --all --inputs inputs.jsonl
# exit 0 — оба слоя прошли, релиз разрешён
# exit 1 — regression упал → жёсткий блок (known-bad вернулся)
# exit 2 — distribution drift → мягче: сигнал на ревью, не автоблок
Разделение неслучайно: regression — это «известное сломалось», однозначный
стоп; distribution drift — «поведение поехало», повод для человека, а не
автоматический отказ. Снапшот обновляется явным
--update-snapshot, то есть
baseline двигается осознанно, а не сам собой.
- github.com/dobryakov/eval-harness — regression + distribution check, adapter interface, demo-кейс из инцидента. Harness вайб-кожен и иллюстративен: это скелет практики, а не библиотека.
Где ломается
- Eval-датасет = demo-датасет — самый частый антипаттерн: «eval» оказывается стейкхолдерским демо, а не измерением.
- Pass criteria определены после прогона — «выглядит разумно» вместо конкретного измеримого порога.
- Нет owner — sign-off делегируется в «в стейджинге выглядело нормально».
- Реальные failure modes, давшие эту методику: RAG корректен на курированном корпусе и галлюцинирует на полном; классификатор тихо деградирует после смены входной схемы upstream; AI-код проходит автотесты, но вносит security-паттерн, который тесты не покрывали.
- Порог не ловит изменение формы. Distribution-слой видит сдвиг среднего и разброса, но пропустит бимодальность и утолщение хвоста при том же среднем. Митигация: при росте набора до сотен сэмплов — заменить пороги на PSI или two-sample KS. Что мониторить в проде параллельно eval: доля выводов у краёв confidence и p95 длины ответа — ранние сигналы дрейфа между релизами.
Для кого и почему
Риск: eval зелёный, прод красный — стандартная история. Узнают после релиза, чинят дороже, чем если бы поймали до.
Решение: фича не уходит в прод, пока три слоя eval не прошли — не потому что «выглядит хорошо», а потому что по критерию.
Метрика: борд спрашивает «что у нас с AI-качеством» — отвечаешь не «тестировали», а показываешь regression и distribution diff.
Ближе всего к playbook: артефакт уровня «как устроена практика» для Head of AI и технического CTO. Вайб-кодинг harness'а делает из методики воспроизводимый код-артефакт — закрывает code-modus, не только playbook.
Читать дальше
Об авторе
Григорий Добряков — fractional / interim eng + AI leadership
Хотите построить eval-процесс для AI-фич в вашей команде?
Постановка eval как release gate: от regression set и distribution check до sign-off процесса. Не теория — воспроизводимая практика с checklists и harness.
Обсудить fractional-аудит Написать на почтуДругие разборы
Серия инженерных разборов: реальная задача → методика → работающий артефакт → честный разбор, где он ломается.
К серии →