Как тестировать AI-агентов и ловить галлюцинации с помощью Giskard
Обычный pytest отлично справляется с функциями, где на вход подали 2 и 2, а на выходе ждут 4. С языковыми моделями такой трюк не проходит. Ответ меняется от запуска к запуску, формулировки плавают, а вместо ожидаемого JSON агент вдруг начинает извиняться или выдавать бред.
Когда я впервые выкатил бота для ответов по документации, мы проверяли его руками. Десяток запросов в консоли, вроде работает, катим в прод. Через пару дней пользователи нашли способ заставить бота советовать товары конкурентов и сливать системный промпт. Стало понятно, что для LLM нужны принципиально другие тесты.
В репозитории giskard-oss как раз лежит фреймворк, созданный специально для тестирования, оценки качества и редтиминга AI-агентов. Проект недавно пережил мажорный переезд на третью версию: авторы выкинули тяжелые зависимости, переписали ядро на асинхронный лад и сфокусировались именно на агентах и RAG.
Что умеет библиотека
В третьей версии Giskard разделили на независимые пакеты. Если вам нужны только базовые проверки без сканирования уязвимостей, можно поставить легкий модуль giskard-checks. Если нужен полный аудит безопасности, доставляется giskard-scan.
Вот четыре основные вещи, которые берет на себя фреймворк:
- Оценка приземленности ответов (Groundedness). Проверка того, опирается ли бот на переданный контекст из базы знаний или выдумывает факты на ходу.
- LLM в роли судьи. Готовые эвалы для семантического сравнения, соответствия политикам компании и проверки сложных условий, которые невозможно описать регулярками.
- Автоматический редтиминг. Генерация атак по категориям OWASP Top-10 для LLM, включая инъекции промптов, попытки джейлбрейка и провокации на токсичные ответы.
- Тестирование многошаговых диалогов. Прогон целых сценариев общения пользователя с агентом, а не только единичных запросов.
Проверка сценариев на практике
Базовая единица тестирования в giskard-checks называется сценарием (Scenario). Вы задаете входные данные, вызываете свою функцию или агента, а затем натравливаете цепочку проверок.
Для работы потребуется Python 3.12 или новее. Установка минимального набора выглядит так:
pip install giskard "giskard[openai]"
Напишем простой асинхронный тест, проверяющий, что модель не сочиняет отсебятину, отвечая на вопрос о столице:
import asyncio
from giskard.checks import Groundedness, Scenario
def my_agent(inputs: str) -> str:
# Здесь вызывается ваша реальная модель или пайплайн
return "Paris is the capital city of France."
async def main() -> None:
scenario = (
Scenario("test_france_capital")
.interact(inputs="What is the capital of France?", outputs=my_agent)
.check(
Groundedness(
name="answer is grounded",
context="France is in Western Europe. Its capital is Paris.",
)
)
)
result = await scenario.run()
result.print_report()
asyncio.run(main())
В качестве судьи по умолчанию выступает gpt-4o-mini, но через провайдеры можно подключить Anthropic или другие совместимые модели. Судья анализирует трейс выполнения, сопоставляет ответ с переданным контекстом и выдает структурированный отчет.
Автоматический поиск уязвимостей
Самая любопытная часть проекта находится в модуле giskard-scan. Ручной подбор вредоносных промптов быстро утомляет, да и фантазии разработчика редко хватает на все сценарии атак.
Сканер генерирует враждебные тест-сьюты на основе текстового описания вашей системы. Ему достаточно объяснить роль бота, после чего он сам синтезирует сотни хитрых запросов:
import asyncio
from giskard.scan import vulnerability_scan
async def customer_support_bot(inputs: str) -> str:
# Ваша логика обработки сообщений
return f"Support response to: {inputs}"
async def main() -> None:
await vulnerability_scan(
target=customer_support_bot,
description="A customer support chatbot for an e-commerce platform.",
languages=["en"],
)
asyncio.run(main())
Сканер прогоняет встроенный датасет пейлоадов и генерирует новые атаки через LLM. На выходе получается детальная таблица с упавшими проверками, где видно, на каких именно фразах бот согласился нарушить правила или слил внутренние инструкции.
Что изменилось в третьей версии
Если вы пользовались Giskard год назад, текущая версия вас удивит. Раньше проект был комбайном для классического табличного ML: анализировал датафреймы, искал смещения в данных (bias) и строил интерактивные дашборды.
Во второй ветке сканирование табличных моделей и генератор датасетов для RAG (RAGET) жили внутри одного монолита. В v3 авторы практически полностью отказались от старого ML-наследия в пользу LLM. Табличный скан остался доступен только в ветке giskard < 3, а все силы команды ушли в асинхронные эвалы для агентов.
Из приятного: архитектура стала модульной. Базовый giskard-core не тянет за собой лишние тяжелые библиотеки вроде pandas или scikit-learn, если они вам не нужны в продакшн-контейнере.
Кстати, в библиотеку встроен сбор анонимной телеметрии. Промпты и ответы никуда не отправляются, но если вы работаете в закрытом контуре, отключите ее переменной окружения GISKARD_TELEMETRY_DISABLED=1 еще до импорта пакета.
Практические сценарии
В каких ситуациях Giskard экономит время:
- CI/CD пайплайны для LLM-сервисов. Можно запускать набор сценариев на каждый пуллреквест, отслеживая регрессии в качестве ответов перед деплоем.
- Тестирование RAG-систем. Проверка того, что ретривер подтягивает релевантные куски текста, а генератор не додумывает несуществующие правила возврата товара.
- Аудит безопасности перед релизом. Прогон сканера уязвимостей помогает заранее закрыть дыры в системных промптах.
- Сравнение разных моделей. Один и тот же набор проверок можно запустить на GPT-4, Claude и локальной Llama, чтобы понять, справляется ли дешевая модель с вашей задачей.
Итоги
Giskard v3 превратился в удобный инструмент для тех, кто устал тестировать языковые модели наугад. Он избавляет от необходимости писать собственные громоздкие обвязки вокруг LLM-as-a-judge и собирать вручную базы промпт-инъекций.
Библиотека понравится разработчикам поисковых ботов, ассистентов поддержки и сложных цепочек агентов. Если у вас классический ML на таблицах, лучше остаться на v2 или посмотреть в сторону других утилит. Но для генеративного AI это один из самых продуманных открытых инструментов на сегодня. Поставить проект и погонять базовый сценарий на своих данных займет минут пятнадцать.
