Локальный RAG на n8n: опыт Flowwow с self-hosted LLM | AiManual
AiManual Logo Ai / Manual.
06 Май 2026 Гайд

Как собрать локальный RAG на n8n: опыт Flowwow с self-hosted LLM

Пошаговое руководство по сборке корпоративного RAG на n8n с self-hosted LLM. Экономия в 5,5 раз. Кейс Flowwow: архитектура, ошибки, результаты.

В середине 2026 года счёт за GPT-4o и Claude 4 Opus в Flowwow перевалил за $12 000 в месяц. Маржа таяла, юристы разводили руками из-за GDPR, а latency бесила даже ботов. Мы решили засунуть всё в свой дата-центр. Итог: RAG-ассистент на n8n с self-hosted LLM, который обходится в 5,5 раз дешевле и работает быстрее облачных аналогов. Да, без фанатизма и без API.

Дисклеймер: статья — не реклама вендоров. Мы используем то, что реально работает в проде. Все цифры — из нашего счета.

Почему n8n, а не LangChain или ручное API?

Сначала хотели написать логику на Python. Но поддержка 50+ интеграций, визуальные workflow, мониторинг прямо в UI — это перевесило. n8n (версия 1.82 на момент написания) позволяет инженерам не из AI-команды менять pipeline без деплоя кода. Плюс community-ноды для Ollama и Qdrant уже есть в маркетплейсе. Не пришлось даже писать кастомную ноду для ретривера.

Кстати, если вы ещё не в курсе, как n8n работает с агентами, советую глянуть наш гайд про голосового ассистента на n8n — там разобраны основы работы с памятью и инструментами.

Архитектура: что у нас под капотом

Мы не изобретали велосипед. Стандартный RAG chain: query → embed → retrieve → rerank → generate. Но с тремя особенностями:

  • Self-hosted LLM — Qwen2.5-14B-Instruct через Ollama (1× RTX 6000 Ada в нашей стойке). Не Mistral, не Llama — именно Qwen дал лучший balance quality/speed для русскоязычной базы знаний.
  • Векторная БД — Qdrant (не Chroma, не FAISS). Причина: sharding и гибридный поиск из коробки, без костылей.
  • Chunking — не фиксированный size, а семантическое разделение по заголовкам Markdown + hierarchical parent-child (родительский чанк 512 токенов, дочерние 128).
КомпонентЧто используемПочему
Оркестраторn8n 1.82 (self-hosted)Low-code, Community nodes, webhooks
LLMQwen2.5-14B-Instruct (Ollama)Лучшее качество для русского языка в 14B
Embeddingsmxbai-embed-large-v1 (Ollama)768 dim, отлично работает с Qdrant
Vector DBQdrant 1.12Sharding, гибридный поиск, быстрый deploy
RerankerBAAI/bge-reranker-v2-m3Поднимает precision на +15%

Шаг 1. Поднимаем железо и софт

Железо: одна машина с RTX 6000 Ada (48GB VRAM) хватает на Qwen2.5-14B (int4 quant) + embeddings + reranker + Qdrant. Для прода докупили вторую карту — на раздельные инференс и векторный поиск, но для старта хватит и одной.

Ставим Docker Compose на Ubuntu 24.04 LTS. Вот рабочий конфиг:

version: '3.8'
services:
  n8n:
    image: n8nio/n8n:1.82.0
    ports:
      - "5678:5678"
    volumes:
      - ./n8n_data:/home/node/.n8n
    environment:
      - N8N_METRICS=true
      - EXECUTIONS_DATA_PRUNE=true
    restart: unless-stopped

  qdrant:
    image: qdrant/qdrant:v1.12.0
    ports:
      - "6333:6333"
    volumes:
      - ./qdrant_storage:/qdrant/storage

  ollama:
    image: ollama/ollama:0.5.7
    ports:
      - "11434:11434"
    volumes:
      - ./ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
  reranker:
    image: ghcr.io/huggingface/text-generation-inference:3.0.0
    command: --model-id BAAI/bge-reranker-v2-m3
    ports:
      - "8080:80"
    volumes:
      - ./reranker_cache:/data
    environment:
      - HF_TOKEN=${HF_TOKEN}

Внимание: без NVIDIA Container Toolkit docker не увидит GPU. Не забудьте установить nvidia-container-toolkit перед стартом.

Шаг 2. Заливаем базу знаний и индексируем

У нас база знаний — 2000+ markdown-файлов с документацией, FAQ и инструкциями. Пишем скрипт на Python (запускаем как n8n Execute Command), который:

  1. Читает все .md файлы.
  2. Сплитит по заголовкам второго уровня (##) — каждый блок становится родительским чанком.
  3. Внутри блока режет по 128 токенов с overlap 20 — дочерние чанки.
  4. Для каждого дочернего чанка генерирует эмбеддинг через Ollama.
  5. Записывает в Qdrant коллекцию с payload (текст, метаданные, id родителя).

Код для эмбеддинга (используем Ollama REST API):

import requests

def get_embedding(text: str) -> list[float]:
    resp = requests.post(
        "http://ollama:11434/api/embeddings",
        json={"model": "mxbai-embed-large-v1", "prompt": text}
    )
    return resp.json()["embedding"]

После индексации проверяем в n8n: триггер на Webhook → HTTP Request к Qdrant на поиск → возвращаем топ-5 chunks.

Шаг 3. Строим workflow в n8n

Самый ответственный момент. Workflow состоит из пяти нод:

  • Webhook — принимает вопрос от пользователя (например, из Telegram бота).
  • HTTP Request — отправляет запрос к Ollama embeddings.
  • HTTP Request — поиск в Qdrant (hybrid query: dense + sparse).
  • HTTP Request — reranker на TGI (переранжирует 20 candidates до 5).
  • Ollama Chat Model node (из n8n Community) — генерирует ответ с контекстом.

Вот пример конфигурации поискового запроса в Qdrant (n8n HTTP Request):

{
  "method": "POST",
  "url": "http://qdrant:6333/collections/knowledge_base/points/search",
  "headers": {
    "Content-Type": "application/json"
  },
  "body": {
    "vector": {{$json.embedding}},
    "limit": 20,
    "with_payload": true,
    "params": {
      "hybrid": true
    }
  }
}
💡
Мы используем гибридный поиск, потому что dense embedding плохо ловит точные совпадения по номерам заказов. Sparse вектор (splade-v3) компенсирует этот недостаток.

После reranker формируем prompt для LLM:

// n8n Code node
const context = $items("Reranker").map(item => item.json.payload.text).join("\n---\n");
const question = $json.question;

return {
  messages: [
    {
      role: "system",
      content: "Ты поддержка Flowwow. Отвечай на русском, используя только контекст. Если не знаешь — скажи честно."
    },
    {
      role: "user",
      content: `Контекст:\n${context}\n\nВопрос: ${question}`
    }
  ]
};

Типичные ошибки (наши грабли)

Ошибка №1. Chunking без учёта структуры.

Сначала резали по 256 токенов тупо. Ответы LLM были неполными, потому что обрывались на середине инструкции. Решение — семантический сплит по Markdown-заголовкам с parent-child.

Ошибка №2. Забыли про rate limit Ollama.

Когда запустили prod, Qdrant и reranker начали слать запросы параллельно — Ollama на одном GPU упал в OOM. Пришлось добавить очередь: n8n нода "Wait" перед каждой генерацией (только на первом запросе — дальше кэшируем embeddings).

Ошибка №3. Не поставили reranker.

Первые версии без reranker выдавали мусор: LLM могла ответить на основе нерелевантного чанка. BGE-reranker поднял accuracy с 72% до 89% на нашем тестовом сете.

Если у вас мало GPU — reranker можно заменить простым косинусным расстоянием, но точность упадёт. Лучше всё-таки выделить отдельный CPU-инференс для reranker (через ONNX).

Во сколько это обошлось?

Считаем ежемесячные затраты (дата-центр + железо + амортизация):

  • Аренда 2× RTX 6000 Ada + 64GB RAM — $1 200 (hetzner auction).
  • Обслуживание, сетевое, электричество — $400.
  • Амортизация сервера (за 3 года) — $300.
  • Итого: ~$1 900 / месяц.

До этого мы платили за GPT-4o и Claude 4 Opus ~$12 000 (токены + фиксированные планы). Экономия в 5,5 раз. Да, мы потеряли в скорости (6-8 секунд против 1-2 у облачных), но для внутреннего ассистента это некритично.

Для полного погружения в локальный RAG без API советую почитать этот гайд про Agentic RAG — он идеально дополняет наш кейс (у нас chain, а там самостоятельные агенты).

Кстати, мы также используем эту инфраструктуру для голосовых ассистентов. Если интересно — вот отдельный кейс с n8n и RAG в голосе.

Неочевидный совет (зачем я это писал)

Большинство материалов про RAG научат вас ставить Ollama, Qdrant и писать простой pipeline. Но реальная боль начинается, когда модель отвечает "я не знаю" на вопрос, на который есть ответ в базе. Главная причина — перекос токенов в системном промпте. Мы потратили неделю, чтобы выставить правильный temperature (0.15) и добавить few-shot примеры из нашей базы прямо в system prompt. Без этого ни reranker, ни правильный chunking не спасают.

Второй момент: не гонитесь за самой большой моделью. Qwen2.5-7B дал нам 85% качества, 14B — 92%, а Llama-3.1-70B (quantized) — 94%, но прирост скорости падал в 3 раза. Для внутреннего ассистента 92% — золотая середина.

И напоследок: если вы думаете, что self-hosted — это про анархию и "никаких облаков", то ошибаетесь. Через месяц после запуска мы поняли, что для обновления эмбеддингов при изменении базы знаний нужна CI/CD. Сейчас у нас GitHub Actions → n8n webhook → переиндексация одной коллекции. Без автоматизации локальный RAG превращается в ад ручного управления.

Технологии не стоят на месте. В 2026 году локальные LLM уже на равных конкурируют с облачными. Наш кейс — лучшее тому доказательство.

Подписаться на канал