Перейти к содержимому

ADR 0001 — GraphRAG: отложенное внедрение и условия включения

Это содержимое пока не доступно на вашем языке.

ADR 0001 — GraphRAG: отложенное внедрение и условия включения

Section titled “ADR 0001 — GraphRAG: отложенное внедрение и условия включения”
  • Статус: Accepted (defer-with-seam)
  • Дата: 2026-05-30
  • Контекст-аудиты: docs/audits/audit_claude_30_05_26.md (§3.1 — GraphRAG отсутствует, обоснованно отложен), docs/research/rag-landscape-2026.md (§2 — GraphRAG «для корпусного понимания»)
  • Связано: демо-корпус data/uploads/aircargo/ (201 док, ~7K чанков), docs/plans/2026-05-30-demo-corpus-and-rag-grounding.md

Продукт позиционируется как универсальный гибкий RAG, а не как support-бот на 3 дока. До 2026-05-30 KB содержал 3 игрушечных дока (warranty/returns/errors). Сейчас в проект заведён реальный демо-корпус из 201 документа (HR-политики, договоры, претензии, транспортная логистика, комплаенс, FAQ; RU; медиана ~21 200 символов на документ; ~7000 чанков при текущем chunking). Это первый момент, когда «масштаб» перестал быть гипотезой.

Вопрос: нужен ли GraphRAG, и если да — когда и в какой форме, чтобы он был предусмотрен архитектурно, а не прикручен задним числом.

Что такое GraphRAG и почему он дорогой

Section titled “Что такое GraphRAG и почему он дорогой”

Классический Microsoft-style GraphRAG строит граф сущностей/отношений поверх корпуса:

  1. По каждому чанку — LLM извлекает сущности и связи (entity/relation extraction).
  2. Граф кластеризуется (Leiden community detection).
  3. По каждому сообществу — LLM пишет summary (community report).
  4. Запрос: local search (по сущностям) или global search (map-reduce по community-summaries).

Цена: шаг 1 — это один LLM-вызов на чанк на этапе индексации. Для нашего корпуса (~7000 чанков) это ~7000 LLM-вызовов только на построение графа — ровно тот fan-out, который аудит (R3/R4) уже отмечает как болевую точку даже на одном ответе. На текущем железе (Windows-ноут — thin client; Mac — слабый; см. AGENT_STATE.md thin-client boundary) полная индексация GraphRAG локально нереалистична — это Colab/remote-only задача.

Польза при этом реальна, но узкая: multi-hop recall +6.4 п., снижение галлюцинаций 20–30 % (arxiv 2506.00054) — на «глобальных» вопросах («как связаны A и B?», «какие темы проходят через корпус?»). На фактологических single-hop вопросах поддержки (90 %+ реального трафика) hybrid+rerank уже даёт верный ответ дешевле.

Отложить полный GraphRAG как дефолт, но заложить архитектурный шов сейчас.

1. Шов в коде (предусмотреть, не включать)

Section titled “1. Шов в коде (предусмотреть, не включать)”
  • Ввести настройку RAG_RETRIEVAL_STRATEGY ∈ {vector, hybrid, graph} (дефолт hybrid). Сейчас HybridRetriever жёстко зашит; вынести за интерфейс Retriever.retrieve(query) -> docs, чтобы graph-ретривер подключался как третья реализация без правки графа LangGraph.
  • Узел classify_complexity уже существует и уже различает сложность запроса. Добавить класс global/multi_hop и ветку маршрутизации: global → graph_retrieve, иначе → hybrid. Это превращает GraphRAG в опциональный путь для подмножества запросов, а не в замену основного ретривера.

2. Условия включения (trigger)

Section titled “2. Условия включения (trigger)”

Включать graph-путь, когда выполнено И то, и другое:

  • Масштаб корпуса: > ~2 000 документов ИЛИ > ~50 000 чанков на тенант. (Текущие 201 / ~7K — ниже порога; для них hybrid+rerank достаточно и дешевле.)
  • Класс запроса: classify_complexity пометил запрос как глобальный/multi-hop.

Оба условия защищают от того, чтобы платить graph-цену на трафике, который её не требует.

3. Чем строить, когда дойдём (НЕ катать руками)

Section titled “3. Чем строить, когда дойдём (НЕ катать руками)”

Приоритет — по стоимости индексации, от дешёвого к дорогому:

  1. Дешёвый промежуточный слой (можно сделать без LLM-extraction уже сейчас): metadata/relational граф из уже имеющейся структуры корпуса — категория (01_hr, 03_legal, 05_tlog…), тип документа, явные перекрёстные ссылки между документами. Это «граф документов», а не «граф сущностей»: 0 LLM-вызовов, строится из метаданных loader’а. Покрывает часть multi-hop («покажи все документы, связанные с договором X»).
  2. LightRAG / nano-graphrag — на порядок дешевле MS GraphRAG (dual-level retrieval, инкрементальные апдейты, кратно меньше LLM-вызовов на индексацию). Рекомендованный первый «настоящий» GraphRAG для этого проекта.
  3. LlamaIndex PropertyGraphIndex — если нужен зрелый property-graph с готовыми экстракторами.
  4. Microsoft GraphRAG — только если заказчику нужен именно его global-search map-reduce и бюджет на индексацию это оправдывает.

Во всех случаях: использовать готовую библиотеку, не реализовывать извлечение графа руками.

  • Построение графа — Colab/remote-only (GPU + отсутствие RAM-лимита локальной машины).
  • Уважать DAILY_COST_LIMIT_USD; индексировать инкрементально (только новые/изменённые документы — DocumentChangeTracker уже есть в ingestion/loader.py).
  • Кэшировать промежуточные артефакты графа (узлы/рёбра/summaries) как parquet/jsonl, не пересчитывать на каждый прогон.
  • (+) Продукт «предусматривает» GraphRAG: шов + trigger + выбранный стек задокументированы; включение — это смена флага и подключение реализации, а не переписывание пайплайна.
  • (+) Не платим graph-цену на текущем масштабе и на single-hop трафике.
  • (+) Дешёвый metadata-граф из структуры корпуса доступен уже сейчас как первый шаг.
  • (−) До включения multi-hop «глобальные» вопросы обслуживаются хуже (ограничение hybrid). Принимаем: такой трафик в support-сценарии редок.
  • (−) Шов (RAG_RETRIEVAL_STRATEGY + ветка global) — это код, который надо написать и покрыть тестами до того, как graph-реализация появится; иначе шов протухнет.

Вернуться к включению graph-пути, когда любой тенант перешагнёт ~2 000 документов / ~50 000 чанков, или когда eval (R7) покажет систематический провал на multi-hop классе вопросов, который hybrid+rerank не закрывает.