Архитектура двухконтурной 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.
- PFRAG получает файл или URL.
- Worker превращает источник в
raw_md. - LLM cleanup создаёт
clean_md. - Dedup убирает повторяющиеся чанки, строки или шаблонный шум.
- PFRAG отправляет готовый материал в LightRAG.
- RAG индексирует документ, обновляет статус и делает его доступным в чате.
Такой контракт проще поддерживать: на вход retrieval-контура приходит уже подготовленный текст, а не произвольный набор сырых файлов с разным качеством.
Где проходит граница production-доработок
В текущем виде RAG уже содержит фоновые задачи FastAPI для индексации, а PFRAG использует Celery/Redis для тяжёлой обработки. Для production-версии логично сделать границу ещё строже: ingestion тоже можно перевести на устойчивые очереди, добавить миграции, расширить мониторинг и аккуратнее развести права доступа.
Главная идея архитектуры остаётся прежней: сначала отдельный контур готовит знания, потом отдельный контур отвечает по ним на вопросы.