RAG с нуля: как построить пайплайн поиска и генерации
Большая часть данных в мире приватная. Языковые модели учатся на публичном интернете, и про внутренние документы вашей компании они не знают ничего. Ещё недавно это было непреодолимо: контекстное окно моделей упиралось в 4-8 тысяч токенов, примерно дюжина страниц текста. Сейчас фронтирные модели держат до миллиона токенов, то есть тысячи страниц. Но как выбрать из огромной базы знаний именно те документы, которые нужны для ответа? Этим занимается RAG, retrieval augmented generation.
Полный пайплайн RAG разобрал Лэнс Мартин, инженер LangChain, в курсе RAG From Scratch на канале freeCodeCamp. Два с половиной часа практики, 1,7 миллиона просмотров, путь от простейшего прототипа до активного RAG, который проверяет сам себя.
Что такое RAG
RAG (retrieval augmented generation) это подход, при котором модель сначала ищет релевантные фрагменты в базе знаний, а потом генерирует ответ на их основе, вместо того чтобы отвечать по памяти. Пайплайн состоит из трёх шагов: индексация документов, поиск по запросу и генерация ответа с опорой на найденное. Модель остаётся универсальным процессором текста, а знания приходят из внешнего источника, который можно обновлять хоть каждый день, без переобучения.
Индексация: как документы превращаются в векторы
Индексация начинается с нарезки. Каждый документ режут на чанки, куски по несколько сотен токенов, затем каждый кусок прогоняют через модель эмбеддингов и получают вектор, набор чисел, кодирующий смысл текста. Векторы складывают в индекс, чаще всего в векторную базу данных.
Почему по векторам вообще можно искать? Эмбеддинг проецирует текст в многомерное пространство, где положение точки определяется содержанием. Если представить, что у эмбеддинга всего три измерения, каждый фрагмент окажется где-то в этом 3D-пространстве, и фрагменты про одно и то же соберутся рядом. Чтобы найти ответ, достаточно отыскать ближайшие точки к вектору вопроса. На этом простом наблюдении стоит большинство современных систем поиска.
В курсе это демонстрируют вживую: вопрос «what is task decomposition», параметр k задаёт число ближайших соседей, которые забираем из индекса. Ставим k=1, получаем ровно один фрагмент, и он действительно посвящён декомпозиции задач.
Тут же прячется главная слабость базового пайплайна. Размер чанка почти всегда выбирают на глаз, а сам вопрос может быть сформулирован так, что в пространстве эмбеддингов он окажется далеко от нужных документов. Обе проблемы решаются на следующих уровнях пайплайна.
Поиск и генерация: базовый RAG в работе
В момент запроса вопрос пользователя проходит тот же путь, что и документы при индексации: его эмбеддят, индекс выполняет similarity search, и система забирает top-k ближайших фрагментов. Дальше начинается генерация. Найденные куски текста вместе с исходным вопросом уходят в промпт, и языковая модель собирает ответ, опираясь на них, а не на память. Это и есть augmented generation, генерация с опорой на извлечённые данные.
Базовый пайплайн из трёх шагов работает на демо, но в реальных задачах начинает ошибаться. Дальше в курсе разбирают четыре группы техник, которые закрывают конкретные слабые места.
Перевод запроса: четыре способа починить вопрос
Самый частый источник ошибок находится на входе. Плохо сформулированный запрос после эмбеддинга оказывается в стороне от релевантных документов, и модель получает неверный контекст. Query translation переписывает вопрос до поиска. В курсе разбирают четыре приёма.
Multi-query берёт исходный вопрос и генерирует несколько его версий, сформулированных с разных сторон. Каждая версия ищет в индексе независимо, а результаты объединяются. Логика простая: если исходная формулировка неудачна, одна из переформулировок попадёт ближе к цели.
RAG-Fusion устроен почти так же, но добавляет финальное ранжирование через reciprocal rank fusion. Документы из разных списков получают ранги, и те, что всплыли сразу в нескольких выдачах, поднимаются наверх. Вход и поиск идентичны multi-query, отличается только способ слияния результатов.
Decomposition разбивает сложный вопрос на подвопросы, каждый решается отдельно, после чего ответы собираются в общий. Классическая работа этого направления, least-to-most от Google, показывает, что такой порядок помогает модели решать задачи, которые целиком ей не по силам.
Step-back действует в обратную сторону: сначала вопрос поднимают на уровень абстракции выше, получают общий ответ, и только потом возвращаются к исходной формулировке. Приём помогает, когда за деталями не видно контекста.
Маршрутизация: как вопрос находит свой источник
Когда база знаний не одна, а несколько, векторный индекс документации, реляционная база, граф знаний, появляется задача: понять, куда отправлять запрос. Роутинг решает именно её.
Logical routing даёт модели описания всех доступных источников и просит рассудить, какой подходит. На практике это оформляют как классификацию через function calling: схема с тремя вариантами (документация Python, JavaScript или Go) привязывается к модели, и она обязана вернуть строго один из них. Получается не свободный текст, а предсказуемый структурированный ответ.
Semantic routing работает без рассуждений: вопрос эмбеддят и сравнивают с эмбеддингами промптов, закреплённых за каждым маршрутом. Побеждает ближайший промпт. Дешевле и быстрее логического, но менее гибко.
Конструирование запросов: от языка к DSL
Не все источники понимают векторную близость. Реляционная база ждёт SQL, графовая база Cypher, а векторный индекс с метаданными ждёт структурированный фильтр. Query construction переводит естественный язык в нужный DSL, формат запроса для конкретного источника.
В курсе подробно разбирают фильтры по метаданным. Запрос вида «найди видео про chat langchain, опубликованные после 2024 года» превращается в структурированное условие. Схема метаданных индекса (например, поля topic и date) передаётся модели, и она через function calling возвращает объект с фильтрами, который векторная база применяет поверх поиска по близости. Для реляционных баз тот же приём называется text-to-SQL, для графовых text-to-cypher, и там цена ошибки выше: неточный запрос вернёт неправильные данные, а не приблизительно похожие.
Продвинутая индексация: multi-representation и RAPTOR
Следующий блок курса посвящён тому, как улучшить саму базу знаний. Первая техника, multi-representation indexing, пришла из статьи про proposition indexing. Идея: развести документ и единицу поиска. Обычно чанк ищется и возвращается в одном и том же виде. Здесь же каждый фрагмент дистиллируется языковой моделью в короткое чёткое утверждение, которое лучше подходит для поиска. В векторном индексе хранятся эти сжатые версии, а полный документ лежит в отдельном хранилище и подтягивается по идентификатору после того, как нашёлся релевантный фрагмент. Получается двухуровневая схема: ищем по смыслу, отдаём модели полный контекст. Для длинных контекстов это особенно удобно.
RAPTOR закрывает другую слабость. Часть вопросов требует деталей из одного абзаца, а часть требует обобщения по всему корпусу, и плоский индекс одинаково плохо отвечает на крайние случаи. RAPTOR строит иерархию: фрагменты кластеризуются, для кластеров генерируются саммари, саммари объединяются в кластеры следующего уровня, и так до корня. Поиск проходит по всем уровням сразу, поэтому находится и мелкая деталь, и общий вывод.
Активный RAG: система, которая проверяет себя
Последний крупный блок курса называется flow engineering, или активный RAG. Идея: встроить проверки прямо в пайплайн. После поиска документы оцениваются на релевантность вопросу. После генерации ответ проверяется на верность найденным документам, то есть на галлюцинации. Если проверка провалилась, система возвращается на шаг назад: переформулирует вопрос, повторяет поиск или генерирует ответ заново.
Так устроены исследовательские подходы Corrective RAG и Self-RAG. В курсе их реализуют через стейт-машины на LangGraph: каждый узел графа это отдельный шаг (поиск, оценка, перегенерация), переходы задаются явно, и вся логика остаётся читаемой. Там же ссылка на блог Хамела Хусейна об оценке RAG: он предлагает встраивать проверки прямо в процесс инференса, чтобы система автоматически повторяла шаги, которые не прошли проверку.
RAG не умер: что меняют длинные контексты
Финал курса посвящён вопросу, который в 2026 году звучит ещё острее, чем на момент записи: нужен ли RAG, если контекстное окно выросло до миллиона токенов? Ответ Лэнса Мартина: RAG не умер, но изменится. Как в известной шутке про джаз, он просто будет звучать иначе.
Что теряет смысл: агрессивный чанкинг. Если модель спокойно держит целые документы, нарезка на куски, размер которых выбирался почти произвольно, перестаёт быть обязательной. Выгоднее отдавать документ целиком.
Что остаётся: анализ запроса, маршрутизация и конструирование запросов. Вопрос «куда направить этот запрос» никуда не уходит, и никто не станет скармливать модели всю SQL-базу. Остаются и техники вроде multi-representation indexing и RAPTOR, они хорошо ложатся на длинный контекст. А главное, растёт роль рассуждений до и после поиска: пайплайн превращается в цикл, где система оценивает собственные шаги.
О выборе между классическим RAG и длинным контекстом у нас есть отдельный разбор: RAG vs длинный контекст. А если хочется понять, как RAG встраивается в общую картину стека, начните с материала AI-стек с нуля.
Частые вопросы
Нужен ли RAG, если у модели контекст на миллион токенов?
Для небольшой базы знаний можно обойтись длинным контекстом. Но маршрутизация между источниками, точность поиска и стоимость запроса никуда не уходят: скормить модели всю базу дороже и медленнее, чем найти десять нужных документов. На практике выигрывает гибрид: длинный контекст для генерации, поиск для отбора.
С чего начать, если я никогда не строил RAG?
С базового пайплайна из трёх шагов: нарезать документы, построить индекс эмбеддингов, добавить генерацию с опорой на найденные фрагменты. Этого хватит для первого рабочего прототипа. Усложнять стоит по мере появления проблем: плохой поиск лечится переводом запроса, разросшаяся база маршрутизацией, галлюцинации проверками в активном RAG.
Почему простой RAG даёт неточные ответы?
Чаще всего виноват не поиск, а сам вопрос. Криво сформулированный запрос в пространстве эмбеддингов оказывается далеко от нужных документов, и модель получает неверный контекст. Multi-query, decomposition и step-back переписывают вопрос до поиска. Если контекст найден верно, а ответ всё равно ошибается, включайте проверку на верность документам.
Итог
Курс Лэнса Мартина показывает RAG как конструктор: базовый пайплайн из трёх шагов, поверх него перевод запроса, маршрутизация, конструирование запросов, продвинутая индексация и активные проверки. Начинать стоит с простого и добавлять техники под конкретную боль, а не все сразу.
Главный сдвиг последних двух лет в том, что RAG превращается из конвейера «поиск, ответ» в цикл, где система рассуждает до и после поиска и проверяет собственные шаги. Именно эта версия RAG, по мнению автора курса, будет развиваться дальше.
Если хотите пройти весь путь руками, посмотрите курс на freeCodeCamp. Там все техники разобраны в коде: от первого индекса до стейт-машины Self-RAG.