Skip to main content

VikingRAG 0.4.2

VikingRAG

Structure-aware retrieval for documents that actually have structure.

Production hierarchical RAG inspired by the VikingRAG paper.
Hierarchy-preserving ingestion. Multi-granular semantic Search. Built to extend.

GitHub stars   GitHub forks   GitHub watchers

Release v0.4.2 Apache 2.0 Python 3.12+ FastAPI PostgreSQL + pgvector Redis PyPI arXiv paper

Install · Features · Architecture · Quick start · SDK · API · Docs · Cite

LinkedIn   mhuzaifa.com   GitHub


Why VikingRAG?

Classic RAG often flattens documents into unrelated chunks. Structure is lost - sections, subsections, and provenance disappear into a top-k bag of text.

VikingRAG (Gao et al., 2026) showed that hierarchy-preserving storage, multi-granular indexing, evidence-gap tools (Search / List / Grep / Read), and adaptive escalation can improve accuracy while cutting tokens.

This project turns those ideas into a production-oriented stack:

Research idea This repo today
Hierarchical documents document → section → subsection → chunk with stable + canonical object URIs
Multi-granular indexing Bottom-up abstracts + embeddings at document/section/chunk
Semantic Search pgvector cosine discovery returning viking:// URIs
Cheap path / agents Algorithm 1 agentic loop; E+ one-round fast path then escalate
Evidence-first grounding Authoritative Reads, citations, POST /v1/answers
Experience edges Algorithm 2 construction + Algorithm 3 Search+ (γ-gated)
Operational constraints Auth allowlist, migrations, prod Compose, eval smoke, typed settings

Independent implementation inspired by the paper - not a fork of the AGPL research artifacts.

Paper Table 3: token cost vs highest-accuracy baseline

Paper Table 3: VikingRAG-E+ token ratios vs gold/silver baselines

Charts redrawn from Gao et al., arXiv:2609.11390 Table 3 / abstract. Paper experiments — not measurements from this repository. Regenerate: uv run python scripts/render_paper_comparison_charts.py


Install

Option A — PyPI (fastest on any laptop)

python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -U vikingrag
# optional richer DOCX parsing:
# pip install "vikingrag[docx]"

You still need Postgres + pgvector and Redis, plus a .env (copy from the repo .env.example):

export VIKINGRAG_DATABASE_URL=postgresql+asyncpg://vikingrag:vikingrag@localhost:5432/vikingrag
export VIKINGRAG_REDIS_URL=redis://localhost:6379/0
# Offline wiring only (not semantic quality):
export VIKINGRAG_LLM_PROVIDER=fake
export VIKINGRAG_EMBEDDING_PROVIDER=deterministic
# Real retrieval: openai | deepseek | gemini | anthropic (+ matching embeddings)

vikingrag-migrate upgrade head
vikingrag-api
# API: http://localhost:8000/docs

Option B — Clone + Docker (API already on :8000)

git clone https://github.com/mhuzaifadev/VikingRAG.git
cd VikingRAG
cp .env.example .env
# Python 3.12+, https://docs.astral.sh/uv/
make install && make docker-up && make migrate
# Compose already serves the API at http://localhost:8000 — do not also `make dev` (port conflict).

Host-only API with reload (when Compose API is not running):

make dev

Option C — pip from GitHub (pre-release / specific tag)

pip install "git+https://github.com/mhuzaifadev/VikingRAG.git@v0.4.2"

Option D — Docker Compose

git clone https://github.com/mhuzaifadev/VikingRAG.git && cd VikingRAG
cp .env.example .env
docker compose up -d --build

Production-shaped: docker compose -f docker-compose.prod.yml up -d --build — see docs/OPERATIONS.md.


Features

  • Hierarchical documents - preserve section / subsection / chunk structure instead of flattening everything
  • Stable URIs - address any node with viking://documents/... (storage-independent)
  • Structure-aware ingestion - Markdown, TXT, and PDF with region-local chunking
  • Idempotent uploads - skip_identical, replace, or create_version
  • Structural navigation - parent, children, ancestors, descendants, and URI resolve
  • Hierarchical abstracts - bottom-up summaries with token budgets and idempotent reuse
  • Multi-granular embeddings - chunk content + structural summaries with explicit embedding identity
  • Semantic Search - pgvector cosine retrieval with granularity weights and URI-addressable hits
  • List / Grep / Read - structural children, scoped literal Grep, authoritative Read with provenance
  • Evidence collection - bounded Search→List/Read pipeline assembling deduplicated evidence bundles
  • Evidence sufficiency - structured assessment (sufficient / insufficient / unknown) with citation checks
  • Agentic Algorithm 1 - tool-calling Search/List/Grep/Read loop with shared budgets and finalization reserve
  • Answers API - POST /v1/answers and POST /v1/query with modes vikingrag / vikingrag_e / vikingrag_e_plus
  • Experience edges - Algorithm 2 learning jobs + Algorithm 3 Search+ expansion
  • Evaluation scaffolding - six dataset adapters + offline smoke (vikingrag-eval smoke --offline)
  • Auth - optional API-key + server document allowlist (single-tenant)
  • Shared budgets - cumulative tool/embedding/read/LLM limits across a request
  • Replaceable providers - openai / deepseek / gemini / anthropic / vllm; fakes rejected in production
  • SDK facade - VikingRAGClient for embed-in-process use without FastAPI
  • Production foundation - FastAPI, PostgreSQL + pgvector, Redis, object store, typed settings, health checks

Docs hub: docs/README.md · docs/RETRIEVAL.md · docs/PAPER_PARITY.md · AGENTS.md


Architecture

flowchart TB
    Client[Client / SDK / UI]
    API[FastAPI Gateway]

    subgraph Ingest[Ingestion]
      Parse[Parsers TXT / MD / PDF]
      Hier[Hierarchy builder]
      Chunk[Structure-aware chunker]
      Persist[(PostgreSQL + object store)]
    end

    subgraph Retrieve[Retrieval]
      Search[Search]
      List[List]
      Grep[Grep]
      Read[Read]
      Judge[Evidence sufficiency]
      Agent[Bounded agent]
    end

    Client --> API
    API --> Ingest
    API --> Retrieve
    Parse --> Hier --> Chunk --> Persist
    Search --> Persist
    List --> Persist
    Grep --> Persist
    Read --> Persist
    Judge -->|insufficient| Agent

Document model

Documents are not flat chunk lists:

flowchart TD
    D["DOCUMENT<br/>viking://documents/{id}"]
    S1[SECTION · Storage]
    S2[SECTION · Retrieval]
    S3[SECTION · Operations]
    SS1[SUBSECTION · PostgreSQL]
    SS2[SUBSECTION · Object Storage]
    SS3[SUBSECTION · Semantic Search]
    C1[CHUNK]
    C2[CHUNK]

    D --> S1
    D --> S2
    D --> S3
    S1 --> SS1
    S1 --> SS2
    S2 --> SS3
    SS1 --> C1
    SS1 --> C2

Stable URIs:

viking://documents/{document_id}
viking://documents/{document_id}/nodes/{node_id}

Ingestion pipeline

flowchart LR
    A[Upload] --> B[Hash / idempotency]
    B --> C[Parse]
    C --> D[Structure extract]
    D --> E[Normalize]
    E --> F[Hierarchy]
    F --> G[Chunk in-region]
    G --> H[Persist nodes + blob]

Layout

src/vikingrag/
  api/             FastAPI routes & schemas
  application/     Use-cases (ingest, navigation)
  domain/          Models, URIs, errors
  ingestion/       Parse → hierarchy → chunk pipeline
  infrastructure/  Postgres, Redis, object store
  providers/       LLM / embedding / rerank Protocols
  observability/   Structured logging + correlation
  settings/        Typed configuration

Quick start

After Install, check health:

curl -s http://localhost:8000/health/live  | jq
curl -s http://localhost:8000/health/ready | jq

Ingest a document, index it, and search. Defaults below are offline wiring (fake LLM + deterministic embeddings) — fine for API plumbing, not real semantic quality:

curl -s -X POST http://localhost:8000/v1/documents \
  -F "file=@tests/fixtures/system_architecture.md;type=text/markdown" \
  -F "strategy=skip_identical" | jq

DOC_ID="<document_id from response>"
curl -s "http://localhost:8000/v1/documents/${DOC_ID}/tree" | jq

curl -s -X POST "http://localhost:8000/v1/documents/${DOC_ID}/index" \
  -H "Content-Type: application/json" \
  -d '{"force_summaries":false,"force_embeddings":false}' | jq

curl -s -X POST http://localhost:8000/v1/search \
  -H "Content-Type: application/json" \
  -d '{"query":"How do we verify retrieved evidence?","top_k":5}' | jq

curl -s -X POST http://localhost:8000/v1/answers \
  -H "Content-Type: application/json" \
  -d "{\"query\":\"How do we verify retrieved evidence?\",\"document_ids\":[\"${DOC_ID}\"],\"execution_mode\":\"vikingrag\"}" | jq

Interactive API docs: http://localhost:8000/docs · Ops: docs/OPERATIONS.md


SDK

Embed VikingRAG in-process (no FastAPI server required). Still needs Postgres + Redis + env:

import asyncio
from vikingrag import VikingRAGClient
from vikingrag.domain.models.answer import AnswerRequest, ExecutionMode
from vikingrag.domain.models.representation import SearchRequest

async def main() -> None:
    client = VikingRAGClient.from_settings()
    try:
        hits = await client.search.search(
            SearchRequest(query="How do we verify retrieved evidence?", top_k=5)
        )
        print(len(hits.candidates), "hits")
        answer = await client.answer_generator().generate(
            AnswerRequest(
                question="How do we verify retrieved evidence?",
                execution_mode=ExecutionMode.VIKINGRAG,
            )
        )
        print(answer.status, (answer.answer or "")[:200])
    finally:
        await client.aclose()

asyncio.run(main())

Providers via env: VIKINGRAG_LLM_PROVIDER=openai|deepseek|gemini|anthropic|vllm (and matching embeddings). Empty VIKINGRAG_LLM_MODEL uses the provider preset (e.g. Gemini → gemini-2.5-flash). Production rejects fake / deterministic / scripted.


API

Method Path Purpose
GET /health/live Liveness
GET /health/ready Readiness (Postgres + Redis)
POST /v1/documents Multipart ingest (.md / .txt / .pdf / .docx)
GET /v1/documents/{id} Document metadata
GET /v1/documents/{id}/tree Structural tree
POST /v1/documents/{id}/index Summarize + embed (idempotent)
GET /v1/documents/{id}/index-status Index stage and counts
POST /v1/search Semantic Search (scope_uri optional)
POST /v1/retrieval/list List direct children
POST /v1/retrieval/grep Scoped Grep
POST /v1/retrieval/read Authoritative Read
POST /v1/retrieval/evidence Collect evidence + assess sufficiency
POST /v1/answers Cited answer (vikingrag / vikingrag_e / vikingrag_e_plus)
POST /v1/query Mode-switched query orchestration
GET /v1/nodes/{id} Node metadata (+ optional content)
GET /v1/uris/resolve?uri= Resolve a viking://… URI

Development

Command Purpose
make install Sync deps (uv) + pre-commit
make dev API with reload
make lint Ruff
make typecheck mypy (strict)
make test Unit tests
make test-integration Integration tests (Postgres + Redis)
make migrate Apply Alembic migrations
make docker-up / make docker-down Compose stack (volumes preserved on down)
uv run vikingrag-eval smoke --offline Offline evaluation scaffolding smoke

Citation

If you use ideas from VikingRAG or this software in research, please cite the paper:

@article{gao2026vikingrag,
  title   = {VikingRAG: Accurate and Token-efficient Retrieval-augmented
             Generation over Structured Documents},
  author  = {Gao, Peiyuan and others},
  year    = {2026},
  eprint  = {2609.11390},
  archivePrefix = {arXiv},
  primaryClass  = {cs.CL},
  url     = {https://arxiv.org/abs/2609.11390}
}

Paper: arXiv:2609.11390 · Machine-readable: CITATION.cff · Legal notices: NOTICE


License

Apache License 2.0 - see LICENSE.

VikingRAG is independently authored for production use. Do not copy code from AGPL research repositories into this tree unless you intentionally accept those obligations.


Contributing

Issues and PRs are welcome. Please:

  1. Keep layers clean (API ≠ domain ≠ adapters)
  2. Prefer typed contracts over dict[str, Any]
  3. Add tests with features
  4. Run make lint && make typecheck && make test before opening a PR

⭐ If this project helps you, starring the repo helps others find it.



LinkedIn · mhuzaifa.com · GitHub

built with curiosity   shipped with love

Metadata

Release files for vikingrag 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vikingrag 0.4.2
File Size Uploaded
vikingrag-0.4.2.tar.gz 139.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vikingrag 0.4.2
File Interpreter ABI Platform
vikingrag-0.4.2-py3-none-any.whl Python 3 none any Details

Total release size: 348.4 kB

Release files / vikingrag-0.4.2.tar.gz

Download URL vikingrag-0.4.2.tar.gz
Size 139.5 kB
Tags Source
SHA-256 checksum
How to use checksums
1b63c5bcee9fcc5d1c6e2f9993841bfbfd181bfcf15034278cd3bfd4aa9b9c8a
BLAKE2b-256 checksum
How to use checksums
c3f0ca23604be01551b2c084dacf8ea86ec635734f6dd3d8a09e48bb44b7f6a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / vikingrag-0.4.2-py3-none-any.whl

Download URL vikingrag-0.4.2-py3-none-any.whl
Size 208.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5ebed21dbb73e97f6dc5dd469dcb79deda26cdaab0900c191adc6b770eb78ad8
BLAKE2b-256 checksum
How to use checksums
3687880832ffbeb94fcab4b6d6736f7abe986884f071cadee11e42916d484464
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

This release

0.4.2 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page