Как интегрировать тестирование агентов в CI/CD?

Краткий тезис

Интеграция тестирования AI-агентов в CI/CD (Integration / Continuous canary deployment|Deployment) требует многослойного подхода: от юнит-тестов отдельных инструментов до сквозных регрессионных и performance-тестов. Ключевое отличие от традиционного ПО – агенты недетерминированы (зависит от LLM), поэтому нужны моковые модели, property-based тесты (непротиворечивость, faithfulness) и чёткие quality gates (пороги качества). Развёртывание рекомендуется через canary-релиз (1% → 10% → 100%) с мониторингом метрик в продакшене.


1. Зачем тестировать агентов в CI/CD

Агент – это система, которая самостоятельно принимает решения: выбирает инструменты, формирует промпты, обращается к внешним API. Ошибка агента может дорого стоить (неверный ответ, утечка данных). CI/CD-пайплайн должен ловить:

  • Регрессии (работающий агент сломался после изменения промпта);
  • Ухудшение качества (например, падение faithfulness);
  • Неожиданное поведение (вызов не тех инструментов, зацикливание).

Без автоматизации тесты проводятся вручную – это медленно, невоспроизводимо и масштабируется плохо.


2. Типы тестов для агентов

Тип тестаЧто проверяетИнструмент / подход
Unit tests (юнит-тесты)Отдельные функции: парсеры, валидаторы, расчётыpytest, unittest
Integration tests (интеграционные)Взаимодействие агента с внешними API (с моками)pytest + responses / WireMock
Regression tests (регрессионные)Золотой набор (golden set) кейсов – ответы должны совпадать с эталономLangSmith, DeepEval
Property-based tests (свойственные)Свойства модели: faithfulness, consistency, отсутствие галлюцинацийhypothesis + LLM-асессор (RAGAS, LangChain)
Performance tests (нагрузочные)Latency, cost (токены), throughputLocust, k6 + мониторинг CloudWatch/Prometheus

2.1 Unit tests

Проверяют изолированные компоненты: парсинг ответа LLM, форматирование промпта, логику выбора инструмента. Например:

def test_parse_tool_call():
    raw = '<tool_call>{"name": "search", "args": {"query": "AI"}}</tool_call>'
    assert parse_tool_call(raw) == {"name": "search", "args": {"query": "AI"}}

Такие тесты быстрые, детерминированные – выполняются на каждом push.

2.2 Integration tests с моками

Агент вызывает внешние сервисы (API погоды, базы знаний). Чтобы тест был стабильным, мокаем API – заменяем на заранее записанные ответы (fixtures). Использовать responses (Python) или WireMock (Java). Пример:

import responses
responses.add(responses.GET, 'https://api.weather.com/current',
              json={'temp': 20}, status=200)
response = agent.get_weather('Moscow')
assert '20' in response

2.3 Regression tests (golden set)

Создаём датасет из типичных запросов пользователей с ожидаемыми ответами (эталоны). После каждого изменения агента прогоняем этот набор и сравниваем ответы. Сравнение может быть:

  • Точное (если ответ детерминирован – например, сумма чисел);
  • Семантическое (используем эмбеддинги + порог косинусной близости);
  • LLM-as-a-judge (другой LLM оценивает, эквивалентны ли ответы).

Инструменты: LangSmith (датасеты, автотесты), DeepEval (оценка по метрикам).

2.4 Property-based tests

Проверяем свойства, которые должны выполняться для любых входов. Например:

  • Faithfulness (верность фактам) – ответ агента должен быть подтверждён документами контекста;
  • Consistency – ответ на один и тот же запрос не должен радикально меняться (если не изменились данные);
  • No loops – агент не зацикливается.

Используем hypothesis (генерация запросов) + LLM-асессор (RAGAS, LangChain). Пример проверки faithfulness:

from hypothesis import given, strategies as st
@given(st.text())
def test_faithfulness(query):
    result = agent.run(query)
    faithfulness_score = evaluate_faithfulness(result.context, result.answer)
    assert faithfulness_score > 0.85

2.5 Performance tests

Измеряем:

  • p50/p95/p99 latency – время полного цикла агента;
  • Token usagecost (стоимость);
  • Throughput – сколько запросов в минуту выдерживает.

Нагрузочное тестирование запускаем на dedicated окружении (staging) с реалистичными профилями запросов. Инструменты: locust (Python), k6 (JS), Artillery.


3. Quality gates (качественные ворота)

На каждом этапе CI/CD устанавливаем пороговые значения, при которых пайплайн останавливается:

МетрикаПорогПояснение
Faithfulness (RAGAS)> 0.9Доля ответов, которые полностью соответствуют документам
Answer relevance> 0.85Ответ соответствует вопросу, не уходит в сторону
Regression success rate100%Все golden-тесты должны пройти (с учётом семантического допуска)
Latency p95< 2000 ms95% запросов укладываются в 2 секунды
Cost per request< 0.05 USDНе превышаем бюджет

Эти значения хранятся в коде (например, в конфиге YAML) и применяются в CI-скрипте.


4. Пайплайн CI/CD (пример YAML)

# .github/workflows/agent-ci.yml
name: Agent CI/CD
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with: { python-version: '3.11' }
      - name: Install deps
        run: pip install -r requirements.txt
      - name: Unit & integration tests
        run: pytest tests/unit tests/integration -v
      - name: Regression tests (golden set)
        run: pytest tests/regression --golden-set ./data/golden.json
      - name: Property-based tests
        run: pytest tests/property --count=100
      - name: Performance tests
        run: locust -f tests/locustfile.py --headless --host http://staging --run-time 5m --json
      - name: Check quality gates
        run: python scripts/check_quality.py --config .qa/gates.yaml
  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Canary 1%
        run: ./deploy.sh canary 0.01
      - name: Monitor for 10 min
        run: ./monitor.sh --time 600 --metric error_rate
      - name: Canary 10%
        run: ./deploy.sh canary 0.10
      - name: Monitor for 10 min
        run: ./monitor.sh --time 600 --metric error_rate
      - name: 100% rollout
        run: ./deploy.sh full

5. Версионирование агентов

Агент – это не только код, но и:

  • Промпты (версионировать через git или отдельное хранилище prompt registry);
  • Модель LLM (версия, провайдер);
  • Инструменты (описания, схемы).

Рекомендуется:

  • Все промпты хранить в репозитории (как код);
  • При каждом изменении тегировать релиз (git tag v1.2.3);
  • В конвейере собирать Docker-образ с зафиксированной версией LLM (через model_id или model endpoint).

Пример структуры:

agent/
  prompts/
    system_prompt_v2.txt
    tool_descriptions.json
  code/
    agent.py
    tools.py
  tests/
  Dockerfile

6. Инструменты для тестирования агентов

ИнструментНазначениеПлюсы
RAGASОценка faithfulness, answer relevance, context recallСпециализирован под RAG, метрики из коробки
LangSmithТрейсинг, датасеты, автотесты, регрессииЭкосистема LangChain, встроенный CI
DeepEvalUnit-тесты для LLM, LLM-as-a-judgeЛёгкий, интеграция с pytest
HypothesisГенерация тестовых данныхМощная генерация, поддержка property-based
Locust / k6Нагрузочное тестированиеOpen source, гибкие сценарии

7. Canary deploy и мониторинг

После успешных тестов развёртываем новую версию агента порционно:

  1. Canary 1% – отправляем 1% трафика на новую версию, остальные 99% на старую.
  2. Мониторинг – отслеживаем:
    • Error rate (количество ошибок > baseline);
    • Latency degradation (p95 вырос > 10%);
    • User feedback (количество негативных реакций);
    • Cost spikes (резкий рост токенов).
  3. Если падение метрик – auto-rollback на предыдущую стабильную версию.
  4. Если всё хорошо – увеличиваем до 10%, снова мониторим, затем 100%.

Автоматизация развёртывания: ArgoCD, Spinnaker, Helm (для Kubernetes), или простые скрипты.


8. Мета-метрики и непрерывное улучшение

После деплоя собираем телеметрию в продакшене:

Эти данные используем для обновления golden set и пересмотра quality gates. Таким образом CI/CD становится петлёй обратной связи.


Пет-проект для закрепления

Задача Разработать CI/CD пайплайн для простого RAG-агента, отвечающего на вопросы по документации.

Инструменты

Шаги:

  1. Создать агента с двумя инструментами: search_docs (поиск по векторной БД) и get_time.
  2. Написать unit-тесты для парсинга вызова инструментов.
  3. Написать integration-тесты с моками поискового API.
  4. Сформировать golden set из 10 запросов с эталонными ответами (LLM-as-a-judge).
  5. Добавить property-based тест на faithfulness (генерация 50 случайных запросов, проверка через RAGAS).
  6. Настроить GitHub Actions: при push запускать тесты; если все quality gates пройдены – собирать Docker-образ и пушить в registry.
  7. Написать скрипт canary-деплоя на локальном Kubernetes (minikube) с мониторингом ошибок через Prometheus.
  8. Эмулировать сбой (удалить важный документ из БД) и проверить, что регрессионный тест падает, блокируя деплой.

Ожидаемый результат Полностью автоматизированный конвейер (push → test → gate → deploy), который обнаруживает регрессии и некачественные изменения.


Связь с другими вопросами

ВопросТема
5Оценка качества retrieval (метрики faithfulness, context relevance)
7Уменьшение latency RAG-системы (performance тесты)
10Self-RAG (влияние на тестирование faithfulness)
15Мониторинг RAG-систем в продакшене
20Версионирование и A/B тестирование промптов
50CI/CD для ML-моделей (смежные практики)

Навигация