COMRAD404 / HOWTO

Как собрать RAG-систему: пошагово

Пошаговое руководство по сборке RAG-системы: корпус, чанки, эмбеддинги, векторный поиск, reranking, prompt, оценка качества и запуск.

Короткий ответ

RAG-система для практики собирается так: вы готовите корпус документов, режете его на чанки, считаете эмбеддинги, кладете их в векторное хранилище, на запросе ищете релевантные фрагменты, при необходимости пересортировываете их reranker-моделью и передаете в LLM вместе с жесткой инструкцией отвечать только по найденному контексту. Метод плохо подходит, если весь нужный контекст стабилен и целиком помещается в prompt, если ответ должен быть строго детерминированным из транзакционной БД, или если критична минимальная задержка и нет права на длинный retrieval-контур.

Минимальный рабочий контур состоит из пяти узлов:

  • ingestion — загрузка и очистка документов;
  • chunking — разбиение на фрагменты с метаданными;
  • embeddings + index — преобразование текста в векторы и индексация;
  • retrieval + reranking — поиск и пересортировка кандидатов;
  • generation — ответ по контексту с цитированием источников.

Для MVP обычно достаточно одного корпуса, одной модели эмбеддингов, одного векторного индекса и простого промпта с отказом от ответа при нехватке доказательств. Основная ошибка на старте — пытаться лечить плохой retrieval сложным промптом. Если не находите нужные фрагменты, генерация не спасет.

Если источник истины — структурированная запись в таблице или API, сначала проверьте вариант с SQL, полнотекстовым поиском или tool calling. RAG нужен там, где ответ приходится собирать из текста, а не читать из одного поля.

Что понадобится

Для первого запуска нужен не «идеальный стек», а воспроизводимая цепочка: корпус документов, модель эмбеддингов, векторное хранилище, LLM для генерации, набор эталонных вопросов и логирование. Если у вас уже есть PostgreSQL, разумно начать с него и не выносить поиск в отдельный сервис без необходимости.

Инструмент Когда выбирать Сильные стороны Ограничения
PostgreSQL + pgvector MVP, уже есть PostgreSQL в стеке, умеренный объем данных Простое администрирование, единая БД для метаданных и векторов Не лучший выбор, если нужен отдельный масштабируемый поисковый контур
Qdrant Отдельный векторный поиск, фильтрация по метаданным, быстрый пилот Удобный API, хороший практический баланс для продуктовой команды Появляется отдельный сервис, который надо наблюдать и обслуживать
Milvus Крупные коллекции, выделенный поисковый кластер Подходит для масштабирования и специализированного поискового слоя Избыточен для маленького пилота и сложнее в эксплуатации
Модель эмбеддингов Нужно превратить тексты и запросы в векторы Единое семантическое пространство для retrieval Нужен контроль стоимости, версии модели и пересчета индекса

Критерии выбора простые: размер корпуса, требования к фильтрам, скорость обновления, существующая инфраструктура и политика доступа. Не выбирайте движок по рекламе. Для команды важнее понять, как вы будете хранить document_id, source_url, updated_at, acl и версию чанка, чем спорить о «лучшем» векторном индексе.

  • Корпус: статьи, PDF, wiki, тикеты, спецификации, кодовые документы.
  • Метаданные: источник, раздел, дата обновления, тип документа, права доступа.
  • Эталонные вопросы: хотя бы 50–200 реальных запросов для офлайн-проверки.
  • Политика ответа: что делать, если доказательств не хватило.
  • Логи и трассировка: текст запроса, найденные чанки, итоговый prompt, ответ и задержка.

Пошаговый план

1. Зафиксируйте задачу и границы

Опишите один конкретный сценарий. Например: «ответить на вопрос по внутренней документации продукта с цитатами». Не начинайте с универсального ассистента «на все случаи». Для сценария определите вход, выход и критерий успеха:

  • какой тип вопросов поддерживаете, а какой нет;
  • должен ли ответ содержать цитаты и ссылки на источник;
  • что считать приемлемой задержкой;
  • нужен ли контроль доступа по пользователю или группе;
  • как обрабатываются отсутствие ответа и конфликтующие источники.

Если этих правил нет, вы не сможете объективно оценить систему: одно и то же поведение будет выглядеть то как «полезная гибкость», то как галлюцинация.

2. Подготовьте корпус документов

RAG ломается не на LLM, а на плохом корпусе. Уберите дубли, устаревшие версии, мусорные шаблоны, служебные колонтитулы и куски, которые не должны попадать в ответы. Для каждого документа сохраните стабильный идентификатор и ссылку на исходник.

  • Преобразуйте файлы в нормализованный текст.
  • Сохраняйте заголовки и иерархию разделов.
  • Отдельно помечайте таблицы, код, списки и предупреждения.
  • Добавьте поле acl, если документы приватные.
  • Версионируйте документы, чтобы уметь удалять старые чанки.

Для PDF и сканов сначала решите вопрос с качеством извлечения текста. Если OCR ошибается в терминах, retrieval будет неточным независимо от модели.

3. Разбейте документы на чанки

Стартовый ориентир — чанки по 300–800 токенов с overlap 10–20%. Но размер надо подбирать под тип корпуса. Для коротких регламентов и FAQ часто подходят компактные фрагменты. Для длинных технических описаний полезно сохранять больший контекст вокруг подзаголовка.

  • Не режьте внутри логического блока, если можно сохранить раздел целиком.
  • Добавляйте в чанк заголовок раздела и путь по иерархии.
  • Не делайте слишком крупные чанки: retrieval найдет документ, но не точный фрагмент.
  • Не делайте слишком мелкие чанки: ответ потеряет смысловой контекст.
  • Для таблиц и кода часто лучше отдельные правила chunking.

Хорошая практика — хранить и сам текст чанка, и смещение в исходном документе. Это упрощает цитирование и отладку.

4. Постройте эмбеддинги и индекс

Используйте одну модель эмбеддингов для документов и запросов, если не строите специальную двухбашенную схему. В индекс сохраняйте не только вектор, но и полезные поля: chunk_id, document_id, section_title, source_url, updated_at, acl.

  • Индексируйте только очищенный текст, который реально можно цитировать.
  • Сразу подумайте о переиндексации при смене модели эмбеддингов.
  • Проверяйте, что запросные и документные эмбеддинги создаются одной версией пайплайна.
  • Храните исходный текст рядом, чтобы не тянуть его отдельно на каждом запросе.

На этом этапе не нужно оптимизировать все до предела. Важнее получить воспроизводимый индекс и список найденных кандидатов, который можно объяснить и проверить руками.

5. Настройте retrieval

Начните с простого семантического поиска и параметра top_k в диапазоне 10–30. Затем добавьте фильтры по типу документа, продукту, языку и правам доступа. Если в корпусе много кодов, артикулов, названий функций и точных терминов, рассмотрите гибридный поиск: векторный плюс лексический.

  • Сначала меряйте recall@k: вообще нашли ли вы правильный фрагмент.
  • Не поднимайте top_k бесконечно: лишний шум ухудшит генерацию.
  • Используйте фильтры раньше, чем сложный query rewriting.
  • Сохраняйте список кандидатов для отладки каждого неудачного ответа.

Query rewriting полезен, но это не средство первой необходимости. Если исходный запрос пользователя уже хороший, переписывание может внести лишние допущения.

6. Добавьте reranking и сборку контекста

Если retrieval находит подходящий документ, но в неправильном порядке, поможет reranker. Типичный прием: сначала взять 20–50 кандидатов быстрым поиском, потом пересортировать их более точной моделью и собрать в prompt только 3–8 лучших фрагментов.

  • Убирайте почти одинаковые чанки из одного и того же места документа.
  • Ограничивайте общий бюджет токенов на контекст.
  • Сохраняйте порядок: сначала самый доказательный фрагмент, потом уточнения.
  • Не смешивайте в один контекст куски с разными версиями одного документа.

Именно на этом шаге появляется практическое качество: модель получает не «все подряд», а короткий набор проверяемых доказательств.

7. Сформируйте prompt генерации

Хороший prompt для RAG короче, чем обычно думают. Ему не нужен литературный стиль, ему нужны правила. Полезный минимум:

  • отвечай только на основе переданного контекста;
  • если доказательств недостаточно, явно скажи об этом;
  • цитируй источники или хотя бы source_url и заголовок;
  • не придумывай недостающие параметры, даты, версии и команды;
  • если в контексте есть конфликт, перечисли варианты и укажи источник каждого.

Для прикладных систем обычно ставят низкую температуру, чтобы уменьшить вариативность. Но низкая температура не исправляет плохой retrieval; она лишь делает ошибки более стабильными.

8. Проведите оценку на наборе вопросов

Соберите тестовый набор из реальных запросов. Разделите его хотя бы на три класса: простые фактоиды, многосоставные вопросы и запросы, где правильный ответ — отказ из-за отсутствия данных. Для каждого кейса храните эталонный источник или хотя бы правильный документ.

  • Проверьте retrieval отдельно от генерации.
  • Проверьте качество ответа по фактам и по цитатам.
  • Сравните несколько настроек chunking и top_k.
  • Отдельно измерьте кейсы с правами доступа и свежими документами.

Не принимайте решение по одному красивому демо. Нужен повторяемый офлайн-прогон и ручной разбор промахов.

9. Подготовьте прод-контур

Когда MVP отвечает приемлемо, добавьте регулярный ingestion, мониторинг и защиту от регрессий. Минимум для продакшена:

  • очередь или расписание обновления индекса;
  • удаление и переиндексация устаревших чанков;
  • логирование retrieval-результатов и итогового ответа;
  • тесты на доступ, свежесть и цитирование;
  • алерты на рост задержки и падение полноты retrieval.

Если у вас несколько источников с разными правами доступа, контроль acl должен происходить до генерации, а не после. Иначе модель может увидеть запрещенный фрагмент, даже если вы не покажете его пользователю напрямую.

Типичные ошибки

  • Нет четкого сценария. Система пытается отвечать и по базе знаний, и по тикетам, и по коду без единой политики качества.
  • Плохой корпус. В индекс попадают дубли, старые версии, мусор из шаблонов и служебные блоки.
  • Неправильный chunking. Слишком крупные чанки размывают точность, слишком мелкие — рвут смысл.
  • Отсутствие метаданных. Без source_url, версии и acl невозможны нормальная отладка, цитирование и контроль доступа.
  • Слепая ставка на векторный поиск. Для кодов, артикулов и точных терминов часто нужен гибридный retrieval.
  • Слишком много контекста. Если складывать в prompt десятки фрагментов, модель начнет путаться и терять главные доказательства.
  • Нет отказа при нехватке данных. Модель будет заполнять пробелы догадками.
  • Оценка только по финальному ответу. Нужно разделять retrieval-ошибку и ошибку генерации.
  • Отсутствие переиндексации. После смены модели эмбеддингов или структуры документа качество может незаметно просесть.
  • Проверка прав доступа после генерации. Это архитектурно небезопасно.

Как проверить результат

Проверяйте RAG в два слоя: сначала находите ли вы правильные фрагменты, потом умеет ли модель корректно отвечать по ним. Иначе вы будете лечить симптомы, а не причину.

Что проверять Как измерять На что смотреть
Полнота retrieval recall@k на размеченном наборе вопросов Правильный фрагмент или документ должен попадать в топ кандидатов
Порядок кандидатов Сравнение выдачи до и после reranking Нужные фрагменты должны подниматься вверх без роста шума
Фактическая точность ответа Ручная проверка на эталонном наборе Нет ли выдуманных дат, версий, параметров и ссылок
Привязка к источнику Проверка цитат и source_url Ссылка должна вести на документ, откуда реально взят тезис
Контроль доступа Тесты на запросы от разных ролей Запрещенные документы не должны участвовать в retrieval и генерации
Свежесть знаний Тест после обновления корпуса Новые версии документов должны попадать в ответы без ручной правки
Задержка Логи p50 и p95 по этапам Где узкое место: поиск, reranking, генерация или сеть

Практически полезный тестовый набор обычно включает:

  • вопросы, где ответ лежит в одном чанке;
  • вопросы, где надо собрать ответ из нескольких источников;
  • запросы с точными терминами, кодами и названиями;
  • провокационные запросы, где правильный ответ — «в корпусе нет данных»;
  • запросы от разных ролей для проверки acl.

Если retrieval стабильно находит правильные фрагменты, а ответ все равно плохой, дорабатывайте prompt, формат контекста, порядок чанков и политику отказа. Если retrieval не находит материал, не тратьте время на косметику генерации.

FAQ

Какой векторный движок выбрать для первого запуска?

Если в компании уже есть PostgreSQL и корпус умеренный, начните с pgvector. Это сокращает число движущихся частей. Если нужен отдельный поисковый сервис с удобной фильтрацией и вы готовы поддерживать еще один компонент, смотрите на Qdrant. Milvus логичен, когда вы заранее строите выделенный поисковый слой под большие коллекции.

Какой размер чанка взять на старте?

Безопасный старт — 300–800 токенов и overlap 10–20%. Но это не правило на все случаи. Для API-справки и FAQ можно идти ниже, для архитектурных документов — выше. Итоговое решение выбирают по recall@k, качеству цитат и числу случаев, где модель теряет контекст.

Нужен ли reranker?

Не всегда. Для компактного, однородного корпуса иногда хватает хорошего retrieval. Но если документы длинные, тематика смешанная, а точный фрагмент часто не на первом месте, reranker дает заметный практический выигрыш, потому что улучшает порядок кандидатов до генерации.

Можно ли обойтись без fine-tuning?

Да. Для большинства прикладных RAG-сценариев сначала доводят retrieval, chunking, метаданные и prompt. Fine-tuning имеет смысл позже, когда вы уже понимаете, что именно не хватает модели: формата ответа, стиля, терминологии или устойчивости на узком домене.

Как обновлять индекс без полного пересчета?

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

Что делать с PDF, таблицами и кодом?

Не смешивать все в один плоский текст без структуры. Для PDF сначала проверьте качество извлечения текста. Таблицы часто лучше сохранять как отдельные логические блоки с заголовками строк и столбцов. Код и конфигурации полезно индексировать по отдельным правилам, потому что для них важны точные совпадения и имена сущностей.

Как уменьшить галлюцинации?

Три работающих меры: улучшить retrieval, ограничить ответ только переданным контекстом и требовать цитаты. Плюс обязательный отказ от ответа при нехватке доказательств. Если модель должна «догадаться», вы уже вышли за границы корректного RAG-сценария.

Читайте также

LINKS