learn-rag-with-phoebe / Builder session 9 of 10
Learn RAG with Phoebe · Builder track · Session 9 of 10

RAG evaluation: measuring what "good" means

You have built the whole pipeline - chunk, embed, store, retrieve, rerank, augment, generate, cite. Now the hard question: is it any good? "It felt right in the demo" is how RAG systems quietly rot in production. This session gives you a scorecard. You will learn to split failures into two buckets - the retriever's fault or the generator's fault - build a golden set of questions with reference answers, and run real metrics: faithfulness, answer relevancy, context precision and recall, hit rate and MRR, all powered by an LLM-as-judge. By the end, Recall stops being a vibe and starts being a number you can move.

🔴 Builder track · advanced Practitioners · some Python Concept + code Session 9 of 10
0-3 · Welcome 3-22 · Concepts 22-40 · Golden set + eval 40-45 · Q&A
Part 0

Why "it feels right" is a trap

A RAG system has a lot of moving parts, and each one can fail silently. Bad chunks, a retriever that misses, a reranker that hurts, a model that hallucinates confidently over perfect context. When the answer looks wrong, which part do you fix? Without measurement you are guessing, and guessing at a five-stage pipeline is how a week disappears. Evaluation turns "something is off" into "context recall dropped to 0.4 - the retriever is missing chunks". That is the whole game today.

Live - presented in session Self-study - full depth after class ★ Recall gets a scorecard Sources covered at the end
★ What you build today A working mental model of retrieval metrics vs generation metrics, a golden/reference set built from Recall's real failures, and a RAGAS-style eval script that scores faithfulness, answer relevancy, and context precision/recall - so every future change to Recall can be judged, not felt.
Part 1 · covers the two metric families + diagnosis

Retrieval metrics vs generation metrics 10 min live

Every RAG metric answers one of two questions: did we fetch the right context? (retrieval) or did we write a good answer from it? (generation). Keeping them apart is the single most useful habit in RAG evaluation, because it tells you which half of the pipeline to fix. A low retrieval score points at chunking and search; a low generation score points at your prompt and model.

RETRIEVAL · did we fetch the right context? GENERATION · did we answer well from it? Hit rate Is a relevant chunk anywhere in the top-k? Context precision Are the top-ranked chunks the right ones? (ranking) Context recall Did we retrieve everything the answer needs? Faithfulness Is every claim supported by the context? (hallucination) Answer relevancy Is the answer on-topic for the question asked? Answer correctness Does it match the ground-truth answer? (needs reference) low recall → fix the retriever (chunking, search, top-k) low faithfulness → fix the generator (prompt, model, grounding) Split the score into two families first - it tells you which half of the pipeline to touch.
🔍 Click to zoom - the two metric families and what a low score in each is telling you
LiveThe retrieval side: can it find the right context?3 min

Retrieval metrics judge the chunks you fetched, before the model writes a word. If these are bad, nothing downstream can save you - a perfect model over the wrong context still gives a wrong answer.

  • Hit rate. The blunt one: was a relevant chunk anywhere in the top-k? It ignores position. Great for a first pulse on the retriever.
  • Context precision. Ranking quality - are the most relevant chunks ranked highest? A retriever that buries the right chunk at position 8 scores poorly here even if hit rate says "found it".
  • Context recall. Completeness - of everything needed to answer, how much did we actually retrieve? This one needs a reference answer to know what "everything" was.
Hit rate + MRR (the LlamaIndex pair) LlamaIndex's RetrieverEvaluator reports Hit Rate and MRR (mean reciprocal rank). MRR rewards ranking the relevant doc high: if the right chunk is always at position 1, MRR = 1.0; at position 2, each query contributes 1/2; and so on. Hit rate says "did we find it", MRR says "how near the top". Use both - they answer different questions about the same retriever.
LiveThe generation side: is the answer good and honest?3 min

Generation metrics judge the answer the model wrote, given the context it was handed. Two of them (faithfulness, relevancy) need no reference answer at all - a huge practical win.

  • Faithfulness. The anti-hallucination metric. RAGAS computes it as supported claims / total claims: it breaks the answer into claims and checks how many are backed by the retrieved context. 1.0 means every statement is grounded.
  • Answer relevancy (RAGAS now calls it Response Relevancy). It generates questions from the answer and measures their mean cosine similarity to the real question. High = the answer stays on-topic. Note the trap: it measures on-topic-ness, not factual accuracy - a confident wrong answer can still be "relevant".
  • Answer correctness. The one that needs a ground-truth answer: a blend of factual F1 (claims that match) and semantic similarity to the reference.
Real world

The relevancy false comfort. A team (anonymized) shipped a bot scoring 0.9 answer relevancy and celebrated - until users complained. The answers were beautifully on-topic and factually wrong. Relevancy was high because it only checks "is this about the question". Faithfulness was the metric that would have caught it, and it was sitting at 0.5. Never read relevancy as accuracy.

Here is the whole family on one card - what each measures and, crucially, the failure it catches:

MetricWhat it measuresFailure it catches
Hit rateA relevant chunk is somewhere in top-kRetriever misses the answer entirely
MRRHow high the relevant chunk is rankedRight chunk found but buried too low
Context precisionRanking quality of retrieved chunksNoise ranked above the good chunk
Context recallCompleteness vs the reference answerPart of the answer was never retrieved
FaithfulnessSupported claims / total claimsHallucination - claims not in the context
Answer relevancyAnswer stays on-topic for the questionRambling, evasive, or off-topic answers
Answer correctnessFactual F1 + similarity to ground truthAnswer that is on-topic but simply wrong
Part 2 · covers the golden set + a RAGAS-style run

Building a golden set and running an eval 9 min live

A metric is only as good as the questions you run it on. A golden set (reference set) is a small, curated list of questions - each with a reference answer and, ideally, the reference contexts that should have been retrieved. You do not need thousands. Twenty to fifty questions that cover your real usage, including the ones that failed, will move you faster than any benchmark. The flow is always the same: build the set, run the metrics, read the scorecard.

1 · Build golden set • question • reference answer • reference contexts 20-50 real questions, including your failures 2 · Run metrics LLM-as-judge: faithfulness, relevancy needs reference: recall, correctness one judge model scores each 3 · Read scorecard faithfulness 0.91 answer relevancy 0.88 context precision 0.79 context recall 0.42 recall is your bottleneck Build once, run on every change. The scorecard is the diff between "before" and "after".
🔍 Click to zoom - build the golden set, run the metrics, read the scorecard
Self-studyA RAGAS-style eval, end to end4 min read

RAGAS wraps all of these metrics behind one evaluate() call. You assemble a small dataset - question, the answer Recall produced, the contexts it retrieved, and the ground-truth answer - then pass the metrics you care about. Faithfulness and answer relevancy work without ground truth; context recall and correctness use it.

Python · a RAGAS-style eval over Recall's golden setfrom datasets import Dataset from ragas import evaluate from ragas.metrics import ( faithfulness, # supported claims / total claims (LLM-as-judge) answer_relevancy, # a.k.a. response relevancy - on-topic, not accuracy context_precision, # ranking quality of retrieved chunks context_recall, # completeness - REQUIRES ground_truth ) # one row per golden-set question. answer + contexts come from Recall; # ground_truth is the reference answer you wrote by hand. data = { "question": [ "How do I get a refund?", "What is the duplicate-charge policy?", ], "answer": [ # what Recall generated "Refunds go to the original payment method in 5-7 business days.", "Duplicate authorization holds drop off automatically within 3 days.", ], "contexts": [ # the chunks Recall retrieved (list per question) ["Refunds are issued to the original payment method within 5-7 business days."], ["A duplicate authorization hold is released automatically within 72 hours."], ], "ground_truth": [ # your reference answers "Refunds are returned to the original payment method within 5-7 business days.", "Duplicate authorization holds are released automatically within 72 hours.", ], } dataset = Dataset.from_dict(data) result = evaluate( dataset, metrics=[faithfulness, answer_relevancy, context_precision, context_recall], # llm=... a judge model such as gpt-4o-mini or a Claude model powers # claim extraction, verification, and question generation under the hood. ) print(result) # -> {'faithfulness': 0.91, 'answer_relevancy': 0.88, # 'context_precision': 0.79, 'context_recall': 0.42}

Read that last line the way a mechanic reads a dashboard. Faithfulness and relevancy are healthy - the generator is doing its job. Context recall at 0.42 is the alarm: the retriever is leaving out chunks the answers needed. You now know exactly where to spend the next hour, and you never had to guess.

LiveWhich metrics need a reference, which are self-judging3 min

This distinction decides how much labelling work you sign up for, so hold it clearly:

  • Need a reference answer / ground truth: context recall, answer correctness, and reference-based context precision. These compare against something you wrote by hand - more work to build, but they measure completeness and correctness that self-judging metrics cannot.
  • LLM-as-judge only (no reference): faithfulness and answer relevancy. A judge model extracts and verifies claims, or generates questions from the answer, and scores from that alone. Cheap to run on every query - even in production.
The LLM-as-judge, demystified Most of these scores are not hand-computed - a judge model (e.g. gpt-4o-mini or a Claude model) does the reading. For faithfulness it extracts the answer's claims and checks each against the context. For relevancy it generates plausible questions from the answer and compares them to the real one. The judge is a model grading a model. It is not perfect, but it is consistent and fast, which is what makes eval-on-every-change affordable.
Practice: vibe check first, then component-wise Run an end-to-end vibe check before you reach for the microscope - eyeball ten answers, get a feel for whether the system is broadly working. Only then go component-wise: split retrieval from generation and read the individual metrics to localize the fault. Skipping the vibe check wastes time optimizing a metric while a gross bug hides in plain sight.
Build-along · score Recall

Turn your failures into a golden set ★ 12 min

Back in b1 you saved three queries where retrieval returned the wrong chunk, and in b4 you collected more failures while tuning the retriever. Those failures are the most valuable eval questions you own - they are exactly where Recall is weak. Turn them into a golden set and score them.

Gather your failures. Pull the three failing queries from b1 and any from b4. For each, write the question, the correct reference answer (by hand), and the chunk(s) that should have been retrieved.

Run Recall on them. For each question, capture what Recall actually generated and the contexts it actually retrieved. This is your answer and contexts columns.

Score it. Run the RAGAS-style eval with faithfulness, answer relevancy, context precision, and context recall. Do the end-to-end vibe check first, then read the numbers.

Diagnose. In one line per failure: is this a retriever problem (low recall/precision) or a generator problem (low faithfulness)? Now you know what to fix - and you have proof, not a hunch.

★ Recall's status after b9 Recall now has a scorecard. Its failures are named questions with reference answers, and every future change can be judged: did faithfulness climb, did context recall move? In b10 - the final session - we take Recall to production: freshness, caching, latency, monitoring, and cost, then hand it off to LangChain.
Homework

Before session b10 ◐ 45 min total

Source material

Official sources covered

Taught from the RAGAS and LlamaIndex evaluation docs plus OpenAI's cookbook. This page covers ~80% of their working content on RAG metrics - the rest (hosted dashboards, paid keys) stays with the source.

RAGAS · metrics referencePart 1-2 · faithfulness = supported/total claims · response (answer) relevancy · context precision + recall · which need a reference
LlamaIndex · evaluation (RetrieverEvaluator)Part 1 · Hit Rate + MRR for the retriever in isolation
OpenAI cookbook · Evaluate RAGPart 2 · the golden-set + eval-loop framing; LLM-as-judge scoring
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · Your RAG answer is wrong. Faithfulness is high (0.95) but context recall is low (0.4). What is the most likely problem?

High faithfulness means the answer is faithful to the context it got; low context recall means the retriever didn't fetch everything needed. That points at the retriever, not the generator.

2 · In RAGAS, faithfulness is computed as...

RAGAS faithfulness breaks the answer into claims and measures how many are supported by the retrieved context - it is the anti-hallucination metric.

3 · Which metric does NOT require a reference answer / ground truth?

Answer relevancy is self-judging - it generates questions from the answer and compares to the real one, no reference needed. Context recall and answer correctness both require ground truth.

Builder session 9 cheat sheet · pin this

Two familiesRetrieval metrics (did we fetch right?) vs generation metrics (did we answer well?). Split first.
DiagnosisLow recall → fix retriever. Low faithfulness → fix generator. The scorecard names the culprit.
FaithfulnessSupported claims / total claims. The anti-hallucination metric. No reference needed.
Answer relevancyOn-topic-ness via generated questions. NOT accuracy. RAGAS renamed it response relevancy.
Context precision / recallPrecision = ranking quality. Recall = completeness (needs a reference answer).
Hit rate + MRRLlamaIndex RetrieverEvaluator. Hit rate = found it. MRR = how near the top (1.0 = always first).
Golden set20-50 real questions + reference answers/contexts. Build from failures. Run on every change.
PracticeEnd-to-end vibe check first, then component-wise. LLM-as-judge powers the scoring.