Qdrant и n8n: RAG-поиск по базе знаний с фильтрами и версионированием ¶
Обновлено: 2026-05-30
Импортируйте JSON в n8n, замените credentials, URL API, поля CRM/БД и лимиты под вашу инфраструктуру.
Проблема: RAG-боты часто отвечают уверенно, но не тем документом: чанки без метаданных, устаревшие версии остаются в индексе, фильтры по продукту не работают, а score threshold не настроен. Пользователь получает “умный” ответ без проверяемого источника.
Решение: проектируем Qdrant как контролируемый retrieval-слой: коллекция с размерностью embedding-модели, payload metadata, doc_version, фильтры по разделу/языку/статусу, порог релевантности и обязательные цитаты на найденные документы.
Проблема: почему RAG без metadata и фильтров даёт галлюцинации ¶
Векторная база сама по себе не гарантирует качество ответа. Если все документы лежат в одной коллекции без product, version, language и source_url, retrieval возвращает похожий, но не обязательно актуальный фрагмент. Особенно часто это ломается в FAQ-ботах, где старые инструкции конкурируют с новыми.
Вторая ошибка — не разделять ingestion и question answering. Индексация должна уметь обновлять документ по версии и удалять устаревшие чанки, а runtime workflow должен отказываться отвечать, если score ниже порога или источников недостаточно.
Архитектура Qdrant RAG workflow в n8n ¶
| Блок | Задача | Production-проверка |
|---|---|---|
| Ingestion trigger | получает документ из CMS, Git или Notion | document_id, version, status |
| Chunk and metadata | делит текст и добавляет payload | source_url, product, language, doc_version |
| Create embeddings | получает вектор для каждого чанка | одинаковая модель и размерность |
| Upsert to Qdrant | пишет points в collection | stable point_id, payload indexes |
| Search query | ищет top_k по вопросу | filters, score threshold |
| Answer with sources | формирует ответ только по найденным чанкам | цитаты, отказ при низкой уверенности |
Для production RAG важно индексировать не только текст, но и правила доступа. Если база знаний содержит внутренние документы, фильтр по роли должен применяться до генерации ответа.
Контракт документа и metadata для Qdrant ¶
{
"document_id": "faq-n8n-webhook-auth",
"doc_version": "2026-05-30",
"source_url": "https://example.ru/docs/webhook-auth",
"language": "ru",
"product": "n8n",
"status": "published",
"chunk_index": 3,
"text": "Для проверки подписи webhook используйте HMAC SHA-256 и сравнивайте подпись constant-time способом."
}
Metadata нужна не для красоты: по ней Qdrant будет фильтровать устаревшие, черновые или нерелевантные документы до того, как модель начнёт писать ответ.
Code Node: chunk metadata, point id и filter policy ¶
const doc = $json.body ?? $json;
const text = String(doc.text ?? '').replace(/\s+/g, ' ').trim();
if (text.length < 200) throw new Error('Document text is too short for RAG indexing');
const chunkSize = Number($env.RAG_CHUNK_SIZE ?? 900);
const overlap = Number($env.RAG_CHUNK_OVERLAP ?? 120);
const chunks = [];
for (let start = 0, i = 0; start < text.length; start += chunkSize - overlap, i++) {
const chunk = text.slice(start, start + chunkSize).trim();
if (chunk.length < 120) continue;
chunks.push({
id: `${doc.document_id}:${doc.doc_version}:${i}`,
text: chunk,
payload: {
document_id: doc.document_id,
doc_version: doc.doc_version,
source_url: doc.source_url,
language: doc.language ?? 'ru',
product: doc.product ?? 'general',
status: doc.status ?? 'published',
chunk_index: i
}
});
}
return chunks.map(c => ({ json: c }));
Какой score threshold выбрать для RAG
Начните с ручной оценки 30–50 типовых вопросов. Слишком высокий порог даст много отказов, слишком низкий — уверенные ответы по нерелевантным чанкам. Порог должен быть частью тестов, а не догадкой.
Готовый workflow JSON: скачать и импортировать ¶
Скачать готовый workflow JSON Скачать тестовый payload
{
"name": "Nodbot - Qdrant RAG retrieval with metadata filters",
"nodes": [
{
"name": "Webhook question/input",
"type": "n8n-nodes-base.webhook",
"purpose": "Принять вопрос или документ"
},
{
"name": "Chunk or normalize query",
"type": "n8n-nodes-base.code",
"purpose": "Подготовить документ или вопрос"
},
{
"name": "Create embedding",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Получить embedding"
},
{
"name": "Qdrant upsert/search",
"type": "n8n-nodes-base.httpRequest",
"purpose": "Записать или найти points"
},
{
"name": "Validate sources",
"type": "n8n-nodes-base.if",
"purpose": "Проверить score и metadata"
},
{
"name": "Respond with citations",
"type": "n8n-nodes-base.respondToWebhook",
"purpose": "Вернуть ответ с источниками"
}
],
"connections": "Webhook question/input → Chunk or normalize query → Create embedding → Qdrant upsert/search → Validate sources → Respond with citations"
}
Пошаговая настройка Qdrant collection, embeddings и retrieval ¶
- Создайте Qdrant collection с размерностью вашей embedding-модели.
- Опишите payload metadata: document_id, doc_version, source_url, language, product, status.
- Импортируйте workflow JSON и настройте ingestion и search branches.
- Добавьте filters для published-версий и нужного продукта.
- Проверьте score threshold на реальных вопросах.
Тесты перед production ¶
curl -X POST "https://YOUR-N8N-DOMAIN/webhook/integration-qdrant-n8n" \
-H "Content-Type: application/json" \
--data @integration-qdrant-n8n-payload.json
- Вопрос по актуальному документу должен вернуть правильный source_url.
- Вопрос по устаревшей версии не должен использовать archived chunk.
- Вопрос вне базы знаний должен дать отказ, а не фантазию.
- Фильтр product/language должен ограничивать результаты.
- Повторная индексация версии не должна плодить старые chunks.
Production-риски ¶
- Нет versioning. Старые инструкции конкурируют с новыми.
- Нет source_url. Ответ невозможно проверить.
- Одинаковая коллекция для публичных и внутренних данных. Можно раскрыть закрытый документ.
- Score threshold не протестирован. Бот отвечает по слабым совпадениям.
- Chunking слишком крупный. Retrieval цепляет лишний контекст и ухудшает точность.
Полезные ссылки и смежные материалы ¶
Критерии готовности ¶
- Каждый chunk имеет source_url, doc_version и status.
- Search применяет filters до генерации ответа.
- Низкий score возвращает отказ или human review.
- Индексация умеет заменять старые версии документа.
- Ответ содержит источники, а не только сгенерированный текст.
Nodbot спроектирует Qdrant + n8n: ingestion, chunking, metadata, filters, score threshold, citations и тесты качества retrieval.
Обсудить RAG-проект