Что такое RAG и как создать поиск по своим документам
Что такое RAG и как собрать систему поиска по своим документам
Языковая модель может уверенно рассуждать о программировании, объяснять архитектуру приложений и писать вполне рабочий код. Но стоит спросить её о внутренней инструкции вашей компании, свежем каталоге продукции или закрытой базе знаний - и уверенность никуда не исчезает, хотя фактов у модели уже нет.
В результате она либо честно признается, что не знает ответа, либо начнёт достраивать недостающие детали. Второй вариант выглядит убедительно, но для рабочего продукта это опасная история.
Здесь и появляется RAG - Retrieval-Augmented Generation. По-русски этот подход обычно называют генерацией с дополненным поиском. Перед ответом система находит подходящие данные во внешнем источнике, добавляет их в контекст запроса и только после этого обращается к языковой модели.
Проще говоря, модель сначала получает шпаргалку, а уже потом отвечает пользователю.

Зачем нужен RAG, если модель и так многое знает?
Представим чат-бота службы поддержки интернет-магазина. Он должен рассказывать о доставке, возвратах, гарантии и наличии товаров. Общие правила модель, скорее всего, знает. Но она не знает, какие условия действуют именно в этом магазине и какие изменения появились вчера.
Можно попытаться записать всю информацию в системный промт. Для пары страниц такой подход ещё работает. Когда документов становится несколько сотен, промт разрастается, запросы дорожают, а нужные сведения теряются среди лишнего текста.
Можно дообучить модель. Звучит солидно, но обновлять её после каждой правки документации неудобно. Да и дообучение не превращает нейросеть в надёжную базу фактов.
RAG идёт другим путём. Документы хранятся отдельно, а система извлекает из них только фрагменты, связанные с текущим вопросом. Изменилась инструкция - обновили документ или индекс. Переобучать модель не пришлось.
Получается небольшое противоречие: RAG делает модель умнее, хотя сама модель не меняется. Секрет в том, что меняется контекст, который она получает перед генерацией ответа.
Из каких частей состоит RAG-система
В базовом варианте нужны источник данных, модуль обработки документов, модель embeddings, поисковый индекс и языковая модель.
Источником может быть почти всё: HTML-страницы, Markdown-файлы, PDF-документы, база знаний, тикеты поддержки, таблицы, записи из CRM или данные из API. На первом этапе лучше взять один понятный тип документов. Иначе отладка быстро превратится в поиск ошибок сразу в пяти разных местах.
Документы разбиваются на небольшие части, которые обычно называют chunks. Затем каждый фрагмент преобразуется в embedding - массив чисел, отражающий смысл текста. Эти массивы сохраняются в векторном хранилище вместе с исходным содержимым и метаданными.
Когда приходит вопрос, он тоже преобразуется в embedding. Поисковый механизм сравнивает его с векторами документов и возвращает ближайшие по смыслу фрагменты.
Дальше найденный контекст добавляется к промту. Модель получает не просто вопрос «Как оформить возврат?», а вопрос вместе с выдержками из реальных правил магазина.
Шаг 1. Определите задачу, а не начинайте с базы данных
Честно говоря, многие RAG-проекты начинаются с обсуждения моделей, фреймворков и векторных баз. Это интересная часть, поэтому к ней хочется перейти сразу. Но начинать стоит с вопросов пользователей.
Запишите хотя бы 20-30 реальных запросов, на которые должна отвечать система. Для каждого запроса укажите правильный ответ и документ, где лежит нужная информация.
Например, для внутреннего помощника IT-отдела набор может включать вопросы о выдаче доступов, настройке VPN, восстановлении пароля, правилах работы с репозиториями и порядке оформления заявки.
Такой список станет первым тестовым набором. Без него вы не сможете понять, система действительно работает или просто периодически выдаёт правдоподобный текст.
Шаг 2. Подготовьте документы
RAG плохо воспринимает беспорядок в данных. Если в папке лежат три версии инструкции, а две из них устарели, поисковый механизм может вернуть любую. Языковая модель аккуратно объединит противоречивые фрагменты и создаст ответ, которого никогда не существовало в документации.
Перед индексацией удалите дубликаты, архивные версии, технические колонтитулы и лишние элементы навигации. Сохраните заголовки разделов, номера пунктов и связи между текстом и таблицами.
Особое внимание потребуется PDF-файлам. Визуально документ может выглядеть нормально, но при извлечении текста строки перемешиваются, таблицы распадаются, а заголовки оказываются в конце страницы. Сканированные документы сначала придётся распознать.
А знаете что? На практике очистка и нормализация данных часто занимают больше времени, чем написание самого RAG-конвейера. Это нормально. Качество ответа начинается не с нейросети, а с исходного текста.

Шаг 3. Разбейте текст на смысловые фрагменты
Документ редко передаётся модели целиком. Его делят на chunks подходящего размера.
Слишком большой фрагмент приносит много лишнего текста. Поиск может найти нужный раздел, но вместе с ним в контекст попадут соседние темы. Слишком маленький фрагмент теряет смысл: ответ находится в одном абзаце, условие - в предыдущем, а исключение - в следующем.
Для начала можно делить текст по заголовкам и абзацам, сохраняя небольшой overlap между соседними частями. Но фиксированное количество символов - лишь стартовая точка. Техническую документацию лучше делить по разделам, API-справочник - по методам, а базу вопросов - по отдельным карточкам.
Каждый chunk стоит снабдить метаданными: названием документа, разделом, датой версии, языком, категорией и правами доступа. Позже эти поля помогут фильтровать результаты поиска и показывать источники.
Шаг 4. Создайте embeddings и поисковый индекс
Embedding превращает текст в числовое представление. Фразы с близким смыслом получают близкие векторы, даже если в них мало одинаковых слов.
Пользователь может спросить: «Что делать, если товар сломался?». В документе при этом написано: «Порядок возврата продукции ненадлежащего качества». Обычный поиск по словам легко пропустит такой фрагмент. Векторный поиск заметит смысловую связь.
Для хранения векторов подойдут специализированные базы и расширения обычных СУБД. Конкретный инструмент не так важен на старте. Для прототипа достаточно хранилища, которое умеет сохранять embedding, исходный текст и метаданные, а затем выполнять поиск ближайших векторов.
Важно зафиксировать модель embeddings. Если проиндексировать документы одной моделью, а запросы преобразовывать другой, сравнение потеряет смысл. При смене модели весь индекс обычно создают заново.
Шаг 5. Найдите релевантные фрагменты
На входе находится вопрос пользователя. Система создаёт для него embedding и запрашивает несколько ближайших chunks.
Возвращать один фрагмент рискованно - важное уточнение может лежать рядом. Передавать двадцать тоже не стоит: контекст наполнится шумом, запрос станет дороже, а ответ - менее точным.
Начните с небольшого числа результатов и проверяйте их на тестовых вопросах. Важно оценивать поиск отдельно от генерации. Если правильный фрагмент не попал в результаты, языковая модель уже не спасёт ситуацию.
Для кодов изделий, номеров договоров, артикулов и точных терминов одного векторного поиска мало. Здесь полезен гибридный подход: смысловой поиск работает вместе с полнотекстовым. Один механизм понимает формулировку, второй цепляется за точное значение.

Шаг 6. Добавьте reranking
Первичный поиск быстро находит группу вероятных кандидатов, но порядок результатов не всегда удачен. Reranker получает вопрос и найденные фрагменты, после чего повторно оценивает их релевантность.
Это похоже на отбор резюме. Первый фильтр убирает явно неподходящие варианты, а второй внимательнее читает оставшиеся.
Reranking добавляет ещё один запрос к модели и немного увеличивает задержку. Поэтому для небольшого прототипа он не обязателен. Подключать его стоит тогда, когда нужные документы попадают в выдачу, но часто оказываются ниже менее полезных фрагментов.
Шаг 7. Соберите промт без магии
На этапе генерации модель получает инструкцию, найденный контекст и вопрос пользователя.
Инструкция должна быть прямой: отвечать только на основании предоставленных материалов, не дополнять отсутствующие факты, сообщать о нехватке данных и указывать источники. Чем критичнее предметная область, тем строже должны быть эти правила.
Полезно явно отделять документы друг от друга и передавать их названия. Тогда модель сможет сослаться на конкретный раздел, а пользователь - проверить ответ.
Не просите модель «всегда давать полезный ответ». Такая формулировка подталкивает её заполнять пробелы догадками. Иногда лучший результат звучит так: «В предоставленных документах нет этой информации».
Шаг 8. Показывайте источники
Ответ без источника трудно проверить. Это особенно заметно во внутренних системах, где сотрудники знают документацию и быстро замечают неточности.
Сохраняйте вместе с каждым фрагментом название файла, номер страницы, раздел и ссылку на оригинал. После генерации показывайте пользователю, какие материалы участвовали в ответе.
Источники повышают доверие, но дело не только в доверии. Они сильно упрощают отладку. Когда система ошибается, можно быстро понять, проблема возникла на этапе поиска или модель неверно интерпретировала найденный текст.
Шаг 9. Проверьте качество на реальных вопросах
Демонстрация из трёх удачных запросов ничего не доказывает. Нужен набор вопросов с ожидаемыми ответами и известными источниками.
Для каждого теста проверьте три вещи. Нашёлся ли нужный документ? Присутствуют ли в ответе требуемые факты? Добавила ли модель сведения, которых не было в контексте?
Ошибки удобно разделить по этапам. Если нужный chunk не найден, меняйте подготовку документов, разбиение, embeddings или параметры поиска. Если chunk найден, но ответ неверен, проверяйте промт и модель генерации.
Такое разделение экономит массу времени. Иначе команда начинает менять модель, хотя проблема на самом деле скрыта в неудачно разобранной PDF-таблице.

Где RAG чаще всего ломается
Первая типичная проблема - плохие исходные данные. Устаревшие документы, дубли и разорванные таблицы неизбежно попадают в ответы.
Вторая - неудачное разбиение. Система находит половину правила без условия или исключения. Текст выглядит верным, но смысл уже изменился.
Третья - отсутствие точного поиска. Векторная модель хорошо понимает общую тему, но может спутать похожие артикулы, версии продукта или номера регламентов.
Четвёртая - слишком много контекста. Разработчик пытается подстраховаться и передаёт модели десятки фрагментов. В итоге важный факт тонет в соседних разделах.
Пятая - отсутствие контроля доступа. Если поиск выполняется по общей базе, сотрудник может получить фрагмент документа, который не должен видеть. Права нужно проверять до передачи текста языковой модели, а не после генерации ответа.
Когда RAG действительно оправдан
RAG подходит, когда ответы должны опираться на часто обновляемые, специализированные или закрытые данные. Это корпоративные базы знаний, техническая документация, поддержка клиентов, каталоги продукции, внутренние регламенты и справочники.
Если данных мало и они помещаются в короткий системный промт, отдельный поисковый контур может оказаться лишним. Не всякому чат-боту нужна векторная база.
Не стоит ждать от RAG математической точности. Он снижает число выдуманных фактов, но не исключает их полностью. Для финансовых, юридических, медицинских и технически ответственных процессов необходимы проверка источников, ограничения сценариев и участие специалиста.
Как собрать первый прототип без лишней тяжести
Возьмите небольшую коллекцию проверенных документов и несколько десятков реальных вопросов. Очистите текст, разделите его на смысловые части и сохраните метаданные. Затем создайте embeddings, добавьте векторный поиск и передавайте найденные фрагменты модели.
После этого не спешите подключать агентов, графы, цепочки моделей и автоматическую генерацию запросов. Сначала добейтесь стабильного поиска по простым вопросам.
Рабочий MVP должен уметь принять вопрос, найти источник, сформировать ответ и показать ссылку на документ. Этого уже достаточно, с чем сравнивать следующие изменения.
Итог
RAG - это не новая языковая модель и не волшебная кнопка точности. Это архитектурный подход, который соединяет поиск по внешним данным с генерацией текста.
Сначала система находит подходящие материалы. Затем добавляет их в контекст. Только после этого модель формирует ответ.
Главная трудность здесь скрыта не в API и не в выборе базы данных. Она находится в документах: их качестве, структуре, актуальности и правилах доступа. Если эта основа подготовлена хорошо, даже простой RAG-прототип может приносить пользу. Если нет - более мощная модель лишь убедительнее перескажет беспорядок.