Коротко — практики, которые реально применяют в продакшн‑командах, и которые я видел работать. Без теории, только «как сделать» + реальные хинты и примеры проверок.
1) Общее развитие процесса валидации (практическая последовательность)
- Unit тесты (fast, deterministic)
- Мокать вызовы модели (заглушки) и проверять логику обработки ответа, парсинга, ошибок, таймаутов, retry.
- Проверки схемы результата (JSON/поля) через Pydantic/JSON Schema; валидировать типы, обязательные поля, форматы (email, дата).
- Integration tests (живой LLM, ограниченный набор)
- Набор «золотых» примеров (golden dataset) — 100–500 кейсов, покрывающих типичные, пограничные и один-два злостных случая. Запускать их в CI по расписанию (не при каждом коммите, а nightly / on-demand).
- Включать семантическую проверку (см. дальше).
- End-to-end / UI tests (Playwright)
- Энд‑ту‑энд сценарии с симуляцией пользователя, проверка поведения UI + ответов модели, откатов и ошибок.
- Acceptance / Human in the loop (HITL)
- Набор из N ручных аннотаций перед релизом (см. сколько ниже).
- Разбивка по приоритетам: safety/abuse cases получают больше ручной проверки.
- Canary и gradual rollout
- Сначала ~1–5% пользователей, отслеживание метрик, затем 25% → 100%.
- Включать автоматические откаты по триггерам.
- Пост‑релиз мониторинг и быстрый фидбек
- Логирование запросов/ответов (соблюдая приватность), дашборды с метриками, sampling для ручной ревью, алерты.
2) Практические типы тестов и как их реализовать (конкретика)
- Golden tests + tolerant comparisons
- Не exact match. Сравнивайте по embedding cosine (например, sentence‑transformers). Порог — 0.75–0.85 в зависимости от задачи.
- Нормализуйте ответы (убрать лишние пробелы, нормализовать числа/даты, отсечка знаков).
- Snapshot tests (только для стабильных ответов)
- Подходят для служебных сообщений/форматируемых ответов (JSON, таблицы). Для генеративных текстов применяйте с осторожностью.
- Property‑based / assertions
- Примеры: «ответ содержит все требуемые поля», «не содержит запрещённых слов», «сохранены числовые значения», «цитируется источник, если используется RAG».
- Execution tests (для code‑generation)
- Скомпилировать / выполнить сэндвичные unit tests в изолированном контейнере (sandbox). Критично для кода.
- Safety / Moderation checks
- Прогоны через модерацию API (OpenAI Moderation или внутренняя), списки блокировок (regex), проверка на приватные данные (SSNs, e‑mails) — если найдены, фолбэк.
- Adversarial / red‑team tests
- Наборы «злых» подсказок, созданных людьми или генерированных LLM для попытки вывести модель на нарушение правил.
- Fuzz / prompt‑variation tests
- Генерировать вариации промптов (перефразирования) и проверять стабильность ответов / критичные свойства.
- Automated self‑evaluation
- Запросить LLM оценить/проверить собственный ответ (self‑critique), но не полагаться на это как на единственную оркестрацию — использовать как сигнал и триггер для человеческой проверки.
- Ensembles / consensus
- Генерировать несколько ответов (n samples) и агрегировать (vote, ranker) или требовать согласия. Это снижает случайные галлюцинации.
3) Метрики, которыми оперируют в продакшне (практические пороги)
- Business / UX:
- Task success rate (TSR): % сессий, где пользователь достиг цели. Целевой порог зависит от фичи (например, >85%).
- Deflection / containment: % вопросов решённых ассистентом без человеческой помощи.
- Model correctness:
- Human pass rate: доля ручных аннотаций, где ответ «приемлем» — часто >= 80–90% для не‑критичных фич.
- Hallucination rate: доля ответов с проверяемыми фактическими ошибок — таргет близок к 0, но допустимый уровень зависит от риска.
- Latency / reliability:
- P95 latency < SLA, error rate < X%.
- Monitoring triggers:
- Резкий спад semantic similarity по золотому набору или рост жалоб пользователей → откат.
4) Сколько ручной проверки нужно? (конкретные числа)
- Перед релизом: 200–1000 аннотаций для основной фичи. Для safety‑критичных функций — 1000–5000+.
- Для routine spot checks в проде: еженедельный сэмпл 200–500 ответов по стратифицированной случайной выборке.
5) Что показать новому разработчику, чтобы доказать «работает»
- Репозиторий с:
- Golden набором тестов + ожидаемыми порогами (embedding scores, regex pass/fail).
- Unit тесты, которые мокают LLM и покрывают логику (парсинг, retry, errors).
- Интеграционные тесты, которые запускают несколько живых примеров и показывают метрики (output examples + оценка).
- Дашборд (с примерами):
- Реальные сэмплы «перед/после» и их оценки, метрики pass rate и rollback triggers.
- Перечень «фейлов» и багфиксов:
- Истории реальных багов (input → bad output → как тест поймал → фиксы).
- Runbook:
- Что делать при инциденте (откаты промпта/пин модели, ограничение трафика, как собрать сэмплы).
- Мини‑demonstration:
- Запустить 10 показательных кейсов в реальном времени и показать, как система их валидирует (автоматически + человек).
6) Главные отличия тестирования LLM‑фич от «обычного» кода (практически)
- НЕДЕТЕРМИНИЗМ: ответы не стабильны → нельзя опираться на exact matches. Решение: mocking + tolerant checks + seed/temperature control в тестах.
- ОТСУТСТВИЕ ОДНОЗНАЧНОГО ОРАКЛА: часто нет единственно правильного ответа → нужны человеческие оценки или автоматические proxy‑метрики (embeddings, BERTScore).
- РУЧНАЯ РАБОТА: необходимость HITL и red‑teaming для safety и edge cases.
- ДРЕЙФ: модель и данные изменяются (удаление/обновление моделей, новые знания) → постоянное регресс‑тестирование и версионирование промптов/моделей.
- КОСТЫ: тестирование живого LLM дорогое — мокать в unit тестах, запускать живые тесты реже.
- ЭКСПЕКТЕД‑FAILURES: нужно строить поведение при низкой уверенности (фолбэки), а не 100% корректность.
7) Примеры реальных кейсов (коротко, «на костылях»)
- Summarizer (RAG):
- Golden dataset 300 доков + reference summaries.
- Проверка: embedding similarity > 0.8; факт‑чек: если в summary упоминается факт, сверить его через retrieval (QA) и требовать подтверждение из источника; иначе — вернуть «нет уверенности».
- Урок: добавили правило «если summary добавляет факты не в источнике — отклонить и попросить пользователя уточнить».
- Code generation assistant:
- Pipeline: generate → sandbox compile & run unit tests → если тесты проходят — вернуть; иначе — повторная генерация n=3.
- В CI: mock LLM, unit tests на парсинг и executable pipeline; в nightly — живые примеры, % успешных сборок > 70%.
- FAQ bot
- Golden set + fuzzy match; если confidence < threshold (embedding cosine < 0.7) — перевести на human escalation.
- Добавлены blacklist regex и moderation API для safety.
- Customer support automations
- Проверка того, что модель никогда не раскрывает PII: встроенный PII detector → reject. Тесты: набор искусственно вставленных PII → assert model never outputs их.
8) Практические технические приёмы (checklist / реализация)
- В CI:
- Unit tests (mocked) — fast.
- Nightly integration tests (real model) — golden suite.
- В тестовых скриптах:
- Закреплять модель и параметры (model id, temperature, max_tokens).
- Нормализовать ответы перед проверки: strip, lower, redact timestamps/uuids.
- Использовать embeddings для «semantic asserts» + порог.
- Проверять JSON schema + required keys.
- Выполнять safety checks (moderation API, regex).
- Для нестабильных тестов:
- Добавить retry / повторные прогоны; пометить flaky тесты и разруливать.
- Документировать версии промптов:
- Хранить промпты и их версии рядом с тестами. Включать diff в PR‑review.
- Логировать и sample‑ing:
- Сохранять 1–5% вызовов в проде для ручного ревью, автоматически помечать по сигналам (low confidence, user complaint).
- Автоматические оркестраторы оценки:
- Скрипт «eval.py» который запускает golden набор и складывает результаты в CSV / dashboard.
- Алёрты:
- Если human pass rate падает на X% за 24h или similarity по golden set падает — alert.
9) Что бы я порекомендовал вам развивать в вашем тулсете
- Оставить Vitest + Playwright для E2E/UI.
- Добавить:
- Модуль для semantic scoring (embeddings + thresholds).
- JSON schema asserts и sanitizer/normalizer.
- Набор «red team» кейсов и runner для них.
- Инструмент для versioning prompts (можно просто git + tests tied to prompt version).
- Canary runner: script, который берёт N% трафика (или emulate) и собирает метрики.
- Метрики и dashboard (простейший вариант — CSV → Grafana/Metabase) + sampling UI для ручной аннотации.
10) Pitfalls и как их избежать (коротко)
- Не полагайтесь только на LLM‑оценку (LLM как судья) — обязательно человеческая проверка.
- Не тестируйте только happy path — тесты должны включать злостные/провокационные кейсы.
- Не привязывать тесты к exact text — используйте semantic metrics.
- Не забывайте о приватности в логах.
Если хотите, могу:
- Просмотреть ваш текущий тулсет (Vitest + Playwright) и предложить конкретные тесты/ассерты.
- Сгенерировать шаблон «golden test runner» с использованием embeddings и порогов.
- Посоветовать, какой размер выборки для ручного QA брать под ваш риск‑профиль.
Скажете, какая у вас задача LLM (summarization / chat / code / retrieval), и я пришлю конкретный набор тестов и порогов.