Qdrant troubleshooting в n8n: почему RAG не находит документы и как это чинить ¶
Обновлено: 2026-05-29
Короткий ответ ¶
Qdrant troubleshooting в n8n почти всегда сводится к пяти зонам: документы не попали в коллекцию, embeddings сделаны не той моделью или размерностью, metadata filters отрезают нужные chunks, retrieval возвращает нерелевантные фрагменты, а агент неправильно использует найденный context. Чинить нужно не “промптом”, а цепочкой: ingestion log → collection health → sample search → metadata audit → retrieval evaluation → answer validation.
Как Qdrant используется в n8n ¶
Qdrant Vector Store в n8n может использоваться несколькими способами: как обычный node для insert/retrieve документов, как tool для AI Agent, через Vector Store Retriever или через Vector Store Question Answer Tool. От выбранной схемы зависит диагностика. Если Qdrant стоит в обычном flow, вы проверяете входные items и output node. Если Qdrant подключён к агенту как tool, добавляется ещё один слой: агент может вообще не вызвать tool или вызвать его с плохим query.
Поэтому первый вопрос troubleshooting: где именно ломается цепочка? На ingestion, embedding, storage, retrieval, tool selection или generation? Без этого люди часто меняют prompt, хотя проблема в том, что коллекция пустая или фильтр tenant_id не совпадает.
Карта RAG-пайплайна ¶
Production RAG с Qdrant обычно выглядит так:
- Source loader получает документы.
- Cleaner убирает HTML, мусор, дубли и навигацию.
- Chunker режет документ.
- Metadata builder добавляет source_id, tenant_id, language, version, access_level.
- Embeddings node создаёт векторы.
- Qdrant insert/upsert сохраняет chunks.
- Query normalizer готовит вопрос.
- Retriever ищет chunks.
- Rerank/filter выбирает лучшие источники.
- LLM отвечает с цитированием source_id.
- Evaluation проверяет качество.
Если любой шаг пропущен, RAG может “работать”, но отвечать плохо.
Симптомы и причины ¶
| Симптом | Вероятная причина | Что проверить |
|---|---|---|
| всегда пустой ответ | коллекция пустая, фильтр слишком строгий | count points, sample query, metadata |
| находятся не те документы | плохие chunks, неверная модель embeddings | chunk size, overlap, embedding model |
| часть документов не находится | stale index, пропущенный ingestion | ingestion log, source version |
| ошибка размерности | разные embedding models | vector size collection vs model |
| ответы без источников | generation prompt не требует source_ids | retrieved context, output schema |
| чужие документы | metadata/access filters не применены | tenant_id, role, access_level |
| дубли в ответах | повторный insert без stable IDs | point_id, source_id, version |
Проверка ingestion ¶
Начните с журнала загрузки. Для каждого source document нужно знать:
{
"source_id": "kb_refunds_2026_05",
"source_url": "https://internal/kb/refunds",
"source_version": "2026-05-29",
"chunk_count": 18,
"embedding_model": "configured_embedding_model",
"collection": "support_kb_ru",
"tenant_id": "public",
"language": "ru",
"ingested_at": "2026-05-29T10:00:00Z",
"status": "success"
}
Если нет такого журнала, вы не сможете понять, какие документы в индексе. Особенно опасны “тихие” ошибки: workflow загрузил 100 документов, 20 упали, но execution считается success, потому что ошибка была проигнорирована.
Stable IDs и дубли ¶
Для обновляемой базы знаний используйте стабильные IDs. Если каждый refresh создаёт новые random point IDs, коллекция будет пухнуть дублями. Пользователь спросит “как вернуть оплату”, и retriever принесёт старую и новую политику одновременно.
Пример stable ID:
const crypto = require('crypto');
const sourceId = $json.source_id;
const chunkIndex = $json.chunk_index;
const version = $json.version || 'current';
const pointId = crypto.createHash('sha256')
.update(`${sourceId}:${chunkIndex}:${version}`)
.digest('hex');
return [{ json: { ...$json, point_id: pointId } }];
Если нужна только актуальная версия, удаляйте старые points по source_id перед insert или используйте metadata is_current и фильтр.
Metadata filters ¶
Metadata — причина половины “Qdrant ничего не нашёл”. Проблемы бывают такие:
tenant_idзаписан какTenant_1, а фильтр ищетtenant_1;- язык
ru-RU, а фильтрru; - access_level хранится строкой, а фильтр ожидает массив;
- document_type не заполнен;
- дата refresh устарела;
- фильтр применён в одном node, но не применяется в tool mode.
Сделайте metadata audit:
{
"source_id": "kb_shipping",
"tenant_id": "public",
"language": "ru",
"access_level": "public",
"doc_type": "policy",
"product": "delivery",
"is_current": true,
"updated_at": "2026-05-29"
}
Не храните важные фильтры только в тексте chunk. Они должны быть отдельными metadata fields.
Embeddings mismatch ¶
Если collection создана под одну размерность embeddings, а вы начали использовать другую модель, получите ошибку или плохое качество. Даже если размерность совпала, embedding space может отличаться. Не смешивайте модели в одной коллекции без явной стратегии.
Записывайте embedding_model и embedding_version в metadata. При смене модели лучше создать новую коллекцию или полностью переиндексировать старую. Для migration используйте shadow collection: новая коллекция собирается параллельно, затем evaluation сравнивает старый и новый retrieval.
Диагностика retrieval ¶
Не тестируйте RAG только итоговым ответом LLM. Сначала смотрите raw retrieved chunks:
{
"query": "как вернуть деньги за заказ",
"top_k": 5,
"filters": {"language": "ru", "access_level": "public"},
"results": [
{"source_id": "refund_policy", "score": 0.82, "chunk": "..."},
{"source_id": "delivery_terms", "score": 0.41, "chunk": "..."}
]
}
Если top-1 релевантен, но ответ плохой — проблема в prompt/generation. Если top-5 нерелевантны — проблема в retrieval, chunks, embeddings или query rewriting.
Chunking для Qdrant ¶
Слишком большие chunks дают шум, слишком маленькие теряют контекст. Для инструкций и FAQ часто хорошо работают короткие chunks с понятным заголовком и source_id. Для длинных документов добавляйте overlap, но не такой большой, чтобы каждый результат был почти дублем.
Каждый chunk должен содержать локальный смысл: заголовок, подраздел, ответ или процедуру. Не режьте документ по произвольным символам так, чтобы один chunk содержал “Шаг 1”, а следующий — “Шаг 2” без контекста.
Агент не использует Qdrant tool ¶
Если Qdrant подключён как tool к AI Agent, проблема может быть не в Qdrant. Агент может считать, что знает ответ сам. В prompt добавьте policy: для вопросов о внутренних правилах, ценах, документах, клиентах и процедурах agent must use retrieval tool. Для общих вопросов retrieval не нужен.
Смотрите trace: был ли tool call, какой query отправлен, какие filters применены, какие chunks вернулись. Без trace нельзя отличить “Qdrant не нашёл” от “агент не спросил”.
Evaluation ¶
Соберите golden dataset:
{
"question": "Как отменить заказ после оплаты?",
"expected_source_id": "cancel_after_payment_policy",
"must_include": ["статус заказа", "возврат", "срок обработки"],
"must_not_include": ["ручной refund без проверки"]
}
Метрики:
- retrieval hit@k;
- source accuracy;
- answer faithfulness;
- no-answer correctness;
- stale source rate;
- cross-tenant leakage;
- average latency;
- empty result rate.
Runbook: RAG отвечает плохо ¶
- Сохранить user query и trace_id.
- Посмотреть raw retrieved chunks.
- Проверить filters и tenant/access.
- Выполнить manual search без фильтров.
- Проверить ingestion log source document.
- Сравнить embedding model.
- Проверить chunk size/overlap.
- Проверить prompt: требует ли источники.
- Добавить кейс в evaluation dataset.
- Переиндексировать или исправить metadata.
Что нельзя делать ¶
Не лечите плохой retrieval длинным prompt: модель не найдёт документ, которого нет в context. Не смешивайте приватные и публичные документы без metadata filters. Не обновляйте базу знаний без версии и журнала. Не давайте агенту отвечать на внутренние вопросы без source_ids. Не используйте in-memory vector store для production, где данные должны переживать рестарт.
FAQ ¶
Почему Qdrant в n8n возвращает пустой результат?
Чаще всего коллекция пустая, фильтр metadata слишком строгий, query не нормализован, документы не были проиндексированы или используется другая коллекция/environment.
Почему RAG на Qdrant находит не те документы?
Проверьте chunking, embedding model, metadata, top-k, query rewriting и raw retrieved chunks. Если retrieval плохой, prompt не исправит проблему.
Можно ли смешивать разные embedding models в одной коллекции?
Нежелательно. Даже при одинаковой размерности качество может просесть. Лучше фиксировать embedding_model в metadata и переиндексировать коллекцию при смене модели.
Как защититься от выдачи чужих документов?
Используйте metadata filters по tenant_id, access_level, role, language и is_current. Проверяйте фильтры в тестах и логируйте source_ids каждого ответа.
Что логировать для Qdrant troubleshooting?
query, normalized_query, collection, top_k, filters, retrieved source_ids, scores, embedding_model, index_version, latency, empty_result и final answer status.