Skip to content

Знання — LightRAG

Що і навіщо

knowledge = LightRAG (бібліотека HKUDS), взята свіжо (greenfield — не порт кастомної 1.x реалізації на OpenSearch + Neo4j). Це graph-RAG рушій: чанкінг → LLM-видобування сутностей/зв'язків → граф знань → multi-mode retrieval (naive / local / global / hybrid).

Деплой: окремий сервіс

LightRAG — Python, а api — NestJS. Тому:

  • LightRAG крутиться окремим сервісом (Python, server-режим) у Hetzner k8s.
  • agent/knowledge — тонкий gateway до нього: CRUD баз знань, заливання документів, проксі retrieval, експозиція через mcp. Турботи ingestion / query / graph схлопуються всередину LightRAG — це не наші сабслайси.

Storage-бекенд (РІШЕННЯ ВІДКРИТЕ)

LightRAG абстрагує сховища KV / vector / graph. Два кандидати:

  • Unified Postgres (pgvector + Apache AGE) — app-дані + KV + вектор + граф в одному Postgres. Прибирає окремий infra/vector і Neo4j. Потребує self-host Postgres на Hetzner (managed Neon скоріш за все не дасть розширення AGE). Краще для small/medium розмірів баз.
  • Neo4j (граф) + виділений vector-DB (Qdrant/Milvus) — для великих баз; знову відкриває Neon для app-даних.

Вибір залежить від очікуваної форми масштабу (нижче).

Масштаб: стіна — це індексація

Для мільйонів файлів обмеження — індексація, а не зберігання. LightRAG робить на кожен чанк LLM-видобування сутностей/зв'язків → мільйони файлів = великі токени + час (властивість graph-RAG). Тому:

  • індексація має бути async / у черзі (tasks + BullMQ), інкрементальною, rate-limited, з бюджетом токенів;
  • тримаємо дешевий naive vector-RAG шлях — граф вмикаємо лише там, де він окупається;
  • мультитенантність рятує: це не один гігантський граф, а багато баз (LightRAG workspaces), здебільшого невеликих → природний шардинг. Важкий кейс — мільйони в одній базі.

Бекенд за формою масштабу: багато невеликих баз → unified PG(pgvector+AGE) ок; мільйони в одній базі → pgvector напружується (~кілька M), а AGE не обкатаний на величезних графах → краще Neo4j + Qdrant/Milvus.

Референс (уже працює в Ranch): cleanslice/ranch/k8s/platform/lightrag/* ганяє ghcr.io/hkuds/lightrag на Postgres з pgvector + AGE (LIGHTRAG_{KV,VECTOR,GRAPH,DOC_STATUS}_STORAGE=PG*). Нюанс: у стокового CNPG немає AGE, тому LightRAG-БД — окремий Postgres (образ gzdaniel/postgres-for-rag), окремо від app-БД на CNPG — поки немає кастомного CNPG-with-AGE. EMBEDDING_DIM фіксується при першому індексі (зміна ⇒ реіндекс). Див. GitOps.

WARNING

LightRAG молодий (2024). Бенчмарк на цільовому масштабі до коміту і пінь версію (схема сховища змінюється між релізами).

Мультитенантність через workspace

Параметр workspace у LightRAG дає логічну ізоляцію всередині спільного сховища (підтека для файлових бекендів; префікс / неймспейс / label графа для БД-бекендів — перевіряй per backend & version).

Дизайн:

  • 1 workspace = 1 база знань.
  • Сервіс LightRAG тримає пул інстансів LightRAG за workspace (lazy-init + LRU/idle-евікшн), усі ділять креди одного бекенда.
  • Безпека: api (agent/knowledge) виводить workspace з автентифікованого team/kb — ніколи не довіряй workspace від клієнта — і є єдиним, хто зве внутрішній сервіс LightRAG. Завжди непорожній workspace (порожній = спільний дефолт → витік між тенантами).
  • Життєвий цикл: видалення бази зносить її workspace (delete-by-doc + зачистка бекенда, напр. drop AGE-графа). Холодний старт інстансу на першій операції бази → враховуй у латентності (прогрів/кеш).
python
# Сервіс LightRAG (Python), спрощено
_pool: dict[str, LightRAG] = {}             # workspace -> instance (LRU)

async def get_rag(workspace: str) -> LightRAG:
    if workspace not in _pool:
        rag = LightRAG(
            working_dir=f"/data/{workspace}",
            workspace=workspace,             # ← ізоляція
            kv_storage="PGKVStorage",
            vector_storage="PGVectorStorage",
            graph_storage="PGGraphStorage",  # AGE
            # llm / embedding функції ...
        )
        await rag.initialize_storages()
        _pool[workspace] = rag               # + евікшн за розміром/idle
    return _pool[workspace]
# ендпоінти: POST /insert {workspace, docs} ; POST /query {workspace, query, mode}

Gateway у api зве ці ендпоінти з workspace = kb_id власника.