Архитектура двухконтурной RAG системы

В RAG Content Pipeline два разных проекта работают как части одной системы. PFRAG занимается подготовкой и операционным управлением контентом. RAG отвечает за индексацию, retrieval и чат.

Такое разделение выглядит чуть сложнее, чем один монолитный сервис, но оно хорошо ложится на реальные задачи. Подготовка документов и ответы пользователю — разные процессы по нагрузке, ошибкам и требованиям к интерфейсу.

Контур 1. PFRAG preprocessing и operations

PFRAG — это рабочий интерфейс и backend для контента до индексации. Его задача — принять материалы, обработать их и довести до состояния, где они не ломают поиск.

Внутри этого контура есть:

  • Solid.js SPA для загрузки файлов, URL-парсинга, предпросмотра Markdown, настроек моделей и промптов;
  • FastAPI backend для REST API, статусов, файлов, настроек и логов;
  • Celery worker для тяжёлых задач: OCR, парсинг сайтов, LLM-очистка, дедупликация, PDF export;
  • Redis как брокер очередей;
  • PostgreSQL для файлов, статусов, настроек, промптов, моделей и dedup-отчётов;
  • Nginx как reverse proxy для frontend и /api.

Это операционный контур. В нём важны очереди, retry, статусы, возможность открыть результат, вручную проверить Markdown, объединить файлы или запустить dedup повторно.

Контур 2. RAG retrieval и chat backend

RAG — это backend, к которому можно обращаться после подготовки контента. Он индексирует документы и отвечает на вопросы.

Подтверждённая архитектура RAG-контура:

  • FastAPI backend;
  • LightRAG как RAG engine;
  • Qdrant для векторного хранилища;
  • Neo4j для графа знаний;
  • PostgreSQL для документов, статусов и истории чата;
  • REST, SSE и WebSocket endpoints для чата;
  • опциональный Bearer-токен и rate limiting;
  • healthcheck PostgreSQL, Qdrant и Neo4j.

Этот контур ближе к product API. Для него важны режимы поиска, streaming-ответы, multi-turn контекст, история сессий и понятные endpoints для внешних интерфейсов.

Почему не смешивать эти роли

Если всё держать в одном сервисе, появляются неприятные компромиссы. OCR и LLM-cleanup могут быть долгими задачами, а чат должен отвечать быстро и предсказуемо. Парсинг сайта может упасть из-за внешнего URL, а retrieval backend не должен из-за этого терять доступность.

Разделение даёт несколько практических преимуществ:

  • Изоляция ошибок: сбой OCR или парсинга не обязан ломать чат по уже готовой базе.
  • Разные интерфейсы: редактору контента нужен файловый workspace, пользователю чата — простой вопрос-ответ.
  • Разные очереди нагрузки: ingestion и preprocessing можно выносить в фон, а чат держать отдельным API.
  • Более честная ответственность данных: PFRAG отвечает за качество Markdown, RAG — за поиск и ответ.

Как данные проходят между контурами

Связка между PFRAG и RAG проходит через подготовленный Markdown и ingestion API.

  1. PFRAG получает файл или URL.
  2. Worker превращает источник в raw_md.
  3. LLM cleanup создаёт clean_md.
  4. Dedup убирает повторяющиеся чанки, строки или шаблонный шум.
  5. PFRAG отправляет готовый материал в LightRAG.
  6. RAG индексирует документ, обновляет статус и делает его доступным в чате.

Такой контракт проще поддерживать: на вход retrieval-контура приходит уже подготовленный текст, а не произвольный набор сырых файлов с разным качеством.

Где проходит граница production-доработок

В текущем виде RAG уже содержит фоновые задачи FastAPI для индексации, а PFRAG использует Celery/Redis для тяжёлой обработки. Для production-версии логично сделать границу ещё строже: ingestion тоже можно перевести на устойчивые очереди, добавить миграции, расширить мониторинг и аккуратнее развести права доступа.

Главная идея архитектуры остаётся прежней: сначала отдельный контур готовит знания, потом отдельный контур отвечает по ним на вопросы.