Document ENgine for Deep Retrieval and Analysis
Multigraph document intelligence engine. Строит мультиграф из любого документа (17K+ фактов, 2K+ сущностей, 3.5K+ саммари, 15K+ связей) и использует его как интеллектуальный слой для точного поиска. 8-фазный pipeline индексации, GPU оркестрация (GLiNER + vLLM), bundle isolation, 100% локальный инференс.
95% retrieval accuracy на DENDRA-Bench (400 вопросов, 10 документов, 6 доменов). +23% vs Plain RAG. Legal 99%, Finance 97%, Fiction 96%, Tech 95%, Medical 94%.
DENDRA-Bench: 400 вопросов, 10 документов, 6 доменов, все русскоязычные. 8 категорий вопросов: factual, cross-doc, reasoning, semantic, negative, multi-hop, slang, impact.
DENDRA █████████████████████████████████████████ 95% 382/400
Plain RAG ████████████████████████░░░░░░░░░░░░░░░░░ 72% 289/400
LlamaIndex ██████████████████████░░░░░░░░░░░░░░░░░░░ 65% 261/400
По доменам (DENDRA / Plain RAG / LlamaIndex):
Legal: 99% / 58% / —
Finance: 97% / 80% / —
Fiction: 96% / 78% / —
Tech: 95% / 86% / —
Medical: 94% / 80% / —
Tables: 76% / 56% / —
Все системы на одном LLM (Llama 8B via vLLM) и одном корпусе. Честное сравнение.
Мультиграф: 17,510 propositions, 2,023 entities, 3,500+ RAPTOR summaries, 15,386 edges, 132 cross-doc edges, 7 bundles. Всё на одном SQLite файле (180MB).
Методология: chunk size 800, embedding e5-large multilingual (ONNX), метрика text_coverage с Snowball stemming для русской морфологии. Hybrid metric: stemming для реальных вопросов, exact для negative. Расположение: tests/benchmark/dendra_bench/.
INDEXING (8-phase pipeline with GPU orchestration):
1. Parse+Chunk → 2. Embed (ONNX) → 3. GLiNER entities (GPU subprocess)
→ 4. Propositions (vLLM) → 5. Re-embed → 6. Bundles+cross-refs
→ 7. RAPTOR trees (parallel, numpy k-means) → 8. SENTINEL (NLI)
SEARCH (graph as intelligence layer):
Query → Vector+FTS5+Keywords (RRF merge, chunks only)
→ Proposition enrichment (additive boost)
→ Sibling expansion → top-30 results
MULTIGRAPH (3 layers):
Structural tree: document → chapter → article → chunk (15K+ edges)
Entity network: entity ↔ chunk, entity ↔ entity (2K+ entities)
Proposition layer: atomic facts → parent chunks (17K+ propositions)
+ RAPTOR summaries (3.5K, 3 levels) + cross-doc edges (bundle-scoped)
| Модуль | Что делает | Научная основа |
|---|---|---|
| SCOPE — Structural Context Overlay for Precise Embeddings | Добавляет контекст документа/секции к чанкам перед эмбеддингом | Anthropic Contextual Retrieval (2024) |
| ATOM — Atomic Text Origination Module | Декомпозирует текст в атомарные факты через LLM. Batch mode (3 чанка/вызов), auto-retry, полное покрытие всех текстовых нод | Dense X Retrieval (2024) |
| RAPTOR — Recursive Abstracting Processing for Tree-Organized Retrieval | Иерархическая кластеризация + LLM-суммаризация для многоуровневого поиска | RAPTOR, ICLR 2024 (Stanford) |
| TRACE — Traversal-Ranked Associative Chain Expansion | Multi-hop поиск сущностей через Personalized PageRank на графе знаний | HippoRAG, NeurIPS 2024 |
| LENS — Layout-Evaluated Narrative Scoring | Автоопределение типа документа + query intent detection (type-aware boost + definition title boost) | Оригинальная разработка |
| BRIDGE — Bundle-Resolved Inter-Document Graph Exploration | Кросс-документные бандлы + soft document diversity (inject missing docs, 0.1x penalty вместо hard filter) | Оригинальная разработка |
| PROOF — Pipeline for Retrieval Output Oversight & Filtering | Гейт качества: оценивает уверенность ответа, запускает повторный поиск при сомнениях | CRAG (2024) |
| COMPASS — Structural Reference Router | "статья 5" → мгновенный SQL lookup, ноль embeddings | Оригинальная разработка |
| PHANTOM — Hypothetical Document Embeddings | LLM генерирует гипотетический ответ → embed → поиск по нему | HyDE (Gao et al., 2023) |
| PRISM — Content Density Filter | Фильтрация коротких keyword-dense нод (содержания, оглавления) | Оригинальная разработка |
| NEXUS — Adjacent Node Discovery | ±N соседних нод в порядке документа для контекста | Оригинальная разработка |
| SENTINEL — Semantic Gap Detection + Reranker | Dual role: (1) NLI (DeBERTa-v3) + LLM детекция противоречий между документами на уровне пропозиций; (2) LLM reranking кандидатов 0-10 | Cross-encoder reranking (2022), NLI |
| SCOUT — Self-Correcting Output via Unified Traversal | Итеративный цикл: поиск → оценка → уточнение запроса → повторная попытка | Agentic RAG Survey (2025) |
| A-RAG — Agentic Retrieval (ReactAgent) | LLM-агент (ReAct) с 5 инструментами: keyword_search, semantic_search, decompose_and_search (RT-RAG), graph_walk, chunk_read. Интегрирует 6 статей: A-RAG, RT-RAG (Tree-of-Queries), HopRAG (PruneStep), multilingual reranker, SiReRAG (entity-proposition linking), sufficient context detection. Auto-search + фоллбэк на 14-шаговый pipeline | A-RAG, RT-RAG, HopRAG, SiReRAG (2025) |
- Парсеры: PDF (PyMuPDF, 3 уровня: шрифтовой анализ → регулярки → LLM-фоллбэк), DOCX, TXT, Markdown, XLSX/XLS/CSV (TableParser — spreadsheets в структурные ноды с markdown-таблицами)
- Двухслойные ноды: Структурные (статья/секция/глава) + Чанки (~800 символов, sentence-aware)
- Графовый движок: Типизированные рёбра (parent, references, depends_on, cross-doc)
- Entity Knowledge Layer: LLM-извлечение → граф сущностей → TRACE multi-hop → анализ воздействия
- Search v2: Vector + FTS5 + Keywords → 3-channel RRF merge → proposition enrichment (additive) → sibling expansion → top-30 chunks. Graph boosts ranking but never appears in results
- 8-phase indexing: Parse → Embed → GLiNER (subprocess) → Propositions (vLLM) → Re-embed → Cross-refs → RAPTOR (parallel, numpy k-means) → SENTINEL (NLI)
- GPU Orchestrator: Manages GLiNER ↔ vLLM switching. GLiNER runs in subprocess for clean CUDA release
- ReactAgent (A-RAG): LLM-агент (ReAct) с 5 инструментами: keyword_search, semantic_search, decompose_and_search, graph_walk, chunk_read. LLM-agnostic (Llama/YandexGPT/GigaChat/Qwen)
- Хранилище: SQLite + FTS5 — ноль внешних зависимостей, работает где угодно
- LLM-провайдеры: OpenAI, Google, Anthropic, Ollama (локальный), vLLM (высокая пропускная способность, ~60x быстрее Ollama) — подключаемые через Protocol
- Эмбеддинг-провайдеры: ONNX (1024d), Ollama, OpenAI, Google, локальный — подключаемые через EmbeddingProvider Protocol
- Цепочка фоллбэков: Облако → Локальный → Rule-based (работает офлайн)
# Установка
git clone https://github.com/IsaacClarke2/dendra.git
cd dendra
uv sync
# Для локального LLM (рекомендуется)
export GS_LLM_PROVIDER=vllm
export GS_VLLM_HOST=http://localhost:8000
# Индексация документа (полный 8-фазный pipeline)
uv run python -c "
import asyncio
from pathlib import Path
from graph_search.storage.db import Database
from graph_search.pipeline import DendraPipeline
from graph_search.llm.registry import create_default_registry
async def main():
db = Database('dendra.db')
reg = create_default_registry()
pipeline = DendraPipeline(db, embed_provider=reg.get_embedding_provider(),
llm_provider=reg.get() if reg.available() else None)
result = await pipeline.index_document(Path('your_document.pdf'))
print(f'Indexed: {result.total_nodes} nodes, {result.total_entities} entities')
asyncio.run(main())
"
# Поиск
uv run python -c "
import asyncio
from graph_search.storage.db import Database
from graph_search.search.engine import SearchEngine
from graph_search.llm.registry import create_default_registry
db = Database('dendra.db')
engine = SearchEngine(db, create_default_registry().get_embedding_provider())
result = asyncio.run(engine.async_search('Какие ключевые требования?', limit=30))
for hit in result.hits[:5]:
print(f'{hit.score:.1f} [{hit.doc_id[:20]}] {hit.text[:100]}')
"| Провайдер | Модель | Размерность | Скорость | Стоимость | Офлайн |
|---|---|---|---|---|---|
| ONNX (рекомендуемый) | intfloat/multilingual-e5-large | 1024 | ~5ms/text | Бесплатно | Да |
| Local (PyTorch) | all-MiniLM-L6-v2 | 384 | ~15ms/batch | Бесплатно | Да |
| Ollama | nomic-embed-text (или любая Ollama-модель) | 768 | ~50ms/batch | Бесплатно | Да |
| OpenAI | text-embedding-3-small | 1536 | ~300ms/batch | $0.02/1M tok | Нет |
| text-embedding-004 | 768 | ~300ms/batch | $0.01/1M tok | Нет |
# ONNX (рекомендуемый — multilingual-e5-large, 1024d, 100+ языков)
pip install 'graph-search[onnx]'
export GS_EMBEDDING_PROVIDER=onnx
# Ollama embeddings (альтернатива — любая модель через Ollama)
export GS_EMBEDDING_PROVIDER=ollama
export GS_OLLAMA_EMBEDDING_MODEL=nomic-embed-text # 768d, или mxbai-embed-large и т.д.
# Без API-ключей, без интернета, бесплатноВсе настройки через переменные окружения — никаких магических чисел:
| Переменная | По умолчанию | Описание |
|---|---|---|
| LLM и эмбеддинги | ||
GS_LLM_PROVIDER |
auto | openai, google, anthropic, ollama, vllm |
GS_EMBEDDING_PROVIDER |
auto | onnx, openai, google, local, ollama |
GS_ONNX_MODEL |
intfloat/multilingual-e5-large | ONNX модель (1024d, 100+ языков) |
GS_OLLAMA_EMBEDDING_MODEL |
nomic-embed-text | Ollama embedding модель (768d) |
GS_VLLM_HOST |
http://localhost:8000 | vLLM server address |
| Чанкинг (SCOPE) | ||
GS_CHUNK_ENABLED |
true | Включить двухслойную нарезку |
GS_CHUNK_SIZE |
800 | Размер чанка в символах |
GS_CONTEXT_ENABLED |
true | Контекстные префиксы |
| Пропозиции (ATOM) | ||
GS_PROP_ENABLED |
false | Извлечение атомарных фактов |
GS_PROP_BATCH |
5 | Размер батча для LLM |
| RAPTOR | ||
GS_RAPTOR_ENABLED |
false | Иерархические суммаризации |
GS_RAPTOR_MAX_LEVELS |
3 | Максимальная глубина дерева |
| PPR (TRACE) | ||
GS_PPR_ENABLED |
false | Personalized PageRank |
GS_PPR_DAMPING |
0.85 | Коэффициент затухания |
GS_PPR_TOP_K |
15 | Топ сущностей для буста |
| Скоринг | ||
GS_GRAPH_WEIGHT |
0.3 | Вес графового скора |
GS_GRAPH_PARENT_BONUS |
0.15 | Бонус за совпадение заголовка родителя |
GS_ENTITY_BONUS |
0.10 | Бонус за совпадение сущности |
| Кросс-документы (BRIDGE) | ||
GS_DIVERSITY_ENABLED |
false | BRIDGE: soft document diversity (0.1x penalty, не hard filter) |
GS_FANOUT_ENABLED |
false | Fan-out поиск по каждому документу |
| Query Intelligence | ||
GS_STRUCTURAL_ROUTING |
true | COMPASS: мгновенный lookup по "статья 5", "chapter 3" |
GS_HYDE_ENABLED |
false | PHANTOM: гипотетический ответ → embed → поиск |
GS_HYDE_MODEL |
— | Модель для PHANTOM генерации (требует LLM) |
GS_TYPE_AWARE |
true | LENS: буст по типу ноды (definition, article, table) |
GS_TYPE_AWARE_BOOST |
0.20 | LENS: размер буста за совпадение типа |
GS_SUBSTANCE_ENABLED |
true | PRISM: фильтр коротких keyword-dense нод |
GS_ADAPTIVE_ROUTING |
true | Пропуск тяжёлых шагов для простых запросов |
GS_SIBLING_CONTEXT |
true | NEXUS: поиск соседних нод (±N siblings в документе) |
GS_SIBLING_WINDOW |
1 | NEXUS: количество соседей с каждой стороны |
GS_SIBLING_SCORE_FACTOR |
0.50 | NEXUS: множитель score для обнаруженных siblings |
GS_ASSEMBLY_DOC_ORDER |
false | Сборка assembled_text в порядке документа (ranking = score order) |
GS_RERANKER_ENABLED |
false | SENTINEL: multilingual cross-encoder reranking (mmarco-mMiniLMv2, 14 языков) + LLM reranking |
GS_SENTINEL_ENABLED |
false | SENTINEL: NLI + LLM детекция противоречий (Phase 8) |
GS_SENTINEL_NLI_ONLY |
false | SENTINEL: только NLI, без LLM refinement |
GS_CONTEXT_BUDGET |
50000 | Бюджет контекста в символах для LLM |
| Кэширование | ||
GS_QUERY_CACHE_ENABLED |
true | Семантический кэш запросов |
GS_QUERY_CACHE_THRESHOLD |
0.95 | Порог cosine similarity для cache hit |
GS_QUERY_CACHE_SIZE |
256 | Максимум записей в кэше |
| A-RAG Agent (6 papers) | ||
GS_AGENT_ENABLED |
true | A-RAG: ReAct агент с 5 инструментами (требует LLM) |
GS_AGENT_MAX_STEPS |
10 | A-RAG: макс. шагов ReAct loop |
GS_AGENT_TIMEOUT |
30 | A-RAG: таймаут в секундах |
GS_PRUNE_ENABLED |
false | HopRAG: LLM batch оценка топ-20 кандидатов |
То, чего нет ни у одного конкурента (LlamaIndex, MS GraphRAG, обычный vector RAG):
- Анализ воздействия — "Что сломается, если изменить статью 5 GDPR?" Обход графа + entity impact через документы
- Кросс-документные бандлы — Объединяйте связанные документы, резолвите межодокументные ссылки, ищите по всему бандлу
- Адаптивное профилирование (LENS) — Автоопределение типа документа и применение оптимальной стратегии поиска
- Цепочки доказательств (PROOF) — Каждый ответ прослеживается до исходных узлов с оценкой уверенности
- Полный офлайн-режим — Ни один байт данных не покидает сервер. Для банков и enterprise
DENDRA работает полностью автономно — без интернета, без API-ключей, без облачных сервисов:
| Компонент | Онлайн | Офлайн (по умолчанию) |
|---|---|---|
| Эмбеддинги | OpenAI API ($0.02/1M tok) | ONNX multilingual-e5-large (1024d, ~5ms/text, бесплатно) |
| Entity extraction | LLM API ($$$) | GLiNER ONNX (zero-shot NER, Apache 2.0, бесплатно) |
| Propositions | LLM API ($$$) | LLM only (sentence fallback deprecated) |
| RAPTOR summaries | LLM API ($$$) | Extractive TF-IDF (бесплатно) |
| Генерация ответов | OpenAI / Anthropic | Ollama (llama3, mistral — локально) |
# Установка для полного офлайна
pip install 'graph-search[onnx,gliner]'
export GS_EMBEDDING_PROVIDER=onnx
export GS_ENTITY_EXTRACTOR=gliner
export GS_RAPTOR_SUMMARIZER=extractive
# Propositions пропускаются без LLM (и это нормально — качество 85% без них).
# Всё. Никаких API-ключей.Все компоненты — open source (Apache 2.0 / MIT). Все модели скачиваются один раз и кэшируются локально. Подходит для банков, госструктур и закрытых контуров.
src/graph_search/
├── parsers/ # Парсеры: PDF, DOCX, TXT, Markdown, XLSX/XLS/CSV
├── chunking/ # Sentence-aware нарезка + SCOPE контекстуализация
├── contextualization/ # SCOPE: структурный контекстный оверлей
├── propositions/ # ATOM: извлечение атомарных фактов
├── raptor/ # RAPTOR: иерархические суммаризации
├── entities/ # Извлечение сущностей + граф знаний
├── profiling/ # LENS: определение типа документа + стратегия
├── evidence/ # PROOF: гейт качества + цепочки доказательств
├── agents/ # SCOUT: итеративный retrieval-агент
├── search/ # 14-шаговый retrieval pipeline + TRACE (PPR) + A-RAG (6 papers)
│ ├── retriever.py # GraphAugmentedRetriever (подключаемые шаги + A-RAG agent mode + PruneStep + PropositionClusterStep)
│ ├── react_agent.py # A-RAG: ReactAgent (ReAct loop, 5 tools, RT-RAG decompose, sufficient context detection)
│ ├── reranker.py # CrossEncoderReranker (multilingual mmarco-mMiniLMv2, 14 languages)
│ ├── engine.py # SearchEngine (3-channel RRF: vector + FTS5 + keyword terms, cross-lingual)
│ └── ppr.py # TRACE: Personalized PageRank
├── references/ # BRIDGE: кросс-документная резолюция
├── storage/ # SQLite + FTS5 + vector store
├── llm/ # Подключаемые провайдеры (OpenAI, Google, Anthropic, Ollama)
├── core/ # Графовый движок, контракты, детекция гэпов
└── api/ # REST API (FastAPI)
| Модуль | Работа | Площадка |
|---|---|---|
| SCOPE | Contextual Retrieval | Anthropic (2024) |
| ATOM | Dense X Retrieval: Propositions | Chen et al. (2024) |
| RAPTOR | RAPTOR: Recursive Abstractive Processing | Sarthi et al., ICLR 2024 |
| TRACE | HippoRAG: Neurobiologically Inspired LTM for LLMs | Gutierrez et al., NeurIPS 2024 |
| PHANTOM | Precise Zero-Shot Dense Retrieval without Relevance Labels (HyDE) | Gao et al. (2023) |
| PROOF | Corrective RAG (CRAG) | Yan et al. (2024) |
| SCOUT | Agentic RAG Survey | Singh et al. (2025) |
| SENTINEL (NLI) | DeBERTa: Decoding-enhanced BERT with Disentangled Attention | He et al. (2021) |
| BRIDGE | LightRAG: Simple & Fast RAG | Guo et al., EMNLP 2025 |
| A-RAG | A-RAG: Agentic Retrieval-Augmented Generation | arXiv:2602.03442 (2025) |
| A-RAG (RT-RAG) | RT-RAG: Tree-of-Queries Decomposition | arXiv:2601.11255 (2025) |
| A-RAG (HopRAG) | HopRAG: Multi-hop Graph RAG with Pruning | arXiv:2502.12442 (2025) |
| A-RAG (SiReRAG) | SiReRAG: Entity-Proposition Linking for Retrieval | arXiv:2412.06206 (2024) |
| A-RAG | Google Research: Sufficient Context in RAG | Google (2025) |
| SENTINEL (reranker) | mMARCO: Multilingual Cross-Encoder Reranking | Bonifacio et al. (2022) |
| — | Attention Is All You Need | Vaswani et al., NeurIPS 2017 |
| — | ColBERT v2 | Santhanam et al. (2022) |
MIT
Ноль внешних зависимостей. Работает на SQLite. Работает офлайн.