Qdrant - Vector Database
Production RAG Pipeline
RAG работает в demo. В production - hallucinations, неправильные источники, старые данные. Разница между demo и production RAG - в деталях: как нарезать, как индексировать, как искать, как ранжировать. Разберём каждый слой.
- **Юридическая система:** договоры нарезаются по статьям (recursive по заголовкам), reranking через Cohere, ответ с номерами статей-источников
- **Поддержка клиентов:** база знаний + тикеты → hybrid search (keyword exact match важен) → reranking → GPT-4o-mini ответ с правкой агента
- **Корпоративный поиск:** 100k документов разных форматов → IngestionPipeline, ежедневное обновление, идемпотентный upsert по deterministic ID
Предварительные знания
Стратегии нарезки документов (chunking)
**Качество RAG на 70% определяется качеством чанкинга.** Правильная нарезка документов - foundation любого production RAG. Три основные стратегии: fixed-size, semantic, recursive. Выбор зависит от типа контента.
| Стратегия | Размер | Плюсы | Минусы | Когда использовать |
|---|---|---|---|---|
| Fixed-size | 512-1024 токен | Простота, предсказуемость | Разрывает смысловые блоки | Однородный контент (статьи) |
| Recursive | 512 токен + overlap 50 | Уважает структуру документа | Сложнее настройка | Код, документация с заголовками |
| Semantic | Адаптивный | Чанки = смысловые единицы | Дорого (требует LLM) | Нарративный текст, диалоги |
**Overlap** - обязательный параметр. Без overlap LLM не получит контекст на границах чанков. Стандарт: 10-15% от chunkSize. При chunkSize=512 → overlap=50. Слишком большой overlap (>20%) создаёт дублирование без пользы.
У вас документация API: Markdown файл с заголовками H1/H2/H3, code blocks, таблицы. Какую стратегию чанкинга выбрать?
Batch upsert pipeline: embeddings + Qdrant
**Production upsert pipeline** должен быть идемпотентным (повторный запуск = те же результаты), батч-оптимизированным (не по одной точке) и устойчивым к ошибкам. Ключевые паттерны: upsert по deterministic ID, батчинг 100-500 документов, обработка ошибок с retry.
**`wait: true` в upsert** - критически важно для production. Без него Qdrant подтверждает приём данных но не запись на диск. При crash после ответа данные могут потеряться. `wait: true` ждёт полного сохранения. Да, чуть медленнее - но надёжно.
Вы обновляете документ: старая версия была 5 чанков, новая - 3 чанка. Что нужно сделать помимо upsert новых 3 чанков?
RAG поиск: hybrid search + reranking + LLM
**Production RAG поиск** - это не просто `similaritySearch`. Паттерн: hybrid search (dense + sparse) → получить N кандидатов → reranking (cross-encoder или Cohere) → топ-K → LLM. Reranking поднимает recall@5 на 15-30%.
**Почему reranking важен:** embedding-based поиск оптимизирован для recall (найти релевантные документы), но плохо ранжирует их внутри топ-20. Cross-encoder / Cohere rerank делает попарное сравнение query↔document - это точнее но медленнее. Паттерн: быстрый retrieval (20) + точный reranking (5) = лучший из двух миров.
«Хороший embedding поиск не нуждается в reranking»
Embedding models оптимизированы для recall, не для точного ранжирования. Reranking - отдельная задача с другими моделями (cross-encoder). Для production RAG reranking стандартен.
Embedding similarity - приближение семантической близости. Cross-encoder reranker видит и запрос, и документ одновременно, делая более точную оценку релевантности. Они дополняют друг друга: ANN retrieval для скорости, reranker для точности.
Recall@20 вашего поиска = 95% (нужный документ в топ-20), но Recall@5 = 60% (нужный документ редко в первых 5). Что добавить?
Ключевые идеи
- **Chunking выбор:** recursive для структурированных документов, fixed-size для однородных, semantic для нарративных текстов
- **Обогащение метаданных:** sourceId, chunkIndex, contentType, language — это основа для фильтрации и показа источников
- **Deterministic ID** (hash от sourceId+chunkIndex) = идемпотентный upsert: повторный запуск не создаёт дубликатов
- **Batch upsert** с `wait: true`: батчи 100-500, rate limiting, retry logic
- **RAG поиск:** hybrid search (20 кандидатов) → reranking → топ-5 → LLM. Reranking поднимает Recall@5 на 15-30%
Что дальше
Production RAG pipeline готов. Теперь - как масштабировать на множество клиентов и безопасно изолировать данные.
- Мультитенантность — Как в одном Qdrant обслуживать множество клиентов с изоляцией данных
- NestJS интеграция — Обернуть RAG pipeline в production NestJS сервис с BullMQ async indexing
- Hybrid Search — Подробности о dense+sparse поиске используемом в pipeline
Вопросы для размышления
- Почему deterministic ID важен для production upsert? Что произойдёт если использовать случайные UUID при каждой индексации?
- Вы замечаете что reranking занимает 500мс на каждый запрос (Cohere API). Как снизить latency не жертвуя качеством?
- Chunking overlap создаёт дублирование контента в соседних чанках. Как это влияет на качество RAG ответов? Когда overlap вреден?