Когда тестов становится больше, чем кода: история одного провала
Мы начали с благих намерений. Наша команда внедряла LLM для генерации SQL-запросов из текстовых описаний. Первый прототип работал, инвесторы радовались, пользователи тестировали. Потом пришел я со своим "давайте делать правильно".
Evals Driven Development звучало идеально. Пишем тесты, проверяем качество, автоматизируем оценку. Через месяц у нас было 2000 тест-кейсов, 15 метрик и... абсолютно парализованный процесс разработки. Каждый PR требовал 8 часов на прогон тестов, метрики противоречили друг другу, а самое страшное - модель деградировала, хотя все метрики показывали рост.
Ошибка номер один: измерять всё, что можно измерить. Парадокс - чем больше метрик, тем меньше понимания, что на самом деле происходит с вашей моделью.
Что такое Evals Driven Development на самом деле (а не в красивых статьях)
EDD - это не про то, чтобы обложить модель тысячами тестов. Это про создание обратной связи, которая действительно помогает улучшать систему. Представьте, что вы строите дом. У вас есть рулетка, уровень, угломер. EDD - это когда вы не просто мерите всё подряд, а знаете, какие именно измерения критичны для устойчивости крыши.
В мире LLM на 2026 год это означает три вещи:
- Золотой датасет - не просто набор примеров, а тщательно отобранные кейсы, которые отражают реальное использование
- LLM-as-a-judge - когда сама модель оценивает свои ответы (да, звучит как матрешка, но работает)
- Пайплайн - автоматизированный процесс, который не ломается при каждом изменении промпта
1Шаг первый: собираем золотой датасет, который не устареет через неделю
Вот как НЕ надо делать: берем 500 случайных запросов из логов, размечаем вручную, называем "золотым стандартом". Через месяц оказывается, что 30% кейсов уже нерелевантны, потому что продукт поменялся.
Правильный подход: динамический золотой датасет. Мы разделили его на три слоя:
| Слой | Примеры | Частота обновления | Кто размечает |
|---|---|---|---|
| Ядро | 20-30 критических кейсов | Раз в квартал | Эксперты предметной области |
| Стабильный | 200-300 частых запросов | Раз в месяц | Разработчики + валидация LLM |
| Экспериментальный | Новые сценарии, краевые случаи | Постоянно | LLM-as-a-judge с человеческим надзором |
Ключевой инсайт: ядро должно быть маленьким, но безупречным. Эти 20-30 примеров - ваш компас. Если модель начинает ошибаться на них, это красная тревога, даже если все остальные метрики зеленые.
2LLM-as-a-judge: когда модель сама себя проверяет (и это не безумие)
Раньше мы думали, что нужны сложные эвристики: сравнение синтаксических деревьев, анализ семантики, проверка выполнения запросов. Потом поняли - проще заставить более мощную модель оценивать работу нашей.
Наша текущая конфигурация на февраль 2026:
# Конфигурация LLM-as-a-judge
EVAL_CONFIG = {
"judge_model": "claude-3-7-sonnet", # Самый свежий Claude на дату публикации
"temperature": 0.1, # Минимальная креативность для оценки
"system_prompt": """Ты эксперт по SQL и анализу данных.
Оцени ответ модели по критериям:
1. Синтаксическая корректность (да/нет)
2. Семантическая корректность (да/нет/частично)
3. Оптимальность запроса (1-5)
4. Безопасность (есть ли риски SQL-инъекций)
Отвечай строго в формате JSON.""",
"scoring_rules": {
"syntax": {"weight": 0.3, "pass_threshold": 1.0},
"semantic": {"weight": 0.4, "pass_threshold": 0.8},
"optimization": {"weight": 0.2, "pass_threshold": 3.0},
"security": {"weight": 0.1, "pass_threshold": 1.0}
}
}Важный нюанс: LLM-as-a-judge не заменяет все тесты. Это дополнительный слой проверки, который особенно полезен для сложных, субъективных случаев. Для простых проверок ("вернул ли запрос правильное количество столбцов?") используйте обычные assertion.
Мы наступили на грабли: сначала использовали ту же самую модель для оценки, что и для генерации. Результат - она слишком "дружила" с собой, завышала оценки. Решение - брать модель на уровень выше (Claude 3.7 оценивает GPT-4.5) или хотя бы другого вендора.
3Строим пайплайн, который не падает от каждого чиха
Наш первый пайплайн был монолитом: 2000 тестов -> все метрики -> единый отчет. Падал часто, работал медленно, отлаживать было невозможно.
Текущая архитектура (работает в продакшене 6 месяцев):
# pipeline.yml - CI/CD для LLM evals
stages:
- fast_checks # 2-3 минуты
- core_evaluation # 10-15 минут
- full_evaluation # 1-2 часа (только в main)
fast_checks:
tests: "ядро (30 тестов) + критичные баги из трекера"
judge: none # только автоматические проверки
on: [push, pull_request]
core_evaluation:
tests: "стабильный слой (300 тестов)"
judge: "gpt-4.5-turbo" # быстрая оценка
on: [pull_request]
cache: "результаты fast_checks"
full_evaluation:
tests: "все тесты + стресс-тесты"
judge: "claude-3-7-sonnet" # глубокая оценка
on: [merge_to_main]
schedule: "weekly" # еженедельный полный прогонСекрет в кэшировании. Если промпт не менялся, а изменилась только бизнес-логика вокруг - зачем гонять все тесты заново? Мы кэшируем эмбеддинги промптов и сравниваем хеши. Нет изменений - берем результаты из кэша.
Используйте инструменты вроде SAARAM на Amazon Bedrock для параллельного запуска тестов. 2000 тестов последовательно - это 5 часов. 2000 тестов параллельно на 20 инстансах - 15 минут.
Метрики, которые имеют смысл (и те, что его не имеют)
Раньше мы отслеживали 15 метрик. Теперь - 4. Вот почему:
- Точность (Accuracy) - бесполезна в вакууме. 95% точности на простых примерах скрывают 40% ошибок на сложных
- BLEU, ROUGE - для текстовых задач может работать, для SQL или кода почти бесполезны
- Время ответа - важно, но не должно быть в одной куче с качественными метриками
Наша текущая dashboard метрик:
{
"core_pass_rate": 0.98, // Процент прохождения ядра
"complex_case_score": 0.82, // Оценка на сложных кейсах (LLM-as-a-judge)
"regression_count": 2, // Число регрессий с прошлой версии
"user_feedback_score": 4.3 // Средняя оценка от реальных пользователей (1-5)
}Если core_pass_rate падает ниже 0.95 - блокируем деплой. Если complex_case_score ниже 0.7 - срочный багфикс. Все просто, все понятно.
Типичные ошибки (чтобы вы их не повторили)
1. Тестирование не того. Мерили точность SQL, а пользователи жаловались на скорость. Оказалось, модель генерировала корректные, но неоптимальные запросы, которые падали по таймауту.
2. Забывать про деградацию. Модель учится на своих же ответах. Если в тестовых данных есть шаблоны - она начинает их повторять, теряя креативность. Решение - регулярно обновлять тестовый набор, добавлять шум.
3. Игнорировать стоимость. LLM-as-a-judge на Claude 3.7 стоит денег. 2000 тестов × $0.01 = $20 за прогон. При 10 прогонах в день - $6000 в месяц. Наше решение - многоуровневая система: быстрые/дешевые тесты на каждом коммите, дорогие - только перед релизом.
Интеграция с существующими процессами
EDD - не остров. Он должен работать с вашим текущим CI/CD. Наша интеграция:
- GitHub Actions запускает fast_checks на каждый PR
- Все результаты пишутся в базу данных (у нас ClickHouse)
- Grafana dashboard показывает тренды качества
- При падении core метрик - автоматически создается issue в Jira
- Раз в неделю - автоматический отчет в Slack с графиками
Самое важное - сделайте результаты видимыми. Разработчики должны видеть, как их изменения влияют на качество. Не "тесты прошли/не прошли", а "точность на сложных кейсах упала на 5%".
Когда всё идет не по плану (спойлер: часто)
Сценарий: все метрики зеленые, пользователи жалуются. Что делать?
1. Проверьте расхождение между тестовыми и реальными данными. Может, в продакшене приходят запросы, которых нет в тестах?
2. Добавьте A/B тестирование. Запустите старую и новую версию параллельно на 5% трафика, сравните реальные метрики.
3. Слушайте пользователей. Каждая жалоба - потенциальный новый тест-кейс. У нас есть процесс: пользовательская жалоба -> воспроизведение -> добавление в тестовый набор (если это баг) -> фикс -> проверка.
EDD не гарантирует, что всё будет идеально. Он гарантирует, что вы будете знать, когда что-то пошло не так, и сможете это починить.
Что дальше? Эволюция EDD в 2026
Сейчас мы экспериментируем с автономными ИИ-агентами для QA, которые сами генерируют тест-кейсы на основе анализа кода и пользовательского поведения. Представьте: система видит, что пользователи часто спрашивают про JOIN трех таблиц, но в тестах этого нет - автоматически добавляет соответствующие кейсы.
Другое направление - персональные evals для разных сегментов пользователей. Бизнес-аналитики и дата-инженеры используют SQL по-разному. Зачем мерить их одним аршином?
И последнее: EDD постепенно сливается с подходом AI Engineer. Мы перестаем думать о "модели" и начинаем думать о "системе". Модель может быть идеальной, но если промпт инженерия хромает, или контекст неправильно формируется, или пост-обработка ломает результат - вся система падает.
Начните с малого. 20 золотых тестов. Простой пайплайн. Одна метрика, которая действительно важна. Когда это заработает - масштабируйте. И помните: лучше иметь 100 тестов, которые вы понимаете и доверяете, чем 10000 тестов, результаты которых никто не смотрит.