Индексировал. Запустил. Задал вопрос. Получил странное. Сегодня — про то, как именно работает RAG-pipeline на запросе, и почему базовая реализация почти всегда сначала разочаровывает.
Pipeline RAG-запроса — это пять шагов: получить запрос → эмбеддить его → найти top-N похожих векторов → достать тексты этих чанков → собрать промпт с ними и спросить LLM. На бумаге просто. На практике на каждом шаге что-то ломается: семантический поиск не находит, что нужно; находит, но не то; находит правильное, но модель его не использует. Сегодня — типичные провалы и куда дальше копать.
В Дне 21 мы видели общую схему. Теперь детально, что происходит на каждом шаге:
Эмбеддить запрос той же моделью, что индексировала базу. Иначе векторы из разных пространств — поиск не работает.
На старте 3-5. Меньше — рискуешь не найти. Больше — много шума в контексте. Подбирается под задачу.
Чанки лучше класть с метаданными (источник). Порядок — обычно по score, но иногда лучше по дате/иерархии.
В system prompt явно: «опирайся ТОЛЬКО на предоставленный контекст, если не нашёл — скажи». Об этом — День 25.
Векторная БД на шаге 3 возвращает score для каждого найденного чанка — число от 0 до 1 (или от -1 до 1, зависит от метрики). Это мера близости вектора чанка к вектору запроса.
Полезная практика — порог отсечения. Если score лучшего результата ниже, например, 0.7 — считать, что «ничего не нашлось». Лучше честно ответить «не нашёл», чем подсунуть нерелевантное и получить уверенную галлюцинацию.
Найденные чанки нужно правильно подать модели. Это не просто «склеить тексты» — это тщательно собранный промпт, в котором модель явно знает, что делать с контекстом.
Типичная структура промпта в RAG-системе:
Как именно оформить найденные чанки в промпте — отдельная небольшая инженерия. Несколько подходов:
<document source="...">...</document>. Anthropic-стиль, хорошо парсится моделью, удобно для извлечения цитат.Все три работают. Главное — стабильность: всегда одинаковая структура, чтобы модель не путалась.
Запустил pipeline на своих данных, проверил 20 запросов — половина работает, половина нет. Это нормально. Разберём топ провалов базового RAG и куда смотреть для починки:
Пользователь спросил «как сбросить пароль», в базе есть страница «восстановление доступа к аккаунту». По смыслу — то же, но эмбеддинг плохо это уловил.
Куда смотреть:
Пользователь спросил «лимиты на плане Pro», поиск вернул чанки про разные планы — Pro упомянут, но не в правильном контексте.
Куда смотреть:
Чанк с правильным ответом — в top-3 контекста, но модель отвечает что-то общее или «не нашёл». Часто — потому что чанк лежит «в середине» из 5-7 чанков, lost-in-the-middle.
Куда смотреть:
Запрос «какая ставка налога», в твоей базе — 13%, но модель отвечает «обычно 13-15% в зависимости от региона». Размывает свежий факт собственными знаниями.
Куда смотреть:
«Когда у нас next big event?» — в одном чанке есть «Q2 launch», в другом — «June», в третьем — «next major event». Каждый по отдельности слабо матчится на запрос. Все вместе — точный ответ.
Куда смотреть:
Базовый RAG работает на ~60-70% запросов. Чтобы дойти до 90%+, нужны дополнительные слои: реранкинг, фильтры, специальные техники. Об этом — Дни 24 и 25.
Большое N — больше шансов найти ответ, но больше шума в контексте. Маленькое — чисто, но рискуешь пропустить.
Прагматичный подход — двухэтапная стратегия:
Это и есть реранкинг, которому посвящён весь День 24. Базовое решение — N=5 без реранкинга — нормально для начала, но обычно требует улучшения.
Категорически — да. На каждый запрос логировать:
Это — твой единственный способ понять, где система ломается. Без логов RAG — чёрный ящик. С логами через неделю работы у тебя есть статистика: «на 30% запросов score <0.6 — улучшаем эмбеддинги», «на 20% — пользователи дизлайкают — смотрим, какие именно».
«В блоге OpenAI пишут, что top-5 даёт 90% accuracy». На их бенчмарке. На твоих данных — другая база, другие запросы, другие критерии «правильности». Может быть 50%, может 95%.
Привычка: каждое решение проверяй на 20-50 своих типичных запросов. RAG-инжиниринг — это эмпирическая работа с твоей конкретной базой, не следование чужим рекомендациям.
«Сразу делаю HyDE + multi-query + cross-encoder reranker». Получается сложная система, в которой непонятно, что улучшает, а что портит. Дебажить — кошмар.
Правильный порядок: сначала базовый RAG (как в этом уроке) → видишь, какие именно провалы → добавляешь конкретное улучшение под конкретный провал. Так у тебя есть видимый прогресс и понимание, что работает.
Делаешь RAG, проверяешь на 5 запросах, которые сам придумал. Запускаешь в прод — половина пользовательских запросов не работает.
Привычка: собрать 20-50 реальных запросов (из логов, от первых пользователей, из FAQ команды) с правильными ответами, и прогонять на них каждое изменение RAG. Это твой бенчмарк, не отвлекайся на чужие.
Запросы вида «привет», «спасибо», «помоги мне» — это не RAG-запросы. На них поиск возвращает случайный мусор (потому что «привет» эмбеддингово близок к чему попало), модель пытается этим мусором ответить — получается странно.
Решение: перед RAG — классификатор (на маленькой LLM или правилами): это «запрос к базе» или «общение»? Если общение — обходи RAG, отвечай прямо.
Загрузи в один из этих сервисов свой PDF или большой документ (15+ страниц). Задай 5-7 вопросов разного типа: точный («какая ставка X?»), широкий («о чём документ?»), сложный («сравни главы 2 и 4»), отсутствующий (про что-то, чего в документе нет). Понаблюдай: на какие отвечает хорошо? Где видно, что RAG нашёл правильный кусок? Где «домыслил»? Часто можно даже увидеть, какие куски документа достаются (есть подсветка). Это даёт живое ощущение слабых и сильных сторон RAG.
Возьми кейс из Дня 21 (свой потенциальный RAG-агент). Напиши system prompt: какая роль, как именно работать с контекстом, что делать если ответа нет, как цитировать. 200-400 токенов нормально. Этот промпт — основа будущей системы, и обычно его шлифуют неделями.
Возьми тот же кейс. Составь 20 запросов, которые реально могут задать пользователи. Для каждого напиши, какой ответ ты считаешь правильным (одна строка, плюс ссылка на «правильный документ» из базы). Это твой будущий бенчмарк. Без него — нельзя сравнивать варианты RAG. С ним — можно прогнать улучшение и увидеть, стало лучше или хуже.