RAGXRay
RAGXRay is a lightweight RAG debugging toolkit that answers one question:
Why did my RAG application give this answer?
It takes the query, the generated answer, and the retrieved contexts from
your RAG pipeline and produces an explainable diagnostic report: scores for
retrieval quality, context sufficiency, and answer grounding; a single primary
root cause; and concrete recommendations for fixing it.
RAGXRay is not a RAG framework, vector database, LLM wrapper, or dashboard. It doesn't call any LLM, download any embedding model, or require an API key. Everything runs offline using explainable heuristics (TF-IDF similarity, token overlap, and pattern matching for numbers/dates).
Install
pip install -e .
(Once published: pip install ragxray.)
Quickstart
from ragxray import diagnose
report = diagnose(
query="What is the waiting period for pre-existing diseases?",
answer="The waiting period is 48 months.",
contexts=[
"Pre-existing diseases are covered after 36 months.",
"Other conditions have a waiting period of 24 months.",
],
)
report.show()
RAGXRAY DIAGNOSTIC REPORT
Overall Score: 58/100
Status: Poor
Scores:
Retrieval Quality: 94/100
Context Sufficiency: 100/100
Answer Grounding: 0/100
Primary Root Cause:
UNSUPPORTED_ANSWER
(heuristic confidence: 0.80 - not a statistical probability)
Issues:
- Answer mentions a number not found in the matched context: The waiting period is 48 months.
- The answer is not supported by the retrieved evidence.
Recommendations:
- Add grounding checks and restrict generation to retrieved evidence.
- Return "I don't know" when evidence is insufficient.
What it checks
| Analyzer | Question it answers |
|---|---|
| Retrieval Quality | Are the retrieved contexts relevant to the query? |
| Context Sufficiency | Is there enough information in the contexts to answer the query? |
| Answer Grounding | Is the generated answer actually supported by the retrieved contexts? |
| Root Cause Engine | What's the single most likely reason for a bad answer? |
| Recommendations | What should you change in your pipeline? |
Root causes
RAGXRay always names exactly one primary root cause:
RETRIEVAL_FAILURE - retrieval found little/nothing relevant
LOW_RETRIEVAL_RELEVANCE - retrieval is weak but not a total failure
INSUFFICIENT_CONTEXT - the retrieved contexts don't contain the needed facts
UNSUPPORTED_ANSWER - the answer states things the context doesn't support
CONTRADICTORY_ANSWER - the answer directly contradicts the retrieved evidence
UNKNOWN - no significant issue detected by current heuristics
Note:
confidenceon the root cause is a heuristic diagnostic score in[0, 1], not a calibrated statistical probability. It reflects how strongly the detected signals point at the chosen root cause.
Working with the report
report.score # 0-100 overall score
report.status # "Excellent" | "Good" | "Needs Attention" | "Poor" | "Critical"
report.retrieval_score
report.context_score
report.grounding_score
report.primary_root_cause # RootCause enum
report.issues # list[str] of detected problems
report.recommendations # list[str] of actionable next steps
report.to_dict() # plain JSON-serializable dict
report.to_json() # JSON string
report.show() # pretty-print to the terminal
Each analyzer's full detail is also available:
report.retrieval_analysis.per_context # per-context relevance scores
report.context_analysis.missing_terms # query terms not found anywhere
report.grounding_analysis.unsupported_claims # specific unsupported/contradicted claims
Context input formats
Plain strings:
contexts = ["Some text", "Another text"]
Structured, with metadata:
contexts = [
{
"text": "Pre-existing diseases are covered after 36 months.",
"source": "policy.pdf",
"page": 12,
}
]
Both (and a mix of the two) are normalized internally into a Context model.
Scoring
Overall Score = 30% Retrieval Quality
+ 30% Context Sufficiency
+ 40% Answer Grounding
90-100 Excellent
75-89 Good
60-74 Needs Attention
40-59 Poor
0-39 Critical
All weights and thresholds are configurable via RAGXRayConfig:
from ragxray import diagnose, RAGXRayConfig
config = RAGXRayConfig(
weight_retrieval=0.2,
weight_context=0.2,
weight_grounding=0.6,
grounding_sentence_support_threshold=0.4,
)
report = diagnose(query=..., answer=..., contexts=..., config=config)
How the heuristics work (v1)
- Retrieval Quality: TF-IDF cosine similarity between the query and each context (falls back to token overlap if TF-IDF's vocabulary is empty), rescaled against a calibrated "strong match" reference point.
- Context Sufficiency: fraction of the query's meaningful (non-stopword) terms that appear anywhere in the retrieved contexts.
- Answer Grounding: each answer sentence is matched against the most similar context sentence. If nothing is similar enough, the claim is unsupported. If something is similar but numbers/dates disagree, that's flagged as unsupported with the specific mismatch. Explicit negation clashes (e.g. "is covered" vs. "is not covered") are flagged as direct contradictions.
These are explainable heuristics, not semantic entailment or fact-checking models - RAGXRay tells you what looks wrong and why it flagged it, but it can't verify real-world truth, and it can miss issues heuristics simply aren't built to catch (e.g. subtle logical errors phrased without numbers or negation words).
What's intentionally NOT in v1
- No citation-level analysis
- No chunk-level analysis
- No LangChain/framework integrations
- No LLM-based evaluation
- No embeddings requiring model downloads
These may come in future versions - v1 is deliberately focused and offline.
Development
pip install -e ".[dev]"
pytest
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ragxray-0.1.0.tar.gz.
File metadata
- Download URL: ragxray-0.1.0.tar.gz
- Upload date:
- Size: 26.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6b64aa827014ef20798abdfdb9beba78ca1a18d7ee8c98bebf1df5b9885d445
|
|
| MD5 |
9e3f9dcb9f86094a5cb197d6c8fca405
|
|
| BLAKE2b-256 |
8858ccb7870ff059b9c9804e7bc35b55ab3b233c4f324f75ef24ce5daec6fb32
|
File details
Details for the file ragxray-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ragxray-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7b2f67b0ce0d7da8fecc779f5776ed626777e14b205c39c4cae45fed61fd09e
|
|
| MD5 |
65db32f35f1ac1f25484e50124db6d63
|
|
| BLAKE2b-256 |
f4d23199c3e317cf2d3dacc7182c6dfb2cb09ef6c4e9c5205f2170f5ad98e2f5
|