Evaluation · Evaluation · урок 5 · 12 мин
Evals на практике: смотреть в traces
Evals in practice: reading traces
Зачем
После урока ты сможешь описать рабочий метод практиков: сначала дешёвые assertions (проверки кодом), потом чтение traces и error analysis (разбор ошибок), и только потом judge и A/B-тесты. Вопрос «you've shipped an LLM feature and quality feels off — what do you do first?» проверяет именно это, и ответ «напишу judge» — слабый.
Три уровня и их порядок
Hamel Husain в статье «Your AI Product Needs Evals» описывает три уровня оценки на примере Lucy — AI-ассистента для риелторов компании Rechat, у которого улучшения prompt перестали давать результат:
| Уровень | Что это | Когда гоняют |
|---|---|---|
| 1. Unit tests (assertions) | быстрые проверки кодом | на каждое изменение |
| 2. Human & model eval | чтение traces людьми, затем judge | регулярно, по расписанию |
| 3. A/B testing | сравнение версий на живых пользователях | после крупных изменений продукта |
Цена растёт снизу вверх: уровень 3 дороже уровня 2, уровень 2 дороже уровня 1. Поэтому порядок такой же: сначала дешёвое, что ловит очевидное.
Уровень 1: assertions идут первыми
Assertion — проверка кодом, как в pytest. У Rechat пример: regex проверяет, что во внешний ответ не попали внутренние UUID (идентификаторы записей). Для поиска объектов недвижимости — три входа: найден один, найдено несколько, не найдено ничего.
Как их писать: разбить продукт на функции и сценарии и попросить LLM сгенерировать тестовые входы, например «напиши 50 разных инструкций, которые риелтор мог бы дать ассистенту, чтобы создать контакт». У Rechat таких тестов сотни, и они пополняются с каждым новым видом провала. Процент прохождения — продуктовое решение: 100% не обязательно.
Почему первыми: - дёшево и быстро — секунды, без вызова judge, можно гонять в CI на каждый pull request; - детерминированно — нет вопроса «а можно ли верить оценщику»; - ловят худшее — утечку чужих данных, неверную сумму, сломанный формат; - освобождают людей — читать traces имеет смысл, когда очевидные провалы уже отсеяны.
Пример для банка — ответ не должен показывать внутренние идентификаторы:
import re
UUID = re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", re.I)
def check_no_internal_ids(answer: str) -> bool:
return UUID.search(answer) is None
Уровень 2: traces и как их читать
Trace — журнал одного запроса: вход пользователя, найденные chunks (куски документов) с их ID и версиями, что попало в context, какие tools вызваны с какими аргументами, что они вернули, ответ, число токенов, задержка, цена, версии prompt и модели. Без traces нельзя найти, почему ответ плохой.
Чтение — работа, а не формальность. Советы Husain: - Убери трение. Сделай простой просмотрщик под свою предметную область (на Gradio или Streamlit он собирается быстро), где весь контекст на одном экране. - Бинарные метки. Хорошо или плохо, а не шкала 1–5. - Смотри всегда. «You can never stop looking at data»: traces всех тестовых случаев и реальных пользователей; со временем выборку можно уменьшать, но не до нуля.
Error analysis: open coding → axial coding
В FAQ Husain и Shankar (18.09.2026) метод разбора ошибок выглядит так: 1. Набор. Около 100 разнообразных traces; если трафика нет, синтетические. 2. Open coding (свободные пометки). Эксперт читает traces и пишет короткую заметку о проблеме, как в дневнике. Помечать первый провал в trace: ошибка выше по цепочке вызывает ошибки ниже. Первые 30 разметь сам, прежде чем доверять подсказкам модели. 3. Axial coding (группировка). Заметки сводятся в taxonomy (классификацию) провалов, и провалы каждого вида считают. Здесь LLM может помочь. 4. До насыщения. Продолжать, пока новые traces не перестанут давать новые виды провалов.
Если реального трафика ещё нет, синтетику делают по осям, а не «придумай 100 вопросов»: выбирают измерения (тип вопроса, язык, настроение клиента), руками пишут несколько комбинаций, и только потом модель превращает каждую комбинацию в живой текст. Оговорка авторов: синтетика не скажет, как часто провал случается в production, и ненадёжна в узких областях, на редких языках и там, где ставки высоки.
Пример с числами. 100 traces банковского ассистента, 31 с проблемами:
| Вид провала | Число |
|---|---|
| процитирован старый тариф (retrieval взял прошлую версию документа) | 12 |
| не уточнил, о какой карте речь | 8 |
| ответил по-английски на вопрос по-казахски | 6 |
| обещал то, чего не может (отменить комиссию) | 5 |
Решение: начать со старых тарифов — 12 из 31 и чинится кодом (фильтр по дате вступления в силу на retrieval). Проверка для suite — тоже код: сумма в ответе совпадает с действующим тарифом. «Обещал отменить комиссию» — размытое: сюда judge, но только с примерами из этих пяти traces.
Почему не отдать всё сразу judge
- Критерии рождаются из данных. Husain: нельзя написать хороший prompt для judge, не увидев данных. Пока не прочитал traces, ты не знаешь, какие провалы бывают; judge закодирует твои догадки.
- Общие метрики врут. «Helpfulness», «coherence» из коробки, по словам Husain и Shankar, тратят время и дают ложную уверенность. Твои виды провала конкретны: старый тариф, чужой счёт.
- Judge надо проверять по людям, а для этого люди всё равно размечают traces. Разметка из error analysis и становится набором для проверки judge.
Сами авторы пишут, что тратят 60–80% времени разработки на error analysis и evals. Это не отдельная статья бюджета, а основная работа.
Из traces в regression set
Размеченные traces не выбрасывают: из них собирают regression set (набор, на котором новая версия prompt или модели не должна стать хуже прежней).
- Выборка. Из логов production берут разнообразные traces. Clustering (группировка по embeddings) помогает не набрать сто вариантов одного вопроса: Husain называет его способом выборки. Важность кластер не показывает: самый большой кластер — самый частый вопрос, а не самый дорогой провал. Что важно, решает error analysis.
- Эталон. LLM может набросать черновик ожидаемого ответа, но эталоном его делает человек, который прочитал и поправил. Где можно, эталон — проверка кодом (верный тариф, нет чужих данных), а не текст целиком.
- Прогон на каждую версию. Набор гоняют в CI; падение на известном виде провала блокирует выпуск.
- Приватность. В логах клиентов есть PII: перед набором trace проходит маскирование (урок a4-1), а сам набор хранят там же, где эти данные.
Уровень 3: A/B
A/B testing (сравнение двух версий на живых пользователях) показывает, меняет ли продукт поведение людей. Husain разрешает отложить его, пока продукт не созрел для реальных пользователей. В банке перед ним идут shadow (новая версия отвечает параллельно, клиенты видят старую) и canary (новая версия на малой доле трафика).
Схема
Термины · Key terms
- assertion
- проверка кодом на одно правило
- trace
- журнал одного запроса со всеми шагами и tools
- error analysis
- разбор ошибок по traces с подсчётом видов провала
- open coding
- свободные пометки о проблемах при чтении traces
- axial coding
- группировка пометок в виды провала
- failure taxonomy
- классификация видов провала с частотами
- theoretical saturation
- новые traces больше не дают новых видов провала
- A/B testing
- сравнение двух версий на живых пользователях
- shadow / canary
- параллельный прогон без показа / выкатка на малую долю трафика
- regression set
- набор случаев из прошлых провалов, на котором новая версия не должна стать хуже
Сделай сам
Напиши три проверки уровня 1 для банковского агента — функциями Python или словами, по строке на каждую: в ответе нет номера чужого счёта; сумма комиссии совпадает с таблицей тарифов; нет обещаний отменить комиссию. Для каждой отметь, где она честно работает кодом, а где код даст ложные срабатывания и нужен judge.
Обсуди с тьютором: покажи три проверки и спроси, какие входные данные (session, таблица тарифов) нужны каждой, чтобы она была детерминированной.
Проверь себя · ответ под вопросом
1Почему traces надо читать самому, а не сразу отдавать judge?
2Сколько traces смотреть на старте?
3Почему тесты уровня 1 идут первыми?
Interview questions · US / UK
1You've shipped an LLM assistant and users say quality "feels off". What do you do in the first week?
2What belongs in a trace for a RAG agent, and why?
3Follow-up: why not just set up an LLM judge on helpfulness and track that number?
Ключевые фразы · Say it aloud
- Look at your data before you write a judgeпосмотри на данные, прежде чем писать judge
- Start with cheap assertions in CIначни с дешёвых проверок кодом в CI
- Open-code the first failure in each traceпомечай первый провал в каждом trace
- Group the notes into a failure taxonomy and countсгруппируй пометки и посчитай
- Generic metrics give false confidenceобщие метрики дают ложную уверенность
- You can never stop looking at dataсмотреть на данные нельзя перестать
Материалы
- Hamel Husain, Your AI Product Needs Evals — раздел «The Types Of Evaluation»: Level 1 и в Level 2 «Logging Traces» и «Looking At Your Traces» (12 минут)
- Hamel Husain, Shreya Shankar, AI Evals FAQ — вопросы про error analysis и сколько traces смотреть (10 минут)
- Anthropic, Demystifying evals for AI agents — абзацы «Read the transcripts» и совет начать с 20–50 задач (5 минут)
- Hamel Husain — Why is error analysis so important, and how is it performed? — clustering как способ выборки и пул из ~100 traces, открыто 28.10.2026 (8 минут)