
Explainable multi-hop RAG · one pip install away
Tortus
Toroidal Semantic Graph Retrieval for explainable, multi-hop RAG.
“Query concepts, not just chunks. Return reasoning paths, not just citations.”
Abstract
Tortus is a local-first, package-distributable retrieval engine for explainable, multi-hop RAG over federated databases. By modeling knowledge bases as typed semantic graphs embedded onto a soft toroidal manifold, it lets developers query concepts rather than flat text chunks — and returns the exact evidence paths that connect disparate documents.
Standard RAG relies on flat vector search. It is excellent at retrieving single facts and weak when the answer requires connecting points across multiple documents. Bounded agentic loops try to fix this, but introduce latency, cost, and reliability concerns of their own.
Tortus offers the middle ground: topology-aware graph traversal without the unbounded agent loop. Wrapping axes into a toroidal neighborhood layout eliminates edge-clustering boundary effects and enables seamless portal hops between overlapping subgraphs.
Key features
Graph-aware traversal
Connects the dots across document boundaries using semantic relations and concept portals.
Deterministic local fallbacks
Runs entirely on-device out of the box with zero external configuration.
Built-in developer tooling
Interactive visual workbench, GraphQL API, and local telemetry reporting.
Empirical verification
Reproducible, multi-size scale evaluation harness ships with the package.
Try it in 30 seconds
Install Tortus, point it at your own docs, and ask the question you actually need answered.
pip install tortus-rag tortus solve "Why did this incident happen, and what should we fix?" ./docs
Requires Python 3.12+. Runs out of the box with deterministic local embedding & synthesis — no keys required.
The painful problem
The hard part of internal knowledge work is often not finding a relevant document. It is figuring out how several relevant documents connect.
In an incident review, the evidence might be split across an auth migration note, a gateway retry runbook, an observability guide, and the incident timeline. Search can find each fragment. A normal RAG answer can summarize the retrieved text. The painful part is still left to the user:
Tortus is built for that gap. It tries to answer “why did this happen?” or “what should we fix?” by returning the evidence path across documents, not only a list of matching chunks.
Why current RAG fails at multi-hop
Most production RAG systems are strong at retrieving nearby text and weak at preserving relationships between ideas. That creates recurring failures:
| Failure mode | What happens | Why it matters |
|---|---|---|
| Chunk blindness | Retriever finds fragments but misses the path between them. | Locally plausible, globally incomplete. |
| Boundary artifacts | Clusters and shards create artificial edges in the space. | Cross-domain questions degrade where synthesis is needed. |
| Weak provenance | Citations point to documents, not to reasoning. | Users cannot audit why facts were connected. |
| Hidden retrieval logic | Traversal lives inside prompts and app code. | Developers cannot inspect or constrain behavior. |
| Cost drift | Agentic search expands until a budget stops it. | Latency and LLM spend become unpredictable. |
Core hypothesis · why a torus
A semantic graph embedded on a toroidal coordinate space can make retrieval more navigable by combining vector search for fast candidates, typed graph edges for explainable hops, toroidal locality for wraparound neighborhoods, GraphQL directives for developer-controlled traversal, and budget-aware synthesis over explicit evidence paths.
The torus is not treated as magic. It is a systems hypothesis to validate against measurable baselines — and replace if it does not hold.
| Job | Expected benefit | What must be proven |
|---|---|---|
| Neighborhood traversal | Smooth cyclic continuity around dense concept regions. | Better multi-hop recall at equal latency. |
| Sharding | Locality-preserving partitioning without hard semantic edges. | Higher shard affinity and cache hit rate. |
| Federation | Portal hops between overlapping subgraphs under budget. | Better cross-domain path quality. |
Architecture
Tortus is a complete, package-distributable RAG engine designed to run locally or integrate as a service. Two pipelines — ingest on the left, query on the right — meet at the graph and toroidal embedding.
Data model
| Entity | Purpose |
|---|---|
| ConceptNode | A concept, entity, claim, chunk, document section, API, decision, or event. |
| SemanticEdge | A typed relationship: supports, contradicts, depends_on, caused_by, implements, related_to. |
| SubgraphMembership | Weighted membership in domains, teams, products, sources, or tenants. |
| PortalEdge | A controlled cross-subgraph jump used when a query needs domain switching. |
| EvidenceSpan | A source-backed span attached to a node or edge for traceability. |
| TraversalPolicy | Runtime constraints: hop budget, latency, personalization, freshness, locality. |
Retrieval algorithm
At query time, Tortus follows a bounded retrieval plan:
- Parse query intent, constraints, and GraphQL directives.
- Generate seed candidates with ANN vector search.
- Map candidates to graph nodes and toroidal coordinates.
- Estimate local density around each seed.
- Expand through typed edges using a density-aware radius.
- Score frontier nodes with similarity, edge weight, freshness, evidence quality, and policy.
- Trigger portal hops when frontier coverage is low or the query implies domain switching.
- Select evidence paths under hop, latency, and token budgets.
- Synthesize an answer only from selected evidence.
- Return the answer, confidence, path, and degraded-mode warnings.
Traversal score
score(next) =
semantic_similarity(query, next)
+ edge_weight(current, next)
+ evidence_quality(next)
+ freshness_bias(next)
− traversal_cost(next)
− uncertainty_penalty(next)The exact scoring function is intentionally replaceable. Tortus is built to make retrieval policies easy to compare, not to hard-code one strategy.
Benchmark evidence
A scale sweep over 10 public engineering sources (Kubernetes, OpenTelemetry, W3C, RFCs, the Google SRE book), split into source-preserving doclets at 50, 200, 500, and 1000 documents. At the 1000-doclet point, graph-aware strategies recovered labeled path structure that rank-only baselines did not.
Table 1 · Strategy at 1000 docs
| Strategy | Pass | Source recall | Path recall | p95 ms |
|---|---|---|---|---|
| hybrid_graph_rerank_local | 1.00 | 0.75 | 1.00 | 92.5 |
| tortus_torus | 0.83 | 0.75 | 0.83 | 162.2 |
| vector_only_local | 0.00 | 0.83 | 0.00 | 19.0 |
| bm25_local | 0.00 | 0.67 | 0.00 | 98.9 |
Benchmark · 118 questions · 1,652 rows
| Strategy | Pass | Source | Path | Faith | p95 ms |
|---|---|---|---|---|---|
| tortus_torus | 0.80 | 0.73 | 1.00 | 0.88 | 3.4 |
| hybrid_graph_rerank_local | 0.80 | 0.74 | 1.00 | 0.88 | 5.7 |
| bounded_agentic_local | 0.73 | 0.67 | 0.95 | 0.89 | 3.0 |
| graph_local | 0.14 | 0.58 | 0.17 | 0.88 | 2.2 |
| llamaindex_external | 0.01 | 0.72 | 0.03 | 0.88 | 7.5 |
| hybrid_dense_bm25_local | 0.01 | 0.73 | 0.03 | 0.88 | 1.5 |
| vector_only_local | 0.01 | 0.71 | 0.03 | 0.88 | 0.8 |
| bm25_local | 0.02 | 0.65 | 0.03 | 0.88 | 1.0 |
What Tortus beats — and does not, yet
| Scenario | Current read |
|---|---|
| Single-hop factual retrieval | Vector, BM25, and Tortus all perform well; Tortus may be overhead. |
| Multi-hop incident analysis | Tortus is useful — it exposes the evidence path and portal hops. |
| Boundary-crossing questions | Tortus helps when traversal must cross domains under budget. |
| Unanswerable questions | Tortus withholds answers when selected evidence has no lexical support. |
| Large-scale production search | Not yet proven. FAISS support is the first step, not the endpoint. |
Useful failure modes
- Weather or stock queries return “not enough source-backed evidence” rather than forcing a path.
- Broad incident queries can over-expand through portals if shared terms are too generic.
- Local-only graph policies can find sources but miss expected boundary-crossing labels.
- Layout-only probes can retrieve nearby nodes without proving a reasoning path.
Quickstart
1 · Install
# Python 3.12+
pip install tortus-rag
# optional extras
pip install "tortus-rag[baselines]"
pip install "tortus-rag[api]"2 · Solve in one command
tortus solve "Why did this incident happen, and what should we fix?" \
./docs https://example.com/runbookCreates a hidden local project under ~/.tortus/projects/, snapshots the supplied files & URLs, builds the graph and vector index, traverses the evidence path, and returns a cited diagnosis, the likely root-cause path, recommended actions, and missing-evidence warnings.
3 · Try the packaged demo
tortus ingest --corpus acme-payments-demo --data-dir .tortus/acme-demo
tortus index --corpus acme-payments-demo --data-dir .tortus/acme-demo
tortus query "What should Acme fix to stop EU refund trace fragmentation?" \
--corpus acme-payments-demo --data-dir .tortus/acme-demo --explain4 · Open the dashboard
pip install "tortus-rag[api]"
tortus serve --port 8010
# → http://127.0.0.1:80105 · Or use it from Python
import tortus
from tortus.config import Settings
from tortus.pipeline import build_index, load_engine
settings = Settings(TORTUS_CORPUS="public-engineering")
build_index(settings)
engine = load_engine(settings)
result = engine.answer("How do service accounts connect to tracing?")
print(result.answer)
for hop in result.reasoning_path:
print(f"{hop.from_node} --[{hop.edge_type}]--> {hop.to_node}")Principles we ship by
- Make retrieval inspectable before making it clever.
- Treat LLMs as synthesis and policy helpers, not hidden databases.
- Return evidence paths for claims that cross concepts.
- Put budgets in the API, not only in deployment config.
- Prefer replaceable retrieval policies over one monolithic agent loop.
- Measure against boring baselines before adding exotic machinery.
The roadmap
Tortus is a fully functional v2, but the retrieval space is evolving rapidly. The roadmap is built to push the limits of multi-hop recall and scale the toroidal engine under extreme data pressure.
- Distributed graph sharding. Push beyond local memory toward partitioned graph databases (e.g. PostgreSQL + Apache AGE) so the toroidal policy scales to millions of nodes without latency degradation.
- Learned portal routing. Replace hand-tuned edge-weight thresholds with a lightweight portal router that dynamically optimizes cross-domain jumps from path-level user feedback.
- Streaming traversal paths. An async generator-based traversal engine that emits reasoning hops as they are visited, so client UIs can render live retrieval steps in real time.
- Adversarial benchmark suites. A benchmark family built specifically to break path retrieval — contradictory source claims, semantic decoy bridges, duplicate context blocks.
- Unified ingest connectors. Native connectors for enterprise sources (Postgres CDC, Notion, Confluence, Slack archives) under strict cryptographic provenance contracts.