DeepEval — библиотека на Python, которая превращает проверку ответов ИИ-агента в обычные тесты: у каждого случая есть вход, фактический ответ и метрика с порогом. Если агент уже работает на реальных задачах и команда правит инструкции раз в неделю, такой набор ловит регрессии до выкладки. Для одноразового эксперимента с моделью хватит ручного просмотра, и фреймворк обойдётся дороже пользы.
Тест как код
В DeepEval тестовый случай описывается объектом LLMTestCase с полями input, actual_output и при необходимости expected_output, проверка делается функцией assert_test, запуск идёт командой deepeval test run.
Главная идея в том, что проверка качества живёт рядом с кодом агента и подчиняется тем же правилам, что остальные тесты: лежит в репозитории, проходит ревью, запускается автоматически. Разработчик, поменявший инструкцию, видит красный результат в тот же день, тогда как жалоба сотрудника пришла бы через месяц. По документации, библиотека работает поверх pytest, поэтому привычные фикстуры и параметризация доступны.
- Вход: обезличенная заявка или вопрос, взятые из реальных обращений.
- Фактический ответ: то, что вернул ваш агент на этом входе при текущей версии кода.
- Ожидание: описание допустимого результата, если метрике нужен эталон.
- Порог: граница оценки, ниже которой случай считается проваленным.
Установка сводится к команде pip install -U deepeval и настройке ключей. Библиотека читает переменные окружения из файлов .env.local и .env. Положите ключи в секретное хранилище окружения сборки, а в репозиторий кладите только пример файла без значений. Общий план проверок описан в материале про тестирование ИИ-агентов; здесь разбирается именно код.
Откуда брать входы. Лучший источник — реальные обращения, прошедшие обезличивание: они содержат опечатки, обрывки фраз и странные просьбы, которые трудно выдумать за рабочим столом. Для каждого случая запишите, почему он попал в набор: жалоба, дорогая ошибка, редкий тип заявки. Эта пометка пригодится через полгода, когда кто-то решит удалить половину примеров ради скорости прогона.
Метрики и пороги
Метрика превращает впечатление в число от нуля до единицы, и порог решает, пройден ли случай. Самая гибкая метрика называется GEval: вы пишете критерий обычным языком, а модель-судья оценивает ответ по нему. Критерий должен быть узким. Фраза «ответ хороший» даёт случайные оценки, а фраза «в ответе названы все условия из заявки и нет новых обязательств» работает повторяемо.
| Что проверяем | Чем проверяем | Кто решает спорный случай |
|---|---|---|
| Полнота ответа по заявке | GEval с письменным критерием и порогом | Сотрудник процесса |
| Формат и обязательные поля | Обычное утверждение assert в тесте | Разработчик |
| Нужный инструмент вызван | Сравнение журнала вызовов с ожиданием | Разработчик и владелец процесса |
| Тон и допустимые обещания | GEval с отдельным критерием | Руководитель направления |
Часть проверок обходится без модели вообще. Длину, наличие номера заявки, отсутствие запрещённых слов проверяет детерминированный код, и он надёжнее любого судьи. Судью оставляйте для смысла. Судье нужен доступ к модели. В примерах документации это модель OpenAI с ключом, однако библиотека позволяет подключить и другую, и тут действуют два пути: сервис вендора напрямую, где он доступен вашей команде, либо открытые веса на своём или арендованном сервере. Выбор фиксируйте в настройках сборки, чтобы результаты были сравнимы между прогонами.
Порог подбирайте на практике. Прогоните набор на текущей версии, посмотрите распределение оценок и поставьте границу ниже типичного уровня уверенно хороших ответов, но выше уровня ответов, которые сотрудники забраковали вручную. Так число получает смысл. Порог, выбранный наугад, либо пропускает брак, либо краснеет без причины и приучает команду игнорировать сборку.
Путь агента
Агент отличается от чат-бота тем, что решает по ходу работы, какие инструменты вызвать. Проверять только финальный текст мало: ответ может выглядеть гладко, а путь к нему окажется неверным. Для таких случаев в DeepEval есть метрика TaskCompletionMetric: по документации, она анализирует всю упорядоченную трассу шагов и оценивает, выполнена ли задача. Для многоходовых диалогов есть отдельные метрики и тестовые случаи диалога.
Оценка по трассе подходит, когда задача решается несколькими способами и жёсткого списка шагов нет. Если порядок обязателен, например сначала поиск клиента, затем черновик, затем запрос подтверждения, запишите это в тест прямым сравнением. Библиотека также позволяет вешать метрики на отдельные участки трассы, и тогда провал указывает на конкретный шаг: поиск вернул лишнее или инструкция плохо описывает инструмент.
Тесты проверяют решения агента, а полномочия закрывает сервер. Что бы ни выбрал агент, запись в карточку клиента проходит через права пользователя и подтверждение человека, об этом мы писали в статье про инструменты, права доступа и тестовые задачи агента LangChain. Хороший тест содержит и негативный случай: заявку, в которой нужного права нет, и ожидание отказа. Второй обязательный негативный случай — заявка с неполными данными: агент должен запросить недостающее, а выдумывать значения ему запрещено. Оба случая проверяются утверждением в коде, судья здесь лишний.
Запуск в CI
Подключение к сборке занимает один шаг: установить зависимости и выполнить deepeval test run для файла с тестами. Красный прогон можно сделать условием слияния изменений в настройках репозитория. Сразу решите, какой набор гоняется на каждый коммит, а какой раз в сутки: прогон с судьёй занимает время и расходует токены, поэтому быстрый срез из самых важных случаев идёт в каждую сборку, полный набор запускают по расписанию.
Оценки судьи колеблются от прогона к прогону. Поэтому порог выбирают с запасом, а случаи около границы разбирают глазами. Нестабильный тест лучше пометить и исследовать, чем отключить: за каждым таким случаем обычно стоит расплывчатый критерий. Практичный приём — запускать пограничный случай несколько раз подряд и смотреть разброс: если оценка гуляет сильнее запаса порога, переписывайте критерий, а число порога оставьте в покое. Результаты красных прогонов прикладывайте к запросу на слияние, чтобы ревьюер видел вместе с фактом провала и ответ агента на проблемном входе. Для облачного просмотра результатов библиотека предлагает вход через deepeval login, но этот шаг необязателен, и перед отправкой текстов в сторонний сервис проверьте политику данных компании.
Расходы на прогоны тоже контролируются: считайте число случаев, умноженное на число вызовов судьи, и держите бюджет сборки в пределах, согласованных с владельцем процесса. Актуальные тарифы выбранной модели смотрите на странице вендора. Пока вы выбираете, какие проверки оставить в быстром срезе, пригодится ответ на простой вопрос.
Что в вашем агенте сейчас проверяется только вручную?
Слово человека
Автоматический набор говорит, что версия осталась на прежнем уровне на известных случаях. Допустимость нового поведения утверждает человек. Когда правка меняет формулировки ответов, владелец процесса просматривает пары «до и после» на спорных примерах и фиксирует решение в описании изменения. Только затем обновляется эталон. Иначе набор подгоняется под текущее поведение и перестаёт что-либо проверять. Запишите в описании изменения, кто и по какому примеру принял новое поведение: так любое следующее расхождение разбирается за минуты.
- Выберите один сценарий и соберите для него десять реальных обезличенных входов, включая два-три сложных.
- Напишите для каждого LLMTestCase и один письменный критерий для GEval, а структурные проверки оформите обычными утверждениями.
- Запустите deepeval test run локально, разберите провалы и поправьте либо агента, либо слишком расплывчатый критерий.
- Добавьте быстрый срез в сборку, а полный набор поставьте на ночной запуск.
Возьмите самую дорогую ошибку агента за последний месяц и превратите её в тест, который сегодня красный. Когда он позеленеет после правки, у вас появится первая настоящая гарантия. Если нужен проект с тестами, подтверждениями и приёмкой, обсудите его на странице про внедрение ИИ под ключ.