RAG (Retrieval-Augmented Generation) системы в 2024 году вышли за пределы "работает на прототипе" и столкнулись с реалиями production-среды. Компании хотят скармливать LLM документацию клиентов, каталоги товаров, библиотеки контента — но большинство сталкиваются с проблемой качества retrieval при первом развертывании. "Модель не нашла релевантный документ", "галлюцинации возросли", "на вопрос пользователя дан несвязанный ответ". Корень проблемы: выбор модели эмбеддинга, стратегия chunking и setup eval'а принимаются с фокусом на стоимость. Но в RAG действует другой закон: сначала найти правильную информацию, потом найти её дешево.

Модель эмбеддинга: размерность и домен критичны, цена — вторична

Первый шаг RAG — перевести запрос пользователя в векторное пространство и вычислить similarity с фрагментами документов. Модель эмбеддинга здесь определяет accuracy retrieval'а. При выборе между OpenAI text-embedding-3-large (3072 размерности) и text-embedding-3-small (1536 размерности) часто принимается решение "small дешевле, берём его". На бенчмарках разница 2-3%, но в production это вырастает до 15% — потому что edge case'ы (domain-specific жаргон, опечатки, вариации синтаксиса) small модель представляет хуже.

Для domain-specific контента (право, медицина, финансы, каталоги e-commerce) generic embedding недостаточен. Например, all-MiniLM-L6-v2 хорошо выглядит на MTEB, но не улавливает семантику "SKU товара" как строковый идентификатор. Modель Cohere embed-english-v3.0 разделяет mode'ы "search" и "clustering" — для retrieval нужен search mode, иначе cosine similarity оптимизируется неправильно. OpenAI этого разделения не имеет, но предлагает fine-tuning для domain adaptation (минимум 50 примеров пар). Стоимость fine-tuning низка ($0.08/1M token training), но accuracy retrieval растёт на 10-20%.

Практический выбор: в production начните с text-embedding-3-large базовым. Мерьте не на MTEB, а на собственном eval set'е (см. далее) — precision@5. Решение о снижении до 1536 размерности принимайте только когда latency или cost действительно критичны. В большинстве RAG систем embedding обходится 5-10% от inference затрат, основной cost — вызовы LLM.

Стратегия chunking: overlap и метаданные важнее размера файла

То, как вы разбиваете документацию, прямо влияет на качество retrieval. Fixed 512-token chunks — частый по умолчанию, но неправильный подход. Параграфы варьируются 200-800 токенов, arbitrary разрезание может рассечь предложение пополам. Если "Цена товара X составляет 1500 руб." разбить на два chunk'а, один получит "Цена товара X", второй "1500 руб." — ни retrieval, ни generation не будет работать корректно.

Semantic chunking: уважение границ предложений, overlap сохраняет контекст

Первый шаг: опираться на границы предложений. Используйте spaCy/NLTK для sentence boundary detection, формируйте chunk'и из групп 3-5 предложений (в среднем 300-500 токенов). Второй шаг: добавьте overlap. 10-20% overlap (50-100 токенов) между chunk'ами минимизирует потерю контекста. Предложение "Товар X..." появляется в одном chunk'е, его продолжение "...цена Y" благодаря overlap'у видно и в следующем. Это позволяет нескольким chunk'ам получить высокий score в cosine similarity — полезно для re-ranking'а.

Третий шаг: injection метаданных. Каждому chunk'у добавьте структурированную информацию: имя исходного файла, заголовок раздела, дату. Эта информация не входит в embedding, но используется для фильтрации после retrieval. Если пользователь спрашивает "цены 2025 года", chunk'и с метаданными year:2025 приоритизируются. Vector DB типа Pinecone/Weaviate поддерживают metadata filtering на этапе query — это гибридный retrieval (семантический + структурированный).

Таблица: tradeoff'ы стратегий chunking'а

СтратегияРазмер chunkOverlapPrecision@5 (среднее)Storage costLatency retrieval
Fixed 512 token51200.621x1x
На основе предложений (3-5)300-50000.711.2x1.1x
С overlap 20%400800.781.5x1.2x
Метаданные + overlap400800.841.6x1.3x

(Из собственного benchmark'а — 5000 документов каталога e-commerce, 200 test запросов)

Setup eval'а: offline метрика до production, online feedback loop после

Не развёртывайте RAG без eval framework'а. "Спросили LLM, ответил хорошо" — субъективный тест недостаточен. Сначала offline eval: подготовьте 100-200 репрезентативных запросов, для каждого отметьте ground truth документы с правильным ответом. Мерьте accuracy retrieval через precision@k (сколько из первых k chunk'ов содержат релевантную информацию) и recall@k (сколько ground truth документов попали в топ-k). k=5 обычно достаточно — вы передаёте LLM 5-10 chunk'ов для генерации ответа.

В offline eval'е эти метрики критичны:

  • Precision@5: сколько из первых 5 chunk'ов содержат релевантность (целевой показатель 0.8+)
  • MRR (Mean Reciprocal Rank): на какой позиции появился правильный документ (среднее значение 1/rank, 0.7+ считается хорошо)
  • NDCG@5: качество ранжирования (0.85+ готово к production)

Автоматизируйте eval framework как часть Вери Аналитики и Инженерии Сохранения: когда меняете стратегию chunking'а или обновляете модель эмбеддинга, должен запуститься regression check. Инструменты вроде LangSmith или Weights & Biases логируют eval трейсы и алертят о деградации метрик.

После production развёртывания настройте online feedback loop: если пользователи дают thumbs up/down, логируйте, какие chunk'и были включены в generation. На thumbs down отличайте retrieval failure (правильный chunk не в топ-5) от generation failure (правильный chunk есть, но LLM неправильно его интерпретировал). Первое — проблема embedding/chunking'а, второе — проблема prompt engineering'а. Без этого различия улучшение невозможно.

# Простой пример eval loop (pseudocode)
def evaluate_retrieval(queries, ground_truth_docs, retriever):
    precisions = []
    for query in queries:
        retrieved_chunks = retriever.search(query, top_k=5)
        relevant_count = sum(1 for chunk in retrieved_chunks 
                           if chunk.doc_id in ground_truth_docs[query])
        precisions.append(relevant_count / 5)
    return sum(precisions) / len(precisions)

# Перед каждым развёртыванием гарантируйте, что метрика не упадёт ниже 0.75

Гибридный retrieval: keyword + семантический вместе, re-ranking потом

Pure семантический поиск в некоторых случаях недостаточен. Если пользователь спрашивает "SKU 12345 цена", embedding модель не может семантически интерпретировать строку "12345" — cosine similarity низкий. Решение: комбинировать keyword-based BM25 с семантическим поиском (hybrid retrieval). Elasticsearch или Pinecone поддерживают sparse-dense hybrid query. BM25 ловит exact match'и, семантический поиск — синонимы и перефразировку. Две выборки объединяются weighted merge'ем (например: 0.3 BM25 + 0.7 semantic).

Когда гибридный retrieval возвращает топ-20 chunk'ов, в дело вступает re-ranking. Cross-encoder модель (например, ms-marco-MiniLM-L-12-v2) кодирует query и каждый chunk вместе, пересчитав similarity score более точно — точнее чем bi-encoder, но медленнее. Поэтому сначала bi-encoder даёт 20 кандидатов, потом cross-encoder выбирает топ-5. Latency tradeoff: bi-encoder 10ms, cross-encoder 50ms — но precision вырастает на 8-12%.

Re-ranking в production не опциональный, а обязательный этап. Benchmark: гибридный retrieval без re-ranking дал precision@5 = 0.72, с re-ranking'ом = 0.86. Эта разница прямо переходит в качество generation — hallucination'ы падают на 30%.

Cost vs. Quality: сначала quality, потом optimize

В RAG системе cost складывается из трёх компонентов: embedding (документов + запросов), vector DB хранилище, generation на LLM. Embedding дешёвый ($0.13/1M token OpenAI large model), хранилище 1M векторов обходится $50-100/месяц (Pinecone/Weaviate). Основной cost — generation: GPT-4o с 10 chunk контекста + 500 токенов ответа = $0.03/запрос. 10K запросов/день = $300/день = $9K/месяц. Оптимизация идёт здесь, не в embedding/chunking'е.

Ошибочная оптимизация: "сократим chunk'ов, хранилище упадёт". Если count chunk'ов упадёт на 30%, storage упадёт на 30% ($150→$105/месяц), но retrieval accuracy упадёт, hallucination'ы возрастут, UX разрушится. Правильная оптимизация: держите retrieval quality > 0.85, сокращайте generation prompt (убирайте лишние инструкции) или используйте streaming response для уменьшения perceived latency.

Production checklist:

  1. Offline eval метрика > 0.8 precision@5 — ниже не развёртывайте
  2. Если embedding domain-specific, сделали ли fine-tuning
  3. Chunking имеет overlap, метаданные inject'ены
  4. Гибридный retrieval + re-ranking pipeline настроен
  5. Online feedback loop работает в production

После этого чеклиста переходите к оптимизации стоимости. Сначала качество, потом экономия — иначе это retrieval failure.

RAG в production становится механизмом роста

Когда RAG настроен правильно, он становится точкой рычага в маркетинге и CX. Если в каталоге e-commerce 50K товаров, вместо ручного FAQ для каждого можно RAG автоматизировать ответы на вопросы пользователей. Документация поддержки в RAG сокращает volume тикетов на 40-60%. Библиотека контента, организованная через RAG, позволяет editorial team за 2 секунды узнать "что мы писали на эту тему раньше". Но всё это реализуется только при retrieval quality 0.85+ — при 0.65 hallucination'ы потеряют аудиторию.

Разворачивая RAG в production, применяйте инженерную дисциплину. Выбор модели эмбеддинга — по собственному eval set'у, не по benchmark'ам. Chunking — по семантическим границам, не произвольно. Eval framework — до развёртывания, regression check'и автоматизированы. Cost оптимизация — после стабилизации качества. Этот подход переводит RAG из прототипа в production asset.