AI Engineer Dojo Contents
Chapter 7

Evaluating RAG Systems

Retrieval-augmented generation (RAG) means fetching documents first and then answering from them. It's the most common way LLMs are used in production, so it's the system you're most likely to be asked to evaluate. Half the work is classic information retrieval, which search engineers already know well.

Case study

Docket measures the right stage

Docket's documentation assistant was giving wrong answers, and the team had planned a sprint of prompt rewriting. Before starting, they measured the two stages separately. Was the passage with the answer retrieved at all? And when it was, did the model answer faithfully?

Forty percent of the wrong answers were retrieval failures: the right passage never reached the model. When it did get the right passage, the model answered faithfully 94% of the time. A single accuracy number would have sent them to rewrite prompts that couldn't help. They fixed chunking and retrieval instead.

The idea that makes RAG manageable is that it has two places to fail, and you measure them separately before you measure them together. When an answer is wrong, first ask whether retrieval failed or generation failed. The fixes are different, and an end-to-end score can't tell them apart.

Stage 1: retrieval

Did the right documents reach the model's context? This is standard search evaluation: recall@k, precision@k, MRR and nDCG. If retrieval misses, no prompt will rescue the answer, because the facts were never in front of the model.

Stage 2: generation

Given the context, was the answer good? The usual checks are faithfulness (is every claim supported by the context?), answer relevance (does it address the question?), context precision (was the retrieved material useful, or mostly padding?) and citation accuracy (do the cited sources back up what they're cited for?).

Caserecall@5faithfulnessProblemFix
A0.30n/aRetrievalChunking, embeddings, reranking
B0.950.60GenerationPrompt, model, grounding

Both cases look like "a wrong answer" to the user, and they need opposite fixes.

Name to know: the RAG Triad

Context relevance, groundedness and answer relevance are often called the RAG Triad, a term from TruLens. Mention it in an interview, then add context precision and recall, which come from RAGAS, and you've covered both stages with the vocabulary reviewers listen for. Keep the attribution straight: the Triad is those three, and precision and recall come from RAGAS.

A trade-off to manage

A system that always says "the documents don't cover that" will score almost perfectly on faithfulness and help nobody. One that fills gaps with invented details is helpful and dangerous. Track both, and choose where to sit for each use case: very strict for legal or medical answers, looser for brainstorming.

Try it · ~20 minFree · mock judge

Diagnose a broken RAG system

For each wrong answer, decide whether retrieval or generation is at fault. Faithfulness uses a free mock, and one flag switches it to a real model. Aim for the right verdict on each query, backed by its recall@3 and faithfulness.

Lab code · runs free (mock judge by default)

USE_REAL_API = False        # free mock by default; True needs a key

def recall_at_k(retrieved, gold, k):
    top = retrieved[:k]
    return len(set(top) & set(gold)) / len(gold) if gold else 0.0

if USE_REAL_API:
    import anthropic
    from pydantic import BaseModel
    client = anthropic.Anthropic()
    class Grounded(BaseModel):
        reason: str
        grounded: bool
    def faithful(context, answer):
        r = client.messages.parse(model="claude-opus-4-8", max_tokens=300,
            messages=[{"role": "user", "content":
                f"Is every claim in the ANSWER supported by the CONTEXT? "
                f"Reason, then grounded: true/false.\n\nCTX:\n{context}\n\nANS:\n{answer}"}],
            output_format=Grounded)
        return r.parsed_output.grounded
else:
    def faithful(context, answer):
        return "[INVENTED]" not in answer    # mock: ungrounded if it invents

CASES = [   # (query, retrieved_ids, gold_ids, context, answer)
    ("refund window?", ["d2","d9","d4"], ["d1"], "",
     "You have 30 days. [INVENTED]"),
    ("reset password?", ["d5","d1","d7"], ["d5"], "Click 'Forgot password'.",
     "Click 'Forgot password' and check your email."),
    ("export data?", ["d8","d3"], ["d8"], "Export is on the Settings page.",
     "Data export is under Billing. [INVENTED]"),
]

for q, retrieved, gold, ctx, ans in CASES:
    r = recall_at_k(retrieved, gold, k=3)
    if r < 1.0:
        verdict = "RETRIEVAL -> fix chunking / embeddings / reranking"
    elif not faithful(ctx, ans):
        verdict = "GENERATION -> fix prompt / grounding"
    else:
        verdict = "OK"
    print(f"{q:16} recall@3={r:.2f}  {verdict}")
Worked solution
refund window?   recall@3=0.00  RETRIEVAL -> fix chunking / embeddings / reranking
reset password?  recall@3=1.00  OK
export data?     recall@3=1.00  GENERATION -> fix prompt / grounding

In the first case the right document never reached the context (recall 0), so the model answered blind, and the fix is retrieval. In the third case the right document was retrieved (recall 1.0), but the answer says "Billing" where the context says "Settings." Retrieval did its job and generation went off script. One symptom, two causes, and you only see that when you measure the stages separately.

Running case · Meridian × Remi

Remi answers from Meridian's billing-policy documents, so the team evaluates it as a RAG system. Retrieval recall is high overall, but on unusual fee questions Remi cites the wrong fee schedule 18% of the time. An outdated document is still in the index. The fix is cleaning up the documents, and Remi's prompt stays as it is.

If you're starting out

If you haven't studied information retrieval, recall@k is the one to learn first: of the documents that contain the answer, how many showed up in the top k results? MRR and nDCG add credit for ranking the right document higher. A short tutorial on each is enough for most interviews.

"How would you evaluate a RAG chatbot?" is one of the most common interview questions right now. Start by separating retrieval from generation, name a metric for each, and say what you'd do with a wrong answer. That structure alone puts you ahead of many candidates.

If you run the team

If you're building "chat with your documents" or an assistant grounded in company data, you're building RAG. When it gives a customer a confident wrong answer, the team's instinct may be to "improve the prompt." Ask first whether retrieval found the right document. If it didn't, prompt work won't help. If it did and the model still made something up, that's a faithfulness problem, and the team should be measuring it so they'll see if it comes back.

A useful dashboard shows three separate numbers: whether retrieval brought back useful material, whether answers are supported by that material, and whether they answer the question. Ask for retrieval precision and recall alongside those. A single "RAG accuracy" number hides the decision you need to make.

Quiz · Chapter 7

  1. A RAG answer is wrong and recall@5 is 0.30. What do you fix first?
  2. Another system has recall@5 of 0.95 and faithfulness of 0.60. Where's the problem?
  3. What's the basic principle of RAG evaluation?
  4. A system always answers "the context doesn't say" and scores near-perfect faithfulness. Why isn't that good?
  5. Faithfulness (groundedness) measures whether:
Back Continue

The AI Evaluation Engineer · aiengineerdojo.com