RAG с использованием n8n и PostgreSQL: Полное практическое руководство
Retrieval-Augmented Generation (RAG) — это архитектурный подход, который значительно повышает качество и достоверность ответов, генерируемых большими языковыми моделями (LLM), за счет их интеграции с внешними источниками данных. Комбинация n8n, PostgreSQL и LLM представляет собой мощный, гибкий и доступный стек для построения production-готовых RAG-систем. n8n выступает в роли оркестратора рабочих процессов, PostgreSQL — в качестве векторной базы данных для семантического поиска, а LLM (например, через OpenAI API или локальные модели) — в качестве генеративного движка.
Архитектурные компоненты RAG-системы на n8n и PostgreSQL
Система состоит из нескольких ключевых модулей, каждый из которых реализуется с помощью узлов n8n и взаимодействует с PostgreSQL.
1. Подготовка и векторное представление данных (Ingestion Pipeline)
Этот этап преобразует исходные документы (PDF, DOCX, текстовые файлы, веб-страницы) в векторные эмбеддинги и сохраняет их в базе данных.
- Загрузка данных: Использование узлов n8n для чтения файлов из локальной файловой системы, облачных хранилищ (S3, Google Drive) или веб-сайтов (HTTP Request, Webhook).
- Разбиение на чанки (Chunking): Критически важный этап. Текст делится на перекрывающиеся сегменты (например, по 500-1000 символов) с использованием узлов «Code» или «Function» в n8n для реализации логики разбиения. Качество чанкинга напрямую влияет на релевантность поиска.
- Генерация эмбеддингов: Каждый текстовый чанк преобразуется в числовой вектор с помощью модели эмбеддингов (например, OpenAI `text-embedding-3-small`, `all-MiniLM-L6-v2`). В n8n это делается через узел «OpenAI» или «HTTP Request» к соответствующему API.
- Сохранение в PostgreSQL с расширением pgvector: Векторы и метаданные (исходный текст, источник, дата) записываются в таблицу. Для эффективного поиска используется расширение `pgvector`, добавляющее тип данных `vector` и операции с косинусным сходством.
- Векторизация запроса: Пользовательский вопрос преобразуется в эмбеддинг с использованием той же модели, что и на этапе индексации.
- Формирование контекста (Prompt Engineering): Найденные текстовые чанки объединяются в единый контекст, который вместе с исходным вопросом передается в LLM. Промт включает инструкции для модели отвечать только на основе предоставленного контекста.
- Генерация ответа: LLM (например, GPT-4, Claude или локальная модель через Ollama) генерирует финальный, связный ответ, основанный на извлеченном контексте.
- Возврат результата: Ответ, а иногда и ссылки на источники, отправляется пользователю через выбранный канал (веб-интерфейс, мессенджер, API).
- Trigger: Узел «Schedule Trigger» (для периодической индексации) или «Manual Trigger» (для разовой загрузки).
- Read Files: Узел «Local File Trigger» или «HTTP Request» для получения исходных документов.
- Split Text: Узел «Code» с пользовательской логикой на JavaScript для разбиения текста на чанки с перекрытием.
- OpenAI Embedding: Узел «OpenAI» (Embeddings) для создания векторов каждого чанка. Необходимо задать модель (например, `text-embedding-3-small`) и передать текст чанка.
- PostgreSQL: Узел «PostgreSQL» (Insert) для записи в таблицу `document_chunks`. В mapping необходимо передать `content`, `embedding` (как массив чисел), `source` и другие метаданные.
- Trigger: Узел «Webhook» для приема запроса от пользовательского интерфейса.
- OpenAI Embedding: Узел «OpenAI» для создания эмбеддинга пользовательского вопроса.
- PostgreSQL: Узел «PostgreSQL» (Execute Query) для выполнения семантического поиска. Используется запрос вида:
SELECT content, metadata, source, 1 - (embedding '[...]') as similarity
FROM document_chunks
ORDER BY embedding '[...]'
LIMIT 5
Оператор « в pgvector вычисляет косинусное расстояние. - Construct Prompt: Узел «Code» или «Template» для сборки промта. Пример шаблона:
Ты — помощник, отвечающий на вопросы на основе предоставленного контекста. Контекст: { { $json.allResults.map(r => r.content).join("nn") } } Вопрос: { { $input.question } } Ответ: - OpenAI Completion: Узел «OpenAI» (Chat) для генерации ответа. В качестве сообщения передается собранный промт.
- Return Response: Узел «Respond to Webhook» для отправки сгенерированного ответа обратно пользователю.
- Полнотекстовый поиск PostgreSQL: Используйте оператор `ts_rank` вместе с векторным расстоянием в SQL-запросе:
... ORDER BY (embedding $1) + (1 - ts_rank(to_tsvector(content), query)) ... - Фильтрация по метаданным: Добавьте в запрос WHERE-условия, например:
WHERE metadata->>'department' = 'HR'. - Записывать вопросы пользователей, извлеченные чанки и сгенерированные ответы в отдельную таблицу PostgreSQL.
- Рассчитывать и сохранять метрики, такие как время ответа, количество извлеченных чанков, оценка сходства.
- Использовать узлы «Email» или «Telegram» для отправки уведомлений об ошибках.
- LangChain/LlamaIndex + специализированная векторная БД: Более программистко-ориентированный подход, предоставляющий готовые высокоуровневые абстракции для RAG, но требующий написания кода на Python.
- Полностью managed-сервисы: Такие как Azure AI Search, Google Vertex AI Vector Search. Максимальная простота развертывания, но меньшая гибкость и более высокая стоимость.
- Замена PostgreSQL на Qdrant/Weaviate в связке с n8n: Может быть оправдана при работе исключительно с векторными данями в огромных масштабах, где нужна максимальная скорость поиска по векторам.
- Метрики поиска (Retrieval): Precision@K, Recall@K, MRR (Mean Reciprocal Rank). Показывают, насколько релевантные документы извлекаются системой.
- Метрики генерации (Generation): Фактическая точность ответов, их связность, отсутствие галлюцинаций. Оценивается путем ручного разметки тестовой выборки вопросов-ответов или с помощью LLM-ассесоров (например, с использованием GPT-4 как судьи).
2. Рабочий процесс поиска и генерации (Query Pipeline)
Этот процесс запускается при получении пользовательского запроса и формирует итоговый ответ.
Семантический поиск в PostgreSQL: Выполняется SQL-запрос для нахождения N наиболее релевантных чанков по метрике косинусного сходства.
Пошаговая реализация в n8n
Настройка PostgreSQL с pgvector
Перед созданием workflow в n8n необходимо подготовить базу данных.
| Действие | SQL-команда / Описание |
|---|---|
| Установка расширения | CREATE EXTENSION IF NOT EXISTS vector; |
| Создание таблицы для документов |
|
| Создание индекса для поиска | CREATE INDEX ON document_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);Или, для PostgreSQL 12+, USING hnsw для лучшего баланса скорость/точность. |
Workflow индексации документов в n8n
Создайте новый workflow в n8n. Примерная последовательность узлов:
Workflow обработки запроса (Query) в n8n
Ключевые преимущества и недостатки стека n8n + PostgreSQL
| Преимущество | Описание |
|---|---|
| Визуальная разработка и оркестрация | n8n позволяет строить сложные конвейеры данных без глубокого программирования, наглядно отлаживать каждый шаг. |
| Гибкость и интеграции | Огромная библиотека узлов n8n (более 350) для подключения к любым API, базам данных, сервисам уведомлений и т.д. |
| Простота развертывания и стоимость | PostgreSQL — стандартная, надежная БД. pgvector — бесплатное расширение. n8n имеет бесплатный Community Edition с самодостаточным развертыванием. |
| Полный контроль над данными | Все данные, включая векторы, хранятся в вашей собственной инфраструктуре, что критично для соблюдения требований безопасности и конфиденциальности. |
| Гибридный поиск | В PostgreSQL можно комбинировать векторный поиск с полнотекстовым (pg_search) и фильтрацией по метаданным в одном запросе. |
| Недостаток / Ограничение | Описание и возможные решения |
|---|---|
| Производительность на очень больших объемах | Для коллекций в сотни миллионов векторов специализированные векторные БД (Weaviate, Qdrant) могут быть оптимизированнее. Однако для многих корпоративных задач PostgreSQL с индексами HNSW достаточно. |
| Отсутствие встроенного управления чанками | Логику разбиения текста, обновления и удаления чанков необходимо реализовывать самостоятельно в workflow n8n. |
| Зависимость от внешних API для эмбеддингов/LLM | Использование OpenAI влечет затраты и передачу данных третьей стороне. Решение: запуск локальных моделей (например, через Ollama) и использование узла «HTTP Request» в n8n для обращения к ним. |
| Сложность управления состоянием в long-running workflows | Для очень длинных процессов индексации может потребоваться разбиение на несколько workflow и использование очередей. |
Оптимизация и расширенные сценарии
Гибридный поиск
Для повышения точности извлечения контекста векторный поиск можно комбинировать с ключевыми словами.
Рерайтинг (Re-ranking)
Между этапами поиска и генерации можно добавить шаг повторного ранжирования найденных чанков с помощью более точной, но медленной модели (например, `bge-reranker`). Это повышает качество конечного контекста.
Логирование и мониторинг
Для отладки и анализа качества RAG-системы в workflow n8n следует добавить узлы для логирования:
Альтернативы и сравнение
Хотя n8n и PostgreSQL образуют мощную пару, стоит рассмотреть и другие инструменты для конкретных задач:
Ответы на часто задаваемые вопросы (FAQ)
Какой размер чанка (chunk size) и перекрытия (overlap) оптимальны?
Не существует универсального значения. Для технической документации часто используют 500-800 токенов, для нарративных текстов — 1000-2000. Перекрытие в 10-20% от размера чанка помогает сохранить контекст. Необходимо проводить эксперименты на ваших данных, оценивая релевантность извлекаемых фрагментов для тестовых вопросов.
Можно ли использовать локальные LLM и модели эмбеддингов вместо OpenAI API?
Да, это полностью реализуемо. Для локальных моделей (запущенных через Ollama, llama.cpp, Transformers) используйте узел «HTTP Request» в n8n для отправки запросов к их API. Например, для эмбеддингов можно использовать модель `nomic-embed-text`, а для генерации — `llama3` или `mistral`. Это снижает стоимость и повышает конфиденциальность.
Как обновлять данные в RAG-системе при изменении исходных документов?
Требуется стратегия управления версиями чанков. Простейший подход: удалять все чанки, связанные с исходным документом (по полю `source`), и заново запускать pipeline индексации для этого документа. Более сложный — вычислять хэши контента и обновлять только измененные чанки. В n8n это можно организовать с помощью workflow, который сравнивает новые документы с записями в БД.
Как обеспечить безопасность и разграничение доступа к данным в RAG?
RAG на этом стеке позволяет реализовать row-level security (RLS) средствами PostgreSQL. Можно создать таблицу пользователей/групп и привязывать чанки документов к разрешениям. В запросе на поиск (WHERE-условие) добавлять фильтр по идентификатору текущего пользователя. В n8n этот идентификатор можно передавать из веб-хука и использовать в параметризованном SQL-запросе.
Какие индексы pgvector использовать: IVFFlat или HNSW?
Для большинства приложений рекомендуется HNSW (доступен с pgvector 0.5.0). Он обеспечивает лучшее соотношение точности и скорости, особенно при динамическом добавлении данных. IVFFlat требует периодической перестройки индекса при значительном изменении данных и может быть быстрее только на статических коллекциях при очень точной настройке параметров.
Как оценить качество работы моей RAG-системы?
Необходимо отслеживать метрики двух типов:
В n8n можно создать отдельный evaluation workflow, который прогоняет тестовый набор вопросов и автоматически вычисляет часть этих метрик.
Добавить комментарий