Как вы организуете CI/CD для RAG-пайплайна?
Краткий тезис
CI/CD для RAG-пайплайна — это не просто деплой кода, а непрерывная поставка целого набора артефактов: код пайплайна, embedding-модели, промпты и версии документов. Ключевой акцент — retrieval-метрики в CI: без них деградация поиска остаётся незаметной до момента, когда пользователи начнут жаловаться. Использование control|versioning|control|control|versioning|Data control|Version Control (DVC) для документов и blue-green deployment позволяет безопасно обновлять систему без даунтайма.
1. Термин CI/CD в контексте RAG
CI (Integration) — автоматическая сборка и тестирование при каждом изменении в репозитории. Для RAG это означает запуск юнит-тестов, интеграционных тестов на retrieval и генерацию, а также проверку метрик качества.
CD (Continuous Delivery или Continuous Deployment) — автоматический деплой протестированного артефакта в окружение (staging/production). В RAG это развёртывание новой версии API, индекса или модели.
Важность для RAG в отличие от классического ML, RAG-пайплайн включает динамическую базу знаний (документы, чанки). Ошибки в изменении документов или эмбеддингов могут незаметно ухудшить качество ответов. CI/CD с регрессионными тестами на retrieval — единственный способ гарантировать стабильность.
2. Компоненты RAG-пайплайна, требующие CI/CD
| Компонент | Примеры артефактов | Что тестируется |
|---|---|---|
| Код пайплайна | Python-скрипты, классы RAG, цепочки LlamaIndex | Юнит-тесты, линтинг |
| Embedding-модель | Веса модели (e.g., intfloat/multilingual-e5-small) | Качество эмбеддингов на калибровочном датасете |
| Chunking-стратегия | Размер, overlap, разделители | Recall@k на эталонных запросах |
| Промпты | Template, системное сообщение, примеры few-shot | Проверка синтаксиса, faithfulness |
| Документы (корпус) | PDF, статьи, HTML, DVC-tracked файлы | Проверка на ошибки, полнота, соответствие формату |
| Конфигурация | YAML/JSON с параметрами (chunk size, top-k, model name) | Валидация схемы, соответствие версиям |
3. Организация репозитория (Git)
Рекомендуемая структура монорепозитория:
rag-project/
├── .github/
│ └── workflows/
│ ├── ci.yml # CI на PR
│ └── cd.yml # CD на push в main
├── src/
│ ├── pipeline/ # Основной код RAG
│ ├── retrieval/ # Эмбеддинги, поиск
│ └── generation/ # LLM-вызовы, промпты
├── data/
│ └── corpus/ # Исходные документы (DVC)
├── models/ # Кэш эмбеддингов (DVC)
├── tests/
│ ├── unit/ # Юнит-тесты
│ └── integration/ # Retrieval + generation тесты
├── config/
│ └── config.yaml # Параметры пайплайна
├── eval/
│ ├── questions.json # Датасет с золотыми документами
│ └── metrics.py # Функции расчёта recall, hit rate
├── DVC # DVC-файлы
└── docker-compose.yml # Локальное окружение
Git-ветки
main— стабильная версия в productiondev— интеграционные изменения- feature-ветки — разработка отдельных улучшений
Триггеры CI/CD
- При создании/обновлении PR → CI
- При мерже в
main→ CD (деплой на staging, затем manual approval на production) - При изменении DVC-файлов (документов) → отдельный pipeline переиндексации
4. CI этап: тестирование retrieval и generation
При каждом PR автоматически запускается пайплайн:
# .github/workflows/ci.yml
name: RAG CI
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
# 1. Кэширование зависимостей и моделей
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
- name: Install dependencies
run: pip install -r requirements.txt
# 2. Юнит-тесты (chunking, промпты)
- name: Unit tests
run: pytest tests/unit/
# 3. Retrieval тесты на золотом датасете
- name: Integration retrieval tests
run: |
python tests/integration/test_retrieval.py \
--eval-dataset eval/questions.json \
--top-k 5 \
--threshold-recall 0.7
# 4. Generation тесты (проверка faithfulness)
- name: Generation tests (faithfulness)
run: |
python tests/integration/test_generation.py \
--eval-dataset eval/questions.json \
--threshold-faithfulness 0.8
# 5. Проверка метрик (регрессия)
- name: Compare metrics to baseline
run: |
python eval/metrics.py compare \
--new-results results.json \
--baseline baseline.json \
--tolerance 0.05
Ключевые метрики в CI
- Recall@k (например, Recall@5 > 0.7) — доля найденных релевантных документов
- Hit Rate@k (например, HR@5 > 0.9) — хотя бы один релевантный документ найдён
- MRR (Mean Reciprocal Rank) — средняя позиция первого релевантного
- Faithfulness (верность) — доля ответов, не содержащих галлюцинаций (можно проверять с помощью NLI-модели)
Если метрики падают ниже baseline, PR блокируется и требует ручного анализа.
5. CD этап: стратегии деплоя
Для production рекомендуется blue-green deployment:
| Стратегия | Описание | Подходит для RAG |
|---|---|---|
| Rolling update | Постепенная замена подов (Kubernetes) | Да, но может быть разрыв в версиях индекса |
| Blue-green | Два идентичных окружения (blue = текущее, green = новое) | Да, переключение трафика мгновенное |
| Canary | Медленный перелив небольшого процента трафика | Да, для A/B тестирования изменений |
Реализация blue-green для RAG
- Поднять новую (
green) версию API с новым индексом и моделью - Прогреть кэш, запустить smoke-тесты (несколько реальных запросов)
- Переключить load balancer на
green - Держать
blueна случай отката - После подтверждения — утилизировать
blue
Инструменты Kubernetes + Istio, или Docker Compose с Nginx, или serverless (AWS Lambda с двумя alias'ами).
6. Управление версиями документов (Data Version Control)
Документы — это не код, но их изменения напрямую влияют на retrieval. Используем DVC (Data Version Control):
# Инициализация DVC
dvc init
dvc remote add -d myremote s3://my-bucket/rag-corpus
# Отслеживание папки с документами
dvc add data/corpus/
git add data/corpus.dvc
git commit -m "add corpus v1"
# При обновлении документов
dvc add data/corpus/
git commit -m "update corpus v2"
git tag corpus_v2
Процесс при изменении документов
- Новые документы заливаются в
data/corpus/(через Git LFS или DVC) - CI/CD триггерится на изменения corpus.dvc
- Пайплайн перезапускает чанкинг и эмбеддинг
- Генерируется новый индекс (FAISS, Qdrant)
- Упаковывается Docker-образ с новым индексом
- CD деплоит новую версию (blue-green)
Важно версионировать не только документы, но и кэш эмбеддингов (models/). Это ускоряет переиндексацию при откате.
7. Триггеры: автоматическая переиндексация
Триггеры разделяются на два типа:
- Плановые изменения кода (PR → CI → CD). Включают обновление промптов, chunking-стратегии, модели эмбеддингов.
- Изменение документов (push в папку
data/corpus/). Запускается отдельный pipeline:
# .github/workflows/reindex.yml
on:
push:
paths:
- 'data/corpus/**'
- '**.dvc'
jobs:
reindex:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup DVC
run: pip install dvc-s3
- name: Pull new data
run: dvc pull
- name: Reindex
run: python src/pipeline/reindex.py
- name: Build and push new image
run: |
docker build -t rag-api:latest .
docker push registry/rag-api:latest
- name: Deploy green
run: kubectl set image deployment/rag-green rag-api=registry/rag-api:latest
8. Пример полного пайплайна CI/CD с GitHub Actions
# .github/workflows/deploy.yml
name: RAG CI/CD
on:
pull_request:
branches: [main]
push:
branches: [main]
paths:
- 'src/**'
- 'config/**'
- 'Dockerfile'
- 'eval/**'
jobs:
test:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: pip install -r requirements.txt
- name: Extract embeddings model
run: dvc pull models/
- name: Run retrieval tests
run: python tests/integration/test_retrieval.py --eval eval/questions.json --recall-min 0.75
- name: Run generation tests
run: python tests/integration/test_generation.py --faithfulness-min 0.85
- name: Check formatting
run: black --check src/ tests/
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t rag-api:${{ github.sha }} .
- name: Push to registry
run: docker push registry/rag-api:${{ github.sha }}
- name: Deploy to staging (blue)
run: |
kubectl set image deployment/rag-blue rag-api=registry/rag-api:${{ github.sha }}
kubectl rollout status deployment/rag-blue
- name: Run smoke tests
run: python tests/smoke/test_staging.py
- name: Promote to production (switch to green)
run: |
kubectl set image deployment/rag-green rag-api=registry/rag-api:${{ github.sha }}
kubectl rollout status deployment/rag-green
# Обновить сервис на green
kubectl patch service rag-service -p '{"spec":{"selector":{"version":"green"}}}'
9. Мониторинг после деплоя
CI/CD не заканчивается на деплое. Необходим непрерывный мониторинг в production:
- Retrieval-метрики в реальном времени средний recall@5 по тихим запросам (используя logged implicit feedback).
- User feedback: кнопки "Like/Dislike", позволяющие выявить деградацию.
- Алерты если средний score эмбеддингов (cosine similarity) резко падает — автоматический откат.
Можно добавить шаг в CD, который после переключения трафика запускает параллельный прогон baseline-запросов и сравнивает метрики с прошлой версией (A/B-сравнение на продублированном трафике).
10. Проблемы и их решения
| Проблема | Решение |
|---|---|
| Разрастание индекса | Удалять старые версии индексов через политику в S3. Использовать lazy-загрузку только production-индекса. |
| Время сборки > 30 мин | Кэшировать эмбеддинги и зависимости. Разделить пайплайн на отдельные jobs. |
| Сложность отладки регрессии метрик | Хранить историю метрик (MLflow, Weights & Biases) и baseline-датасет. |
| Рассинхрон между версией API и индексом | Номер версии индекса (hash от документов) прокидывать как метку Docker-образа. |
Пет-проект для закрепления
Задача создать MVP RAG-системы с CI/CD через GitHub Actions, DVC и blue-green деплой на локальном Docker или minikube.
Инструменты
- LangChain / LlamaIndex
- FAISS (векторная БД)
- FastAPI + Uvicorn
- DVC (для версионирования документов)
- Docker + docker-compose
- GitHub Actions (бесплатные минуты)
- Minikube (опционально, для K8s)
Шаги:
- Напишите простой RAG: загрузите 3-5 статей, постройте FAISS-индекс, реализуйте API с одним endpoint
/ask. - Создайте датасет
eval/questions.jsonс 10 вопросами и списком идентификаторов релевантных чанков. - Напишите
tests/integration/test_retrieval.py, который загружает индекс, для каждого вопроса ищет top-10 и считаетRecall@5. Порог — 0.8. - Инициализируйте DVC:
dvc add data/corpus/иgit add data/corpus.dvc. - Настройте GitHub Actions: при PR запускаются retrieval-тесты; при push в
main— сборка Docker-образа и развёртывание на staging (или локальном Docker Compose). - Внесите изменение в документ (например, замените статью) и закоммитьте. Убедитесь, что DVC инициирует новый pipeline, а CI ловит падение
Recall@5. - Разверните две версии (blue-green) с помощью docker-compose (два сервиса с разными тегами, Nginx как балансировщик).
Ожидаемый результат рабочий репозиторий с историей изменений, автоматическими тестами retrieval, версионированными документами и инструкцией по ручному переключению blue-green.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 5 | Метрики retrieval, лежащие в основе CI-тестов |
| 7 | Оптимизация индекса и кэширование в CD |
| 8 | Тесты на отказ от ответа (no-answer detection) |
| 10 | Дополнительный этап генерации, влияющий на CI |
| 11 | Комплексная оценка, выходящая за рамки CI |
| 12 | Chunking — центральный параметр, проверяемый в CI |
Навигация
- Предыдущий: 68
- Следующий: 70
- Индекс: 00. Индекс разборов