← Production RAG: retrieval systems that do not hallucinate
05 / 07 · 50 min

Grounding, citations, and hallucination control

Require evidence-backed answers, verify citations mechanically, and measure faithfulness instead of trusting confident prose.

Lesson content is currently available in Russian.

What you will learn

  • →Писать grounded-промпты: правила опоры на контекст, формат цитат и условия отказа.
  • →Строить механическую верификацию цитат: каждая ссылка указывает на реально переданный фрагмент.
  • →Разворачивать NLI/LLM-judge проверку faithfulness на потоке ответов и выбирать действие при провале.

Откуда берутся галлюцинации в RAG

RAG уменьшает галлюцинации, но не устраняет их — меняется их природа. Четыре продакшен-источника. Конфликт контекста и параметрической памяти: в документах «лимит 100 запросов/мин», модель помнит из претрейна «60» — и без жёсткой инструкции может выбрать память; это задокументированный эффект (knowledge conflicts), усиливающийся, когда контекст противоречит «общеизвестному». Слабый retrieval: нерелевантные чанки в промпте — модель «дотягивает» ответ до вопроса из головы. Сшивание фрагментов: два верных факта из разных чанков склеиваются в неверный вывод — даты из одного документа приписываются событию из другого. Давление формата: инструкция «дай развёрнутый ответ» вынуждает заполнять пробелы, когда фактов на развёрнутый ответ нет.

Важное следствие: контроль галлюцинаций — не один приём, а слоёная защита. Слой 1 — retrieval (уроки 1–4): в контекст попадает нужное и не попадает мусор. Слой 2 — промпт: правила опоры на контекст и право на отказ. Слой 3 — формат ответа: обязательные цитаты, делающие проверяемым каждое утверждение. Слой 4 — автоматическая верификация: механическая проверка цитат и семантическая проверка faithfulness. Ни один слой в одиночку не даёт продакшен-надёжности; в этом уроке — слои 2–4.

База для калибровки ожиданий: даже у лучших моделей faithfulness на сложных доменах не абсолютен, поэтому вопрос ставится не «как исключить галлюцинации», а «какой остаточный уровень приемлем для продукта и как его непрерывно измерять» — мостик к следующему уроку.

Grounded-промптинг и право на отказ

Рабочий скелет grounded-промпта — четыре блока правил:

Отвечай ТОЛЬКО по фрагментам в <context>. Правила:
1. Каждое фактическое утверждение снабжай ссылкой [N] на фрагмент-источник.
2. Если фрагменты не содержат ответа — скажи об этом прямо и не отвечай
   по общим знаниям. Не смешивай знания модели с фактами из контекста.
3. Если фрагменты противоречат друг другу — покажи оба варианта с датами
   и источниками, не выбирай молча один.
4. Отвечай ровно настолько подробно, насколько позволяют фрагменты.

<context>
  <doc id="1" source="pricing.md" updated="2026-05-10">…</doc>
  <doc id="2" source="release-notes/v3.2.md" updated="2026-06-01">…</doc>
</context>

Детали, которые решают. Нумерованные doc-теги с метаданными дают модели адреса для цитат и материал для разрешения конфликтов (свежая дата побеждает). Правило 3 против молчаливого выбора — конфликтующие версии документации это норма жизни, а не исключение. Правило 4 снимает давление формата: лучше три подтверждённых предложения, чем десять «гладких».

Отказ от ответа настраивается как продуктовое решение с явным порогом. Полезная шкала: отвечать уверенно (факты покрывают вопрос) / отвечать с оговоркой («в документации указано X, но раздел не обновлялся с версии 2.0») / отказаться с маршрутом («не нашёл в базе; передаю оператору»). Формулировку отказа пишите заранее и тестируйте — дефолтное «я не могу помочь» без маршрута раздражает пользователей и хоронит доверие к продукту быстрее редких галлюцинаций.

Цитаты: механическая верификация и extraction-first

Цитата ценна тем, что её можно проверить машиной. Минимальный контур: ответ парсится на утверждения с метками [N], и для каждой проверяется, что (а) фрагмент N существовал в переданном контексте и (б) утверждение реально им подкреплено. Проверка (а) — тривиальный код; для (б) есть быстрый лексический прокси и точная семантическая проверка:

def check_citations(answer: str, ctx: dict[int, str]) -> list[Claim]:
    claims = split_into_claims(answer)          # предложения с [N]
    for c in claims:
        if c.doc_id not in ctx:
            c.status = 'fabricated_ref'          # ссылка в никуда
        elif token_overlap(c.text, ctx[c.doc_id]) < 0.35:
            c.status = 'suspect'                 # на дообследование NLI
        else:
            c.status = 'ok'
    return claims

Ссылки «в никуда» — реальный и частый класс дефектов: модель пишет [7], когда фрагментов было пять. Ловится строкой кода, а без проверки выглядит как убедительно оформленный ответ.

Более сильная схема — extraction-first (quote-then-answer): первым шагом модель дословно выписывает релевантные цитаты из контекста, вторым — собирает ответ только из выписанного. Дословность шага 1 проверяется посимвольным поиском по контексту — это уже не оценка, а факт. Схема снижает галлюцинации сшивания и почти закрывает конфликт с параметрической памятью, ценой роста токенов на ~30–50% и чуть более «сухих» ответов. Для доменов с ценой ошибки (юридические, медицинские, финансовые ответы) этот размен почти всегда правильный. Anthropic поддерживает этот паттерн нативно через Citations API — модель возвращает структурированные ссылки на переданные документы вместо текстовых [N].

Faithfulness на потоке: NLI и LLM-judge

Лексический overlap не отличит перефразированную правду от тонкого искажения («лимит можно увеличить» → «лимит увеличивается автоматически»). Семантическая проверка faithfulness работает так: ответ разбивается на атомарные утверждения, и для каждого проверяется, следует ли оно из контекста (entailment). Два инструмента: специализированные NLI-модели (дёшево, быстро, слабее на длинных многосоставных фрагментах) и LLM-judge с бинарной рубрикой «подкреплено/не подкреплено» на каждое утверждение (точнее, дороже). Метрика faithfulness в Ragas — доля подкреплённых утверждений — устроена ровно так, и её можно гонять как оффлайн на eval-наборе, так и сэмплированно на живом трафике.

Продакшен-контур: на каждый (или сэмплированный — например, 10% плюс все ответы с низкой уверенностью) ответ считается faithfulness-скор; при провале порога выбирается действие по цене ошибки домена. Варианты действий по возрастанию строгости: залогировать для разбора; показать ответ с плашкой «не удалось проверить по источникам»; перегенерировать с ужесточённым промптом; заменить отказом с маршрутом на человека. Blocking-проверка добавляет латентность (сотни миллисекунд на judge), поэтому её ставят только там, где цена ошибки выше цены задержки.

Закрывающая мысль слоёной защиты: логи верификации — не только предохранитель, но и датасет. Утверждения с провальным faithfulness — это готовые кейсы для error analysis: они показывают, где ломается retrieval (мусор в контексте), где промпт (модель игнорирует правила), а где формат (давление на развёрнутость). Этот поток кейсов питает eval-набор следующего урока — контроль галлюцинаций и измерение качества образуют один цикл.

Practice

Контур grounding и верификации

Перепишите промпт своего RAG по четырёхблочному скелету (цитаты [N], отказ, конфликты, длина по фактам). Реализуйте механическую проверку цитат (fabricated_ref + overlap-прокси) и прогоните 20 вопросов: 12 с ответом в базе, 4 без ответа, 4 с конфликтующими документами. Для 12 первых посчитайте faithfulness через Ragas или LLM-judge по бинарной рубрике.

Deliverable

Промпт, код верификации и отчёт: доля ответов с корректными цитатами, поведение на 4 вопросах без ответа (ожидание: отказ с маршрутом), поведение на конфликтах (ожидание: показаны оба варианта), faithfulness-скор с разбором каждого провального утверждения.

Checkpoint

Продакт спрашивает: «можем ли мы гарантировать, что бот не выдумывает?» Дайте честный инженерный ответ: какие слои защиты есть, что каждый ловит и что остаётся.

  • ✓ Названы источники галлюцинаций в RAG: конфликт с параметрической памятью, слабый retrieval, сшивание фрагментов, давление формата.
  • ✓ Описана слоёная защита: grounded-промпт с правом на отказ, обязательные цитаты с механической проверкой, faithfulness-контур (NLI/judge) на потоке.
  • ✓ Сформулировано, что гарантия невозможна — есть измеримый остаточный уровень, порог приемлемости и действия при провале (плашка, перегенерация, эскалация).

Check yourself

В документах «лимит 100 запросов/мин», модель отвечает «60». Что произошло?

01В документах «лимит 100 запросов/мин», модель отвечает «60». Что произошло?

Что проверяется механически (кодом, без ML) в контуре цитат?

02Что проверяется механически (кодом, без ML) в контуре цитат?

В чём суть extraction-first (quote-then-answer)?

03В чём суть extraction-first (quote-then-answer)?

Как измеряется faithfulness в Ragas?

04Как измеряется faithfulness в Ragas?

Когда faithfulness-проверку ставят blocking (до показа ответа пользователю)?

05Когда faithfulness-проверку ставят blocking (до показа ответа пользователю)?

Sources

Grounding, citations, and hallucination control · Production RAG: retrieval systems that do not hallucinate · VORCL