AI Engineering Academy · Lektion

Hvorfor evaluering er vigtig i RAG

Forstå de to uafhængige fejltilstande i RAG-systemer: fejl ved hentning og fejl ved generering, og lær, hvorfor De har brug for separate metrikker til at diagnosticere hver af dem.

Lektion 1 af 413 trin

Hvorfor evaluering er vigtig i RAG er en gratis AI Engineering Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i AI Engineering Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. AI Engineering Academy-kurset indeholder 4 lektioner i alt.

Du kan ikke forbedre det, du ikke måler

Et RAG-system kan virke, som om det fungerer, fordi det returnerer flydende svar, der lyder plausible. Men uden målinger ved du ikke, om det faktisk henter de rigtige chunks eller genererer troværdige svar. Teams, der springer evalueringen over, bruger ofte måneder på at justere chunking-strategier og promptformater ud fra mavefornemmelsen, blot for at opdage, at de har gjort tingene værre. Grundig evaluering er det, der forvandler RAG-udvikling fra gætteri til softwareudvikling.

To uafhængige fejltilstande

RAG har to forskellige trin, der kan fejle uafhængigt af hinanden: hentning og generering. Hentningen fejler, når de relevante chunks ikke rangeres blandt de K øverste resultater — LLM'en kan ikke generere et godt svar, hvis de rigtige oplysninger aldrig blev hentet. Genereringen fejler, når de korrekte chunks blev hentet, men LLM'en ignorerede eller fejllæste dem eller tilføjede hallucinerede oplysninger. Du har brug for separate målinger for hvert trin for at finde ud af, hvilken komponent der skaber problemet.

Faren ved kun at evaluere fra start til slut

Hvis du kun måler kvaliteten af det endelige svar, skjuler du, hvor fejlene kommer fra. Antag, at dit system giver forkerte svar 30 % af tiden. Skyldes det, at hentningen mangler de rigtige chunks, eller at LLM'en ignorerer gode chunks? Hvis du kun kender den endelige fejlrate, ved du ikke, hvilken komponent du skal rette. Instrumentér begge trin separat: mål kvaliteten af hentningen med gyldne datasæt og kvaliteten af genereringen med troværdighedsscorer.

# 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

Opbygning af et gyldent datasæt

Evaluering kræver et gyldent datasæt: et sæt af spørgsmål-svar-par, hvor du kender det korrekte svar og helst også, hvilket dokument og hvilken chunk svaret stammer fra. Til et minimalt evalueringssæt, der kan bruges i praksis, skal du indsamle 50-100 spørgsmål, som er repræsentative for rigtige brugerforespørgsler. Besvar dem i hånden eller ved at læse kildedokumenterne. Medtag forskellige spørgsmålstyper: faktuelle opslag, sammenligninger, flertrinsræsonnement og spørgsmål uden for domænet, som systemet bør afvise at besvare.

# 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'
    }
]

Generering af guldstandarddatasæt med LLM'er

Det er tidskrævende at oprette 100 spørgsmål manuelt. Du kan gøre det hurtigere med en LLM til datagenerering: giv hvert dokumentstykke til GPT-4o, og bed den generere 3-5 forskellige spørgsmål, hvis svar kan findes i det pågældende stykke, samt den forventede svartekst. Gennemgå et udvalg manuelt for at opdage kvalitetsproblemer. Denne fremgangsmåde kan hurtigt skaleres til tusindvis af spørgsmål, men den kan overse særlige tilfælde, som kun rigtige brugere ville spørge om.

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

Evaluering af hentning: træfrate

Træfrate@K er andelen af spørgsmål, hvor mindst ét relevant tekststykke optræder blandt de øverste K resultater fra hentningen. Det er det enkleste og mest intuitive mål for hentning. En træfrate@5 på 85 % betyder, at det relevante tekststykke var blandt de 5 øverste resultater for 85 ud af 100 spørgsmål. Følg træfraten separat for forskellige dokumenttyper, forespørgselslængder og emnekategorier for at finde ud af, hvor din hentningskomponent har de største problemer.

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

Evaluering af generering: troskab

Troskab måler, om det genererede svar kun indeholder oplysninger, der kan verificeres i den hentede kontekst. Et utro svar tilføjer fakta, som konteksten ikke understøtter – det er en hallucination. Mål troskab ved at få en bedømmende LLM (eller en menneskelig evaluator) til at kontrollere hver sætning i svaret op imod konteksten og markere påstande, der ikke understøttes af de hentede tekststykker. Et troskabsmål på mindst 95 % er målet for produktionssystemer.

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

Evaluering af generering: svarrelevans

Svarrelevans måler, om det genererede svar faktisk besvarer brugerens spørgsmål. Et meget troværdigt svar kan stadig ramme ved siden af ved at besvare et beslægtet, men andet spørgsmål. Mål relevans separat fra troskab. Brug en bedømmende LLM til at vurdere, om svaret direkte besvarer det, der blev spurgt om, på en skala fra 1 til 5. Lav svarrelevans tyder ofte på et problem med promptens struktur eller på, at den hentede kontekst faktisk ikke indeholder svaret.

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

Sporing af mål over tid

Evaluering er mest værdifuld, når du følger mål over tid, efterhånden som du foretager ændringer. Gem evalueringsresultater i en database eller et regneark med tidsstempler og versionsetiketter (f.eks. chunk_size=500, embed=3-small, k=5). Når du prøver en ny strategi for opdeling i tekststykker eller en ny indlejringsmodel, skal du køre den samme evaluering og sammenligne resultaterne. Det forhindrer tilbagegang – du kan f.eks. forbedre troskaben, men ved et uheld reducere træfraten. Kør altid den fulde evaluering, før du integrerer ændringer i produktionen.

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%}')

Evalueringsindstillingen

Ud over specifikke mål kræver evaluering en ændret indstilling: Betragt RAG som et maskinlæringssystem med målbar ydeevne, ikke som en chatbot, du vurderer subjektivt ved at chatte med den. Fastlæg succeskriterier på forhånd (f.eks. træfrate@5 > 85 %, troskab > 95 %). Opret et testsæt, der forbliver fastlåst og aldrig bruges til beslutninger om udviklingen. Reserver et separat udviklingssæt til iterationer. Denne disciplin adskiller teams, der leverer pålidelig RAG, fra teams, der leverer imponerende demonstrationer, som fejler i produktionen.

Testsæt kontra udviklingssæt

En vigtig disciplin inden for maskinlæring, som også gælder for evaluering af RAG, er opdelingen i trænings-, udviklings- og testsæt. Dit testsæt skal være helt fastlåst – brug det aldrig til at træffe beslutninger om udviklingen. Brug et separat udviklingssæt til at eksperimentere med strategier for opdeling i tekststykker, promptændringer og indlejringsmodeller. Kør kun testsættet, når du mener, at en ændring er klar til produktion. Denne adskillelse forhindrer overtilpasning af din RAG-pipeline til testsættet og sikrer, at dine endelige rapporterede mål afspejler ægte generalisering.

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

Hurtigt tjek

Test din forståelse af begreberne inden for AI Engineering fra denne lektion.

Opsummering af lektionen

I denne lektion lærte du om: de to uafhængige fejltilstande for hentning og generering, som kræver separate mål, hvordan du opbygger et guldstandarddatasæt med tre tupler bestående af spørgsmål, svar og tekststykke til objektiv evaluering, træfrate som det centrale mål for hentning samt troskab og svarrelevans som de centrale mål for generering, og betydningen af at følge mål over tid for at forhindre tilbagegang. Dernæst implementerer vi specifikke mål for hentning, herunder MRR og NDCG.

Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Hvorfor evaluering er vigtig i RAG” gratis?

Ja — hele teksten til “Hvorfor evaluering er vigtig i RAG” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af AI Engineering Academy-kurset, skal du opgradere til CoddyKit PRO. AI Engineering Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Hvorfor evaluering er vigtig i RAG”?

Forstå de to uafhængige fejltilstande i RAG-systemer: fejl ved hentning og fejl ved generering, og lær, hvorfor De har brug for separate metrikker til at diagnosticere hver af dem. Du øver dig i AI Engineering Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på AI Engineering Academy?

Der kræves ingen tidligere erfaring. AI Engineering Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Hvorfor evaluering er vigtig i RAG”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne AI Engineering Academy-lektion?

Ja. Alle AI Engineering Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Hvorfor evaluering er vigtig i RAG
  2. Metrikker for hentning: Hit rate, MRR og NDCG
  3. Metrikker for generering: Troværdighed og svarrelevans
  4. Opbygning af et automatiseret evalueringssystem
← Tilbage til AI Engineering Academy