Полгода назад у меня сломался продакшен-пайплайн. Модель, которая месяц работала идеально, начала отвечать чушью. Буквально: вместо нормальных рекомендаций — поток бессмыслицы. Я два дня искал проблему. Думал — данные «поехали». Оказалось, в новом промпте случайно оказался символ, который модель упорно интерпретировала как инструкцию. Просто сломали тестирование.
Эта история — не исключение. ИИ-приложения ломаются не как обычный софт. Там нет стектрейса, нет нуля-деления, нет segfault. Там есть дрейф данных, галлюцинации, prompt injection и ещё сотня подлых способов поехать крышей. И вот про то, как с этим жить — мой разбор.
Чем ИИ-тестирование отличается от обычного
Когда я впервые пытался тестировать LLM-приложение привычными инструментами, было смешно. Pytest, который проверяет, что функция add(2, 3) возвращает 5, — он хорош, но здесь ему делать нечего. Модель не обязана отвечать одинаково дважды. Одна и та же фраза может звучать по-разному в зависимости от температуры, random seed, фазы луны. При этом ответ может быть семантически правильным.
Главное, что я усвоил: ИИ-тестирование — это про свойства, а не про точные значения.
Вместо «ответ должен быть exactly "42"» ты проверяешь «ответ должен содержать ключевые факты из контекста и не противоречить им». Вместо «модель должна выдать именно этот JSON» ты проверяешь «JSON должен иметь нужную схему, поля должны быть заполнены релевантными значениями, а не случайным мусором».
Базовые подходы, которые реально работают
Тесты на релевантность и фактичность
Самый простой и недооценённый паттерн — взять известный вопрос, известный контекст и проверить, что модель не врёт. Я использовал RAGAS — он заточен именно под это: берёшь датасет вопросов-ответов, и он считает метрики — faithfulness, answer relevancy, context precision.
Попробовал также Phoenix от Arize — он хорош для отладки: визуализирует, где именно модель «поплыла». Особенно полезно, когда у тебя длинный документ и нужно понять, из какого чанка модель вытащила неправильный факт.
Golden-датасеты
Берёшь 50–100 типичных запросов, к каждому пишешь «идеальный» ответ. Потом прогоняешь модель и сравниваешь. Да, модель не ответит точно так же, но если использовать эмбеддинговую метрику (например, BERTScore), можно ловить серьёзные деградации.
Минус: составление golden-датасета — это боль. Но разовая. Я обычно начинаю с 20–30 примеров и наращиваю по мере нахождения багов. В индустрии это называют evals-driven development — и это нормальный подход.
Regression-тесты на галлюцинации
Тут хитрость. Нельзя автоматически доказать, что модель не галлюцинирует. Но можно проверить известные галлюцинации. Если модель раньше уверенно врала про дату основания компании — добавь это в регрессионный набор. Прогнал пайплайн — убедился, что та же ошибка не всплыла.
Для этого хорошо подходит Promptfoo — декларативный фреймворк для оценки LLM-приложений. Ты описываешь набор запросов, ожидаемые свойства ответов (regex, содержимое, score) и получаешь отчёт. Встраивается в CI за полчаса.
Инструменты, которые стоит знать
LangSmith (от создателей LangChain) — не просто трейсинг промптов, а полноценная платформа для оценки. Можно запускать eval-цепочки, собирать датасеты из продакшена, смотреть, какие запросы отработали плохо. У меня ушёл примерно день на интеграцию, и потом я пару раз находил баги, которые бы пропустил.
Weave от Weights & Biases — аналогичная штука, интегрируется с OpenAI, Anthropic, и чем угодно через generic-обёртку. Удобен, если у тебя уже W&B для трейнинга моделей — всё в одном месте.
Trulens — библиотека с открытым кодом, заточенная на RAG-системы. Измеряет relevance ответа относительно контекста, понимание контекста моделью, и строит красивые отчёты. Поставил за вечер, настроил метрики за пару часов.
deepeval — pytest-плагин для LLM-тестов. Если ты уже в экосистеме Python + pytest, это самый низкий порог входа. Пишешь тесты как обычные unit-тесты, только вместо assertions — LLM-assertions.
Подвохи, которые я обнаружил на собственном опыте
Промпт-чувствительность. Мелочь в формулировке — и результат меняется кардинально. Я однажды случайно убрал одно слово из system prompt, и accuracy упала на 15%. Без единого лога. Вернул слово — починилось. Лечится только регрессионными тестами.
Дрейф данных. Модель обучена на данных до какого-то момента. Если подаёшь ей контент с актуальными событиями — она может отвечать уверенно, но неправильно. Помогает только мониторинг в продакшене: отслеживать распределение ответов, семантический дрейф эмбеддингов, частоту определённых паттернов.
Prompt injection. Это не академическая угроза. Я видел, как пользователь ввёл в чат-бота «ignore previous instructions and…» и получил доступ к системным данным. Тестировать инъекции нужно руками и автоматически — генерировать известные паттерны и проверять, что модель не поддаётся.
Мультимодальность. Если у тебя приложение работает с изображениями или аудио — стандартные текстовые метрики не работают. Либо Vision-language eval-фреймворки (типа Camel), либо ручная разметка, либо CLIP-based similarity.
Что я делаю в реальном проекте
Последние полгода у меня выстроился простой процесс. Перед каждым релизом:
- Прогоняю golden-dataset через evaluate-пайплайн. Если average score просел больше чем на 3% — откатываю изменения и разбираюсь.
- Запускаю набор regression-тестов на известные баги. Занимает 15 минут и экономит два дня отладки.
- Делаю sanity-check на 10–15 случайных примерах из продуктовых логов. Автоматизация не заменит живого взгляда на реальный барахол.
- Собираю отзывы пользователей в продакшене — если несколько жалуются на одно и то же, помечаю флагом. Что-то сработало плохо — добавляю в следующий eval.
Это не идеально. Но это даёт мне уверенность, что я узнаю о проблеме не от пользователя, а от тестов.
Коротко
ИИ-тестирование — это не магия и не rocket science. Это системный подход к проверке свойств, а не значений. Golden-датасеты, метрики релевантности, регрессионные тесты на известные баги и мониторинг в продакшене — минимальный набор, который у меня работает.
Главное — перестать думать, что если модель молчит и не падает,
