Skip to main content

Agentic RAG pipeline failure diagnosis โ€” no database, no LLM API, no cloud

Project description

๐Ÿฉบ rag-doctor

Diagnose why your RAG pipeline returned the wrong answer โ€” in under 2 seconds.

PyPI version Python 3.9+ License: MIT Tests CI

No database. No API keys. No cloud calls. Just pass your documents and get a root cause.

Quick Start ยท How It Works ยท Examples ยท CLI ยท Docs


The Problem

RAG pipelines fail silently. You get a wrong answer and have no idea if it's a chunking problem, a retrieval miss, a position bias, or a hallucination. Existing evaluation tools give you a score โ€” they don't tell you why.

rag-doctor tells you why.

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  RAG-DOCTOR โœ— ISSUES FOUND
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  Root Cause : context_position_bias (RC-2)
  Severity   : HIGH
  Finding    : Best document at position 1/2 โ€” in danger zone (risk: 1.00)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Fix: Enable a reranker to push the most relevant document to position 0.
  Config Patch: {"retrieval.reranker": true}
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Quick Start

pip install rag-doctor
from rag_doctor import Doctor
from rag_doctor.connectors.mock import MockConnector

connector = MockConnector(corpus=[
    {"id": "doc1", "content": "For liver disease patients maximum acetaminophen dose is 2000mg per day."},
    {"id": "doc2", "content": "Standard adult dose: up to 4000mg per day."},
])

docs   = connector.retrieve("acetaminophen dose liver disease", top_k=3)
answer = "The maximum daily dose is 4000mg."

report = Doctor.default().diagnose(
    query    = "What is the max acetaminophen dose for liver disease?",
    answer   = answer,
    docs     = docs,
    expected = "For liver disease patients max dose is 2000mg per day.",
)
print(report.to_text())

How It Works

rag-doctor runs a deterministic six-tool agent loop. Each tool targets a specific failure mode:

Tool Root Cause What It Catches
RetrievalAuditor RC-1 retrieval_miss Correct document not in top-k results
PositionTester RC-2 context_position_bias Correct doc retrieved but ignored in middle position
ChunkAnalyzer RC-3 chunk_fragmentation Mid-sentence truncation, incoherent chunks
HallucinationTracer RC-4 hallucination Answer claims not grounded in retrieved documents
QueryRewriter RC-5 query_mismatch Query vocabulary doesn't match document vocabulary
ChunkOptimizer RC-3 sub-tool Grid-searches best chunk_size and strategy

No Database. No LLM. No API Keys.

rag-doctor builds an ephemeral VectorStore in memory from whatever documents you pass. Your production database is never touched.

Embedding backends (auto-selected, no config needed):

Priority Backend Install
1 sentence-transformers pip install sentence-transformers
2 Ollama nomic-embed-text ollama pull nomic-embed-text
3 TF-IDF (stdlib + numpy) nothing โ€” built in
4 Char n-gram fallback nothing โ€” always available

Three Ways to Use It

Mode A โ€” Debug from Logs (no re-query needed)

from rag_doctor import Doctor
from rag_doctor.connectors.base import Document

docs = [
    Document(content=row["text"], score=row["score"], position=i)
    for i, row in enumerate(db_rows)
]
report = Doctor.default().diagnose(
    query="What is the refund policy?",
    answer="30 days for all customers.",
    docs=docs,
    expected="Enterprise customers get 90-day refunds.",
)
print(report.root_cause)      # retrieval_miss
print(report.fix_suggestion)  # Increase top_k or check corpus coverage.

Mode B โ€” Corpus-Level Evaluation (CI / pytest)

connector = MockConnector(corpus=YOUR_CORPUS)
docs      = connector.retrieve(query, top_k=5)
report    = Doctor.default(connector).diagnose(query=query, answer=answer, docs=docs, expected=expected)
assert report.severity in ("low", "medium"), report.to_text()

Mode C โ€” Connect Your Production Stack

class ChromaConnector(PipelineConnector):
    def retrieve(self, query, top_k=5):
        results = self.collection.query(query_texts=[query], n_results=top_k)
        return [Document(content=d, score=s, position=i) for i,(d,s) in enumerate(...)]

report = Doctor.default(ChromaConnector(my_collection)).diagnose(...)

CLI Reference

# Single query
rag-doctor diagnose \
  --query    "What is the termination notice?" \
  --answer   "30 days." \
  --expected "Enterprise requires 90 days written notice."

# Batch from JSONL
rag-doctor batch --input examples/batch_example.jsonl --fail-on-severity high

# JSON output for CI
rag-doctor diagnose --query "..." --answer "..." --output json | jq .root_cause

Local Setup (Mac)

git clone https://github.com/your-org/rag-doctor
cd rag-doctor
chmod +x scripts/test_local_mac.sh
./scripts/test_local_mac.sh

Documentation

Doc Description
docs/user-guide.md Complete user guide โ€” all 5 journeys, all 6 root causes
docs/architecture.md Internal design: embedding chain, VectorStore, agent loop
docs/tools-reference.md API reference for all 6 tools
docs/connectors.md Building custom connectors
docs/configuration.md Thresholds and config options
docs/publishing.md How to release to PyPI

License

MIT โ€” free for personal and commercial use.

Project details


Download files

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

Source Distribution

rag_doctor-1.0.0.tar.gz (66.4 kB view details)

Uploaded Source

Built Distribution

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

rag_doctor-1.0.0-py3-none-any.whl (39.0 kB view details)

Uploaded Python 3

File details

Details for the file rag_doctor-1.0.0.tar.gz.

File metadata

  • Download URL: rag_doctor-1.0.0.tar.gz
  • Upload date:
  • Size: 66.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for rag_doctor-1.0.0.tar.gz
Algorithm Hash digest
SHA256 cbbcf0e88d8926af66930d71a86ed85893407bfc5264f980f9459b65011c36d4
MD5 c24ad2819432fe6459ff097048495ea9
BLAKE2b-256 8674958598c8b4a681e4070180e0db363f9f772ef812f9ce8c69d5c54c8ad3d9

See more details on using hashes here.

File details

Details for the file rag_doctor-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: rag_doctor-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 39.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for rag_doctor-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2751bdf9b216a3f35e2d5fe4af9f598a849b78d4a4a487e4ef6ed25d89f3a58a
MD5 25d31408b23849d54d8e18ce027b53a7
BLAKE2b-256 ec163c7fdacc992169c02b0ee82f7e418586271f70ba35b9ec46170d16dc1ddb

See more details on using hashes here.

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