← все статьи
8 мин

RAG в продакшне: что реально ломается

Retrieval-Augmented Generation выглядит понятно на демо: берём документы, разбиваем на чанки, кладём в векторное хранилище, при запросе достаём релевантные кусочки и передаём в LLM. На практике – в каждом шаге есть нюансы, которые не очевидны заранее.

Этот материал разбирает практические вопросы RAG-пайплайна: качество разбиения, поиск, задержки и проверка ответов. Это не отчёт о конкретном клиентском проекте; параметры и примеры нужно проверять на собственной системе.

Два контура RAG-пайплайна

Индексация

  1. 01Документы
  2. 02Разбиение на чанки
  3. 03Модель эмбеддингов
  4. 04Векторное хранилище

Запрос

  1. 01Запрос пользователя
  2. 02Модель эмбеддингов
  3. 03Векторное хранилище
  4. 04Реранжирование
  5. 05Сборка контекста
  6. 06LLM
  7. 07Ответ

Chunking: главная переменная

Самое влиятельное решение во всём пайплайне – как именно вы режете документы. Фиксированный размер по токенам – самое простое, но редко оптимальное. Проблема: смысловые границы не совпадают с токенными. Предложение разрезается посередине, контекст теряется.

// базовый вариант

Recursive character text splitting с chunk_size=512 и chunk_overlap=64 можно использовать как исходную точку. Semantic chunking по смысловым блокам требует отдельной проверки качества и времени индексации на вашем корпусе.

# Пример: semantic chunking через embeddings similarity\n\ndef semantic_chunk(text, threshold=0.85):\n    sentences = sent_tokenize(text)\n    embeddings = embed_model.encode(sentences)\n    chunks, current = [], [sentences[0]]\n\n    for i in range(1, len(sentences)):\n        sim = cosine_similarity(embeddings[i - 1], embeddings[i])\n        if sim < threshold:\n            chunks.append(\" \".join(current))\n            current = []\n        current.append(sentences[i])\n\n    if current:\n        chunks.append(\" \".join(current))\n\n    return chunks

Качество эмбеддингов

OpenAI text-embedding-3-small – хороший выбор для русскоязычных документов. Но если у вас специфический домен (юридический, медицинский, технический) – стоит смотреть на fine-tuned модели или multilingual-e5-large.

Важный момент: эмбеддинг-модель для индексирования и для запросов должна быть одна и та же версия. Звучит очевидно, но при обновлении модели нужно переиндексировать весь корпус – иначе пространства не совпадают, и качество поиска деградирует незаметно.

Деградация качества при несовпадении версий эмбеддинга может быть тихой. Проверяйте поиск на контрольной выборке после каждого обновления и фиксируйте методику измерения.

Latency: где на самом деле тормозит

Стандартный профиль запроса: embed запроса → similarity search → fetch документов → LLM completion. В большинстве случаев узкое место – не LLM, а retrieval.

  • Векторный поиск в pgvector без HNSW-индекса – линейный по размеру корпуса
  • HNSW меняет требования к памяти и скорости; параметры индекса проверяйте на своём корпусе
  • Кэширование эмбеддингов запросов может помочь повторным запросам, но требует проверки актуальности
  • Асинхронная загрузка документов после retrieval может изменить время ответа; измеряйте это на целевом сценарии

Hallucination под нагрузкой

LLM может сформировать неверный ответ, если retrieval возвращает нерелевантный контекст. Связь с нагрузкой проверяйте отдельно: на неё влияют кэширование, очереди, лимиты и деградация поиска.

// mitigation

Порог relevance_score_threshold можно использовать как защитное условие: если ни один чанк не проходит проверку, вернуть нейтральный ответ о нехватке данных. Порог и текст ответа нужно валидировать на своей контрольной выборке.

Второй вариант — cross-encoder reranking поверх первичного retrieval. Он добавляет вычисления, поэтому сравнивайте прирост качества, задержку и стоимость на одной контрольной выборке.

Что в итоге

RAG – это не одно решение, это пайплайн из независимых компонентов, каждый из которых нужно тюнить под конкретный домен и нагрузку. Метрики нужны на каждом уровне: не только финальное качество ответа, но и recall@k, MRR, latency p95 по каждому этапу.

Если строите RAG систему – закладывайте время на эксперименты с chunking и эмбеддингами. Это не инфраструктурная задача, это исследовательская.


← все статьи Следующая →Kubernetes для небольшой команды: когда он оправдан