КЛАСТЕР 05 · RAG ЗАПРОС ~18 МИНУТ
День 23 · из 35

Первый
RAG-запрос

Индексировал. Запустил. Задал вопрос. Получил странное. Сегодня — про то, как именно работает RAG-pipeline на запросе, и почему базовая реализация почти всегда сначала разочаровывает.

Суть урока

Pipeline RAG-запроса — это пять шагов: получить запрос → эмбеддить его → найти top-N похожих векторов → достать тексты этих чанков → собрать промпт с ними и спросить LLM. На бумаге просто. На практике на каждом шаге что-то ломается: семантический поиск не находит, что нужно; находит, но не то; находит правильное, но модель его не использует. Сегодня — типичные провалы и куда дальше копать.

Pipeline шаг за шагом

В Дне 21 мы видели общую схему. Теперь детально, что происходит на каждом шаге:

RAG-запрос · детальный pipeline
1. Запрос пользователя "как настроить SSO?" сырой текст, как есть
эмбеддим запрос
2. Вектор запроса embedding-model(query) → [0.234, -0.891, ...] вектор той же модели, что индексировала
ищем ближайшие в БД
3. Top-N результатов обычно N = 3-10 чанки с их score и метаданными
извлекаем тексты
4. Сборка контекста промпт с найденными чанками system + retrieved + user
отправляем в LLM
5. Ответ модели опираясь на чанки обычно с цитатами/ссылками

Что выбирать на каждом шаге

Шаг 2

Та же модель

Эмбеддить запрос той же моделью, что индексировала базу. Иначе векторы из разных пространств — поиск не работает.

Шаг 3

Сколько top-N

На старте 3-5. Меньше — рискуешь не найти. Больше — много шума в контексте. Подбирается под задачу.

Шаг 4

Порядок и формат

Чанки лучше класть с метаданными (источник). Порядок — обычно по score, но иногда лучше по дате/иерархии.

Шаг 5

Инструкции модели

В system prompt явно: «опирайся ТОЛЬКО на предоставленный контекст, если не нашёл — скажи». Об этом — День 25.

Метрика score — что это

Векторная БД на шаге 3 возвращает score для каждого найденного чанка — число от 0 до 1 (или от -1 до 1, зависит от метрики). Это мера близости вектора чанка к вектору запроса.

  • Высокий score (0.85+): чанк действительно похож на запрос по смыслу. Скорее всего, релевантен.
  • Средний (0.65-0.85): что-то связанное, но может быть не то.
  • Низкий (<0.65): ложное срабатывание. БД нашла «лучшее, что у неё есть», но это не подходит.

Полезная практика — порог отсечения. Если score лучшего результата ниже, например, 0.7 — считать, что «ничего не нашлось». Лучше честно ответить «не нашёл», чем подсунуть нерелевантное и получить уверенную галлюцинацию.

Сборка промпта с контекстом

Найденные чанки нужно правильно подать модели. Это не просто «склеить тексты» — это тщательно собранный промпт, в котором модель явно знает, что делать с контекстом.

Базовый шаблон

Типичная структура промпта в RAG-системе:

  1. System prompt — роль и инструкции: «ты ассистент компании X, отвечаешь на вопросы пользователей, опираясь на предоставленный контекст из документации»
  2. Контекст — найденные чанки с метаданными. Обычно в виде «Документ 1 (источник: docs/sso.md): [текст]. Документ 2 (источник: ...): [текст]»
  3. Инструкции по работе с контекстом — что делать, если в контексте есть ответ, что — если нет
  4. Вопрос пользователя — собственно запрос

Главные принципы промпта

  • Явная инструкция «опирайся только на контекст». Иначе модель будет смешивать знание из обучения с найденным. Это плохо, потому что её обучение могло устареть или не знать твоих специфик.
  • Явная инструкция «если не нашёл — скажи». Без этого модель будет «домысливать», если контекст недостаточен. Это ровно та галлюцинация, ради борьбы с которой ты строил RAG.
  • Цитирование источников. Просить модель указывать, из какого документа взят каждый факт. «Согласно [источник: sso.md]...».
  • Чёткое разделение. Контекст и вопрос должны быть визуально и семантически разделены — модель должна понимать, где её знания, где данные.
i
Главный практический момент
Промпт в RAG — это программирование поведения модели с найденными данными. Чем точнее инструкции — тем меньше галлюцинаций, тем чаще модель честно говорит «не нашёл», вместо того чтобы выдумывать.

Структурирование контекста

Как именно оформить найденные чанки в промпте — отдельная небольшая инженерия. Несколько подходов:

  • Нумерованные блоки: «Документ 1: ... Документ 2: ...». Просто, понятно, модель может ссылаться по номеру.
  • XML-теги: <document source="...">...</document>. Anthropic-стиль, хорошо парсится моделью, удобно для извлечения цитат.
  • Markdown с заголовками: «## Источник: ... [текст]». Читаемо, естественно для модели.

Все три работают. Главное — стабильность: всегда одинаковая структура, чтобы модель не путалась.

Типичные провалы базового RAG

Запустил pipeline на своих данных, проверил 20 запросов — половина работает, половина нет. Это нормально. Разберём топ провалов базового RAG и куда смотреть для починки:

Провал 01 · ничего не нашлось

Запрос есть, в базе есть ответ, но поиск его не вернул

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

user: «как сбросить пароль?»
top-1: «инструкция по настройке SMTP» (не то)

Куда смотреть:

  • Качество эмбеддинг-модели на твоём языке (День 22, разбор моделей)
  • Размер чанков — может, ответ «размылся» в большом чанке
  • Гибридный поиск: эмбеддинги + keyword (BM25). День 24.
Быстрая проверка Возьми текст из «правильного» чанка и сравни его эмбеддинг с эмбеддингом запроса. Если score <0.6 — проблема в модели или чанкинге.
Провал 02 · нашлось, но не то

Top-N содержит похожие, но нерелевантные чанки

Пользователь спросил «лимиты на плане Pro», поиск вернул чанки про разные планы — Pro упомянут, но не в правильном контексте.

user: «какие лимиты на плане Pro?»
top-1: общее описание плана Pro (без лимитов)
top-2: лимиты на плане Free
top-3: список всех планов

Куда смотреть:

  • Реранкинг — второй проход более умной моделью по топ-N результатов. День 24.
  • Фильтры по метаданным — «только разделы про Pro»
  • Переформулирование запроса перед поиском (query rewriting)
Провал 03 · нашли правильное, но ответ плохой

В контексте есть точный ответ, но модель его «не видит»

Чанк с правильным ответом — в top-3 контекста, но модель отвечает что-то общее или «не нашёл». Часто — потому что чанк лежит «в середине» из 5-7 чанков, lost-in-the-middle.

Куда смотреть:

  • Уменьшить N — оставить только лучший чанк
  • Переупорядочить — самые релевантные в начало и конец промпта (не в середину)
  • Усилить инструкцию: «опирайся СТРОГО на предоставленные документы»
Провал 04 · нашли правильное, модель проигнорировала

В контексте есть ответ, модель отвечает из своих общих знаний

Запрос «какая ставка налога», в твоей базе — 13%, но модель отвечает «обычно 13-15% в зависимости от региона». Размывает свежий факт собственными знаниями.

Куда смотреть:

  • Усилить промпт: «отвечай ТОЛЬКО на основе контекста, не используй внешние знания»
  • Анти-галлюцинационные приёмы — День 25
  • Цитирование с обязательным указанием источника каждого факта
Провал 05 · «помню, я где-то это видел»

Запрос про что-то, что модели нужно «соединить» из нескольких документов

«Когда у нас next big event?» — в одном чанке есть «Q2 launch», в другом — «June», в третьем — «next major event». Каждый по отдельности слабо матчится на запрос. Все вместе — точный ответ.

Куда смотреть:

  • Увеличить N (но осторожно — будет шумнее)
  • Multi-query retrieval: задать несколько похожих запросов и объединить результаты
  • HyDE — генерация гипотетического ответа моделью, эмбеддинг этого ответа, поиск по нему. День 24.

Базовый RAG работает на ~60-70% запросов. Чтобы дойти до 90%+, нужны дополнительные слои: реранкинг, фильтры, специальные техники. Об этом — Дни 24 и 25.

Решения AI-инженера

Развилка 1. Сколько top-N доставать

Большое N — больше шансов найти ответ, но больше шума в контексте. Маленькое — чисто, но рискуешь пропустить.

Прагматичный подход — двухэтапная стратегия:

  1. На первом этапе из векторной БД достаём побольше (N=20-30).
  2. На втором — более умная модель (cross-encoder, или сам LLM) отбирает из этих 20-30 лучшие 3-5.
  3. Эти 3-5 идут в финальный промпт.

Это и есть реранкинг, которому посвящён весь День 24. Базовое решение — N=5 без реранкинга — нормально для начала, но обычно требует улучшения.

Развилка 2. Логировать ли результаты поиска

Категорически — да. На каждый запрос логировать:

  • Сам запрос пользователя
  • Топ-N найденных чанков со score
  • Что в итоге вернула LLM
  • Дал ли пользователь thumbs-up / thumbs-down

Это — твой единственный способ понять, где система ломается. Без логов 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, отвечай прямо.

Практика

Эксперимент 01 · Раскадровать RAG-pipeline в существующем продукте

Поработай с Notion AI или ChatGPT с custom GPT по документам

Загрузи в один из этих сервисов свой PDF или большой документ (15+ страниц). Задай 5-7 вопросов разного типа: точный («какая ставка X?»), широкий («о чём документ?»), сложный («сравни главы 2 и 4»), отсутствующий (про что-то, чего в документе нет). Понаблюдай: на какие отвечает хорошо? Где видно, что RAG нашёл правильный кусок? Где «домыслил»? Часто можно даже увидеть, какие куски документа достаются (есть подсветка). Это даёт живое ощущение слабых и сильных сторон RAG.

Эксперимент 02 · Спроектируй промпт RAG для своего кейса

Напиши system prompt

Возьми кейс из Дня 21 (свой потенциальный RAG-агент). Напиши system prompt: какая роль, как именно работать с контекстом, что делать если ответа нет, как цитировать. 200-400 токенов нормально. Этот промпт — основа будущей системы, и обычно его шлифуют неделями.

Эксперимент 03 · Составь test set

20 типичных вопросов с правильными ответами

Возьми тот же кейс. Составь 20 запросов, которые реально могут задать пользователи. Для каждого напиши, какой ответ ты считаешь правильным (одна строка, плюс ссылка на «правильный документ» из базы). Это твой будущий бенчмарк. Без него — нельзя сравнивать варианты RAG. С ним — можно прогнать улучшение и увидеть, стало лучше или хуже.

Что в Дне 24
Базовый RAG = ~60-70% качества. Чтобы добраться до 85-95%, нужны улучшения: реранкинг (второй проход поиска умной моделью), фильтры по метаданным, гибридный поиск (эмбеддинги + ключевые слова). Это и есть «продвинутый RAG».