Автоматический перевод
Эта статья была автоматически переведена с оригинальной английской версии.
Оценка AI-агентов в продакшене: от трейсов к тестовым наборам
Ответ чат-бота — это строка. Запуск агента — это дерево.
Эта разница ломает многие привычки оценки. Финальный ответ может выглядеть нормально, хотя агент пропустил обязательный инструмент, 17 раз повторил один и тот же вызов, неверно интерпретировал результат инструмента или пошёл по пути, который был бы недопустим в продакшене. Если оценивать только ответ, вы не увидите место, где система реально сломалась.
Кратко: для agent evals нужны три слоя: метрики результата, метрики траектории и метрики компонентов. Стройте процесс вокруг такого цикла: trace -> label -> cluster -> dedupe -> versioned dataset -> CI gate -> online monitoring. Используйте детерминированные проверки для порядка вызова инструментов, аргументов, циклов и инвариантов. LLM-судей используйте только там, где проверка зависит от интерпретации, задавайте им форму через Schema-Guided Reasoning (SGR) и калибруйте по человеческой разметке, прежде чем им доверять.
Почему evals для агентов отличаются
Традиционные LLM-evals обычно оценивают одну пару input-output: релевантность, faithfulness, correctness, safety, иногда style. Агенты добавляют планирование, вызовы инструментов, ретраи и проверки завершения, и каждый шаг — это новое место для сбоя.
Возьмём refund-агента. Диалог может закончиться хорошо, хотя trace неверный:
lookup_order -> issue_refund -> final_answer
Проверка выходного ответа проходит. Проверка траектории должна провалиться, потому что verify_identity так и не был вызван до issue_refund. Для агентов, использующих инструменты, evals только по ответу — это smoke-тесты: они ловят полный развал и пропускают всё остальное.
Есть и вторая проблема: ошибки накапливаются. Если workflow из 20 шагов надёжен на 95% на каждом шаге, его end-to-end success rate всё равно будет около 36%:
То есть агент может выглядеть надёжным в изолированных проверках и при этом проваливать большинство полных запусков. Сбой обычно происходит где-то посередине, и чтобы его найти, нужна видимость на уровне компонентов, а не ещё один взгляд на финальный ответ.
Две исследовательские группы выразили это в цифрах.
tau-bench — это бенчмарк, где агент решает задачи клиентской поддержки в доменах авиаперевозок и ритейла: он общается с симулированным пользователем, вызывает API и по ходу должен соблюдать доменные политики. Оценка игнорирует сам диалог. После завершения разговора бенчмарк проверяет, пришла ли база данных в размеченное целевое состояние, так что вежливый и правдоподобный запуск, который оставил после себя неправильные строки, всё равно считается провалом. При такой схеме оценки даже GPT-4o успешно справлялся менее чем с половиной задач. В статье также ввели pass^k: одна и та же задача запускается k раз, и pass засчитывается только если агент успешен во всех k запусках. Оценки в ритейле, которые выглядели терпимо для одной попытки, падали ниже 25% при k = 8. Тот же агент, та же задача, восемь запусков — в основном разные результаты. Эту непоследовательность невозможно увидеть, если в eval каждый кейс прогоняется один раз.
MAST задаёт другой вопрос: не как часто агенты ошибаются, а почему. Авторы разметили более 1,600 execution traces из 7 популярных multi-agent framework'ов и разложили сбои по 14 повторяющимся режимам отказа. Почти ни один из них не выглядит как «модель дала неправильный ответ». Это проблемы вроде размытых определений ролей (system design), ситуации, когда один агент игнорирует то, что ему сообщил другой (inter-agent misalignment), или объявления успеха без проверки результата (no verification). Большинство сбоев живут в harness: в промптах, логике оркестрации, отсутствующих проверках. Более сильная базовая модель уменьшает эти числа, но не исправит шаг верификации, который вообще не был реализован. Поэтому оценивать нужно harness, а не только модель внутри него.
Разрыв между внедрением и оценкой
У большинства команд уже есть сырьё для более качественных evals. У них есть трейсы. Они просто ещё не превратили их в тесты.
Исследование LangChain State of Agent Engineering — самый наглядный публичный снимок этого разрыва. В нём сообщается, что у 57.3% респондентов агенты уже в продакшене, 89% имеют хотя бы какую-то observability, 52.4% запускают offline evals, а 37.3% — online evals. И когда их спросили, что мешает продакшену, 32% назвали quality — выше, чем latency с 20%. То, что измеряют evals, и есть то, на чём команды застряли.
Из-за этого команды оказываются в неудобном промежуточном состоянии: они могут разобрать неудачный запуск постфактум, а потом всё равно отправить тот же сбой в продакшен ещё раз.
Одно правило это исправляет: каждый диагностированный продакшен-сбой должен оставлять после себя trace, label, строку датасета и scorer. Если это может повториться, это должно попасть в regression suite.
Подбирайте метрики по режиму отказа
Правильная метрика зависит от режима отказа, а не от framework'а. Полезное разделение включает три уровня:
- Outcome evals отвечают на вопрос, была ли задача успешно выполнена.
- Trajectory evals отвечают, был ли путь корректным, эффективным и соответствующим политике.
- Component evals отвечают, какой именно tool, retriever, sub-agent или шаг принятия решения сломался.
Каждый уровень можно запускать offline (фиксированные, воспроизводимые кейсы до релиза) или online (выборочные продакшен-трейсы после ответа); ниже, в разделе про guardrails, это разделение разобрано подробнее. Короткая версия: offline evals могут требовать goldens, а online evals должны предпочитать инварианты, распределения и async-проверки вне request path.
| Вопрос | Семейство метрик | Контракт offline / online | Детерминированно или judge? | На что обратить внимание |
|---|---|---|---|---|
| Вызывал ли агент правильные инструменты? | Корректность tool calls: exact, in-order или any-order match | Exact goldens offline; инварианты обязательных инструментов и аномалии online | Детерминированно | Exact match штрафует валидные альтернативные пути |
| Вызывал ли он их с правильными входами? | Корректность аргументов, schema validation, parameter match | Ожидаемые аргументы offline; schema-, range- и policy-checks online | Оба варианта | Правильный tool с неправильными аргументами — тоже сбой |
| Тратил ли он лишние шаги? | Эффективность шагов, число ретраев, loop detection, cost и latency | Бюджеты на шаги и циклы offline; drift по cost и latency online | В основном детерминированно | Высокий task completion может скрывать дорогие блуждания |
| Была ли задача реально выполнена? | Task completion, outcome grading, diff финального состояния | Simulator или golden state offline; final state, user signal или async judge online | Judge или state check | По возможности оценивайте состояние среды |
| Сохранял ли он контекст между ходами? | Multi-turn fidelity, role adherence, conversation completeness | Скриптовые long-horizon кейсы offline; выборочные длинные сессии online | Judge | Single-turn тесты ничего не говорят о ходе 14 |
| Остановился ли он вовремя? | Корректность завершения, premature success, endless work | Сценарные тесты offline; мониторинги loop, timeout и false-success online | Оба варианта | «Done» может быть галлюцинированным состоянием |
| Правильно ли он интерпретировал результаты инструментов? | Понимание результатов tool, downstream state checks | Adversarial tool outputs offline; downstream state checks и выборочный review online | Оба варианта | Tool может быть корректным, а агент — прочитать его неправильно |
Начинайте с детерминированных метрик. Они дешёвые, быстрые и не дрейфуют.
Корректность вызова инструментов
Tool correctness сравнивает вызванные инструменты с ожидаемыми. Жёсткость нужно выбирать осознанно:
- Exact match: последовательность должна совпасть полностью. Используйте, когда порядок задан политикой, например
lookup_order -> verify_identity -> issue_refund. - In-order match: обязательные инструменты должны появиться в правильном относительном порядке, но дополнительные безвредные вызовы допустимы.
- Any-order match: обязательные инструменты должны появиться, но порядок может различаться.
Чтобы начать, достаточно небольшого локального scorer'а:
def tool_correctness(called: list[str], expected: list[str], mode: str = "in_order") -> float:
if not expected:
return 1.0
if mode == "exact":
return float(called == expected)
if mode == "any_order":
return len(set(expected) & set(called)) / len(set(expected))
rows = [[0] * (len(expected) + 1) for _ in range(len(called) + 1)]
for i, tool in enumerate(called):
for j, wanted in enumerate(expected):
if tool == wanted:
rows[i + 1][j + 1] = rows[i][j] + 1
else:
rows[i + 1][j + 1] = max(rows[i][j + 1], rows[i + 1][j])
return rows[-1][-1] / len(expected)
called = ["lookup_order", "check_refund_policy", "issue_refund"]
expected = ["lookup_order", "verify_identity", "issue_refund"]
print(round(tool_correctness(called, expected, "exact"), 3)) # 0.0
print(round(tool_correctness(called, expected, "in_order"), 3)) # 0.667
Метрика Tool Correctness в DeepEval предоставляет те же настройки через should_consider_ordering и should_exact_match.
Корректность аргументов
Вызвать правильный инструмент с неправильными аргументами часто хуже, чем вызвать неправильный инструмент, потому что trace выглядит нормальным.
Для простых случаев проверяйте JSON schema и точные значения. Для семантических случаев храните ожидаемые аргументы и оценивайте отклонения:
{
"trace_id": "tr_2417",
"input": "Reschedule order A-100 for next Friday.",
"expected_tools": ["lookup_order", "reschedule_delivery"],
"expected_arguments": {
"reschedule_delivery": {
"order_id": "A-100",
"date": "2026-06-19"
}
}
}
Метрика по имени инструмента не поймает 2026-06-17, когда политика требует 2026-06-19. В датасете нужно хранить и аргументы тоже.
Эффективность, циклы и тупики
Путь важен даже тогда, когда цель достигнута. Агент, который завершает задачу после пяти лишних вызовов инструментов, всё равно сигнализирует о проблеме в планировании и обходится дороже.
Дешёвые сигналы, с которых стоит начать:
- Доля избыточных вызовов: одинаковые вызовы одного и того же инструмента с одинаковыми аргументами, повторённые более двух раз.
- Аномалии формы trace: резкие всплески глубины, числа вызовов инструментов, числа токенов, latency или cost.
- Сходимость пути: насколько близок запуск к кратчайшему известному валидному пути для задачи.
- Корректность завершения: остановился ли агент слишком рано, продолжил ли работу после успеха, или объявил успех без требуемого изменения состояния.
Запускайте такие проверки раньше judge, когда это возможно. Детектор циклов — это несколько строк поверх trace. Ему не нужна модель.
Завершение задачи и outcome grading
End-to-end вопрос звучит так: «получил ли пользователь то, о чём просил?»
Лучше всего работают два паттерна:
- Referenceless task-completion judging: извлекаете цель из входа и оцениваете, достигли ли её trace вместе с финальным ответом. Это работает online, потому что в продакшен-трафике редко есть golden outputs.
- Environment-state grading: сравниваете финальные строки в базе данных, файлы, тикеты, бронирования или записи с размеченным целевым состоянием. Это надёжнее, чем сопоставление по диалогу, потому что агенты могут находить валидные пути, которые вы не прописали заранее.
Второй вариант лучше, если вы можете его построить. Финальное состояние — это контракт. Диалог — только свидетельство.
Trace-to-eval flywheel
Не начинайте с брейншторма eval-набора. Добывайте его из продакшен-сбоев.
Цикл:
- Захватить полный trace.
- Разметить, что именно сломалось.
- Сгруппировать похожие сбои.
- Оставить по одному representative golden на кластер.
- Версионировать датасет.
- Гонять его в CI.
- Продолжать online-оценку выборочных продакшен-трейсов.
Добывайте сбои через error analysis
Hamel Husain и Shreya Shankar предлагают workflow error analysis именно для этого шага; в field guide Хамеля он разобран подробно. Названия первых двух шагов заимствованы из качественных исследований, но сам метод прост: читаете трейсы, делаете заметки, называете паттерны.
- Open coding: прочитайте от 30 до 50 реальных трейсов и в свободной форме запишите, что пошло не так.
- Axial coding: сгруппируйте эти заметки в 5–6 именованных категорий сбоев.
- Разметьте всё по этой таксономии.
- Постройте метрики для самых крупных корзин.
Не начинайте с меток вроде reasoning_issue или tool_problem. Они слишком расплывчаты для тестирования. Используйте метки вроде missing_identity_verification, date_argument_mismatch, retried_same_tool_after_429 или stopped_before_database_update. Такая конкретика сразу говорит, что именно должен проверять regression test.
Удаляйте дубликаты до промоушена
У цикла добычи трейсов есть ловушка: добавлять каждый плохой trace навсегда. Это создаёт датасет, который большой, дорогой и узкий. Он проходит по почти одинаковым дубликатам из марта, но пропускает новую форму той же ошибки в июне.
Сначала группируйте. Затем повышайте до golden только один representative кейс на кластер. Связанные trace ID храните в metadata, чтобы ревьюер позже мог проверить продакшен-доказательства.
Если кластер сбоев повторяется после исправления, значит regression case не обобщился. Перекластеризуйте и расширьте golden вместо того, чтобы добавлять 15 точечных примеров.
Версионируйте датасет
Версионируйте датасеты так же, как промпты и код. Когда меняется что-то существенное (model, prompt, tool schema, judge prompt или поведение приложения), вы хотите запускать одну и ту же версию датасета до и после изменения.
CI-gate должен фиксировать:
- версию датасета
- версию приложения
- версию промпта
- judge model
- judge prompt
- версию evaluator code
Если что-то из этого сдвигается, сравнение до/после становится мутным. Файла goldens-v3.json в git достаточно на небольшом масштабе. Нативные snapshots в Langfuse, Phoenix, Braintrust или LangSmith помогают, когда датасет становится коллективным.
Гейтите CI
Провалившаяся метрика должна превращаться в провалившийся билд, иначе eval suite — это просто дашборд, который никто не читает.
Тест должен заново прогонять текущего агента на golden input. Он не должен просто воспроизводить старый неудачный trace:
@pytest.mark.parametrize("golden", GOLDENS, ids=[item["id"] for item in GOLDENS])
def test_agent_regression(golden: dict) -> None:
answer, fresh_trace = run_agent_and_capture_trace(golden["input"])
refired = set(flag_failures(fresh_trace)) & set(golden["failure_modes"])
assert not refired, f"failure mode regressed: {sorted(refired)}"
assert tool_correctness(
called=[call["name"] for call in fresh_trace["tool_calls"]],
expected=golden["expected_tools"],
mode=golden.get("tool_match", "in_order"),
) >= golden.get("tool_threshold", 1.0)
В этом различии легко ошибиться. Задача датасета — поймать, когда следующая версия агента повторяет старый сбой, а не архивировать сам сбой.
Откалибруйте judge, прежде чем ему доверять
LLM-as-judge помогает. И с ним очень легко обмануть себя.
У этой идеи есть послужной список. G-Eval показал, что judge, который шаг за шагом проходит по явной rubric, лучше согласуется с человеческими оценками, чем старые автоматические метрики, которые он заменял. MT-Bench показал, что GPT-4 соглашается с человеческими предпочтениями примерно так же часто, как люди соглашаются друг с другом, — именно это сделало LLM judging мейнстримом. Потом пришли оговорки: judges отдают предпочтение ответу, который стоит первым в pairwise prompt, выше оценивают более длинные ответы, предпочитают outputs своей собственной model family и смещаются при изменении prompt или версии модели. JudgeBench тестировал judges на парах ответов, где один ответ объективно неверен, и обнаружил, что даже сильные judges на сложных случаях держатся около точности подбрасывания монеты.
Относитесь к judge как к измерительному прибору.
Когда judge необходим, делайте вердикт структурированным. Schema-Guided Reasoning (SGR) — стандартный паттерн для этого: задайте траекторию рассуждения judge в виде Pydantic schema, пропустите её через Structured Outputs или constrained decoding и заставьте модель выдавать поля вроде evidence, passed_criteria, failed_criteria, failure_mode и score.
Это не делает judge магически правильным. Но делает измерение более воспроизводимым. Judge должен проходить через одни и те же заранее заданные шаги rubric, в одном и том же порядке полей, в каждом запуске и на каждой совместимой модели. Ревьюер может смотреть на именованные поля вместо того, чтобы разбирать абзац текста. CI может diff'ить стабильный JSON-объект. Калибровка становится проще, потому что rubric больше не спрятана внутри свободного текста.
Это также меняет кривую затрат. Когда topology рассуждения задана явно, а выход ограничен, более дешёвые модели часто оказываются достаточно хорошими для рутинного judging. Оставьте более крупного judge для расхождений, high-risk кейсов или калибровочных прогонов, вместо того чтобы платить за него на каждом trace.
| Bias | Что происходит | Как снижать риск |
|---|---|---|
| Position | Pairwise prompts отдают предпочтение одному слоту | Меняйте порядок и усредняйте обе перестановки |
| Verbosity | Более длинные ответы получают более высокий score без роста качества | Штрафуйте неподкреплённую многословность в rubric |
| Self-preference | Judge предпочитает свою собственную model family | Используйте другую model family или jury |
| Sycophancy | Judge засчитывает непроверенные утверждения | Требуйте evidence из trace в вердикте |
| Calibration drift | Обновление модели или prompt сдвигает оценки | Фиксируйте judge model и prompt; перекалибруйте при изменениях |
Чеклист базовой гигиены judge:
- По возможности предпочитайте бинарный pass/fail. Пятибалльные шкалы создают ложную точность.
- Разметьте вручную 30–50 траекторий до написания финальной rubric.
- Измерьте judge-human agreement через Cohen's kappa или просто TPR/TNR.
- Декомпозируйте грубые критерии. «Проверил ли агент личность перед вызовом refund tool?» лучше, чем «Была ли траектория хорошей?».
- Выдавайте вердикт через SGR schema с evidence, failed criteria, failure mode и score.
- По возможности используйте judge из другой model family, чем генератор.
- Рандомизируйте порядок в pairwise-сравнениях и усредняйте оба направления.
- Фиксируйте judge model, prompt, dataset, schema и версию приложения.
- Перекалибруйте после изменений модели, prompt, tool, policy или schema.
Для high-stakes оценок используйте небольшое jury вместо одного большого judge. PoLL тестировал именно такую конфигурацию: панель из небольших judges, взятых из непересекающихся model families, с объединением их вердиктов в один score. На шести датасетах такая панель лучше соответствовала человеческим суждениям, чем одиночный judge GPT-4, избегала bias self-preference, характерного для одиночного judge по отношению к output'ам своей собственной family, и стоила более чем в семь раз дешевле. Человеческое ревью всё равно оставляйте для решений, влияющих на деньги, доступ, безопасность или compliance.
Если judge согласуется с людьми на 0.55 kappa в вашей задаче, не используйте его для блокировки деплоев. Используйте его для сортировки очередей на ревью. Если он держится ближе к 0.75 и стоимость ошибки умеренная, защищать CI-gate уже намного проще.
Online evals — это не guardrails
Люди часто их путают, потому что и те и другие выдают score. Но находятся они в разных местах.
Guardrails работают inline. Они быстрые, детерминированные и видимы пользователю. Guardrail может заблокировать вызов инструмента, отредактировать PII, отклонить prompt injection или принудительно вызвать retry до того, как ответ покинет вашу систему. False positive здесь — это продакшен-баг.
Offline evals запускаются до релиза. Они воспроизводимы. Они гейтят prompts, models, tools, retrievers и policies по фиксированному датасету.
Online evals запускаются после ответа, обычно на семплированном трафике. Они могут использовать более медленных LLM-judges, потому что не находятся в пути latency. Их задача — обнаруживать drift, находить новые кластеры сбоев и наполнять следующий offline dataset.
Если перепутать размещение, будет больно в обе стороны:
- Judge в request path добавляет latency и новый источник флаки.
- Guardrail, отправленный в async scoring, позволяет policy violations доходить до пользователей.
Для систем с большим объёмом трафика оценивайте небольшую выборку более сильным judge и более широкую выборку — дешёвыми классификаторами. Алертите по кластерам и доверительным границам, а не по одной шумной точечной оценке.
Выбор инструментов
Ни один инструмент не закрывает весь цикл целиком. В большинстве серьёзных стеков используются две части: trace store и CI/eval runner.
| Tool | Лучший сценарий | История с CI | История с self-hosting | Компромисс |
|---|---|---|---|---|
| DeepEval | Pytest-native evals для агентов и LLM | Сильная: deepeval test run хорошо ложится в CI |
Базовая библиотека локальная/open source | Judge-вызовы и облачные функции могут добавлять стоимость |
| Inspect AI | Safety, frontier и sandboxed evaluations | CLI и Python API | Полностью локальный/open source | Не является платформой продакшен-трейсов |
| Phoenix | OTel/OpenInference tracing плюс evals | Кастомные скрипты | Сильная self-host опция | Managed alerting находится в коммерческом слое |
| Langfuse | Trace store, datasets, версии промптов | Experiments и кастомные gates | Сильная self-host опция | Eval-метрики менее batteries-included, чем в DeepEval |
| LangSmith | Tracing и evals для LangChain/LangGraph | pytest, Vitest, GitHub workflows | Enterprise self-host | Закрытый код; следите за pricing по seats и объёму trace |
| Braintrust | Eval-driven product loop и PR review | Очень сильный managed flow для PR regression | Enterprise/hybrid | Объём spans, processed data и число score могут быстро расти |
| Promptfoo | Prompt tests и red-team suites | GitHub, GitLab, Jenkins, CircleCI | Локальное/open source core | Отличный prerelease-runner, но не trace hub |
Примечания про компромиссы описывают, откуда берётся стоимость, а не сколько именно она составляет. Страницы с pricing меняются, и вендоры считают разное: traces, observations, spans, scores, users, retention или processed data. Перед принятием решения перепроверьте актуальные цены.
Короткие правила выбора:
- Нужен self-hosted tracing с переносимостью через OTel: начните с Phoenix или Langfuse.
- Нужен code-first CI gate: начните с DeepEval.
- Уже сделали ставку на LangGraph: LangSmith удобен.
- Нужен managed PR regression review: Braintrust трудно превзойти.
- Доминируют security- и red-team-кейсы: Promptfoo — более сфокусированный инструмент.
- Нужны safety research или контролируемые benchmark-исследования: лучше подойдёт Inspect AI.
Выбор инструмента вторичен. Если продакшен-сбои не превращаются в тест-кейсы, вы в основном платите за хранение трейсов.
Практический чеклист внедрения
Прежде чем реализация станет хитрой, постройте pipeline доказательств. Первый вопрос — не «какую метрику нам оптимизировать?». А «откуда возьмутся примеры?»
-
Сначала соберите исторические запуски. Если агент уже существует, выгрузите трейсы, support tickets, bug reports, thumbs-down sessions, manual QA transcripts и dogfooding notes до изменения реализации. Если агента ещё нет, логируйте каждый prototype и manual test run с первого дня.
-
Проинструментируйте форму trace. Захватывайте сообщения, tool calls, arguments, tool outputs, errors, число токенов, latency, cost, user feedback, версию приложения, версию промпта, версию модели, версию schema инструмента и финальное состояние среды. Используйте OpenTelemetry GenAI conventions или spans в стиле OpenInference, если хотите переносимость. Используйте Langfuse, LangSmith, Phoenix или Braintrust, если вам сразу нужны UI для трейсов и workflow для датасетов.
-
Превращайте реальные сбои в стартовые кейсы. Читайте трейсы до того, как суммировать их моделью. Для каждого полезного сбоя храните input, source trace ID, expected state, expected tool invariants, failure mode, severity и заметку ревьюера. Langfuse может связывать элементы датасета обратно с продакшен-трейсами; LangSmith может создавать датасеты из traced runs. Сохраняйте ссылку на источник, чтобы кейс оставался аудируемым.
-
Если истории нет, генерируйте cold-start cases. Попросите LLM набросать задачи по product requirements, policies, tool schemas, state machines и support macros. Генерируйте и happy path, и кейсы «такого происходить не должно»: неверные права, пропущенные identity checks, устаревшие результаты инструментов, неоднозначные даты, ретраи после rate limits и outputs инструментов, которые противоречат запросу пользователя.
-
Не доверяйте synthetic cases, пока их не проверил человек. Синтетические примеры полезны для покрытия, а не для истины. Помечайте их как
source: synthetic, требуйте от ревьюера подтверждения ожидаемого результата, по возможности прогоняйте известный good reference path и не используйте одну и ту же model family и для генерации кейса, и для оценки результата. -
Соберите небольшой сбалансированный датасет. Включите успехи, сбои, отказы, граничные случаи, длинные диалоги, policy-sensitive кейсы и валидные альтернативные пути. Не делайте golden равным «точно старому диалогу». Golden должен кодировать требуемый результат, допустимые инварианты и режим отказа.
-
Сначала добавьте детерминированные проверки. Обязательный порядок инструментов там, где порядок задан политикой, обязательные аргументы, schema validation, diff финального состояния, лимиты на циклы, потолки по токенам и latency, а также инварианты, специфичные для задачи, должны запускаться раньше любого judge.
-
Добавьте одного judge с формой SGR. Используйте его только для той части, где нужна интерпретация. Откалибруйте его по человеческой разметке. Если он не отделяет хорошие примеры от плохих на calibration set, исправьте rubric до подключения в CI.
-
Свяжите цикл. Запускайте маленький offline suite в CI, большой suite — перед релизом, оценивайте выборочный продакшен-трафик online и возвращайте повторяющиеся online-кластеры сбоев обратно в offline dataset.
Ваш первый eval suite будет ошибаться скучными способами. Всё равно выпускайте его. Набор, который вы запускаете каждый день, исправить проще, чем идеальный design doc, который никогда не блокирует плохой PR.
Ключевые выводы
- Evals для агентов — это evals для трейсов. Финальный ответ — только один узел в запуске.
- Выбор инструментов, корректность аргументов, детекция циклов, завершение задачи и fidelity на длинной дистанции должны жить в отдельных метриках.
- Продакшен-маховик выглядит так: trace -> label -> cluster -> dedupe -> dataset -> CI gate -> online score.
- Начинайте с детерминированного. Проверки инструментов, аргументов, состояния и детекторы циклов дешевле и стабильнее, чем judges.
- LLM-judges нуждаются в структуре и калибровке. Используйте SGR для воспроизводимых и проверяемых вердиктов, затем фиксируйте judge model, prompt, schema, версию датасета, версию приложения и выборку с человеческой разметкой.
- Offline evals гейтят известные кейсы до релиза. Online evals добывают информацию из выборочных продакшен-трейсов после ответа. Guardrails блокируют небезопасное поведение inline.
- Большинству команд нужны trace store и CI runner. Выбирайте скучные инструменты, которые быстро превращают продакшен-сбои в regression tests.
References
- LangChain - State of Agent Engineering
- Anthropic - Demystifying Evals for AI Agents
- Hamel Husain - A Field Guide to Rapidly Improving AI Products
- OpenTelemetry semantic conventions for generative AI systems
- DeepEval Tool Correctness
- DeepEval Task Completion
- Schema-Guided Reasoning on vLLM: Structured Outputs with xgrammar and Pydantic
- Langfuse datasets and versioning
- LangSmith - Create and manage datasets programmatically
- Braintrust - Evaluate systematically
- Phoenix LLM evals
- Promptfoo GitHub Action integration
- tau-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains
- Why Do Multi-Agent LLM Systems Fail?
- G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment
- Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena
- Replacing Judges with Juries: Evaluating LLM Generations with a Panel of Diverse Models
- JudgeBench: A Benchmark for Evaluating LLM-based Judges
- Self-Preference Bias in LLM-as-a-Judge