Hybrid Retrieval на LightRAG

RAG-контур в этом проекте построен вокруг LightRAG. Его роль — принять подготовленный текст, разложить его на индексируемые представления и дать API для вопросов по базе знаний.

В отличие от простой схемы «файл → embeddings → ближайшие чанки», здесь используется связка векторного и графового поиска.

Основные хранилища

RAG-сервер поднимается с несколькими backend-хранилищами:

  • Qdrant — векторный слой для embeddings и семантического поиска;
  • Neo4j — граф знаний для сущностей и связей;
  • PostgreSQL — метаданные документов, статусы, сессии и история чата.

LightRAG соединяет Qdrant и Neo4j как retrieval engine. PostgreSQL не заменяет поисковый индекс, но помогает управлять документами, статусами и диалогами.

Ingestion pipeline

Документ попадает в RAG через POST /api/v1/ingest. На входе сервер вычисляет MD5-хеш, проверяет дубликат в PostgreSQL, извлекает текст из поддержанных форматов и создаёт запись со статусом PENDING.

Дальше индексация уходит в фон:

  1. статус обновляется на INDEXING;
  2. LightRAG запускает ainsert(text);
  3. текст разбивается на чанки;
  4. embeddings сохраняются в Qdrant;
  5. сущности и связи извлекаются через LLM и сохраняются в Neo4j;
  6. статус становится COMPLETED или ERROR;
  7. если указан webhook, сервер отправляет уведомление о завершении.

PFRAG может отдавать в этот контур уже очищенный Markdown. Это снижает риск, что LightRAG будет индексировать навигационный шум, дубли или плохо распознанный текст.

Query modes

Для чата доступны режимы поиска:

  • naive — простой векторный поиск;
  • local — поиск с локальным контекстом графа;
  • global — глобальный обход графа;
  • hybrid — комбинированный режим.

hybrid полезен как режим по умолчанию, потому что он не ограничивается только ближайшими embeddings и может использовать графовые связи. Но остальные режимы тоже важны: они помогают диагностировать, где именно retrieval даёт лучший контекст для конкретной базы.

Multi-turn chat

RAG-сервер хранит историю чата в PostgreSQL. Если в запросе передать session_id, backend подгружает последние сообщения сессии и добавляет их в контекст. Это нужно для уточняющих вопросов: пользователь может спросить «а подробнее?» без повторения всей темы.

Если session_id не передан, сервер создаёт новый UUID. Для внешнего UI это простой контракт: сохранять один session id на диалог и передавать его в следующих запросах.

REST, SSE и WebSocket

Чат можно подключать несколькими способами:

  • POST /api/v1/chat — обычный JSON-ответ;
  • POST /api/v1/chat/stream — SSE-стриминг, когда текст появляется по частям;
  • WS /api/v1/ws/chat — WebSocket для real-time сценариев.

Это делает backend гибким. Telegram-боту часто достаточно REST. Web UI удобнее подключать через SSE или WebSocket, чтобы пользователь видел ответ по мере генерации.

Управление документами и healthcheck

Кроме чата, RAG-контур даёт endpoints для списка документов, статуса по хешу, удаления и переиндексации. Есть статистика и healthcheck, который проверяет PostgreSQL, Qdrant и Neo4j.

Для базы знаний это важно не меньше самого чата: оператор должен понимать, какие документы уже готовы, какие зависли, где произошла ошибка и живы ли основные хранилища.

Роль LightRAG в общей системе

LightRAG в этом pipeline — не замена подготовке данных. Он хорошо работает как retrieval engine, когда получает нормальный текст. Поэтому лучший результат получается на границе двух контуров: PFRAG отвечает за чистый вход, а RAG отвечает за индекс, query modes и интерфейсы ответа.