rag-critic
Lightweight adversarial hallucination auditor and citation grounding engine for LangGraph and production RAG pipelines.
Stop deploying unchecked RAG applications. rag-critic provides an adversarial verification loop that decomposes LLM draft answers into atomic factual claims, checks them against retrieved source passages, computes continuous grounding scores, and outputs actionable revision instructions for re-writer agents.
⚡ The Problem: Unchecked RAG in Production
Most production RAG architectures follow a naive, linear pipeline:
[User Query] ──> [Vector DB Retrieval] ──> [LLM Generation] ──> [Emit to User]
In production, single-pass LLMs frequently:
- Invent ungrounded statistics, numbers, and dates absent from the source files.
- Extrapolate beyond retrieved context without acknowledging uncertainty.
- Fabricate phantom citations and misattribute quotes.
🛡️ The Solution: The rag-critic Loop
[User Query] ──> [Retriever] ──> [LLM Draft] ──> [rag-critic Node]
│
┌─────────────────────────────────┴──────────────────┐
▼ ▼
[Grounding >= 0.85] [Hallucination Detected]
│ │
▼ ▼
[Verified Output + Citations] [Re-writer Agent]
│
└──> [Regenerate]
rag-critic acts as an automated critic node:
- Atomic Decomposition: Deconstructs compound sentences into indivisible factual claims.
- Entailment Matrix: Classifies each claim as
SUPPORTED,CONTRADICTED, orUNGROUNDED. - Mathematical Scoring: Computes the continuous Grounding Score $S_{\text{ground}} \in [0.0, 1.0]$ and Hallucination Index.
- Targeted Diagnostic Feedback: Delivers specific, itemized instructions to re-writer nodes explaining exactly what failed and why.
📦 Installation
pip install rag-critic
Zero heavy dependencies. Pure Python with Pydantic v2.
🚀 Quickstart
1. Standalone Python / FastAPI
from rag_critic import RAGCritic
# Use Groq (sub-second LPU speed), OpenAI, Ollama, or offline heuristic mode
critic = RAGCritic(provider="groq", model="llama-3.3-70b-versatile")
draft_answer = (
"DeepTrace uses Error Level Analysis at Q=95 to detect document tampering. "
"The platform raised $50 million in Series A funding in London."
)
retrieved_context = [
"DeepTrace is an open-source forensic platform using Error Level Analysis (calibrated at Q=95) to audit bank statement tampering."
]
result = critic.evaluate(draft_answer, retrieved_context)
print("Status: ", result.status) # REJECTED_HALLUCINATION
print("Grounding Score:", f"{result.grounding_score:.1%}") # 50.0%
print("Ungrounded: ", result.ungrounded_claims) # 1 ($50M Series A claim flagged!)
# Auto-generated diagnostic feedback for your re-writer
print(result.revision_feedback)
# -> [UNGROUNDED] Remove claim not found in reference passages: "The platform raised $50 million in Series A funding in London."
2. LangGraph Native Integration
Add an adversarial hallucination guardrail to any LangGraph workflow in 3 lines:
from typing import TypedDict, List
from langgraph.graph import StateGraph, END
from rag_critic import RAGCritic, create_critic_node, critic_router
class RAGState(TypedDict):
query: str
chunks: List[str]
draft: str
revision_feedback: str
critic_result: Any
workflow = StateGraph(RAGState)
# Define your pipeline nodes
workflow.add_node("retrieve", my_retriever_node)
workflow.add_node("generate", my_generator_node)
# Add rag-critic adversarial node
critic = RAGCritic(provider="groq", threshold=0.85)
workflow.add_node("critic", create_critic_node(critic))
# Define conditional edge
workflow.add_conditional_edges(
"critic",
critic_router,
{
"approved": END,
"hallucination_detected": "generate", # Loops back with exact diagnostic feedback
}
)
📊 Factual Verification States
| Status | Meaning | Action Taken |
|---|---|---|
SUPPORTED |
Context explicitly confirms claim. | Chunk index and citation mapped. |
CONTRADICTED |
Context contradicts the claim. | Flagged with severity penalty; revision generated. |
UNGROUNDED |
Context lacks evidence for claim. | Flagged as hallucination; removed or re-written. |
Mathematical Formulation
$$\text{Grounding Score } S_{\text{ground}} = \frac{\sum \text{SUPPORTED}}{\text{Total Claims}} \in [0.0, ; 1.0]$$
$$\text{Hallucination Index } H = \frac{\sum (\text{UNGROUNDED} + 2 \cdot \text{CONTRADICTED})}{\text{Total Claims}}$$
🛠️ CLI Usage
Audit responses directly from the command line or CI/CD test suites:
rag-critic \
--draft "DeepTrace was built in 2026." \
--context "DeepTrace is a forensic platform built by Shaheer Ul Hassan in 2026." \
--threshold 0.80
🌐 Supported Model Providers
- Groq (
provider="groq", defaultllama-3.3-70b-versatile— Recommended for sub-500ms audit latency) - OpenAI (
provider="openai", defaultgpt-4o-mini) - Ollama (
provider="ollama", defaultllama3.2— 100% offline local inference) - Heuristic Mode (
provider="heuristic"— Deterministic n-gram & entity overlap; zero API keys required) - Custom Callable (
custom_llm=my_custom_inference_fn)
👤 Author & Citations
Engineered by Shaheer Ul Hassan
- Portfolio & Case Studies: shaheerulhassan.com
- GitHub: @samjanjua6
- LinkedIn: Shaheer Ul Hassan
- PyPI Profile: pypi.org/user/samjanjua6/
📄 License
MIT License. Open source and free for commercial and academic use.
Metadata
Release files for rag-critic 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| rag_critic-0.1.0.tar.gz | 18.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rag_critic-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.3 kB
Release files / rag_critic-0.1.0.tar.gz
| Download URL | rag_critic-0.1.0.tar.gz |
|---|---|
| Size | 18.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca17626c3f52d51412a976a213ed124bcd4f5ed8f77c7f80762a125a9f1e94d9
|
|
BLAKE2b-256 checksum How to use checksums |
8a38e9151e5f35a68d806a8882829e6035c46651d356ad1a746f2e44b72e2a6b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / rag_critic-0.1.0-py3-none-any.whl
| Download URL | rag_critic-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6eb0ca13fc3d957b2586c2ef206414f9b106237ec9d1c1ee4293ecef1a61113
|
|
BLAKE2b-256 checksum How to use checksums |
51a9d5142795b875fe2c2ac986f4799ba0c7ad48ae1a0879b2fc88b0f6e97c43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Security for rag-critic 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.