RAG · Retrieval-augmented generation · урок 6 · 13 мин

Диагностика неверного ответа RAG

Debugging a wrong RAG answer

ТемыRAG

Зачем

После урока ты ответишь на самый вероятный вопрос технического раунда по RAG: «клиенту назвали неверную комиссию — что ты делаешь?». Сильный ответ начинается не с исправления, а с диагностики: каждая проверка делит поиск причины пополам. Тот же порядок нужен и на работе, когда жалоба приходит в пятницу вечером.

Главная ошибка: чинить до диагноза

Типичный слабый ответ звучит так: «добавлю в prompt (инструкцию модели) правило брать свежий тариф» или «поставлю ещё одного агента-проверяющего». Оба — исправления наугад. Причина не найдена, значит неизвестно, исправлено ли хоть что-то, и сколько ещё вопросов ломается так же.

Сильный ответ начинается с вопроса «какое доказательство укажет место поломки?». Помогает факт из устройства RAG (retrieval-augmented generation, генерация с опорой на найденные документы): две его половины ломаются независимо. Retrieval (выборка) мог не принести нужный chunk (кусок документа), или generation (генерация ответа) могла неверно использовать принесённое. Первая проверка отвечает именно на это.

Порядок: назад от ответа

Идём от ответа к источнику, и каждая проверка отсекает половину возможных причин.

Шаг 1. Открыть trace (подробный журнал этого запроса: что искали, какие chunks с какими версиями попали в context — всё, что модель видела в запросе, — что ответила модель). Вопрос: был ли верный факт в chunks, которые видела модель?

Шаг 2. Есть ли верный факт в index вообще? Ищем напрямую по индексу, в обход всего pipeline (конвейера).

Шаг 3. На каждом шаге искать конкурирующую старую версию. Для неверной комиссии в банке это самая вероятная причина: в индексе живут тарифы 2025 и 2026 годов, и старый выиграл ранжирование.

Пример: прошлогодняя комиссия

Жалоба: клиенту назвали комиссию за досрочное погашение 2% вместо 1,5% по новому тарифу. Открываем trace. В context пять chunks: на 1-м месте пункт тарифа 2025 года с «2%», на 4-м — тариф 2026 года с «1,5%». Модель процитировала первый. Это значит: retrieval принёс и верное, и неверное; модель выбрала то, что выше. Корень не в модели, а в том, что истёкшая версия вообще могла соревноваться за вопрос о текущей комиссии, а выбор версии был оставлен модели.

Дальше второй вопрос: почему старый документ выше нового? Например, у старого был chunk с заголовком таблицы, а у нового таблица разрезана — это уже ошибка нарезки, и её надо чинить отдельно.

Исправление: у каждого chunk поля valid_from и valid_to; retrieval фильтрует по дате, которая важна для вопроса: сегодня для нового клиента, дата договора для старого, если так велят условия. Старые версии остаются в индексе, но не конкурируют случайно.

Доказательство исправления, а не надежда: детерминированный тест retriever на оба случая дат; набор вопросов о версиях, прогнанный до и после; полный регрессионный набор; наблюдение за жалобами на комиссии после выкатки. А в долгую — комиссию называет tool (функция, читающая из системы учёта), а не текст.

Если виновата generation

Ветка «факт был в context, а ответ неверный» тоже требует диагноза, а не правила в prompt. Частые причины: в context два противоречащих chunks (старая и новая версия — снова шаг 3); нужный chunk утонул среди длинного шумного context; число стоит в таблице, которую parsing превратил в кашу, и модель прочитала не ту колонку; инструкция не требует ссылки на источник для каждого числа. Проверка простая: прогнать тот же вопрос с одним верным chunk в context. Если ответ стал верным — виноват шум или конфликт, и чинить надо отбор и порядок chunks. Если нет — смотреть, как chunk выглядит после parsing.

Сначала защитить клиента

Если ошибка задевает клиентов прямо сейчас, порядок меняется: сначала остановить вред — откатить последнее изменение или направить этот тип вопросов человеку, — а потом спокойно диагностировать. Идеальный диагноз не стоит ещё сотни неверных ответов.

Классы поломок

Barnett и соавторы (2024) по трём проектам из разных областей (исследования, образование, биомедицина) выделили семь точек отказа RAG. Их удобно разложить по нашей схеме:

Точка отказа Что произошло Где искать
Missing content ответа нет в корпусе, а система всё равно отвечает ingestion; поведение «не знаю»
Missed top ranked ответ в корпусе, но ниже top-k (первых k результатов) retrieval, rerank
Not in context найден, но отброшен при сборке context сборка context, лимит длины
Not extracted был в context, модель не извлекла generation, шум и противоречия
Wrong format нарушен требуемый формат generation
Incorrect specificity слишком общо или слишком подробно вопрос и инструкция
Incomplete часть ответа пропущена generation, многочастные вопросы

Сценарий «документ обновился, а индекс нет» — частный случай: верный факт есть в источнике, но не в index (шаг 2, ветка «нет»), а старая версия конкурирует (шаг 3). Это та же болезнь, что прошлогодний тариф.

Что построить заранее

Такая диагностика возможна, только если заранее есть три вещи:

  1. Traces с chunk IDs, версиями документов и рангами до и после rerank.
  2. Effective dates (даты действия) в metadata каждого документа.
  3. Golden set — набор вопросов с известным верным источником, чтобы проверить исправление и не сломать остальное.

Без traces шаг 1 невозможен, без дат исправление невозможно, без golden set невозможно доказательство.

Схема

Термины · Key terms

trace
журнал одного запроса: запрос, chunks с версиями и рангами, ответ
retrieval failure
нужный chunk не попал в найденное
generation failure
chunk был в context, а модель ответила неверно
groundedness check
проверка, что каждое утверждение есть в найденном тексте
metadata filter
отсев chunks кодом по дате, языку, доступу
effective date
дата вступления документа в силу, поля valid_from и valid_to
golden set
вопросы с известным верным источником для проверки
regression suite
набор тестов, который ловит поломку того, что работало
failure point
класс поломки RAG по Barnett и соавторам

Сделай сам

Не подглядывая в урок, ответь вслух за 2 минуты на вопрос: «Клиенту назвали прошлогоднюю комиссию за досрочное погашение. Что ты делаешь?» Запиши голосовую заметку. Потом проверь: начался ли ответ с диагностики, назвал ли ты три шага, старую версию и три вещи, которые нужны заранее.

Обсуди с тьютором: перескажи свой ответ текстом и попроси тьютора отметить, где ты предложил исправление раньше, чем нашёл доказательство.

Проверь себя · ответ под вопросом

1Какой первый вопрос ты задаёшь trace, и куда идёшь при ответе «да» и при ответе «нет»?
Был ли верный факт в chunks, которые видела модель. «Да» — сбой generation, подтверждаю проверкой groundedness. «Нет» — ищу факт напрямую в index: есть, но не найден — retrieval или rerank; нет — ingestion, parsing, chunking или normalization.
2Чем сценарий «документ обновился, а embeddings нет» похож на старую версию тарифа?
В обоих случаях верный факт есть в источнике, но не побеждает в поиске, а старая версия конкурирует с новой. Лечение тоже общее: инкрементальная переиндексация и даты действия в metadata с фильтром по нужной дате.
3Какие три вещи надо построить заранее, чтобы такая диагностика вообще была возможна?
Traces с chunk IDs, версиями документов и рангами; даты действия в metadata каждого документа; golden set вопросов с известным верным источником. Без них нельзя ни найти место поломки, ни доказать исправление.

Interview questions · US / UK

1A customer was quoted last year's early-settlement fee by your RAG assistant. What do you do?
Strong answer: mitigate if customers are harmed; open the trace — was the right chunk in context? yes → generation, confirm with groundedness; no → search the index directly → retrieval/rerank vs ingestion; check for a competing older version; prerequisites: traces, effective dates, golden set.
2Follow-up probe: the right chunk was at rank 4 and the model quoted the stale one at rank 1. How do you fix it, and how do you prove the fix?
Strong answer: root cause is that expired versions compete and the model picks the version; valid_from/valid_to with a date filter in retrieval (today or contract date); find why the old one outranked the new; deterministic retriever test for both dates, versioning set before/after, full regression, monitoring complaints.
3What would you instrument before launch so that this kind of bug is debuggable?
Strong answer: traces with rewritten query, filters, chunk IDs, document versions, ranks before and after rerank, final context and citations; effective dates on every document; a golden set with correct sources; per-slice dashboards.

Ключевые фразы · Say it aloud

Материалы