AI evals concept page: offline eval suite (golden dataset, F1, LLM-as-judge), RAG eval pipeline (recall@k/MRR + faithfulness/answer-relevance via Ragas/DeepEval/TruLens), production A/B test with implicit signals and feedback loop into goldens.
Классический unit test говорит assertEquals(expected, actual). LLM так не тестируется: один и тот же промпт даёт разный вывод; «правильных» ответов десятки; ошибки полуоткрыты («ответ корректный, но грубый», «факт верный, но не из контекста»). Без evals любая итерация над промптом или моделью — это vibes-based engineering: автор меняет system prompt, смотрит на три примера, выкатывает, а через неделю поддержка жалуется, что бот начал галлюцинировать номера счетов в категории, которую никто не тестировал.
Evals — это test suite, где ассерты не ==, а scoring functions. Они дают: (1) численный baseline, чтобы знать, что улучшение в одном случае не сломало десять других; (2) CI-gate, который блокирует регрессии на промпт-чейндже; (3) механизм закрытия петли — production-фейлы возвращаются в датасет и становятся регрессионными тестами.
Cursor, Anthropic, Notion AI, Perplexity, Stripe Radar — все запускают обязательный eval-гейт перед любым прод-релизом промпта или модели. Hamel Husain ("Your AI Product Needs Evals") и Eugene Yan ("Evals" series) формулируют это одинаково: evals — самая высоколевереджная инвестиция в LLM-приложение, точка.
Eval — это test suite, где ассерты — не
==, а scoring functions. У LLM-приложения две петли качества: офлайн (золотой датасет в CI блокирует merge) и онлайн (A/B на проде с implicit-сигналами решает, что реально лучше для пользователя). Production-фейлы возвращаются в офлайн-датасет — это и замыкает контур.
Три уровня измерения, каждый закрывает дыру предыдущего:
Три параллельные группы — три петли eval-цикла:
Offline eval pipeline (CI gate). Разработчик пушит PR с правкой промпта; CI вытягивает system_prompt v4 из prompt registry, поднимает golden dataset (200 примеров: hand-crafted + edge-кейсы + adversarial), прогоняет LLM-under-test, параллельно скорит exact-match/F1 и LLM-as-judge (Sonnet с rubric: helpful/faithful/concise). Результаты диффятся против baseline на main. Regression gate решает merge/block.
RAG eval pipeline (Ragas / DeepEval / TruLens). Эвал-вопросы с ground-truth doc_id идут в retriever (vector DB, top-K). Сразу две независимые ветки: метрика retrieval (recall@k, MRR — попал ли нужный документ в top-K и насколько высоко) и метрика generation (faithfulness через NLI или LLM-judge: каждый атомарный claim в ответе должен быть подтверждён retrieved context; answer-relevance: отвечает ли вообще на вопрос). Без декомпозиции невозможно понять, ретривер виноват или генератор галлюцинирует.
Production A/B test. Traffic router сплитит реальных юзеров 50/50 (sticky-bucket по hash(user_id)). Telemetry собирает implicit-сигналы (copy, regenerate, edit-then-keep, abandon, session-length) — это primary metrics. Thumbs up/down — secondary (1% response rate, перекошен в крайности). Sampler уносит 1-5% interactions в human label queue; оттуда failures «грaduate» в golden dataset — это и есть замыкание петли. Stat-sig analyzer считает p-value и проверяет guardrails (p95 latency, cost/req, safety).
Заметь: между группами нет прямых рёбер на канвасе, но логически онлайн кормит офлайн через label-queue → golden.
offline-suite — happy path и фейл: PR меняет промпт v3→v4, прогон 200 примеров за ~3 мин и $2.40, accuracy=0.78, F1=0.81; baseline diff показывает -2pp vs main (F1=0.83); gate блокирует merge с артефактом side-by-side HTML на 12 регрессирующих refund-related кейсов. Это типичный «aggregate метрика держится, а критичный subset обвалился».
rag-eval — декомпозиция в действии. Вопрос «What is the refund window for Pro plan?» с ground_truth DOC_42. Retriever возвращает top-5, DOC_42 на 2-м месте: recall@5=1.0, MRR=0.5. LLM генерит «14-day refund window», faithfulness разбирает на атомарные claims, NLI проверяет entailment — 1/1 grounded → faith=1.0. В конце контр-сценарий: ответ «30-day refund» (не в retrieved chunks) ловится как faith=0, явная галлюцинация. Главный инсайт сценария: recall@5=0.92, faith=0.71 означает «ретривер ок, генератор врёт» → лекарство — «answer ONLY from context, else say IDK» в system prompt, а не индекс перестраивать.
prod-ab — 10K запросов/час, 14 дней, 140K interactions/arm. Variant B: latency +25%, cost +37%, но copy_rate +6pp (p=0.003). Guardrails: latency в бюджете, cost — флаг продакту. Финальный gotcha: aggregate выигрывает, а enterprise-cohort регрессирует на 10pp — раскатывать на 100% только после фикса cohort-specific промпта.
ADR-001 — Eval-driven development. Решение: треат evals как production code, не «nice to have». Конкретика: (1) старт с 10-20 hand-crafted goldens (quality > quantity, 1000 синтетических хуже); (2) eval-датасет в git/HF Datasets, версионируется; (3) CI-блокировка PR при drop >X% от baseline; (4) комбинировать четыре уровня — unit assertions (дешёвые, хрупкие) + LLM-judge (~80% от human, дёшево) + human eval на calibration sample ($5-15/item, gold) + production telemetry (free, 100% coverage); (5) production-фейлы пайпятся обратно в datasets — там самый высокий сигнал; (6) multi-axis scoring (helpfulness + faithfulness + safety + conciseness), а не одна aggregate-цифра, которая прячет катастрофы в критичных subset-ах.
ADR-002 — RAG: всегда разделять retrieval и generation. Контекст: end-to-end «answer correctness» делает retrieval-miss и generation-hallucination визуально одинаковыми; дебажить невозможно. Решение: на каждом прогоне меряем четыре метрики — (1) recall@k + MRR (retrieval), (2) faithfulness/groundedness через NLI или LLM-judge (entailed atomic claims / total claims), (3) answer-relevance (адресует ли вопрос), (4) context precision (был ли retrieved chunk релевантным). Дальше — diagnostic: низкий recall@k → чанкинг/embeddings/reranker; низкий faith → ужесточить system prompt («answer only from context»), снизить temperature. TruLens называет это «RAG triad»: context relevance, groundedness, answer relevance.
ADR-003 — Какие production-сигналы реально значат «лучше». Контекст: офлайн-метрики необходимы, но не достаточны — промпт с лучшим F1 может убить engagement (многословный, медленный, не тот tone). Explicit thumbs up/down имеют 1% response rate и biased к крайностям. Implicit-сигналы (copy, edit-then-keep, regenerate ← lower better, abandon, return-within-7d) — 100% coverage, лучше коррелируют с реальной value. Решение: трёх-уровневая иерархия — implicit primary (decision metrics), explicit secondary (directional only), guardrails (p95 latency, cost/req, safety violation rate — must not regress). Минимум 2 недели или 10K interactions/arm для power. Ship variant B только если implicit-метрика выигрывает >X% с p<0.05 И ни один guardrail не упал.
evals/ репозиторий + расширенный внутренний RLHF и Constitutional AI scoring.Инструменты: Promptfoo (YAML CI), Braintrust (managed observability + evals), LangSmith (LangChain-shops), Helicone (cost/latency observability), Langfuse (self-hostable OSS), DeepEval (pytest-style), Inspect (UK AISI, agent safety), OpenAI Evals, Ragas (RAG-specific), TruLens (RAG triad).
Везде кроме этого — нужны.