RAG в проде: интерактивная схема из 24 блоков и где каждый ломается
Кликабельная схема продового RAG в трёх слоях: индексация, путь запроса и контур качества. По каждому блоку: что он делает, как ломается, какая метрика это видит и как проверить его отдельно от остальных. В конце упражнение на трассировку вопроса.
ca2bd65
Содержание
Коротко
- Продовый RAG состоит из двух десятков компонентов, и ломается чаще обвязка вокруг модели, чем сама модель. Схема ниже показывает 24 блока в трёх слоях: индексация, запрос, контур качества.
- Многие дефекты, которые пользователь видит как «бот ответил неправильно», появляются ещё до вопроса: в данных, чанкинге, индексе или правах доступа.
- Каждый блок можно проверить отдельно: retriever без модели, кэш без поиска, права без генерации. Так вы находите причину, а не только симптом.
- Четыре метрики RAG смотрят в разные места схемы. По их сочетанию видно, какой слой чинить.
- Контур качества тоже ломается: трейсы без чанков, смещённая выборка, неоткалиброванный судья. Его проверяют так же, как продукт.
Как пользоваться схемой
Во второй части серии RAG помещался в пять прямоугольников: вопрос, retriever, найденные фрагменты, сборка промпта, модель. Для понимания идеи этого хватает. Для тестирования нет: в настоящей системе между вопросом и ответом стоят шлюзы, кэш, гибридный поиск, реранкер, фильтры и логирование, а за поиском прячется целый конвейер индексации.
Схема ниже собрана из типичных компонентов продового RAG. У вас набор может быть другим, но слои и точки отказа повторяются почти везде.
Как с ней работать:
- Нажмите на любой блок. Откроется карточка: что блок делает, как ломается, что смотреть и какие метрики RAG его видят.
- «Проследить вопрос» подсветит путь запроса от пользователя до ответа. «Проследить индексацию» покажет, как документ превращается в индекс.
- Полноэкранный режим удобен на ноутбуке, на телефоне схема читается списком.
Схему можно листать вбок или развернуть на весь экран. Нажмите на блок или выберите его клавишей Enter.
Дальше я иду по слоям сверху вниз и в каждом останавливаюсь на блоках, которые чаще всего виноваты в плохих ответах. Остальные блоки откройте на схеме сами: в карточках есть всё, что нужно для первого теста.
Слой индексации: ошибки, которые случились до вопроса
Индексация работает в фоне и не видна пользователю. Поэтому её дефекты особенно неприятны: ответ выглядит уверенно, метрика генерации высокая, а факт неверный, потому что неверным или неполным был индекс.
Источники: устаревшие и противоречивые документы
В базе лежат две версии регламента, и ассистент отвечает по старой. Модель здесь ни при чём: она честно пересказала найденный документ. Faithfulness такой дефект не поймает, ответ ведь соответствует контексту.
Как проверить отдельно: добавьте в golden-датасет вопросы на актуальность, у которых эталонный ответ ссылается на конкретную версию документа. Это проверка данных, и делать её можно без запуска модели: найдите в базе документы с одинаковой темой и разными датами и решите, какой из них должен побеждать. Как размечать эталонный контекст, я разбирал в статье про golden-датасет.
Indexer: факт разрезан пополам
Indexer разбирает файл, режет его на чанки, считает эмбеддинги и пишет в индексы. Самое частое место отказа здесь чанкинг. Таблица тарифов разрезана посередине, срок возврата оказался в одном чанке, а условие про чек в другом. Retriever находит половину факта, модель отвечает половиной.
Как проверить отдельно: для вопросов из golden-датасета посмотрите, существует ли в индексе хотя бы один чанк, который целиком содержит эталонный факт. Если такого чанка нет, никакой поиск его не найдёт. На схеме у Indexer стоит метка Contextual Recall: правило из карточки простое, если нужного нет в top-k при любых настройках поиска, начинайте с чанкинга. Эксперимент с размером чанков и Recall@K есть в разборе про метрики поиска.
Embedding model и BM25: поиск не знает вашего языка
Векторный поиск хорошо ловит смысл и плохо ловит точные коды, артикулы и термины. Для них рядом стоит лексический индекс BM25. У него своя беда: без нормального анализатора русской морфологии запрос «возврата» не находит документ со словом «возврат».
Как проверить отдельно: прогоните одни и те же вопросы через dense-поиск и через гибрид dense + BM25 и сравните Recall@K. Если гибрид ничего не добавляет на вопросах с кодами и терминами, проверьте анализатор. Ещё одна вещь, которую стоит знать заранее: смена модели эмбеддингов требует полной переиндексации, и это повод перемерить весь поиск.
Postgres: права проверяются слишком поздно
В метаданных чанков лежат источник, версия, дата и права доступа. Фильтр по правам должен срабатывать до поиска. Если права проверяют после, чужой документ уже попал в контекст модели, и дальше всё зависит от того, перескажет ли она его.
Как проверить отдельно: заведите двух тестовых пользователей с разными правами и документ с уникальной меткой, доступный только одному из них. Задайте от имени второго вопрос, который должен вытащить этот документ, и проверьте трейс: метка не должна появиться даже в найденных чанках, не только в ответе.
Слой запроса: путь вопроса до ответа
Нажмите на схеме «Проследить вопрос». Запрос проходит через API Gateway, оркестратор, кэш, retriever, реранкер, LLM Gateway, модель и guardrails. На каждом шаге он может свернуть не туда.
RAG Orchestrator: retriever ищет не то, что спросили
Оркестратор часто переписывает вопрос перед поиском: убирает лишнее, подставляет контекст диалога. Если переписывание кривое, retriever честно ищет по чужому запросу. Пользователь спросил про возврат обуви, а поиск ушёл по «возврат денег».
Как проверить отдельно: логируйте переписанный запрос рядом с исходным и прогоните по golden-датасету только этот шаг. Это дешевле полного прогона: модель-ответчик не нужна, достаточно сравнить исходный и переписанный запрос. На схеме у оркестратора метка Answer Relevancy: когда запрос к retriever сформулирован криво, эта метрика проседает первой.
Redis: семантический кэш отвечает на другой вопрос
Кэш отдаёт готовый ответ, если похожий вопрос уже задавали. Ломается он двумя способами. Первый: после обновления базы знаний кэш продолжает отдавать старый ответ. Второй: «похожий» вопрос оказывается другим вопросом, и пользователь получает ответ, который к нему не относится.
Как проверить отдельно: обновите тестовый документ и задайте вопрос, ответ на который уже лежит в кэше. Затем соберите пары вопросов, близких по словам и разных по смыслу, и проверьте, что кэш на них не срабатывает. Метрики RAG этот блок почти не видят, если оценка идёт мимо кэша, поэтому прогоняйте оценку через тот же путь, что и пользователь.
Retriever и Reranker: нужное не нашлось или стоит в хвосте
Retriever собирает top-k кандидатов из векторного индекса и BM25, склеивает их через Reciprocal Rank Fusion и фильтрует по метаданным и правам. Реранкер пересортировывает кандидатов, чтобы лучшее оказалось в начале: модель лучше использует начало контекста.
Здесь работают две метрики. Contextual Recall отвечает на вопрос, нашлось ли нужное вообще. Contextual Precision отвечает, стоит ли нужное выше шума, и чувствительна к порядку, поэтому на схеме она висит и на реранкере.
Как проверить отдельно: retriever можно тестировать без модели совсем. Подайте вопрос, получите список чанков с позициями и посчитайте Recall@K и MRR по эталонным id документов. Так вы сравниваете настройки поиска, не тратя токены модели и судьи.
LLM Gateway и LLM: смена модели без перепрогона
LLM Gateway маршрутизирует запросы между моделями, делает ретраи и считает токены. Опасное место: автоматическая смена модели по цене или доступности. Качество меняется, а в коде никто ничего не трогал.
Сама модель получает вопрос и чанки и пишет ответ. Здесь рождаются галлюцинации, и здесь смотрят Faithfulness и Answer Relevancy. Правило для обоих блоков одно: любая смена модели, её версии или маршрута — повод прогнать golden-датасет.
Guardrails: фильтр режет полезное или пропускает атаку
Входные и выходные фильтры ловят prompt injection, персональные данные и запрещённые обещания. Ошибаются они в обе стороны. Слишком жадный фильтр блокирует нормальный вопрос со словом «пароль», слишком мягкий пропускает атаку, спрятанную в документе.
Как проверить отдельно: считайте две доли, ложные блокировки на легитимных вопросах и пропущенные атаки на наборе атак. Атаки через документы базы знаний разобраны в статье про непрямую prompt injection.
Где какая метрика смотрит
Четыре метрики RAG привязаны к конкретным блокам схемы. Подробно о том, как они считаются, я писал в разборе про 4 метрики RAG, здесь только карта.
| Метрика | Блоки на схеме | Что говорит о блоке |
|---|---|---|
| Contextual Recall | Indexer, Retriever | Нужный факт есть в индексе и попал в top-k |
| Contextual Precision | Retriever, Reranker | Нужное стоит выше шума |
| Answer Relevancy | RAG Orchestrator, LLM | Ответ и запрос к поиску про тот вопрос, который задали |
| Faithfulness | LLM | Ответ опирается на найденные чанки и не противоречит им |
Обратите внимание, чего в таблице нет. Источники, кэш, права доступа, gateway и guardrails метрики RAG не видят совсем. Для них нужны свои проверки: вопросы на актуальность, тесты на утечку между пользователями, инвалидация кэша, доля ложных блокировок. Если в вашем отчёте только четыре метрики, половина схемы остаётся без тестов.
Диагностика: от сочетания метрик к блоку
Одна метрика редко указывает на виновника. Сочетание указывает. Переключите метрики ниже в положение «высоко» или «низко» так, как они выглядят в вашем последнем прогоне, и посмотрите диагноз. Затем найдите на схеме блоки, на которые он указывает, и откройте их карточки.
Тренажёр: диагностика по сочетанию метрик. Отметьте, какие метрики выше порога, а какие ниже, и посмотрите, где искать причину. Высоко означает не ниже стартового порога из таблицы выше.
ответ опирается на контекст
ответ про заданный вопрос
нужное стоит в начале выдачи
retriever нашёл всё нужное
Порядок разбора провального вопроса остаётся тем же, что в разборе про метрики. Сначала откройте трейс и проверьте, был ли нужный чанк в найденном контексте. Если не был, идите в слой индексации и в retriever. Если был, идите в оркестратор, промпт и модель. Если метрики высокие, а пользователи жалуются, смотрите на блоки, которые метрики не видят: источники и кэш.
Контур качества: как система проверяет себя
Нижний слой схемы отвечает за то, чтобы команда узнала о проблеме раньше пользователей. Нажмите на схеме блок Traces и посмотрите, что от него зависит: без него не работает почти ничего ниже.
Traces: без чанков разбор невозможен
Для каждого запроса сохраняются вопрос, найденные чанки, ответ, задержки и токены. Самый частый дефект: чанки не логируют. Потом по жалобе пользователя невозможно понять, виноват поиск или генерация, а метрики без эталона на трафике не посчитать вовсе. Второй дефект в обратную сторону: в трейсы попадают секреты и персональные данные.
Как проверить: возьмите случайный трейс и попробуйте по нему восстановить, что видела модель. Если не получается, контур качества слеп.
Sampler и оценка: что именно вы меряете
Sampler берёт из прод-трафика выборку диалогов для оценки без эталонов: Faithfulness, Answer Relevancy, Contextual Relevancy. Если в выборку попадают только короткие и простые вопросы, дашборд зелёный, а сложные вопросы не измеряются вовсе. Сравните распределение типов вопросов в выборке и в общем трафике.
Блок оценки считает метрики через модель-судью. Я запускаю оценку через DeepEval и RAGAS из одного интерфейса в DeepRisk: если два судьи сильно расходятся, метрике на этих данных нельзя верить вслепую. Главное требование к блоку: судья откалиброван на ручной разметке. Как это сделать, разобрано в статье про калибровку LLM-судьи.
Golden-датасет и CI release gate: регрессия до релиза
На каждый pull request gate прогоняет golden-датасет и блокирует merge, если метрики ниже порогов. Ломается он тихо: датасет из десятка лёгких вопросов, где всё всегда зелёное, или пороги, выставленные «под красивый отчёт». Пороги ставьте чуть ниже значений текущей рабочей версии, тогда gate ловит ухудшения. Конфиг, пороги по доле и борьба с плавающими тестами есть в разборе про quality gate в CI.
Dashboard и Alerts: среднее врёт
Дашборд показывает тренды и сравнение прогонов, алерты сообщают о падении метрик по расписанию. Две типичные ошибки: смотреть только среднее и не смотреть срезы по типам вопросов, и настроить алерт на каждую мелочь, после чего на алерты перестают смотреть.
Упражнение: проследите вопрос
Нажмите на схеме «Проследить вопрос» и найдите три блока, из-за которых пользователь может получить устаревший ответ уже после того, как документ в базе обновили. Для каждого запишите, как бы вы это воспроизвели.
Проверить себя
- Kafka. Событие об изменении документа обработано с задержкой или потерялось. Индекс старше документа. Смотрите отставание consumer’ов и возраст индекса.
- Redis, семантический кэш. Ответ лежит в кэше и отдаётся без поиска. Воспроизведение: обновить документ и задать вопрос, который уже есть в кэше.
- Источники и Postgres. Старая версия документа не удалена и продолжает находиться наравне с новой. Воспроизведение: вопрос на актуальность и проверка версии в метаданных найденных чанков.
Если вы назвали LLM, это тоже разумный ответ: модель может достроить ответ по своим знаниям. Но это уже другой класс дефекта, его ловит Faithfulness.
Второе упражнение без ответа: проследите вопрос пользователя без доступа к внутренним документам и найдите все места, где внутренний документ может оказаться у него в ответе. Подсказка: таких мест больше одного, и не все они в слое запроса.
Ограничения схемы
Схема обобщённая. В вашей системе может не быть Kafka или семантического кэша, оркестратор может быть сотней строк своего кода, а guardrails могут жить внутри промпта. Технологии в карточках перечислены как типичные варианты, а не как рекомендации.
Агентов на схеме нет. Если ваш ассистент вызывает инструменты, к точкам отказа добавляются выбор инструмента, аргументы, зацикливание и действия без подтверждения. Об этом разбор про тестирование агентов и MCP.
Нагрузка и стоимость показаны только через gateway. Задержка реранкера, лимиты провайдера и цена прогона заслуживают отдельного теста: нагрузочное тестирование LLM.
Что дальше
- Нарисуйте схему своей системы или учебного стенда по этим трём слоям и отметьте минимум шесть точек отказа, хотя бы одну в каждом слое. Для каждой запишите, как воспроизвести и какой проверкой ловить.
- Откройте один трейс из своей системы и проверьте, видны ли в нём найденные чанки. Если нет, это первая задача на неделю.
- Прогоните retriever отдельно от модели на десяти вопросах из golden-датасета и посчитайте, у скольких нужный документ попал в top-k.
- Следующая часть серии про то, как назвать найденный дефект и оформить его так, чтобы разработчик его воспроизвёл: классы дефектов LLM и тренажёр.


