Эвалы для AI-агентов: как понять, что агент действительно работает
Все строят агентов, почти никто их не измеряет. Разбираемся, почему обычные тесты тут ломаются, как собрать первый eval-датасет за час, в чём разница между оценкой результата и оценкой траектории, и как не обмануть себя с LLM-as-judge.
СреднийDevOps с AI35 минDeepEval, Langfuse, Claude API
1
Почему unit-тесты здесь ломаются
Вы написали агента. Он работает на ваших тестовых запросах — значит, готов? Нет: LLM недетерминирована, один и тот же вход даёт разные выходы, и «правильный ответ» часто субъективен. Классический unit-тест проверяет равенство, а здесь равенство — не то, что нужно проверять.
Eval — это не «работает / не работает». Это измерение: насколько хорошо, в каком проценте случаев, где ломается. Вопрос не «прошёл тест?», а «прошёл 47 из 50 кейсов, и вот что общего у трёх провалов». Отношение к провалу другое: это не баг, это данные.
🧪 Unit-тест
- Точное совпадение: 0 или 1
- Бежит на каждом коммите
- Провал = остановись и чини
📊 Eval
- Процент прохождения и распределение
- Бежит по расписанию или перед релизом
- Провал = данные для анализа
Первое, что нужно изменить — отношение к провалу. Если вы хотите 100% pass rate, вы пишете либо тривиальные тесты, либо обманываете себя. Цель — увидеть, где агент ломается, и решить, стоит ли это чинить.
2
Датасет важнее метрики — всегда
Метрики выглядят важно — accuracy, precision, recall. Но без хорошего датасета это термометр в пустой комнате: что-то меряет, только не то, что нужно. Правильный порядок: сначала 20 реальных примеров, потом метрика вокруг них.
Откуда берутся первые 20? Из трёх источников. Логи прода или бета-тестеров — там то, что ломалось у реальных пользователей. Corner cases, найденные руками — пустой вход, неоднозначный запрос, язык, к которому вы не готовились. И синтетика — но только как добавка, не замена: синтетика ровная, реальность — нет.
Логи прода
Отбор руками
Eval-датасет (20)
Прогон
Анализ провалов
Новые кейсы
Не стремитесь к 100 тестам с первого захода. 20 тщательно отобранных примеров, покрывающих разные типы запросов, полезнее 200 случайных. Датасет растёт по мере того, как вы находите новые failure modes в проде.
3
Два взгляда на агента: результат и траектория
Агент отвечает «14» на вопрос «сколько заказов клиент сделал за март?». Правильно? Есть два способа проверить, и они отвечают на разные вопросы.
End-to-end сравнивает «14» с эталоном. Просто, быстро — но ничего не говорит, как агент к этому пришёл. Он мог угадать и всё равно выдать правильный ответ.
Trajectory смотрит на последовательность шагов: вызвал ли `get_orders` с фильтром по марту, применил ли `group_by customer`. Если любой шаг неправильный, а результат случайно совпал — trajectory это поймает.
🎯 End-to-end
- Сравнить ответ с эталоном
- Быстро и дёшево
- Не видит случайных совпадений
🔬 Trajectory
- Проверить каждый шаг и параметр
- Дороже, но надёжнее
- Ловит фальшивые «правильные» ответы
end_to_end_eval:
запрос → агент → ответ
сравнить(ответ, эталон) → pass/fail
trajectory_eval:
запрос → агент → [шаг1, шаг2, шаг3, ответ]
для каждого шага:
правильный_инструмент? правильные_параметры?
итоговый балл = средний по шагам + результатДля trajectory не сравнивайте шаги буквально. «Вызвал get_orders вместо get_customer_orders» — не провал, если оба дают правильные данные. Сравнивайте намерение, не синтаксис.
4
LLM-судья — мощно, но легко обмануть самого себя
Как проверить качество, если «правильный ответ» — это абзац текста, а не число? Посадите второй LLM судьёй: дайте ему ответ агента, эталон, критерии — и попросите оценить. Работает, но ломается тремя способами.
Первая ловушка — судья ставит всем «хорошо». LLM по умолчанию вежливы. Лечение: rubric с явными критериями и обязательным обоснованием каждого балла.
Вторая — судья любит длинные ответы и переоценивает их. Лечение: явно проверяйте лаконичность как отдельный критерий.
Третья — используется та же модель, что и агента. Модель склонна одобрять свой стиль. Лечение: судья должен быть другой моделью, в идеале сильнее.
Хороший rubric для LLM-судьи
Балл от 0 до N, а не «хорошо/плохо»
Требует обоснования каждого балла
Явные критерии: корректность, полнота, тон
Судья — другая модель, не агент
Одна общая оценка «оцени качество»
rubric: оценка ответа поддержки
критерии (каждый 0–2):
корректность — факты совпадают с базой знаний
полнота — все части вопроса адресованы
тон — нейтральный, не снисходительный
вывод: { корректность: 2, полнота: 1, тон: 2, обоснование: "..." }
pass ≥ 5 из 6Раз в неделю берите 20 случайных оценок судьи и проверяйте руками. Если вы согласны меньше чем в 80% случаев — rubric плохой, и метрика показывает не качество агента, а настроение судьи.
5
От первого теста до прода: три этапа и где остановиться
Типичная ошибка — строить идеальный eval перед запуском. Правильный путь — три этапа, на каждом вы смотрите на разные вещи.
Этап 1: 20 примеров, гоняете локально, чините очевидные провалы. Не пытайтесь автоматизировать — вы ещё не знаете, что мерить.
Этап 2: 100 примеров, регрессия перед мержем. Сюда идут LLM-as-judge и trajectory-метрики. Отдельный smoke-набор (10 штук) бежит на каждом коммите — быстрый сигнал, что ничего не сломано радикально.
Этап 3: прод-трейсинг. Каждый реальный вызов логируется, часть логов возвращается в eval-датасет. Это замыкает петлю: агент учится на настоящих провалах, а не на придуманных за кофе.
| Этап | Размер | Частота | Зачем |
|---|---|---|---|
| Локально | 20 | Вручную | Найти очевидные дыры |
| Регрессия | 100 | Перед мержем | Ловить откаты качества |
| Smoke | 10 | Каждый коммит | Быстрый сигнал |
| Прод | ∞ | Непрерывно | Замкнуть петлю |
Знак того, что eval-система готова, — не процент прохождения, а то, что новые провалы приходят из прода, а не из вашей головы. Это значит, датасет догнал реальность.
Результат
Работающая система оценки агента: датасет из реальных примеров, метрики, которые отличают случайное совпадение от правильной работы, и процесс, где провалы из прода становятся новыми тестами — а не багами, о которых все забыли.