RAG · Module 10 of 14 · 10 concepts · about 17 min

Evaluating a RAG System

How to know whether a RAG system works, and which part to fix when it does not: a test set, retrieval metrics, answer metrics, automated judges and checks on live traffic.

At work: What lets a team change a chunk size, a model or a prompt with confidence, and what a manager asks for before letting an assistant talk to customers.

Evaluate retrieval and generation separately

What it is

A RAG answer is produced by two parts in sequence, and each can fail on its own.

  • Retrieval evaluation asks: did the search bring back the chunks that contain the answer?
  • Generation evaluation asks: given those chunks, did the model write a correct, grounded answer?

An end-to-end score, judging only the final answer, tells you something is wrong but not where.

Why it matters

The fix depends entirely on which half failed.

  • Poor retrieval is fixed with chunking, hybrid search or reranking.
  • Poor generation is fixed with the prompt, the context layout or the model.
  • Without separate scores, teams spend weeks rewriting prompts for a problem that lives in the search step.
  • This is the single most important idea in RAG evaluation.

In the real world: A team about to switch to a more expensive model first measures retrieval, finds the right chunk is missing for 30 percent of questions, and fixes the search instead.

Visual example

Diagnosis

The pair of scores tells you which half to work on.

Reading the two scores together
retrievalgenerationwhat it meanswork on
GoodGoodThe system worksCost and speed
BadBad or goodThe model never saw the answerChunking, hybrid search, reranking
GoodBadThe answer was in front of the model and it failedPrompt, context order, model

Judging the system by reading a few answers and deciding they 'look good'. Fluent answers hide retrieval failures: the model writes a confident reply from whatever it was given.

The retrieval golden set

What it is

A golden set is a fixed list of test questions, each paired with the correct answer and with the IDs of the chunks or documents that contain it.

  • Fifty to a few hundred questions is enough to start.
  • They should come from real users where possible, and cover the range of real traffic: easy and hard, short and long, exact codes and loose paraphrases, and questions that have no answer in the documents.

Why it matters

It turns 'I think it got better' into a number.

  • Every proposed change is run against the same questions, and the scores are compared.
  • It is also the first thing an interviewer wants to hear when they ask how you would improve a RAG system: before changing anything, build the set that lets you measure the change.

In the real world: A support team builds its golden set from 200 real tickets and their resolutions, and reruns it automatically on every change to the pipeline.

[
  { "question": "My order was 40 minutes late. Do I get anything back?",
    "relevant_chunks": ["c1"],
    "answer": "Yes, the delivery fee is refunded to your wallet." },

  { "question": "What does error KK-4471 mean?",
    "relevant_chunks": ["c6"],
    "answer": "Your bank declined the payment." },

  { "question": "Do you deliver to Shimla?",
    "relevant_chunks": [],
    "answer": null }
]

Labelling relevant chunks by chunk ID and then changing the chunking. The IDs no longer exist and the set is useless. Label at the level of the document and section, or the exact answer text, so the set survives re-chunking.

Practise it: Design a Production RAG System

Recall@k and precision@k

What it is

Two retrieval metrics computed on the top k results.

  • Recall@k: of all the relevant chunks that exist, what fraction appeared in the top k?
  • Precision@k: of the k chunks returned, what fraction were relevant?

A simpler cousin, hit rate@k, asks only whether at least one relevant chunk made the top k.

Why it matters

Recall@k is the one that matters most for RAG.

  • If the chunk holding the answer is not retrieved, the model cannot answer, so recall sets the ceiling for the whole system.
  • Precision matters for the chunks that finally go into the prompt, where irrelevant ones cost tokens and distract the model.
  • The first stage is tuned for recall, the reranker for precision.

In the real world: A team tracks recall@50 for the first-stage search and precision@5 after reranking, and can tell from the two numbers which stage a regression came from.

Visual example

Computed

Five results for one question; 2 chunks are relevant (c1 and c2). The top 3 contain only one of them.

The retriever's ranked results
positionchunkrelevant?
1c3no
2c1yes
3c5no
4c2yes
5c4no

The metrics

recall@3: 1 relevant found ÷ 2 relevant in total = 0.5

precision@3: 1 relevant ÷ 3 returned = 0.33

recall@5: 2 found ÷ 2 = 1

precision@5: 2 relevant ÷ 5 returned = 0.4

def recall_at_k(ranked: list[str], relevant: set[str], k: int) -> float:
    return len(set(ranked[:k]) & relevant) / len(relevant)

def precision_at_k(ranked: list[str], relevant: set[str], k: int) -> float:
    return len(set(ranked[:k]) & relevant) / k

ranked   = ["c3","c1","c5","c2","c4"]
relevant = {"c1","c2"}

recall_at_k(ranked, relevant, 3)      # 0.5
precision_at_k(ranked, relevant, 3)   # 0.33
recall_at_k(ranked, relevant, 5)      # 1

Reporting recall without saying at what k. Recall@100 is nearly always high and says little about a system that only puts 5 chunks in the prompt. Report it at the k each stage actually uses.

MRR and nDCG

What it is

Two metrics that care about position, not only presence.

  • MRR (mean reciprocal rank): for each question take 1 / position of the first relevant result (1 if it is first, 0.5 if second, 0 if absent), then average over all questions.
  • nDCG (normalised discounted cumulative gain): each relevant result earns credit that shrinks the lower it is placed, 1 / log2(position + 1); the total is divided by the best total possible, giving a score from 0 to 1.

Why it matters

Recall says the right chunk was found; these say how high it was placed.

  • That matters because only the top few reach the prompt, and because models use earlier chunks more reliably.
  • MRR suits questions with one right chunk. nDCG suits questions with several relevant chunks, and can also handle degrees of relevance (very relevant, partly relevant).
  • They are the natural metrics for judging a reranker.

In the real world: A reranker trial shows recall@50 unchanged, as expected, while MRR rises from 0.52 to 0.78: the same chunks are found, but the right one now sits near the top.

Visual example

Computed MRR

Three test questions. MRR is the average of 1 / position of the first relevant result = 0.5.

Mean reciprocal rank over a small golden set
questionresults, in orderrelevantfirst hit atreciprocal rank
late order refundc3, c1, c5, c2, c4c1, c220.5
membership pricec4, c3, c1c411
error KK-4471c1, c3, c5c6not found0

The mean

MRR: (0.5 + 1 + 0) ÷ 3 = 0.5

The last question drags the average down. A miss counts as zero, however good the other results are.

For the ranking above (c3, c1, c5, c2, c4; relevant: c1, c2):

  • Reciprocal rank: the first relevant chunk is at position 2, so 1/2 = 0.5
  • DCG@5: relevant chunks at positions 2 and 4 earn 1/log2(3) + 1/log2(5) = 0.631 + 0.431 = 1.062
  • Ideal DCG: the same two chunks at positions 1 and 2 would earn 1/log2(2) + 1/log2(3) = 1 + 0.631 = 1.631
  • nDCG@5 = 1.062 / 1.631 = 0.65

Averaging away the failures. An MRR of 0.5 can mean every question had its answer in second place, or half were perfect and half found nothing. Always look at the list of questions that scored zero.

Groundedness evaluation (faithfulness)

What it is

Groundedness, also called faithfulness, measures whether the answer is supported by the retrieved context.

  • The usual method: break the answer into individual claims, check each claim against the context (with a judge model), and report the fraction that are supported.
  • A score of 1.0 means nothing in the answer goes beyond the documents.

Why it matters

It is the direct measure of hallucination in a RAG system, and it needs no reference answer, so it can run on live traffic.

  • Note what it does not measure: a faithful answer can still be wrong if the retrieved context was wrong or off-topic.
  • Groundedness checks the answer against the context, not against the truth.

In the real world: A bank samples live answers every day and alerts when the share of fully grounded answers falls, which once caught a prompt change that let the model add 'helpful' unsupported advice.

Context:  If your order arrives more than 30 minutes late, we
          refund the full delivery fee to your wallet.

Answer:   Yes, the delivery fee is refunded to your wallet,
          and you also get a 10% coupon.

Claims:   1. The delivery fee is refunded to the wallet.  supported
          2. The customer also gets a 10% coupon.         NOT supported

Groundedness = 1 supported / 2 claims = 0.5

Treating a high groundedness score as proof of a correct answer. An answer faithfully built from the wrong chunk scores 1.0 and is still wrong. Always read it alongside retrieval metrics and answer correctness.

Practise it: Design a Production RAG System

Answer relevance and answer correctness

What it is

  • Answer relevance asks whether the answer actually addresses the question that was asked, with no reference needed. An answer can be perfectly grounded and still fail here, by responding to a different question or burying the point.
  • Answer correctness compares the answer with the reference answer in the golden set: does it state the same facts?

Why it matters

Together with groundedness these cover the generation side.

  • Grounded but irrelevant: the model summarised the context without answering.
  • Relevant but ungrounded: it answered from memory.
  • Correctness is the measure closest to what users care about, but it needs reference answers, so it only works on the golden set.

In the real world: A product team finds answers scoring high on groundedness and low on relevance: the assistant was quoting the policy accurately and never saying yes or no to the customer.

Measuring correctness by word overlap with the reference (metrics such as BLEU or ROUGE). 'The fee is refunded' and 'you get your delivery charge back' share almost no words and mean the same thing. Use a judge model that compares meaning, not wording.

Context precision and context recall

What it is

Two measures of the retrieved context that can be estimated with a judge model, without hand-labelled chunk IDs.

  • Context precision: what share of the retrieved chunks are actually relevant to the question, with more credit when the relevant ones are ranked first.
  • Context recall: what share of the facts in the reference answer can be found in the retrieved chunks.

Why it matters

They complete a widely used set of four, popularised by the open-source RAGAS framework: context precision and context recall for the retriever, faithfulness and answer relevance for the generator. Naming these four and saying which half each one tests is a complete answer to 'how do you evaluate RAG?'.

In the real world: A team with no labelled chunks uses context recall against its reference answers to compare two chunking strategies, and picks the one that surfaces more of the needed facts.

Visual example

The four core metrics

Two for the retriever, two for the generator.

What each metric tests, and what it needs
metrictestsquestion it answersneeds a reference answer?
Context precisionRetrieverIs what we retrieved relevant?No
Context recallRetrieverDid we retrieve everything needed?Yes
Faithfulness (groundedness)GeneratorIs the answer supported by the context?No
Answer relevanceGeneratorDoes the answer address the question?No

Running an evaluation library and reporting its numbers without reading any examples. These scores are themselves produced by a model and can be wrong. Read twenty low-scoring cases by hand to confirm that the metric is measuring what you think.

LLM-as-judge and its limits

What it is

LLM-as-judge means using a language model to grade outputs: 'does this context support this claim?', 'does this answer match the reference?'. The judge gets a clear rubric, the material to grade, and is asked for a verdict, ideally a simple one such as yes or no, with a short reason.

Why it matters

It is the only way to grade thousands of free-text answers at reasonable cost.

  • But a judge is a model and makes mistakes, so it has to be checked before it is trusted: have people grade a hundred or so examples, compare with the judge's verdicts, and adjust the rubric until they agree most of the time.
  • An unchecked judge gives numbers that look precise and mean little.

In the real world: A team finds its judge agrees with human graders 71 percent of the time, rewrites the rubric with three worked examples, reaches 92 percent, and only then uses it for release decisions.

You are grading a support answer.

Context:  {context}
Claim:    {claim}

Is the claim fully supported by the context? Consider only the
context, not your own knowledge.
First give a one-sentence reason. Then answer exactly
SUPPORTED or NOT_SUPPORTED.

Asking the judge for a score from 1 to 10. Models are inconsistent on fine scales: the same answer gets a 6 one run and an 8 the next. Yes/no questions, or a few clearly described levels, are far more reliable.

Synthetic test questions

What it is

When there are no real user questions yet, a language model can write them.

  • Give it a chunk and ask for a question that this chunk answers; the chunk is then the known relevant result.
  • Repeating this over a sample of the collection produces a test set with labels for free.

Why it matters

It gets a project from zero to a measurable baseline in an afternoon, and it can cover parts of the collection that real users have not yet asked about. It is a starting point to be replaced or mixed with real questions as soon as traffic exists.

In the real world: Before launch, a team generates 500 questions from its policy documents to pick a chunking strategy, then swaps in real questions from the first month of traffic.

Trusting scores from synthetic questions alone. A model writing a question from a chunk tends to reuse the chunk's own words, which makes retrieval look far easier than it is with real users, who phrase things differently and ask things the documents do not cover. Ask for paraphrased, realistic questions, and review a sample by hand.

Online evaluation: feedback, A/B tests and regression gates

What it is

Three checks beyond the offline test set.

  • User feedback: thumbs up or down, whether the user rephrased the question, whether they asked for a human.
  • A/B tests: send a share of live traffic to a new version and compare outcomes.
  • Regression gates: run the golden set automatically on every change and block the release if a key metric drops.

Why it matters

The golden set shows how the system does on questions you thought of; live traffic shows how it does on the questions people really ask. Each feeds the other: failures seen in production become new entries in the golden set, so the same mistake cannot return unnoticed.

In the real world: An online retailer A/B tests a new reranker and ships it because the share of chats handed to a human agent falls by a measurable margin, not because the answers 'read better'.

Visual example

Offline and online

Offline tests guard a release. Online signals tell you what to test next.

Where each kind of evaluation fits
checkwhen it runstells you
Golden set (retrieval + answer metrics)Before every releaseDid this change make things better or worse?
Regression gateAutomatically, on every changeStop: a key metric dropped
A/B testOn a share of live trafficDoes it help real users?
Feedback and behaviourContinuouslyWhere it fails in the real world

Relying on thumbs-down counts alone. Few users click anything, and those who do are not typical. Behavioural signals (rephrasing, abandoning, escalating to an agent) are noisier per event but far more plentiful.

Practise it: Design a Document Intelligence Platform