Zucchetti LLM Course — Lecture 8
How do you know your system is actually working?
Kamyar Zeinalipour
Hour 1 — Theory
S1 — The Evaluation Imperative
S2 — Retrieval Metrics
S3 — Generation Metrics & Hallucination
S4 — LLM-as-Judge
S5 — Observability & Tracing
☕ Break
🔬 Hour 2 — Hands-On Mega-Lab — Build, evaluate, and improve a full RAG pipeline
Four levels of retrieval sophistication — you’ve built all of them (in theory)
L4 — Naive RAG — retrieve + generate, fixed pipeline
L5 — Advanced RAG — re-ranking, HyDE, routing, decomposition
L6 — Graph RAG — knowledge graphs, relationships, entity extraction
L7 — Agentic RAG — function calling, ReAct, self-correcting pipelines
Section 1 — The Evaluation Imperative
Component
“Did we find the right chunks?”
Precision, Recall, MRR
Tests retrieval in isolation
End-to-End
“Is the answer correct and grounded?”
Faithfulness, Relevance
Tests retrieval + generation
System
“Are users satisfied?”
Thumbs up/down, task success
Tests the full user experience
The foundation of every evaluation pipeline
| Field | Example | Purpose |
|---|---|---|
question | “How many sick days am I entitled to?” | The user query |
ground_truth | “Full-time employees receive 12 paid sick days per year.” | The correct answer |
expected_chunks | [“sick_leave_policy.txt, chunk 3”] | Which documents should be retrieved |
| Stage | Size | Purpose |
|---|---|---|
| Development | 15–50 examples | Quick iteration, catch obvious bugs |
| Staging | 50–200 examples | Reliable metrics, regression testing |
| Production | 200+ examples | Statistical significance, edge cases |
Section 2 — Retrieval Metrics
Two fundamental questions about your retrieval system
Precision
“Of what I found, how much is actually useful?”
Noise control — fewer irrelevant chunks
Recall
“Of everything useful, how much did I find?”
Coverage — nothing important missed
What fraction of retrieved chunks are relevant?
What fraction of all relevant chunks did we find?
Retrieved: [✅, ❌, ✅, ❌, ❌] → Precision@5 = 2/5 = 0.40 | Recall@5 = 2/2 = 1.00
Good recall (found everything), mediocre precision (60% noise).
“How high in the list is the first relevant result?”
| Query | Retrieved (✅ = relevant) | First relevant at | Reciprocal Rank |
|---|---|---|---|
| Q1 | [✅, ❌, ❌] | Position 1 | 1/1 = 1.00 |
| Q2 | [❌, ❌, ✅] | Position 3 | 1/3 = 0.33 |
| Q3 | [❌, ✅, ❌] | Position 2 | 1/2 = 0.50 |
MRR = (1.00 + 0.33 + 0.50) / 3 = 0.61
Not all positions are equal — top-1 matters more than top-5
A relevant chunk at position 1 gets a weight of 1/log₂(2) = 1.00
A relevant chunk at position 5 gets a weight of 1/log₂(6) = 0.39
Position matters. The best results should be at the top.
Binary: did we find anything useful? Yes or no.
| Metric | Best For | Target |
|---|---|---|
| Hit Rate@5 | Quick health check | ≥ 0.90 |
| Precision@3 | Context quality (less noise in prompt) | ≥ 0.60 |
| MRR | Top-1 result quality | ≥ 0.70 |
| nDCG@5 | Full ranking quality | ≥ 0.65 |
When your metrics are bad, this flowchart tells you where to look
| Symptom | Likely Cause | Fix (Lecture) |
|---|---|---|
| Low precision, OK recall | Too many irrelevant chunks | Re-ranking (L5) |
| OK precision, low recall | Missing relevant chunks | Better embeddings or HyDE (L5) |
| Both low | Embedding model too weak | Domain-specific model or hybrid search (L4) |
| Zero hits | Chunking split the answer | Parent-child chunking (L5) |
| High metrics, bad answers | Generation problem, not retrieval | Better RAG prompt (L4) or LLM-as-Judge (this lecture) |
Section 3 — Generation Metrics & Hallucination
Faithfulness
Does the answer only use information from the retrieved context? No hallucination.
Answer Relevance
Does the answer actually address the user’s question? Not off-topic.
Completeness
Does the answer cover all aspects of the question? Nothing missing.
Factual Consistency
Are the stated facts correct? No distortion of source material.
“Does the answer ONLY use information from the retrieved context?”
Context: “Employees receive 12 sick days per year.”
Answer: “You get 12 sick days per year.”
Context: “Employees receive 12 sick days per year.”
Answer: “You get 12 sick days, plus 5 personal days.”
[IsSup] token asks exactly this question at runtime: “Is my answer supported by evidence?” Now we measure it offline with a judge.“Does the answer address the actual question asked?”
Q: “How many sick days do I get?”
A: “Full-time employees receive 12 paid sick days per year.”
Q: “How many sick days do I get?”
A: “Our leave policy is comprehensive and designed to support employee well-being…”
Right topic, wrong answer. The model retrieved the right document but gave a generic summary instead of the specific number.
Q: “What are the remote work rules?”
A: “You can work 2 days remote.”
Missing: eligibility criteria, approval process, equipment policy.
Partially correct, but dangerously incomplete.
Context: “Budget limit is €500.”
A: “The budget limit is €5,000.”
Off by 10×. The model distorted the source fact.
Automated evaluation for RAG — the standard framework
| Metric | What It Measures | Needs |
|---|---|---|
| Faithfulness | Answer grounded in context? | Question + Context + Answer |
| Answer Relevancy | Answer addresses the question? | Question + Answer |
| Context Precision | Retrieved chunks actually relevant? | Question + Context + Ground Truth |
| Context Recall | All needed info retrieved? | Context + Ground Truth |
Key insight: Context Precision & Recall measure retrieval quality. Faithfulness & Answer Relevancy measure generation quality. Together, they cover the full pipeline.
Es et al. (2024) — “RAGAs: Automated Evaluation of Retrieval Augmented Generation” — EACL 2024 (System Demonstrations)
Section 4 — LLM-as-Judge
Same technique, different purpose
The retrieval grader runs inside the pipeline
Decides: “Is this chunk relevant?”
Affects the current query’s answer
Real-time, per-query, affects output
The judge runs after the pipeline
Scores: “Was this answer faithful?”
Produces a report, not an answer
Batch, systematic, measures quality
System: You are a strict evaluation judge.
Given:
- QUESTION: {question}
- CONTEXT: {retrieved_context}
- ANSWER: {generated_answer}
Task: Is the ANSWER faithful to the CONTEXT?
Rules:
1. Every claim in the ANSWER must be supported by the CONTEXT
2. If ANY claim is not in the CONTEXT, score = 0
3. If all claims are supported, score = 1
Respond in JSON: {"score": 0 or 1, "reason": "..."}
{"score": 0, "reason": "The claim about donating unused days to colleagues is NOT in the context. This is a hallucination."}| Bias | What Happens | Mitigation |
|---|---|---|
| Position bias | Prefers the first option in comparisons | Randomize order, run twice |
| Verbosity bias | Rates longer answers higher | Instruct: “Length is not quality” |
| Self-enhancement | GPT-4 rates GPT-4 answers higher | Use a different model family as judge |
| Leniency | Gives high scores too easily | Use strict rubrics with binary scores |
Zheng et al. (2023) — “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena” — NeurIPS 2023 (Datasets & Benchmarks Track)
Section 5 — Observability & Tracing
L7 previewed the four pillars — now we go deep
Latency
Retrieval time, generation time, total. P50, P95, P99.
Cost
Tokens per query, cost per query, daily/monthly budget.
Quality Drift
Average faithfulness over time. nDCG trends. Regression alerts.
Error Rates
Tool failures, timeouts, empty retrievals, refusals.
Every query produces a complete trace you can inspect and debug
| Node | Key Fields |
|---|---|
| Retrieval | chunk_ids, similarity_scores, latency_ms, k_requested, k_returned |
| Generation | model_name, prompt_tokens, completion_tokens, latency_ms, temperature |
| Answer | faithfulness_score, relevance_score, sources_cited |
Can every claim be traced to a source chunk?
“Full-time employees receive 12 sick days per year [Source: sick_leave_policy.txt, section 2.1].”
Min et al. (2023) — “FActScore: Fine-grained Atomic Evaluation of Factual Precision in Long Form Text Generation” — EMNLP 2023
| Tool | Type | Best For | Cost |
|---|---|---|---|
| LangSmith | SaaS | LangChain ecosystem, full tracing | Free tier + paid |
| Phoenix (Arize) | Open-source | Embedding drift, retrieval analysis | Free |
| Langfuse | Open-source | Self-hostable, full tracing, cost tracking | Free (self-host) |
| Custom logging | DIY | Maximum control, no vendor lock-in | Dev time |
| Metric | Alert When | Action |
|---|---|---|
| Avg tokens/query | > 2× baseline | Check if chunks got larger or prompt grew |
| Daily cost | > budget × 1.5 | Check for query spike or infinite loops |
| nDCG@5 (7-day avg) | Drops > 10% | Data changed? Embedding model updated? |
| Faithfulness (7-day avg) | Drops > 5% | Prompt regression? Model version change? |
1. Golden datasets are non-negotiable. No ground truth = no evaluation.
2. Retrieval metrics (Precision, Recall, MRR) diagnose whether you’re finding the right chunks.
3. Faithfulness is the most critical generation metric — an unfaithful answer actively harms users.
4. LLM-as-Judge scales evaluation from 10 queries to 10,000 — same technique as L7’s retrieval grader, different purpose.
5. Observability = tracing + cost monitoring + quality alerting. Treat your RAG like any production service.
6. Always diagnose retrieval first. Most RAG failures are retrieval failures, not generation failures.
When we return: Hands-On Mega-Lab — Build, evaluate, and improve a full RAG pipeline
Everything from L4–L8 in one hands-on session
Next → Lecture 9: Efficient Fine-Tuning (LoRA / QLoRA)
When prompting and RAG aren’t enough — teach the model new behavior.
The math of weight updates, low-rank adaptation, and domain-specific training.
Let’s start the lab!
Kamyar Zeinalipour — Zucchetti LLM Course