0Pricing
AI Engineering Academy · Leçon

Pourquoi l’évaluation est importante dans RAG

Comprenez les deux modes d’échec indépendants des systèmes RAG : l’échec de récupération et l’échec de génération, et découvrez pourquoi des mesures distinctes sont nécessaires pour diagnostiquer chacun d’eux.

Pourquoi l’évaluation est importante dans RAG est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

You Cannot Improve What You Do Not Measure

A RAG system can feel like it is working because it returns fluent, plausible-sounding answers. But without measurement, you have no idea whether it is actually retrieving the right chunks or generating faithful answers. Teams that skip evaluation often spend months tweaking chunking strategies and prompt formats based on gut feeling, only to discover they made things worse. Rigorous evaluation is what turns RAG development from guessing into engineering.

Two Independent Failure Modes

RAG has two distinct stages that can fail independently: retrieval and generation. Retrieval fails when the relevant chunks are not ranked in the top-K results — the LLM cannot generate a good answer if the right information was never retrieved. Generation fails when the correct chunks were retrieved but the LLM ignored them, misread them, or added hallucinated information. You need separate metrics for each stage to pinpoint which component is causing the problem.

The Danger of End-to-End Evaluation Only

Measuring only the final answer quality hides where failures come from. Suppose your system gives wrong answers 30% of the time. Is that because retrieval is missing the right chunks, or because the LLM is ignoring good chunks? If you only know the final error rate, you cannot know which component to fix. Instrument both stages separately: measure retrieval quality with golden datasets and generation quality with faithfulness scores.

# Diagnosis example: which stage is failing?

# Test 1: Is retrieval finding the right chunks?
retrieval_hit_rate = evaluate_retrieval(questions, ground_truth_chunks)
print(f'Retrieval hit rate@5: {retrieval_hit_rate:.1%}')
# If this is low (< 80%), fix chunking and embedding first

# Test 2: Given perfect context, does LLM generate correct answers?
generation_faithfulness = evaluate_generation(questions, perfect_context)
print(f'Generation faithfulness: {generation_faithfulness:.1%}')
# If retrieval is fine but this is low, fix your prompts

Building a Golden Dataset

Evaluation requires a golden dataset: a set of question-answer pairs where you know the correct answer and, ideally, which document and chunk the answer comes from. For a minimum viable evaluation set, collect 50-100 questions representative of real user queries. Answer them by hand or by reading the source documents. Include diverse question types: factual lookups, comparisons, multi-hop reasoning, and out-of-domain questions the system should refuse to answer.

# Golden dataset format
golden_dataset = [
    {
        'question': 'How many vacation days do employees receive in their first year?',
        'answer': '15 days',
        'relevant_chunks': ['employee_handbook_p24', 'benefits_summary_p3'],
        'source_doc': 'employee_handbook_2025.pdf'
    },
    {
        'question': 'What is the parental leave duration for primary caregivers?',
        'answer': '16 weeks fully paid',
        'relevant_chunks': ['parental_leave_policy_p1'],
        'source_doc': 'parental_leave_policy.pdf'
    }
]

Generating Golden Datasets with LLMs

Creating 100 questions manually is tedious. Accelerate this with a data generation LLM: feed each document chunk to GPT-4o and ask it to generate 3-5 diverse questions whose answers can be found in that chunk, plus the expected answer text. Review a sample manually to catch quality issues. This approach scales to thousands of questions quickly, though it may miss edge cases that only real users would ask.

def generate_qa_pairs_for_chunk(chunk_text, llm_client):
    prompt = (
        'Given the following document excerpt, generate 3 diverse questions '
        'that can be answered using ONLY this text. '
        'For each question, provide the exact answer from the text.\n\n'
        f'Text:\n{chunk_text}\n\n'
        'Format each as JSON: {"question": ..., "answer": ...}'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

Retrieval Evaluation: Hit Rate

Hit rate@K is the fraction of questions for which at least one relevant chunk appears in the top-K retrieval results. It is the simplest and most intuitive retrieval metric. A hit rate@5 of 85% means that for 85 out of 100 questions, the relevant chunk was among the top 5 results. Track hit rate separately for different document types, query lengths, and topic categories to find where your retriever struggles most.

def compute_hit_rate(golden_dataset, retriever, top_k=5):
    hits = 0
    for item in golden_dataset:
        results = retriever.retrieve(item['question'], top_k=top_k)
        retrieved_ids = {r['id'] for r in results}
        relevant_ids = set(item['relevant_chunks'])
        if retrieved_ids & relevant_ids:  # intersection not empty
            hits += 1
    hit_rate = hits / len(golden_dataset)
    print(f'Hit rate@{top_k}: {hit_rate:.1%} ({hits}/{len(golden_dataset)})')
    return hit_rate

Generation Evaluation: Faithfulness

Faithfulness measures whether the generated answer contains only information that can be verified in the retrieved context. An unfaithful answer adds facts the context does not support — that is hallucination. Score faithfulness by having a judge LLM (or human evaluator) check each sentence in the answer against the context and flag any claims not supported by the retrieved chunks. A faithfulness score of 95%+ is the target for production systems.

def evaluate_faithfulness(answer, context, llm_client):
    prompt = (
        'Given this context and answer, evaluate faithfulness.\n\n'
        f'Context: {context}\n\n'
        f'Answer: {answer}\n\n'
        'For each sentence in the answer, determine if it is '
        'supported by the context (FAITHFUL) or not (HALLUCINATED). '
        'Return a JSON: {"score": 0.0-1.0, "issues": ["sentence..."]}.'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

Generation Evaluation: Answer Relevance

Answer relevance measures whether the generated answer actually addresses the user's question. A highly faithful answer might still miss the point by answering a related but different question. Measure relevance separately from faithfulness. Use a judge LLM to rate whether the answer directly addresses what was asked, using a 1-5 scale. Low answer relevance often indicates a problem with the prompt structure or the retrieved context not actually containing the answer.

def evaluate_answer_relevance(question, answer, llm_client):
    prompt = (
        f'Question: {question}\n\n'
        f'Answer: {answer}\n\n'
        'Rate how well this answer addresses the question on a 1-5 scale:\n'
        '5 = fully answers the question\n'
        '3 = partially answers but misses key aspects\n'
        '1 = does not address the question at all\n\n'
        'Return JSON: {"score": 1-5, "reason": "brief explanation"}'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

Tracking Metrics Over Time

Evaluation is most valuable when you track metrics over time as you make changes. Store evaluation results in a database or spreadsheet with timestamps and version labels (e.g., chunk_size=500, embed=3-small, k=5). When you try a new chunking strategy or embedding model, run the same evaluation and compare. This prevents regression — you might improve faithfulness but accidentally reduce hit rate. Always run the full evaluation before merging changes to production.

import json
from datetime import datetime

def save_evaluation_results(metrics, config, output_file='eval_history.jsonl'):
    record = {
        'timestamp': datetime.utcnow().isoformat(),
        'config': config,
        'metrics': metrics
    }
    with open(output_file, 'a') as f:
        f.write(json.dumps(record) + '\n')
    print(f'Saved eval result: hit_rate={metrics["hit_rate"]:.1%}, '
          f'faithfulness={metrics["faithfulness"]:.1%}')

The Evaluation Mindset

Beyond specific metrics, evaluation requires a mindset shift: treat RAG as a machine learning system with measurable performance, not a chatbot you subjectively assess by chatting with it. Define success criteria upfront (e.g., hit rate@5 > 85%, faithfulness > 95%). Establish a test set that stays frozen and is never used for development decisions. Reserve a separate dev set for iteration. This discipline separates teams that ship reliable RAG from teams that ship impressive demos that fail in production.

Test Set vs Development Set

A critical discipline in machine learning that also applies to RAG evaluation is the train-dev-test split. Your test set should be completely frozen — never used to make development decisions. Use a separate dev set for experimenting with chunking strategies, prompt changes, and embedding models. Only run the test set when you believe a change is production-ready. This separation prevents overfitting your RAG pipeline to the test set and ensures your final reported metrics reflect genuine generalization.

import json
from sklearn.model_selection import train_test_split

def split_golden_dataset(all_questions, test_ratio=0.3, seed=42):
    dev_set, test_set = train_test_split(
        all_questions,
        test_size=test_ratio,
        random_state=seed
    )
    print(f'Dev set: {len(dev_set)} questions')
    print(f'Test set: {len(test_set)} questions (FROZEN)')
    with open('eval/dev_set.json', 'w') as f:
        json.dump(dev_set, f, indent=2)
    with open('eval/test_set.json', 'w') as f:
        json.dump(test_set, f, indent=2)
    return dev_set, test_set

Quick Check

Test your understanding of AI Engineering concepts from this lesson.

Lesson Recap

In this lesson you learned: the two independent failure modes of retrieval and generation that require separate metrics, how to build a golden dataset of question-answer-chunk triples for objective evaluation, hit rate as the core retrieval metric and faithfulness and answer relevance as the core generation metrics, and the importance of tracking metrics over time to prevent regressions. Next up we implement specific retrieval metrics including MRR and NDCG.

Questions Fréquemment Posées

La leçon « Pourquoi l’évaluation est importante dans RAG » est-elle gratuite ?

Oui — le texte complet de « Pourquoi l’évaluation est importante dans RAG » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Pourquoi l’évaluation est importante dans RAG » ?

Comprenez les deux modes d’échec indépendants des systèmes RAG : l’échec de récupération et l’échec de génération, et découvrez pourquoi des mesures distinctes sont nécessaires pour diagnostiquer cha… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?

Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Pourquoi l’évaluation est importante dans RAG » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?

Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Pourquoi l’évaluation est importante dans RAG
  2. Mesures de récupération : taux de réussite, MRR et NDCG
  3. Mesures de génération : fidélité et pertinence des réponses
  4. Construire un banc d’évaluation automatisé
← Retour à AI Engineering Academy