RAG отвечает неправильно: runbook для n8n ¶
Обновлено: 2026-05-29
Intent: runbook RAG bad answers: плохие ответы RAG, retrieval, chunking, metadata filters, stale index, reranking, citations и eval questions
H1: RAG в n8n отвечает неправильно: как найти проблему в индексе, retrieval и prompt
Schema: TechArticle, HowTo, FAQPage, BreadcrumbList
Old word count: 655
New word count: 740
Короткий ответ ¶
Если RAG в n8n отвечает неправильно, не начинайте с переписывания prompt. Сначала проверьте, попал ли нужный документ в vector store, как он разбит на chunks, есть ли metadata filters, свежий ли индекс и какие chunks реально вернул retrieval. Только после этого настраивайте top_k, reranking, prompt и правило ответа “не найдено в базе”. Большинство плохих RAG-ответов возникает не в LLM, а на этапе ingestion или retrieval.
Когда применять этот runbook ¶
Runbook нужен, когда AI-ответы вроде бы основаны на базе знаний, но фактически не помогают: ответ устарел, не содержит ссылку, ссылается не на тот документ, смешивает продукты, придумывает процедуру или игнорирует свежую инструкцию.
Симптомы:
- пользователь спрашивает про известный документ, а AI отвечает “не знаю”;
- ответ есть, но относится к другому продукту/региону;
- RAG ссылается на старую версию политики;
- agent использует общий ответ вместо источников;
- retrieval возвращает нерелевантные chunks;
- top result похож по словам, но не по смыслу;
- после обновления документа ответ не изменился;
- модель уверенно дописывает то, чего нет в базе.
Цель — разделить проблему на четыре слоя: ingestion, index, retrieval, generation.
1. Проверить, есть ли документ в индексе ¶
Начните с конкретного вопроса и ожидаемого источника.
Запишите:
question = "Как клиенту поменять тариф?"
expected_doc = "billing-policy-v3.md"
expected_section = "Смена тарифа"
expected_answer = "..."
Проверьте ingestion:
- документ был загружен;
- парсер не потерял таблицы/заголовки;
- chunk содержит нужный фрагмент;
- metadata включает
doc_id,version,product,locale,updated_at; - старые версии не конкурируют с новой;
- refresh workflow действительно обновляет vector store.
Если нужный chunk отсутствует, prompt не поможет: модели просто нечего извлекать.
2. Проверить chunking ¶
Неправильная нарезка ломает даже хорошую базу знаний.
| Ошибка chunking | Симптом |
|---|---|
| Chunk слишком маленький | ответ теряет контекст и условия |
| Chunk слишком большой | retrieval цепляет много лишнего |
| Нет overlap | важная фраза оказывается между chunks |
| Таблицы распались | тарифы/лимиты смешиваются |
| Заголовки потеряны | модель не понимает раздел |
| Старые версии рядом | ответ склеивает разные политики |
Для инструкций, тарифов и runbook-ов важно сохранять заголовок раздела и источник. Часто полезно добавлять в metadata не только URL, но и section_title, version, audience, status.
3. Посмотреть реальные retrieved chunks ¶
Не оценивайте только итоговый ответ. Нужно увидеть, что retrieval вернул до LLM.
Для каждого тестового вопроса сохраните:
- query;
- top_k chunks;
- score, если доступен;
- document ID;
- metadata;
- snippet;
- final answer;
- expected source;
- verdict: good / partial / wrong / stale.
Если в top_k нет правильного источника, проблема в retrieval или metadata. Если правильный источник есть, но ответ плохой, проблема в prompt/generation/format.
4. Исправить metadata filters ¶
Многие RAG-сбои происходят потому, что один vector store хранит разные продукты, языки, версии и аудитории.
Полезные фильтры:
| Metadata | Зачем |
|---|---|
product |
не смешивать модули/услуги |
locale |
не отвечать русским текстом из английского источника |
version |
отсекать устаревшие документы |
status |
исключать draft/deprecated |
audience |
разделять internal/public |
source_type |
policy, faq, runbook, api docs |
updated_at |
видеть свежесть ответа |
Если фильтры слишком жёсткие, RAG ничего не найдёт. Если слишком мягкие, он найдёт “примерно похожее” и сгенерирует ошибку.
5. Настроить prompt для grounded answer ¶
После проверки retrieval можно чинить generation.
Добавьте правила:
- отвечай только по retrieved context;
- если источника нет, скажи “не найдено в базе”;
- указывай
source_urlилиdoc_id; - не смешивай разные версии;
- не придумывай лимиты, цены и сроки;
- для конфликтующих источников показывай конфликт;
- коротко объясняй, какие документы использованы.
Для клиентского бота лучше дать safe fallback: “Я не нашёл точный ответ в базе, передам вопрос оператору”. Это лучше, чем уверенная галлюцинация.
6. Собрать RAG eval set ¶
Минимальный набор:
- 20 популярных вопросов;
- 10 вопросов по свежим документам;
- 10 “ловушек”, где ответа нет;
- 10 вопросов с похожими продуктами;
- 5 конфликтующих/устаревших источников;
- 5 вопросов с таблицами или тарифами.
Каждый тест должен проверять не только текст ответа, но и источник. RAG без source validation — это обычный чат с иллюзией базы знаний.
FAQ ¶
Почему RAG отвечает старой информацией после обновления документа?
Часто старая версия осталась в vector store или refresh workflow не удалил/не перезаписал chunks.
Что важнее: prompt или chunking?
Для RAG сначала ingestion/chunking/retrieval, потом prompt. Если нужный chunk не найден, prompt не спасёт.
Сколько chunks давать модели?
Достаточно, чтобы покрыть вопрос, но не настолько много, чтобы смешать контекст. Начинайте с малого top_k и проверяйте реальные retrieved chunks.
Нужен ли reranking?
Он полезен, если retrieval находит много похожих chunks, но порядок плохой. Но reranking не исправит отсутствие нужного документа в индексе.
Как применять playbook в команде ¶
Playbook «RAG отвечает неправильно» должен быть понятен человеку, который не писал workflow. Поэтому в нём нужны входной сигнал, частота запуска, критерий тревоги, ответственный и ожидаемое действие после срабатывания.
Используйте этот материал как операционную инструкцию: что проверить, где посмотреть логи, как понять масштаб проблемы и когда эскалировать.
| Слой | Что зафиксировать | Зачем |
|---|---|---|
| Вход | нормализованный prompt, контекст, список источников, версия промпта и ожидаемый JSON-ответ | позволяет повторить проблему без доступа к production-секретам |
| Контроль | validation_error_rate, token_cost, fallback_usage, human_review_rate, source_coverage | показывает деградацию раньше, чем пользователи начинают писать в поддержку |
| Безопасность | получить уверенный, но непроверенный ответ модели, сломанный JSON или дорогой цикл retry | снижает риск скрытых дублей, утечки данных и неконтролируемых write-действий |
| Готовность | есть тест на happy path, пустой вход, повтор и сбой внешнего сервиса для «RAG отвечает неправильно» | делает статью пригодной для runbook, а не только для чтения |
Пример безопасного входного контракта ¶
{
"request_id": "req_demo_001",
"prompt_version": "2026-05-29",
"input": "краткое нормализованное сообщение пользователя",
"allowed_actions": ["read", "draft", "classify"],
"forbidden_actions": ["send_without_review", "change_payment"],
"expected_output": {
"intent": "technical|support|sales|unknown",
"confidence": 0.0,
"needs_human_review": true,
"sources": []
}
}
Критерий готовности ¶
- есть понятный вход, выход и владелец процесса
- проверены пустой input, повтор события и ошибка внешнего сервиса
- результат логируется без секретов и персональных данных
- страница связана с соседними рецептами, ошибками или playbook по теме