RAG для тех, кто разочаровался: почему retrieval ломается и как это починить

RAG для тех, кто разочаровался: почему retrieval ломается и как это починить

Вы собрали RAG-пайплайн: загрузили документы, нарезали на чанки, сгенерировали эмбеддинги, подключили векторную базу. Задаёте вопрос — модель отвечает уверенно и подробно. Показываете заказчику, тот в восторге. Но при тестировании на реальных вопросах оказывается, что на половину из них система отвечает мимо: retrieval находит не тот документ, не тот фрагмент или вообще ничего не находит, а модель уверенно галлюцинирует.

Проблема не в модели. Современные LLM вроде GPT-4 и Claude отвечают хорошо, если им предоставить правильный контекст. Проблема — в retrieval. Качество ответа напрямую зависит от качества извлечённого контекста.

Рассмотрим три основные причины сбоев и способы их устранения.

Проблема 1: чанки нарезаны бездумно

Стандартный подход — делить документ на фрагменты по 500–1000 символов с перекрытием. Но такой способ часто разрезает смысловые блоки пополам.

Например, в договоре пункт о ответственности начинается на одной странице и заканчивается на другой. При нарезке по символам первая часть попадает в один чанк, вторая — в другой. Запрос «какая ответственность по договору» находит только начало, а модель не видит полной информации.

Аналогично с таблицами: заголовок может оказаться в одном чанке, а данные — в другом. Без заголовка данные теряют смысл.

Решение — нарезка по смыслу, а не по длине:

  • Используйте RecursiveCharacterTextSplitter, который разделяет текст по естественным границам: сначала по двойным переносам (параграфы), потом по одинарным, затем по точкам.
  • Для структурированных документов (договоры, регламенты) нарезайте по разделам: каждый пункт или подраздел — отдельный чанк.
  • Добавляйте заголовок раздела к каждому чанку. Это помогает модели понять контекст, даже если фрагмент найден по ключевым словам.
  • Для таблиц — дублируйте заголовок в каждом чанке с данными.

Проблема 2: семантический поиск не находит нужное

Сравнение эмбеддингов через cosine similarity — стандарт, но он не справляется в двух случаях:

  • Разные формулировки одного понятия: «штрафы за просрочку» и «неустойка за нарушение сроков». Слова разные, эмбеддинги — далеко, особенно если модель не обучена на узкоспециализированных текстах.
  • Поверхностное совпадение: запрос «что нужно для оформления возврата» находит общий чанк про «политику возврата», а не конкретные шаги.

Решение — улучшить retrieval за счёт двух подходов.

Гибридный поиск: комбинируйте семантический (на эмбеддингах) и keyword-поиск (BM25).

Параметр alpha балансирует между ними: при alpha=1 — только семантика, при alpha=0 — только ключевые слова. На практике alpha=0.5–0.7 даёт лучший результат, потому что BM25 ловит точные совпадения, а семантический поиск — синонимы.

Reranking: после первичного поиска (retrieval) отберите 20 кандидатов, а затем переранжируйте их с помощью cross-encoder.

В отличие от bi-encoder, который кодирует запрос и документ отдельно, cross-encoder анализирует пару целиком и точнее оценивает релевантность. Он медленнее, поэтому используется не для поиска по всей базе, а только для финальной сортировки топ-20.

Гибридный поиск + reranking значительно повышает точность retrieval.

Проблема 3: отсутствие измерения качества

Многие оценивают RAG на 5–10 вопросах, которые придумал разработчик. Это не показатель. Реальные пользователи задают другие вопросы, и система часто терпит крах.

Решение — создать evaluation dataset: набор реальных или реалистичных вопросов с указанием правильных чанков или ожидаемых ответов. Достаточно 50–100 примеров.

С eval dataset вы можете:

  • Проверить, улучшилось ли качество после смены размера чанка.
  • Оценить, помог ли reranking или гибридный поиск.
  • Сравнить разные эмбеддинг-модели.

Создание датасета — ручная работа, но 50 вопросов можно собрать за час. Зато каждое изменение в пайплайне будет измеримо.

Что ещё влияет на качество

Размер чанка: маленькие (200–500 символов) дают точный retrieval, но мало контекста. Большие (2000–3000) — наоборот. Оптимальный размер зависит от задачи:

  • FAQ: 300–500
  • Юридические документы: 1000–2000
  • Техническая документация: 500–1000

Подбирайте экспериментально и проверяйте через eval dataset.

Эмбеддинг-модель: по умолчанию используют OpenAI text-embedding-3-small или all-MiniLM-L6-v2. Для русскоязычных текстов лучше подходят multilingual-e5-large или BGE-M3 — они обучены на русском языке. Смена модели может дать прирост recall на 10–20% без других изменений.

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

Вместо «Ответь на вопрос на основе контекста» используйте:

Ответь на вопрос на основе предоставленного контекста. Если в контексте нет информации для ответа, скажи об этом. Не додумывай. Ссылайся на конкретные пункты документа.

Инструкция «не додумывай» снижает галлюцинации, а «ссылайся на пункты» делает ответ проверяемым.

Когда RAG не подходит

RAG эффективен для вопросов по документам: «что написано в договоре», «как настроить сервис». Но он не подходит для задач, требующих анализа или рассуждений:

  • «Сравни два договора и скажи, какой выгоднее».
  • «Проанализируй тренд в данных за квартал».

Для таких задач нужны агенты с инструментами, а не retrieval.

Также RAG избыточен при малом объёме данных (меньше 10 страниц). Если весь текст помещается в контекст модели — загружайте его целиком. RAG оправдан, когда документов тысячи страниц.

Retrieval — самое слабое звено в RAG. Нарезка по смыслу, гибридный поиск, reranking и eval dataset — четыре практики, которые превращают демо в рабочее решение. Каждую можно внедрить за день, и каждая даёт измеримое улучшение.

Читать оригинал