BXUP Track progress & test yourself — free
Data Science & ML/AI · Playbook · Core · ~6 min read
DATA SCIENCE & ML/AI · PLAYBOOK · CORE

RAG Evaluation with Ragas and Claim-Level Hallucination Checks

"The RAG bot is hallucinating" is a symptom, not a diagnosis. A RAG failure lives in one of three places — the retriever, the generator, or the contract between them — and each needs a different fix.

Tier: Core · Workflow area: Evaluation Engineering

Ragas (named verbatim in DS/ML job postings) gives you component-attributed metrics: faithfulness, answer relevancy, context precision, context recall. This playbook runs the four metrics on your golden dataset, teaches you to read each score against the right pipeline component, and goes one level deeper with claim-level verification — decomposing answers into atomic claims and checking support for each, which is how you measure hallucination instead of arguing about it.

When to use

  • A RAG pipeline exists and you need quantitative quality numbers attributable to components — before tuning chunkers, rerankers, embedders (pb-31), or prompts.
  • Stakeholders ask "how much does it hallucinate?" and you owe a number with a method behind it.
  • You are about to change any RAG component and need before/after evidence (feeds pb-37's CI gates).

Skip metric selection debates until pb-34's error analysis is done — the taxonomy tells you which of these metrics matters most for your failure Pareto.

Prerequisites

  • Your pb-34 golden dataset in RAG-evaluable form: question, retrieved_contexts (captured at runtime, not re-retrieved later), answer, and where available ground_truth / reference facts.
  • ragas installed; an LLM for metric computation (a cheap-tier model handles it; budget ≤ $2 for ~50 cases) and optionally Phoenix or LangSmith for trace-linked results.
  • Instrumentation that logs retrieved contexts alongside answers — if your app does not capture contexts, fix that first; post-hoc re-retrieval corrupts every metric below.

The workflow

  1. Map the four metrics to components before running anything. Write this table into your report skeleton: faithfulness (is the answer supported by retrieved context?) → generator problem when low; answer relevancy (does the answer address the question?) → generator/prompt problem; context precision (are relevant chunks ranked above irrelevant ones?) → retriever/reranker problem; context recall (did retrieval fetch what the ground truth needs?) → retriever/chunking/embedder problem. Reading scores without this mapping is how teams "fix" the wrong component for a sprint.

  2. Run the Ragas evaluation.

    from ragas import evaluate
    from ragas.metrics import (faithfulness, answer_relevancy,
                               context_precision, context_recall)
    from datasets import Dataset
    
    ds = Dataset.from_list(cases)  # question, contexts, answer, ground_truth
    report = evaluate(ds, metrics=[faithfulness, answer_relevancy,
                                   context_precision, context_recall])
    

    Pin the judge-LLM model and version in config — metric values are not comparable across judge models, so the pin is part of the metric definition.

  3. Interpret with thresholds and the diagnostic grid. Working thresholds to start (tune to your domain): faithfulness < 0.70 → active hallucination investigation; context recall < 0.75 → retrieval is starving the generator. Diagnose combinations: low faithfulness + high recall = generator ignoring or overriding good context (prompt/model fix); low recall + high faithfulness = model faithfully answering from insufficient context — correct behavior, starved inputs (retrieval fix); low precision + high recall = right chunks buried in noise (reranker fix); low relevancy + high faithfulness = grounded but off-target (question-handling/prompt fix).

  4. Drill into hallucination at claim level. Averages hide severity — one fabricated contract clause in an otherwise faithful answer can be the whole incident. For the 10–20 lowest-faithfulness cases: (a) prompt an LLM to decompose the answer into atomic factual claims; (b) for each claim, check support against the retrieved contexts — verdicts supported (quote the span), contradicted, or unsupported; (c) human-verify verdicts on 3–5 cases. Output per case: claim table with verdicts and supporting spans. Unsupported-claim rate (claims unsupported / total claims) is your precise hallucination number; the span attribution is what makes it reviewable.

  5. Slice, then read traces. Break all metrics by pb-34's slice tags (intent, document type, question complexity). Then read the 5 worst traces per weak slice — the metric found where; the trace tells you what. Every eval run ends in trace reading or it ends in guessing.

  6. Fix the indicated component and re-run. One change at a time (the pb-31 discipline): fix, re-run the identical dataset and judge pin, report deltas on all four metrics — a reranker that lifts precision can dent recall; the four-metric panel catches the trade.

  7. Institutionalize. Commit the eval script, dataset version, judge pin, and thresholds; this exact bundle becomes the pb-37 CI regression gate, and the claim-level check becomes the escalation path when the gate trips on faithfulness.

Key Takeaway:

Faithfulness low and context recall high means the generator is the culprit; both low means retrieval starved it — the entire value of Ragas is attribution, and attribution is what turns "it hallucinates" into a fixable ticket.

Tool variants

  • Ragas standalone: the workflow above; open source, runs local, judge calls to any cheap-tier API model.
  • Ragas + Phoenix (self-hosted): metric results linked to traces so step 5's worst-case reading is one click; Phoenix also ships its own hallucination eval to cross-check faithfulness.
  • DeepEval / LangSmith: equivalent metric suites; LangSmith is managed (data leaves your boundary — check the restricted variant), DeepEval slots into pytest natively for pb-37.

Verification

  • All four metrics computed on the versioned golden dataset with runtime-captured contexts and a pinned judge model.
  • Component-attribution table filled in: each weak metric mapped to a suspected component with the diagnostic-grid reasoning.
  • Claim-level tables exist for the worst faithfulness cases, human-verified on a sample; unsupported-claim rate reported.
  • Slice breakdown present; the five worst traces per weak slice were actually read (notes required).
  • Re-run after any fix shows all four metrics, not just the one you targeted.

Pitfalls

  • Re-retrieving contexts at eval time. The index changed since the trace; you are now evaluating answers against contexts the generator never saw. Capture contexts at generation time, always.
  • Treating Ragas scores as absolute truths. They are LLM-judged estimates with noise — compare runs under the same judge pin, and never celebrate a 0.02 move without confidence intervals over cases.
  • Optimizing faithfulness alone. A model that answers "not in the context" to everything scores near-perfect faithfulness; pair it with relevancy and recall or you will ship a very honest, useless bot.
  • Ground-truth-free context recall. Recall needs reference answers or labeled relevant chunks; on cases without ground truth, report the metric as absent, not as zero.
  • Skipping human verification of claim verdicts. The claim checker is itself an LLM judge with judge failure modes; the 3–5-case audit is the calibration anchor (full treatment in pb-36).

Restricted-environment variant

  • Run Ragas with a self-hosted judge (8B-class via Ollama/vLLM) when client contexts cannot reach external APIs; scores shift with the weaker judge, so re-baseline all thresholds and double the human-verified sample.
  • Phoenix self-hosted keeps traces, datasets, and metric results inside the boundary; avoid managed eval SaaS for client workloads unless contractually cleared.
  • Exportable report: metric panel, slice deltas, unsupported-claim rates — numbers and taxonomy only, no verbatim contexts or answers across the boundary.
Note

The judge model pin is part of your metric's identity — a self-hosted judge swap mid-quarter silently redefines every threshold; version it like a schema change.

Success criteria

  • A four-metric panel with slices, thresholds, and a component-attribution diagnosis your RAG engineers agree with.
  • A defensible hallucination number: unsupported-claim rate with span-attributed evidence, human-verified on a sample.
  • At least one component fix chosen because of the metric pattern, with before/after deltas on all four metrics.
  • The eval bundle (script + dataset version + judge pin + thresholds) committed and ready to become a CI gate.
This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in