Как тестировать LLM-приложения: evals, датасеты и LLM-судья
Продвинутое3 минРедакция Innovialabs
Коротко
LLM-приложение тестируют на эталонном наборе реальных примеров с понятными критериями, сочетая автоматические проверки, LLM-судью и выборочную ручную оценку, и прогоняют этот набор при каждой смене промпта или модели.
Короткий ответ
Обычные unit-тесты не работают с LLM напрямую: ответ каждый раз немного разный. Вместо проверки «строка равна строке» строят evals — набор примеров с критериями качества, который запускают автоматически. Основа — эталонный датасет, поверх него — три уровня оценки: детерминированные проверки, LLM-as-judge и выборочная ручная проверка.
Шаг 1. Соберите эталонный датасет
Golden dataset — это входные данные плюс ожидаемый результат или критерии хорошего ответа.
- Берите реальные запросы пользователей, а не придуманные.
- Добавьте сложные случаи: двусмысленные вопросы, запросы вне темы, попытки обойти правила.
- Покройте все сценарии приложения, а не только самый частый.
- Для каждого примера запишите, что считается правильным: точный ответ, обязательные факты, запрещённое содержание.
- Храните датасет в репозитории рядом с промптами и версионируйте.
Начать можно с нескольких десятков примеров и пополнять набор каждым найденным в продакшене сбоем.
Шаг 2. Детерминированные проверки
Всё, что можно проверить кодом, проверяйте кодом — это быстро, дёшево и стабильно:
- ответ — валидный JSON по схеме;
- извлечённое поле совпадает с эталоном;
- в ответе нет запрещённых слов или персональных данных;
- длина в допустимых пределах;
- агент вызвал нужный инструмент с правильными аргументами.
def check(case, output):
data = json.loads(output)
assert data["category"] == case["expected_category"]
assert len(data["reply"]) < 1000
Шаг 3. LLM-as-judge
Для открытых ответов (тон, полнота, точность по контексту) используют модель-судью: она получает вопрос, ответ и критерии и выставляет оценку.
Подводные камни:
- Расплывчатые критерии — «оцени качество от 1 до 10» даёт шум. Лучше бинарные вопросы: «ответ содержит срок доставки? да/нет».
- Предвзятость к длине — судьи склонны завышать оценку длинным ответам.
- Предвзятость к позиции — при сравнении двух ответов порядок влияет на выбор; меняйте их местами.
- Самопредпочтение — модель может выше оценивать ответы своего же семейства.
- Судья тоже ошибается — сверяйте его оценки с человеческими на выборке, прежде чем доверять.
Шаг 4. Ручная оценка
Люди нужны там, где цена ошибки высока или критерий субъективен. Чтобы оценка была полезной:
- дайте экспертам чёткую рубрику, а не «нравится / не нравится»;
- проверяйте выборку, а не всё подряд;
- используйте ручные оценки для калибровки LLM-судьи.
Шаг 5. Регрессионное тестирование
Любое изменение промпта, модели, параметров или RAG-индекса может улучшить одно и сломать другое. Поэтому:
- Прогоняйте весь датасет перед каждым релизом, лучше в CI.
- Сравнивайте метрики с предыдущей версией, а не с абстрактным порогом.
- Смотрите не только на среднее, но и на конкретные примеры, которые ухудшились.
- Фиксируйте версию модели и параметры, чтобы результаты были воспроизводимыми.
- Учитывайте случайность: для важных примеров делайте несколько прогонов.
Частые ошибки
- Тестировать «на глаз» на паре запросов.
- Датасет из одних простых примеров.
- Слепо доверять LLM-судье без сверки с людьми.
- Не добавлять продакшен-сбои в датасет.