Hybrid Retrieval на LightRAG
RAG-контур в этом проекте построен вокруг LightRAG. Его задача не просто «положить документы в базу», а превратить подготовленный текст в основу, по которой можно задавать живые вопросы и получать ответы с опорой на базу знаний.
В простом RAG часто всё сводится к цепочке «файл → embeddings → ближайшие чанки». Такая схема понятна, но в реальных документах смысл редко лежит только в одном похожем фрагменте. Важны соседние понятия, связи между сущностями, повторяющиеся темы и то, как один документ объясняет другой. Поэтому здесь используется гибридный retrieval: embeddings находят близкие фрагменты по смыслу, а граф помогает не потерять отношения между сущностями.
Основные хранилища
RAG-сервер поднимается с несколькими backend-хранилищами, и у каждого из них своя роль в общей картине:
- Qdrant — векторный слой для embeddings и семантического поиска;
- Neo4j — граф знаний для сущностей и связей;
- PostgreSQL — метаданные документов, статусы, сессии и история чата.
LightRAG соединяет Qdrant и Neo4j как retrieval engine: один слой отвечает за смысловую близость, другой — за связи. PostgreSQL не заменяет поисковый индекс, зато делает систему управляемой: помогает понимать, какие документы загружены, что с ними происходит и к какому диалогу относится конкретный запрос.
Ingestion pipeline
Документ попадает в RAG через POST /api/v1/ingest. На входе сервер вычисляет MD5-хеш, проверяет дубликат в PostgreSQL, извлекает текст из поддержанных форматов и создаёт запись со статусом PENDING.
Дальше индексация уходит в фон. Это важно для production-пайплайна: загрузка документа не должна превращаться в непрозрачную операцию, после которой непонятно, готова база к вопросам или нет.
- статус обновляется на
INDEXING; - LightRAG запускает
ainsert(text); - текст разбивается на чанки;
- embeddings сохраняются в Qdrant;
- сущности и связи извлекаются через LLM и сохраняются в Neo4j;
- статус становится
COMPLETEDилиERROR; - если указан webhook, сервер отправляет уведомление о завершении.
PFRAG может отдавать в этот контур уже очищенный Markdown. Для retrieval это не косметика, а качество входа: чем меньше в тексте навигационного шума, дублей и плохо распознанных фрагментов, тем меньше вероятность, что LightRAG построит индекс вокруг случайного мусора.
Query modes
Для чата доступны режимы поиска:
naive— простой векторный поиск;local— поиск с локальным контекстом графа;global— глобальный обход графа;hybrid— комбинированный режим.
hybrid полезен как режим по умолчанию, потому что вопрос пользователя не всегда попадает точно в формулировку исходного документа. Иногда нужен ближайший по смыслу чанк, иногда — связь между сущностями, а часто и то и другое. Комбинированный режим даёт 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.
Для базы знаний это важно не меньше самого чата. Если ответ плохой, причина может быть не в модели, а в данных: документ ещё индексируется, упал один из backend-слоёв, загрузился дубль или в индекс попал не тот текст. Оператору нужны статусы и проверки, чтобы видеть такие проблемы до того, как они станут «магическими» ошибками retrieval.
Роль LightRAG в общей системе
LightRAG в этом pipeline — не замена подготовке данных. Он хорошо работает как retrieval engine, когда получает нормальный текст и может разложить его на чанки, embeddings и графовые связи.
Поэтому лучший результат рождается на границе двух контуров: PFRAG отвечает за чистый вход, а RAG — за индекс, query modes и интерфейсы ответа. Hybrid Retrieval здесь нужен именно для этой связки: дать системе несколько способов найти полезный контекст, а не заставлять весь ответ зависеть от одного канала поиска.