Skip to main content

MothRAG logo

MothRag

CI PyPI Python License: Apache-2.0

Deterministic, agentic-style multi-hop — research-SOTA parity without the graph you'd rebuild every day.

On commodity LLM APIs alone. No GPU, no fine-tuning, a proof tree per answer.

Author: Julian Geymonat · License: Apache 2.0 📄 Paper (Zenodo preprint) · 🔗 Live demo · 🌐 mothrag.com

What it's for

MothRag is for answering questions over a corpus that changes — where the answer also needs multi-hop reasoning (it's spread across several documents and has to be chained). Think live stats and standings, prices and filings, support tickets, news, or internal docs that get updated every day.

The systems that chase this kind of multi-hop accuracy lean on heavy indexing — building a knowledge graph (GraphRAG, HippoRAG) or training a retriever. MothRag outscores the graph-based ones on every benchmark (HotpotQA, 2WikiMultiHop, MuSiQue) — and without their cost: the moment your data changes, each of them has to push the new data through a generative-LLM indexing pass before it's queryable, and some recompute global structures on top. On data that moves daily, you pay that bill every time.

MothRag does the reasoning as query-time orchestration over a plain dense index. An update is embed + append — one embedding call, no LLM extraction, no graph rebuild, no retraining. So it stays current on data that moves under it.

→ See it: a runnable World Cup freshness demo — the answer follows the standings as new results are appended, with no re-index.

Three things you get at once

  1. Freshness — no rebuild. Updates are embedding-only (ingest() embeds the changed chunks and appends). No graph reconstruction, no retraining. The public API is graph-free.
  2. No GPU, commodity APIs, cheap. Reader = Llama-3.3-70B over an API (Groq), embedder = Gemini. ~$0.032/query measured (full config); ~$0.018/query on the economy tier.
  3. Deterministic + auditable. Same input → same output, zero run-to-run variance, and every answer ships an inspectable proof tree.

Every component — reader, embedder, retrieval judges — sits behind a commodity pay-per-call API. No local GPU, no constrained decoding, no non-commercially-licensed model. Deployment is a package install plus API keys.

You don't trade accuracy for any of it

Results (paper, n=1000 per dataset, Llama-3.3-70B reader, single uniform configuration)

Against the most popular RAG systems, MOTHRAG (commodity APIs, no GPU) outscores RAPTOR, GraphRAG and HippoRAG 2 on HotpotQA, 2WikiMultiHopQA and MuSiQue

Against the most popular RAG systems, MOTHRAG outscores every one on every benchmark, on commodity APIs alone.

F1 on HotpotQA / 2WikiMultiHopQA / MuSiQue — MOTHRAG (commodity APIs, no GPU) vs. HippoRAG 2, CoRAG, and NeocorRAG

And against the GPU-bound research frontier (HippoRAG 2, CoRAG, NeocorRAG), MOTHRAG reaches the same tier without the GPU or the non-commercial models.

System Deployment profile HotpotQA 2WikiMultiHopQA MuSiQue AVG
HippoRAG 2 (as published) offline OpenIE graph + NV-Embed-v2 peak 75.5 71.0 48.6 65.0
CoRAG (training-based, as reproduced) trained chain-retrieval 75.1 75.1 52.9 67.7
NeocorRAG (as published) GPU-bound constrained decoding + NV-Embed-v2 78.3 76.1 52.6 69.0
MOTHRAG (ours) commodity APIs only 78.1 76.3 50.5 68.3

F1, competitor numbers as published in the cited sources (same reader class). MOTHRAG attains the highest average F1 among commercially-deployable frameworks — within 0.7 points of the GPU-bound research state of the art (parity on HotpotQA at −0.2, an edge on 2WikiMultiHopQA at +0.2, an honest gap on MuSiQue at −2.1).

Measured cost: $0.032/query (reader + retrieval-judge, measured over 3,000 queries). A documented economy tier (one-flag retrieval-judge swap) runs at ≈$0.018/query (−44%) at statistical parity on HotpotQA and 2WikiMultiHopQA, with a measured trade-off only on MuSiQue (−2.12). All SOTA-parity claims attach to the full configuration.

Answers are proof-tree-structured: each output carries inspectable reasoning steps over the assembled evidence, with a γ-cap fallback when the grounding check cannot be satisfied within budget.

Why deterministic?

Naive single-shot RAG is fading; the field is moving to agentic retrieval — planning, multi-hop iteration, reflection. MOTHRAG takes those mechanisms — query decomposition, grounding-driven iteration, multi-hop evidence chaining — but runs them through deterministic orchestration: same inputs → same answer, with an inspectable audit trail, instead of a flaky free-form agent loop.

We tested the alternative: letting an LLM route the pipeline. Every model we tried (Llama-3.3-70B, Claude Sonnet, Gemini Flash, Claude Haiku) did worse than the deterministic router. Determinism won on accuracy and reproducibility — which is exactly what you want when you put multi-hop retrieval into production or evaluate it cleanly.

Install

pip install mothrag

# Recommended baseline (Gemini embeddings + Groq Llama-3.3-70B reader):
pip install 'mothrag[gemini,openai]'

# Full production stack:
pip install 'mothrag[prod]'
Extra Pulls Used by
gemini google-genai GeminiEmbedder, GeminiReader
openai openai OpenAIReader, GroqReader (Groq's OpenAI-compatible API)
sentence-transformers sentence-transformers local embedding fallback
retrieval scikit-learn, networkx, rank-bm25 classic-RAG features
faiss faiss-cpu vector store for 100k–10M chunk corpora
prod bundles the above + loaders full stack

Quickstart

from mothrag import MothRAG

# Works out of the box (degrades gracefully without keys);
# set GROQ_API_KEY + GEMINI_API_KEY for production quality.
m = MothRAG.from_documents([
    "Paris is the capital of France.",
    "The Eiffel Tower is in Paris.",
])
result = m.query("In which country is the Eiffel Tower?")
print(result.answer)         # the answer
print(result.arm_used)       # which reasoning arm won arbitration
print(result.confidence)     # arbitration confidence

API keys via environment (see .env.example): GROQ_API_KEY (reader), GEMINI_API_KEY (embedder + grounding judge), ANTHROPIC_API_KEY (premium retrieval judge; optional — the economy tier uses Gemini).

From the terminal

The same pipeline, no Python file needed:

pip install mothrag

# Instant multi-hop over a corpus that ships in the package (no key, no setup):
mothrag demo

# Your own docs (a file or directory, repeatable):
mothrag query "What changed in Q3?" --docs ./your_notes/ --json

For real LLM answers instead of the offline echo fallback, add a free reader key:

pip install 'mothrag[openai]'
export GROQ_API_KEY=...   # free-tier key: https://console.groq.com/keys
mothrag demo "Who was the Eiffel Tower named after, and in which country does it stand?"

--docs takes files or directories (repeatable), --json emits a machine-readable result with the winning arm and a reader_mode field. With no API key MothRAG still runs end-to-end on offline fallbacks, and says so loudly: the answer is the echoed top chunk, marked as such on stderr, never passed off as an LLM answer. mothrag smoke -h runs the HotpotQA-style eval.

Keeping the index current

When a fact changes, replace it in place; when it is retracted, drop it. Both are incremental: one embedding pass over the changed document, no graph rebuild and no retraining.

from mothrag import MothRAG, Document

m = MothRAG()
m.ingest([Document(text="The price is $10.", metadata={"source": "price"})])

m.update("price", "The price is $20.")  # supersede in place
m.delete("price")                       # retract entirely

update/delete key on a document's source id and require retrieval="dense" (the default); a clear error is raised on append-only vector stores.

How it works

Three separable stages; every model invocation is a commodity API call:

  1. Bridge retrieval substrate — multi-query ANN fusion re-ranked by a tripartite LLM judge conditioned on retrieved bridge evidence, reshaping every retrieval (primary, sub-question, iterative). A post-retrieval ChainFilter re-scores the ranking by chain density over OpenIE triples, gated by input features only.
  2. Four-arm ensemble pool — direct read, decomposition, iterative refinement (γ-driven re-retrieval), and Pool-Duplicate Dispatch (PDD): a deterministic copy of the iterative arm's candidate that double-weights the grounding-checked voice in arbitration at zero extra inference. Pool cardinality is fixed at N=4 (five-arm pools regressed consistently).
  3. Deterministic arbitration — fixed weights over grounding status (γ, 1.0), cross-arm agreement (0.5), and faithfulness (0.3). No learned components anywhere; all gates condition on input features of the question, never on dataset identity.

Reproducing the paper

The paper numbers come from the evaluation configuration (scripts/route_prospective.py with the full flag set), not from the high-level quickstart API. See paper/REPRODUCE.md for the verbatim CLI, required inputs, and expected outputs. The per-query outputs behind every table in the paper are released in paper/results/ (six JSONs: three datasets × premium/economy tiers, n=1000 each).

Citing

See CITATION.cff. Cite the Zenodo preprint:

@misc{geymonat2026mothrag,
  title  = {MOTHRAG: Training-Free Multi-Hop Question Answering at Research-SOTA Parity on Commodity LLM APIs},
  author = {Geymonat, Julian},
  year   = {2026},
  doi    = {10.5281/zenodo.20668567},
  url    = {https://doi.org/10.5281/zenodo.20668567}
}

License

Apache-2.0. © 2026 Julian Geymonat. Research supported by ItalySoft srl.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mothrag-0.6.2.tar.gz (474.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mothrag-0.6.2-py3-none-any.whl (373.8 kB view details)

Uploaded Python 3

File details

Details for the file mothrag-0.6.2.tar.gz.

File metadata

  • Download URL: mothrag-0.6.2.tar.gz
  • Upload date:
  • Size: 474.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mothrag-0.6.2.tar.gz
Algorithm Hash digest
SHA256 be2cb575b7bdb2b6cda1e65acdb6376bdf7391a4208ab178a0572fa1cac94b81
MD5 cf37f9951e602e4012a576ebe7e6d1d7
BLAKE2b-256 69541a1c638888b6b7a8ebe1b92d95e53aa327adcfe0c23d780e99a95925da56

See more details on using hashes here.

Provenance

The following attestation bundles were made for mothrag-0.6.2.tar.gz:

Publisher: release.yml on juliangeymonat-jpg/mothrag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mothrag-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: mothrag-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 373.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mothrag-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 54c47787a8d8115fd5904412e4fc7d347db83119aa5852f09e5237604b667e5a
MD5 41bc3d11a6bcd216abdea75f39720750
BLAKE2b-256 1921268b1548c013d673094960faa575a435a86b73b91de9008b285454716114

See more details on using hashes here.

Provenance

The following attestation bundles were made for mothrag-0.6.2-py3-none-any.whl:

Publisher: release.yml on juliangeymonat-jpg/mothrag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page