Raj Chhapariya
WorkAboutWriting
ResumeContactGitHub
Raj Chhapariya•© 2026•Bengaluru, India•Privacy
GitHubX (Twitter)LinkedInEmail
Back to All Writing
Systems Research·
August 25, 2026
·
4 min read

Evaluating Hallucination and Citation Faithfulness in Retrieval-Augmented Generation

Methodologies for measuring precision, citation recall, context contamination, and automated offline evaluation suites.

AI EvaluationRAGHallucinationTestingPython

1. The Evaluation Crisis in Production RAG

A standard proof-of-concept RAG pipeline can be assembled in an afternoon using off-the-shelf libraries. However, moving from a demo to a production system capable of handling thousands of varied user inquiries exposes severe reliability vulnerabilities:

  • Silent Hallucinations: The model produces an articulate, convincing answer that includes plausible facts not present in the retrieved reference context.
  • Citation Hallucination: The model outputs superscript citation tags (e.g., [1], [2]) pointing to source documents that do not actually contain or support the asserted claim.
  • Context Distraction: When retrieved chunks contain irrelevant information or conflicting viewpoints across documents, generative models often select the incorrect perspective or blend contradictory numbers.

Without continuous, automated evaluation metrics, engineering teams cannot safely refactor chunking strategies, swap embedding models, or update prompt templates without risking catastrophic regression.


2. The Four Core RAG Evaluation Metrics

A comprehensive evaluation framework decomposes RAG performance into four orthogonal metrics:

text
       User Query ─────────────────► [Retrieval Engine]
           │                                 │
           │                                 ▼
           │                         Retrieved Contexts
           │                       (Context Relevance)
           ▼                                 │
   [LLM Generator] ◄─────────────────────────┘
           │
           ▼
    Generated Answer
   (Faithfulness & Answer Relevance)
  1. Context Relevance: Measures the proportion of retrieved chunks that are genuinely relevant to answering the user query:
Context Relevance = |Relevant Retrieved Sentences| / |Total Retrieved Sentences|
  1. Faithfulness (Grounding): Measures whether every statement in the generated answer can be mathematically derived from the retrieved context without external hallucination:
Faithfulness = |Verified Supported Claims in Answer| / |Total Claims in Answer|
  1. Answer Relevance: Measures whether the generated output directly resolves the user's initial question without deviating into tangential topics.
  2. Citation Recall & Precision:
  • Citation Recall: Proportion of statements in the answer that require attribution and possess an associated citation tag.
  • Citation Precision: Proportion of provided citation tags that actually support the specific claim they are attached to.

3. Citation Grounding & Faithfulness Mathematics

To compute Faithfulness algorithmically:

  1. Decompose the generated response A into a set of atomic propositional claims: C = {c₁, c₂, ..., cₘ}.
  2. For each claim cᵢ, evaluate its entailment against the retrieved context passage set P = {p₁, p₂, ..., pₖ}:
e(cᵢ, P) = 1 (if P ⊨ cᵢ [Entailment]), 0 (if P ⊭ cᵢ [Contradiction or Neutral])
Faithfulness Score(A, P) = (1 / |C|) · Σ e(cᵢ, P)

If Faithfulness Score < 1.0, the pipeline flags the output for automated revision, citation re-verification, or execution refusal.


4. Building an Automated Offline Evaluation Harness

Below is a production-ready Python evaluation harness that extracts claim-level citations and verifies evidence support:

python
from typing import List, Dict, Set, Tuple
import re

class RAGEvaluationHarness:
    def __init__(self, entailment_threshold: float = 0.85):
        self.entailment_threshold = entailment_threshold

    def extract_citations(self, answer_text: str) -> List[Tuple[str, List[str]]]:
        """
        Parses sentences and extracts associated bracketed source chunk IDs.
        Example sentence: 'DuckDB uses columnar storage [chunk_01][chunk_03].'
        """
        sentences = [s.strip() for s in re.split(r'(?<=[.!?]) +', answer_text) if s.strip()]
        extracted = []
        
        for sent in sentences:
            chunk_ids = re.findall(r'\[(chunk_\d+)\]', sent)
            clean_sentence = re.sub(r'\[chunk_\d+\]', '', sent).strip()
            extracted.append((clean_sentence, chunk_ids))
            
        return extracted

    def evaluate_grounding(
        self, 
        answer_text: str, 
        retrieved_chunks: Dict[str, str]
    ) -> Dict[str, float]:
        """
        Computes citation recall, precision, and grounding consistency.
        """
        extracted = self.extract_citations(answer_text)
        if not extracted:
            return {"citation_recall": 0.0, "citation_precision": 0.0, "faithfulness": 0.0}

        valid_chunk_ids: Set[str] = set(retrieved_chunks.keys())
        total_claims = len(extracted)
        claims_with_citations = 0
        valid_citations = 0
        total_citations_provided = 0

        for sentence, cited_ids in extracted:
            if cited_ids:
                claims_with_citations += 1
                for cid in cited_ids:
                    total_citations_provided += 1
                    if cid in valid_chunk_ids:
                        valid_citations += 1

        citation_recall = claims_with_citations / total_claims if total_claims > 0 else 0.0
        citation_precision = (
            valid_citations / total_citations_provided 
            if total_citations_provided > 0 else 0.0
        )

        return {
            "citation_recall": round(citation_recall, 3),
            "citation_precision": round(citation_precision, 3),
            "total_claims_evaluated": total_claims,
            "faithfulness": round((citation_recall + citation_precision) / 2.0, 3)
        }

5. Testing with Budget Limits & Mocked APIs

Running end-to-end evaluation suites across hundreds of test cases using live commercial APIs (e.g., GPT-4o) on every git commit creates significant financial expense and rate-limiting bottlenecks.

The Mocked Embedding & Test Double Strategy:

  1. Deterministic Mock Embeddings: For retrieval test suites, replace live vector APIs with deterministic hashing encoders (e.g., token-count-based orthogonal vectors or pre-computed embeddings cached in SQLite).
  2. Offline Corpus Benchmarking: Run 50–100 regression test cases verifying query planning, hybrid RRF reranking, and citation schema validation completely offline in under 3 seconds without external network calls.
  3. Hard Budget Watchers: Implement token budget counters in integration test runners that abort evaluation if token consumption exceeds strict thresholds.

6. Handling Contradictions & Insufficient Evidence

A resilient RAG system must handle the case where evidence is insufficient or contradictory.

The Refusal Protocol:

When the hybrid retriever returns no chunks with confidence scores exceeding the minimum grounding threshold (e.g., RRF Score < 0.015), the pipeline must trigger an explicit Refusal State:

"The retrieved documentation does not contain sufficient evidence to answer this question accurately. Please refine your query or provide the relevant source documents."

Refusing to answer when evidence is weak is fundamentally superior to generating hallucinated extrapolations.


7. Continuous Evaluation Pipeline Architecture

In a modern CI/CD pipeline:

  1. Pull Request Stage: Runs 58 automated unit test cases verifying query decomposition, schema validation, and citation matching with mocked vector indices.
  2. Nightly Evaluation Stage: Runs a golden dataset of 200 domain queries against the live embedding index to compute automated Faithfulness, Context Recall, and latency distribution percentiles (P50, P95, P99).

Primary References & Literature

  • [1]
    Ragas: Automated Evaluation of Retrieval Augmented Generation (arXiv 2023)Primary paper introducing Faithfulness, Context Relevance, and Answer Relevance triad.https://arxiv.org/abs/2306.05685
  • [2]
    Retrieval-Augmented Generation for Large Language Models: A Survey (Gao et al. 2024)Comprehensive taxonomy of RAG architectures and evaluation benchmarks.https://arxiv.org/abs/2312.10997
  • [3]
    FActScore: Fine-grained Atomic Evaluation of Factual Precision in Long Form Text Generation (EMNLP 2023)Atomic propositional claim decomposition and factual precision scoring.https://aclanthology.org/2023.emnlp-main.741/
Related Case Study

Agentic RAG Knowledge Assistant

Evidence-aware retrieval-augmented generation system with multi-pass planning, atomic claim auditing, and bounded retries.

View System Architecture & Benchmarks
Previous Article
Next.js 16 App Router Architecture: Server Components, Streaming SSR, and Static Site Generation

Table of Contents

  • 1. The Evaluation Crisis in Production RAG
  • 2. The Four Core RAG Evaluation Metrics
  • 3. Citation Grounding & Faithfulness Mathematics
  • 4. Building an Automated Offline Evaluation Harness
  • 5. Testing with Budget Limits & Mocked APIs
  • 6. Handling Contradictions & Insufficient Evidence
  • 7. Continuous Evaluation Pipeline Architecture
  • 8. Primary References & Literature

Author

Raj Chhapariya

AI / Data Engineer

Specializing in AI evaluation, hybrid information retrieval, in-process columnar analytics, and full-stack web applications.

GitHub Profile