[!NOTE] Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
Evaluatie van RAG: Metrieken voor elke fase van een productie RAG-systeem
Deel 1 van de productieserie RAG
Een RAG-systeem met defecte filters kan maandenlang draaien zonder dat er een operationeel alarm wordt uitgegeven. Het levert nog steeds antwoorden en bereikt zijn latency-doelstellingen, maar deze antwoorden zijn gebaseerd op onvolledige bewijsmateriaal. Recall@k tegen het oorspronkelijke gold-set onthult deze fouten; latency- en beschikbaarheidsdashboards doen dit niet.
Een evaluatie kan een fout alleen detecteren wanneer elke pipeline-fase over zijn eigen metriek beschikt. In dit artikel worden veelvoorkomende foutmodi in verband gebracht met deze metrieken, van documentparsing tot productiemonitoring.
[!TIP] Wil je vooruit springen en de code uitvoeren?
De uitvoerbare
slavadubrov/rag-evals-demoHet repository past de metrics toe op SciFact.make evalvoert het suite uit, enmake benchmarkHet vergelijkt de configuraties van chunking, embedding en LLM. De notebooks 00–09 zorgen ervoor dat elke metriek apart wordt weergegeven. De demo maakt gebruik van ingebouwde Qdrant, waardoor er geen Docker nodig is.
Kort samengevat
- Evaluatie bepaalt de kwaliteit van het systeem. Een fase zonder metrieken is een fase die stilletjes faalt.
- Een bruikbare evaluatiestack omvat de invoer, retrieval, generatie grounding, conformiteit met de ontologie, en systeemsignalen. RAGAS, TruLens, DeepEval, Arize Phoenix, en de TREC 2024 RAG Track We leveren de benodigde hulpmiddelen. Zij kiezen je metrieken echter niet voor je uit.
- Voor RAG-gebaseerde metadata- en ontologieoplossingen kan een verkeerde tag of een kwetsbaar, star predicaat de recall tot nul doen dalen. Standaard Recall@k detecteert dit verlies wanneer het het oorspronkelijke gouden dataset behoudt. Een filter voor false-exclusion-metrieken identificeert de oorzaak, terwijl de nauwkeurigheid nog steeds goed lijkt, omdat model trouw heeft verklaard: “Ik weet het niet.”
De secties volgen de volgorde van pipeline. Begin met de besluitentabel en gebruik de latere secties daarna als referentie voor elke fase.
RAG evaluatiebeslissings tabel
Gebruik deze tabel als uitgangspunt voordat u een framework kiest. De juiste metriek hangt af van het fallemodel dat u probeert op te sporen, en niet van de naam van het hulpmiddel.
| Vraag | Metricfamilie | Gebruik dit wanneer | Let op voor |
|---|---|---|---|
| Is de bron intact gebleven na het parseren? | Volledigheid van de extractie, dekking van tabellen/figuren | PDF’s, presentaties, scans en HTML-pagina’s worden opgenomen in het corpus. | Zelfs tekst met een schone uitstraling kan nog steeds ondertitelingen, voetnoten of tabelstructuur verliezen. |
| Heeft retrieval het juiste bewijs gevonden? | Recall@k, nDCG@k, MRR, precisie/recall in de context | U kunt relevante chunks of documenten labelen. | Een strenge metadata-filter kan het juiste document al verwijderen voordat de rangschikking begint. |
| Heeft reranking de shortlist verbeterd? | Reranker verbetering, Precisie@1, nDCG-delta | Cross-encoders of LLM-rankers bevinden zich naast retrieval. | Meet latency en de kosten in relatie tot de behaalde kwaliteitsverbetering. |
| Is het antwoord gebaseerd op de beschikbare bewijsmateriaal? | Getrouwheid, grondigheid, ondersteuning voor citaties | Het antwoord vermeldt documenten of baseert feiten op de context. | Faithfulness kan geen slechte parsing of foutieve retrieval diagnosticeren. |
| Is het systeem stabiel in productie? | Drift, regeneratie, fallback, p95 latency, kosten per antwoord | Verkeerspatronen veranderen na de lancering | Productietelemetrie vereist gemonitorde menselijke evaluatie om gekalibreerd te blijven |
Voor een kortere vergelijking van tools, zie De beste RAG evaluatiehulpmiddelen en -metrieken in 2026.
Deel 1: Definieer succes voordat de architectuur wordt ontworpen
Stel de eval-set op vóór het architectuurdiagram. Hierdoor krijgt elke latere keuze voor een component een meetbaar doel.
Je kunt niet kiezen tussen BM25 en dense retrieval, recursieve en semantische chunking, of Cohere Rerank en BGE totdat duidelijk is wat je precies wilt optimaliseren. “Betere antwoorden” is geen meetgrondslag. Een voorbeeld van een dergelijke contractuele specificatie is: “getrouwheid ≥ 0,85 op een gouden set van 200 vragen die onze drie belangrijkste intenties omvat, met een p95 latency van minder dan 1,5 seconden en een foutieve uitsluitingsratio van onder de 2%.” De cijfers hierin zijn slechts placeholders; het belangrijke is dat er duidelijke criteria zijn voor kwaliteit, dekking, latency, en filtering.
Definieer de harness voordat je de retrieval-code schrijft. De eerste harness zal onjuist zijn, waarna je deze moet herzien. Het herzien van een metriek is aanzienlijk goedkoper dan het herzien van een systeem dat al is geleverd.
Drie pipeline lagen en twee uitvoeringsmodi
Moderne RAG is een pipeline, waardoor de evaluatie een pipeline moet zijn. Er bestaat geen enkele enkele waarde die alle mogelijke foutpatronen kan detecteren.
De productie-evaluatie kent drie pipeline lagen. Ingestie-evaluatie onderzoekt of het corpus en de index de oorspronkelijke inhoud behouden. Evaluatie tijdens het opvragen controleert of herschrijving, filtering, retrieval, reranking en samenstelling van context hebben geleid tot het vinden van de juiste bewijzen. Antwoord- en productie-evaluatie bepaalt of het antwoord deze bewijzen heeft gebruikt en of de kwaliteit behouden blijft onder echte gebruiksomstandigheden. Door deze lagen samen te voegen tot één score kan een normalisatiefout verdwijnen binnen een acceptabele antwoordscore.
Die lagen geven aan waar een fout optreedt. Offline en online geven aan wanneer en tegen welke gegevens de controle wordt uitgevoerd. Offline-evaluatie maakt gebruik van een vaste dataset met bekende referentiewaarden; deze is reproduceerbaar en wordt gebruikt bij componentselectie, A/B-vergelijkingen en CI-gates. Online-evaluatie meet het verkeer dat in werkelijke omstandigheden wordt verwerkt en houdt rekening met procesherstart, verblijfsduur, expliciete feedback en echte query-drift. Deze methode levert meer ruis op en is moeilijker te monitoren.
Elk pipeline-laag kan zowel offline als online controles leveren. Een vast ingesteld corpus helpt bij het opsporen van regressies in de parser vóór publicatie, terwijl monitors voor versheid en parse-fouten live updates in de gaten houden. Een vaste queryset wordt gebruikt om retrieval te meten vóór publicatie, terwijl gemonitorte live traces-gegevens afwijkingen in de productieomgeving aan het licht brengen. Controles die uitsluitend offline worden uitgevoerd, missen live veranderingen; controles die uitsluitend online plaatsvinden, maken het moeilijk om regressies na te bootsen.
Op componentniveau versus end-to-end
Er zijn twee veelvoorkomende fouten. Evaluatie uitsluitend op eind-tot-eind-niveau geeft aan dat het systeem niet werkt, maar niet waar precies. Evaluatie alleen op componentniveau kan aantonen dat alle onderdelen slagen, terwijl het gehele systeem toch faalt. De oplossing bestaat uit enkele belangrijke eind-tot-eind-metingen voor de beslissing of iets goedgekeurd kan worden of niet, gecombineerd met componentmetingen voor diagnostiek. Retrieval-metingen vangen regressies in de retriever op. Generatiemetingen vangen regressies in de generator op. De correctheid van de eind-tot-eind-antwoorden onthult integratiefouten.
De referentie frameworks (opinionated tour)
| Framework | Best in staat om | Waar het misgaat |
|---|---|---|
| RAGAS | Referentievrije RAG-metingen (getrouwheid, relevantie van antwoorden, precisie/recall van context); het feitelijke woordenschat | LLM-judge kosten; ondoorzichtige componenten van de score bij het oplossen van fouten; standaardinstellingen die gericht zijn op de Engelse gebruikerscultuur |
| ARES | Getrainde classificator judges volgens pipeline; minder annotaties dan aanpakken in de RAGAS-stijl; hoge precisie voor nauwkeurige systemen | Zwaardere configuratie; je moet models daadwerkelijk trainen. |
| TruLens | Composable feedbackfuncties met hoge explicatierichtheid; OpenTelemetry traces; geschikt voor productieomgevingen | Er zitten minder batterijen in de specificaties voor RAG dan in de RAGAS-modellen. |
| DeepEval | Unittests in Pytest-stijl voor de uitvoer van LLM; G-Eval, aangepaste metrieken, en integratie met CI/CD-pipelines | Zware LLM-judge-gebruik = stijgingen in de kosten |
| Arize Phoenix | Sterke visualisatie van tracing en embedding; visuele detectie van embedding-afwijkingen; OTEL-natief | Je brengt je eigen definities van metrics mee. |
| TREC 2024 RAG Track | Openbare benchmark voor de evaluatie van nuggets (AutoNuggetizer), ondersteuning bij evaluaties en beoordeling van vloeiendheid op MS MARCO Segment v2.1 | Geen runtime-hulpmiddel; een benchmark om tegen te kalibreren |
Mijn standaardstack bestaat uit RAGAS voor het metriekvocabulaire, DeepEval voor CI-gates, Phoenix voor productie tracing, plus aangepaste code voor metrieken die specifiek zijn voor de ontologie. U zult uiteindelijk alles wat u nu begint te gebruiken te klein vinden. Kies de framework die het mogelijk maakt om aangepaste metrieken eenvoudig te genereren.
Voor benchmarks, gebruik dan BEIR (Thakur et al., NeurIPS 2021) voor zero-shot retrieval-generalisatie. MTEB voor een algemene embedding kwaliteit, MIRACL voor meertalige retrieval, en de TREC 2024 RAG Track voor evaluatie op eind-tot-eindniveau van RAG.
Deel 2: Evaluatiepunten koppelen aan pipeline
Een productiesysteem voor RAG is complexer dan louter het embedden van documenten, het ophalen van chunks, en het aanroepen van een LLM. Op elk stadium tussen het verkrijgen van de documenten en het leveren van het antwoord kan er een fout optreden.
Elk stadium in het diagram beschikt over ten minste één metriek. Een stadium zonder metriek kan falen zonder dat iemand het opmerkt.
De drie kanalen komen overeen met de punten waar bewijsmateriaal verloren kan raken. Het inlaatkanaal omvat parsing, zuivering, chunking, embedding, en indexeren. Het kanaal tijdens het opvragen omvat herformulering, filteren, retrieval, reranking, en samenstelling van context. Het antwoord- en productiekanaal houdt rekening met nauwkeurigheid, controle van citaten, gebruikersignalen, drift, latency, en kosten.
Fouten stapelen zich op langs de keten. Onjuist parseren beperkt chunking. Onjuiste chunking-waarden beperken op hun beurt retrieval. Onjuiste retrieval-waarden beperken vervolgens reranking. Onjuiste reranking-waarden beperken de generatie van resultaten. Betrouwbaarheid meet uitsluitend het eindresultaat, nooit de oorzaken daarboven in de keten.
Deel 3: Evaluatie van de invoer
Veel fouten bij RAG in productie beginnen al tijdens de invoer. Het systeem werkt goed met schone testdocumenten, maar faalt vervolgens bij echte PDF’s, scans, tabellen en ongeorganiseerde pagina’s uit het corpus.
Documentverzameling en parsing
Wat te meten valt:
-
Volledigheid van de tekstextractie:
extracted_chars / expected_charsop een gelabeld voorbeeld, berekend per documentklasse. Er is geen standaardpakket — schrijf een klein harness dat de uitvoer van de parser vergelijkt met een handmatig gecorrigeerde referentie. Let op ontbrekende voetnoten, koppen en bijschriften. -
OCR nauwkeurigheid: CER (Character Error Rate) en WER (Word Error Rate), de standaardmetrieken voor spraak/OCR:
waarbij , , karakterniveau-substituties, deleties en inserties zijn en het referentieaantal karakters is (onderstrept voor de woordversie). Pas niet één CER-grens toe aan elk corpus. Calibreer deze door middel van de documentklasse en de verliesmarges van de downstream-antwoorden; gedrukte tekst, handschrift en meerstalig materiaal hebben verschillende foutprofielen. Bereken dit met
jiwer(jiwer.cer(refs, hyps),jiwer.wer(refs, hyps)) of HuggingFaceevaluate. Voor evaluatiecorpora’s, FUNSD en SROIE ze zijn publiek benchmarks.from jiwer import cer, wer refs = ["Mars has two moons, Phobos and Deimos."] hyps = ["Mars has two m00ns, Phobos and Deirnos."] print(f"CER = {cer(refs, hyps):.3f}") # CER = 0.105 print(f"WER = {wer(refs, hyps):.3f}") # WER = 0.286 -
Nauwkeurigheid van tabelextractie: TEDS (Tree-Edit-Distance-based Similarity) meet in hoeverre de voorspelde HTML-tabelboom overeenkomt met de referentieboom, gecorrigeerd voor het formaat van de grotere boom. Van Zhong et al., 2020 (PubTabNet):
TEDS maakt gebruik van zowel de structuur (rijen, kolommen, spans) als de inhoud van de cellen; TEDS-S verwijdert de inhoud en evalueert uitsluitend de structuur. Referentiemechanisme: PubTabNet’s
teds.py(gebruikt)aptedonder de motorkap). Voor evaluatiecorpora, zie PubTabNet. FinTabNet, en SciTSR. Naïeve parsers falen vaak bij het verwerken van tabellen; benchmark voordat men ze kan vertrouwen. -
Behoud van lay-out/structuur: volgorde van koppen, integriteit van lijsten en leesvolgorde in meerkolommige PDF’s. Gebruik DocLayNet voor een gelabelde benchmark. Een standaard beschikbare vergelijking kan span een elementparser zoals
unstructured, een PDF-bibliotheek zoalspymupdf, en een VLM-parser zoalsdocling.
Vergelijk verschillende families parsers, zoals een Tesseract-baseline, een OCR model gebaseerd op VLM, en de optie van uw leverancier. Gebruik hiervoor een gestrateerde steekproef van echte documenttypen bij een vaste DPI, waarbij ook schone scans, foto’s, tabellen, meertalig tekstmateriaal, wiskundige formules en handschrift worden opgenomen. Rapporteer de CER of WER voor elk type document, evenals de TEDS voor pagina’s met tabellen.
Reiniging en normalisatie
-
Nauwkeurigheid van het verwijderen van boilerplate: precisie/herinnering vergeleken met door mensen gelaagde boilerplate spans. Agressief verwijderen vernietigt relevante inhoud; traag verwijderen vervuilt embeddings. Hulpmiddelen voor vergelijking:
trafilatura,jusText,Resiliparse. Barbaresi (2021) benchmarks deze head-to-head confrontaties. -
Unicode-normalisatie: percentage van de documenten die identieke NFC- en NFKC-output genereren (berekend met de stdlib)
unicodedata.normalize) Dit vormt een nuttig signaal voor driftdetectie. Onovereenstemmingen zijn de oorzaak waardoor zero-width joiners en lookalike-tekens de retrieval-recall aantasten. -
Nauwkeurigheid taalherkenning: F1-score op een gemarkeerd multilinguaal voorbeeld. Essentieel voor multilinguale indexen. Gebruik
fasttext-langdetect(Facebook’slid.176),lingua-py, ofcld3. FLORES-200 Het levert evaluatie‑tekst in 200 talen, maar de combinatie van productietalen die u gebruikt, moet bepalen welk deel van de test wordt uitgevoerd. -
Effectiviteit van deduplicatie (MinHash / LSH): de precisie/recall van uw detector voor near-duplicates tegenover een handgemaakte geëtiketteerde set. Het onderliggende principe: schatten van de Jaccard-similarity J(A, B) = \frac|A ∩ B|}{|A ∪ B| tussen documentsets via willekeurige permutatiehashesBroder, 1997) en naburige duplicaten samenvoegen met LSH-banding (Indyk & Motwani, 1998). Houd de hash-telling en de Jaccard-threshold bij in uw corpus. Meet de foutieve samenvoegingsratio (die antwoorden verstoort) apart van de gemiste samenvoegingsratio (die indexruimte verspilt).
datasketchhet biedt de hieronder gebruikte implementatie; de parameters zijn illustratief:from datasketch import MinHash, MinHashLSH def shingles(text: str, k: int = 5) -> set[str]: text = text.lower() return {text[i:i + k] for i in range(len(text) - k + 1)} def to_minhash(text: str, num_perm: int = 128) -> MinHash: m = MinHash(num_perm=num_perm) for s in shingles(text): m.update(s.encode("utf-8")) return m docs = { "d1": "Mars has two moons, Phobos and Deimos.", "d2": "Mars has two moons, Phobos and Deimos!", # near-dup "d3": "Curiosity rover landed on Mars in 2012.", } lsh = MinHashLSH(threshold=0.8, num_perm=128) for did, text in docs.items(): lsh.insert(did, to_minhash(text)) print(sorted(lsh.query(to_minhash(docs["d1"])))) # ['d1', 'd2'] -
PII scrubbing: nauwkeurigheid en herinneringsratio, beide apart berekend per entiteitentype (e-mails, SSN’s, namen, adressen). Fouten op het gebied van de herinneringsratio leiden tot risico’s met betrekking tot naleving; fouten op het gebied van de nauwkeurigheid beïnvloeden de kwaliteit van de antwoorden. Stel het optimale werkpunt vast in overleg met het juridische team. Mogelijke hulpmiddelen zijn Microsoft Presidio,
scrubadub, of een gefineerde NER model op een gelabeld dataset.
Chunking stelt de kwaliteit van retrieval vast
Chunking kan een meerpuntrige kloof in de recall veroorzaken, zelfs wanneer de embedding model constant blijft. In NVIDIAs leverancier voor 2024 benchmark, Op pagina-niveau leverde chunking de hoogste nauwkeurigheid en de laagste variatie op voor gepagineerde documenten. Beschouw dit resultaat als bewijs voor het geteste corpus, en niet als een universele winnaar.
Semantic chunking groepeert aangrenzende zinnen op basis van embedding-gelijkenis en snijdt bij ongelijke grenzen. LangChain’s SemanticChunker en die van LlamaIndex SemanticSplitterNodeParser Implementeer deze strategie. Hiermee kan de recall worden verbeterd ten opzichte van vaste tijdsvensters wanneer thematische grenzen van belang zijn.
Bij recursieve splitsing van tekens worden eerst paragraafbreuken geprobeerd, gevolgd door zinsbreuken en vervolgens woordbreuken, totdat elke chunk binnen de gewenste grootte past. LangChain’s RecursiveCharacterTextSplitter De sequentie wordt geïmplementeerd door kandidaatvensters en overlappingwaarden te kiezen die passen bij de structuur van uw document, waarna de gouden set de definitieve waarden bepaalt.
Metrics die in de gaten moeten worden gehouden:
- Chunk coherentie: , waarbij zinnen zijn embeddings. Gezonde chunks zijn intern vergelijkbaar en verschillend aan de grenzen. Bereken dit met
sentence-transformersplusscikit-learn’scosine_similarity. - Kwaliteit van de grenzen: menselijke labeling van “Is dit een logische splitsing?” op een voorbeeld, gecombineerd met een structurele controle om te voorkomen dat chunks tabellen, lijsten of genummerde secties splitst.
- Optimale chunk grootte: test verschillende token groottes (128, 256, 512, 1024) en traceer de relatie tussen Recall@k en grootte op je gouden dataset. Kies het punt waar de curve het meest scherp stijgt. Kies niet zomaar wat in de handleiding wordt aanbevolen.
- Effectiviteit van overlapping: teste verschillende percentages overlapping en meet de Recall@k-waarde. Stopt u met het verhogen van de overlapping wanneer de lokale recall-curve plat wordt of wanneer de kosten van duplicaten groter zijn dan de voordelen.
- Chunk nauwkeurigheid van toewijzing: het percentage chunks dat nog steeds een verifieerbare bronverwijzing bevat (paginanummer, sectieanker, document-ID). Auditbaarheid vereist dit.
- Laat versus vroeg chunking: te laat chunking (Günther et al., 2024) integreert het volledige document en segmenteert dit vervolgens, waardoor de globale context behouden blijft (referentieimplementatie in
jina-embeddings-v3). Contextueel Retrieval (Anthropic, 2024) voegt voor elk chunk de door LLM gegenereerde context toe aan het begin. Beide maatregelen hebben een kostenfactor. Onderzoek eerst de Benchmark van uw corpus voordat u er één van gaat gebruiken.
Mijn mening: structurele chunking (splitsing op koppen, tabellen en secties — geïmplementeerd door parsers zoals) unstructured.io Of door het AST dat uw parser al heeft gegenereerd te doorlopen, wordt nauwelijks benut. Als uw documenten een structuur hebben, maak u deze eerst gebruik van voordat u similariteitsheuristieken toevoegt. Recursieve karaktersplitsing vormt de basis; semantische chunking is pas de moeite waard vanwege de extra overhead wanneer er sprake is van ongestructureerde tekst.
Extractie en verrijking van metadata
- NER precisie/herinnering/F1: per entiteitentype, op een gelabeld deelgeheel. In de standaard CoNLL/MUC-stijl. Berekenen met
seqeval(from seqeval.metrics import f1_score) voor de versie die rekening houdt met BIO/IOB-tags, of scikit-learn voor span-setvergelijkingen. CoNLL-2003 en OntoNotes 5.0 vormen de standaardreferentiecorpora. - Relation extraction F1: nog belangrijker voor op ontologie gebaseerde systemen. Label een set handmatig, gestratificeerd naar relatietype en documentklasse. TACRED en DocRED zijn publiek beschikbaar benchmarks; mogelijke implementaties omvatten
opennreenspaCyrelatie pipelines. - Nauwkeurigheid van titel/hoofdingsextractie: exacte overeenkomst gecombineerd met genormaliseerde Levenshtein-similarity () vergeleken met de ground truth —
python-LevenshteinofrapidfuzzIk lever ze beide aan in één enkele oproep. - Behoud van hiërarchische metadata: het percentage van chunks waarbij de respectievelijke oudersecties, ouderdocumenten en afstammingspaden correct worden behouden. Dit is de metriek die bepaalt of uw RAG in staat is om vragen van het type “Wat zegt het kind van beleid X?” te beantwoorden.
Embedding generatie
- Model selectie benchmarks: MTEB voor algemene capaciteit (nDCG@10 vormt de belangrijkste indicator; de MTEB Python-pakket waardoor u de leaderboard lokaal kunt reproduceren), BEIR voor zero-shot generalisatie. MIRACL Voor meertalige toepassingen is de beste retrieval models-cluster te vinden binnen een smalle nDCG@10-bereik, maar Engelse MTEB-scores voorspellen slecht de prestaties op talen met beperkte bronnen.
- Domain-specifieke evaluatie: beschouw een algemene rang van benchmark niet als een resultaat voor een specifieke domein. Bepaal de omvang van een domeingouden set op basis van diens dekkingsmatrix en de onzekerheid die je beslissing kan verdragen. Rangschik de kandidaat-models-elementen vervolgens opnieuw op basis daarvan.
ranxofpytrec_eval. Een domeinverzameling kan de volgorde op de ranglijst omdraaien; publiceer daarom de dataset-slice, het retrieval-protocol en het betrouwbaarheidsinterval samen met het resultaat. - Embedding driftdetectie: houd de distributieve KL-waarde of de op model gebaseerde drift in de gaten tussen een vaste referentieruimte en een rollende productie embeddings; meet tevens de stabiliteit op basis van de dichtstbijzijnde buren voor een vaste set monsters.
evidentlyenalibi-detectImplementeer detectoren die gebaseerd zijn op model en statistische methoden. Evidently’s vergelijkend onderzoek Dit is slechts één evaluatie van een leverancier; vergelijk de methoden op bekende verschuivingen in uw eigen embeddings. - Meervoudige vector versus enkele vector: late interactie behoudt de representaties op token-niveau in plaats van elke document om te zetten in één vector; ColBERT dit is het canonieke ontwerp, met referentiemodellen in RAGatouille en PyLate. Die rijkere representatie verhoogt de kosten voor indexeren en retrieval. Vergelijk de kwaliteit, opslagbehoeften en latency met een baselinescenario dat slechts één vector gebruikt, op dezelfde domeinset, voordat u deze aanpak adopteert.
Indexopbouw
- Recall@k onder benadering: vergelijk de index op basis van het meest nabije buurtonderzoek (ANN) met een exacte brute-force-benadering bij dezelfde waarde van k — in FAISS, dat is
IndexHNSWFlat(of)IndexIVFFlat) versusIndexFlatIP/IndexFlatL2. Stel de acceptabele recall-verlieswaarde in op basis van uw downstream-kwaliteitsbudget. Deann-benchmarksHet project monitort de recall–QPS Pareto-curven voor verschillende bibliotheken. - HNSW tuning: HNSW (Hierarchisch navigeerbaar klein wereldmodel — een gestapelde nabijheidsgraaf; zie Malkov & Yashunin, 2018, geimplementeerd in
hnswlib, FAISS’sIndexHNSWFlat, en de meeste vector-Databases) bieden drie instellingen:M(graphfanout)efConstruction(breedte van de kandidaat tijdens de bouw)efSearch(de breedte van de kandidaten tijdens het query-proces). Begin met de door de bibliotheek gedocumenteerde standaardwaarden en passeer daarna de parameters totdat de recall–latency-curve voldoet aan de eisen van uw evaluatiegegevens. - IVF-tuning: IVF (Inverted File Index — partition vectors met k-means in)
nlistcellen, en scannen ze vervolgens bij het uitvoeren van de querynprobedichtstbijzijnde cellen; zie FAISS’sIndexIVFFlatenIndexIVFPQ). ZuiverennlistennprobeIn tegenstelling tot de recall van exacte zoekopdrachten en latency, worden Benchmark gefilterde zoekopdrachten apart geanalyseerd, aangezien indexfamilies en vector databases het doorlopen van filters op verschillende manieren implementeren. - Update freshness lag: de tijd tussen het maken van een wijziging in een document en het moment dat dit beschikbaar is voor opvraging. Houd rekening met de waarden p50 en p99. Voor systemen met regelgevende eisen dient ook het percentage zoekopdrachten dat wordt verwerkt met verouderde indexen te worden bijgehouden.
Deel 4: Evaluatie tijdens het opvragen
De query-tijdbaan bevat de metrics die worden gebruikt om een retrieval-pad te diagnosticeren. Alleen Recall@k kan niet aangeven of het falen is veroorzaakt door herschrijving, filtering, reranking, of contextsamenvoeging.
Vraagbegrip en herschrijving
- Kwaliteit van query-expansie: De verbetering in Recall@k op uw gouden dataset, vergeleken tussen de geexpandeerde query en de oorspronkelijke query. Definieer van tevoren het minimale bruikbare voordeel en de bijbehorende onzekerheid voordat u test. Als de expansie deze lokale drempel niet overschrijdt, is dit geen rechtvaardiging voor het gebruik van latency en de daarmee gepaard gaande kosten. Classieke PRF-baselines (pseudo-relevance feedback) zoals RM3 en Bo1 Ze blijven nuttige sanity checks; de op basis van LLM uitgevoerde expansie moet ze overtreffen.
- HyDE-evaluatie: HyDE (Gao et al., 2022) genereert een hypothetisch antwoord met LLM, voegt dit toe en voert vervolgens een zoekopdracht uit op basis daarvan. Hierdoor ontstaat er zowel generatie latency als een nieuwe bron van fouten. Meet de Recall@10 apart voor domein-specifieke, externe en lage-zekerheidsslices, om daarna te bepalen of het antwoord moet worden opgenomen in het standaardpad, als fallback, of nergens.
- Meervoudige query-generatie: de Recall@k-unie van N herwerkingen versus één enkele query. Verander N en kies een punt op de recall–latency-frontier. Implementaties: LangChain’s
MultiQueryRetriever, LlamaIndex’sQueryFusionRetriever. - Accurate classificatie van intenties: standaard precisie/herinnering/F1 per intentie (berekenen met
sklearn.metrics.classification_report), maar de belangrijkste metriek is routingcorrectheid — wordt de juiste downstream pipeline aangeroepen? - Adaptieve routing: Adaptieve-RAG (Jeong et al., NAACL 2024) stelt dat niet elke query recht heeft op dezelfde retrieval strategie. Meet de router nauwkeurigheid als een classificatieprobleem aan de hand van een gelabeld dataset met categorieën zoals “geen retrieval nodig / one-shot / iteratief.”
Retrieval metrics
Dit zijn de basismetrieken. Als u deze niet bijhoudt, kunt u niet bepalen of retrieval zich verbetert.
| Metrica | Wat er wordt gemeten | Wanneer te gebruiken |
|---|---|---|
| Recall@k | het deel van de relevante documenten van een query dat in de top k wordt weergegeven | Gebruik wanneer het ontbreken van een onderdeel uit de relevante set van belang is. |
| Precision@k | het percentage van de top-k elementen dat relevant is | Handig wanneer context window de bottleneck is |
| MRR | gemiddelde van 1/rank van het eerste relevante document | wanneer gebruikers alleen naar de top-1 of top-3 kijken |
| nDCG@k | positiegerelateerde winst, gewogen naar relevantiegraden | de standaard retrieval-metriek voor geclassificeerde relevantie |
| MAP | gemiddelde precisie voor alle zoekopdrachten | wanneer je rekening houdt met de volledige gerangschikte lijst |
| Hit Rate@k | of er ten minste één relevante document in de top k voorkomt | De binaire uitkomst gemiddelden over meerdere queries om snel een indicatie van de betrouwbaarheid te verkrijgen. |
| Dekking | Het percentage gouden documenten dat ooit is teruggevonden bij alle zoekopdrachten | vindt systematische gaten in de index |
De formules, ter referentie (binaire relevantie met het relevante verzameling voor de query , en indien het -de opgehaalde document zich in bevindt):
Voor geclassificeerde relevantie geldt dat ; binaire nDCG is het speciale geval dat wordt gebruikt in de onderstaande code. MAP is de gemiddelde waarde over alle zoekopdrachten van . Zie Manning, Raghavan, Schütze, Inleiding tot informatieopvinding, Hoofdstuk 8 voor de afleidingen.
Voor productiecode moet u deze gebruiken. ranx, pytrec_eval, of ir_measures — Zij implementeren de volledige TREC-metriekfamilie en verwerken gegradeerde relevantie correct. Stel release-doelstellingen vast op basis van een realistisch gouden dataset, de kwaliteit van de downstream-antwoorden en de kosten van een fout. Neem geen drempelwaarden over uit een handleiding.
De test harness voor deze componenten is kort. U kunt hem al uitvoeren vanuit een notebook, nog voordat u een vector database hebt geselecteerd.
from math import log2
from statistics import mean
# synthetic gold set: query_id -> set of relevant doc ids
gold = {
"q1": {"d3"},
"q2": {"d7", "d2"},
"q3": {"d11"},
"q4": {"d5"},
}
# ranked retrieval results: query_id -> ranked list of doc ids (top-10)
runs = {
"q1": ["d8", "d3", "d1", "d4", "d2", "d9", "d6", "d10", "d12", "d13"],
"q2": ["d2", "d6", "d4", "d7", "d1", "d3", "d8", "d11", "d5", "d9"],
"q3": ["d11", "d2", "d3", "d4", "d1", "d6", "d7", "d8", "d10", "d12"],
"q4": ["d1", "d2", "d3", "d6", "d8", "d9", "d10", "d12", "d13", "d14"],
}
def recall_at_k(ranked, gold_set, k):
if not gold_set:
return 0.0
hit = sum(1 for d in ranked[:k] if d in gold_set)
return hit / len(gold_set)
def reciprocal_rank(ranked, gold_set):
# MRR contribution per query: 1/rank of the first relevant doc.
for rank, d in enumerate(ranked, start=1):
if d in gold_set:
return 1.0 / rank
return 0.0
def ndcg_at_k(ranked, gold_set, k):
# binary relevance: rel ∈ {0, 1}
gains = [1.0 if d in gold_set else 0.0 for d in ranked[:k]]
dcg = sum(g / log2(i + 2) for i, g in enumerate(gains))
# ideal DCG: all gold docs ranked first, capped by k
n_gold_in_topk = min(k, len(gold_set))
idcg = sum(1.0 / log2(i + 2) for i in range(n_gold_in_topk))
return dcg / idcg if idcg else 0.0
K = 5
print(f"Recall@{K}: {mean(recall_at_k(runs[q], gold[q], K) for q in gold):.3f}")
print(f"MRR: {mean(reciprocal_rank(runs[q], gold[q]) for q in gold):.3f}")
print(f"nDCG@{K}: {mean(ndcg_at_k(runs[q], gold[q], K) for q in gold):.3f}")
# Recall@5: 0.750
# MRR: 0.625
# nDCG@5: 0.627
Dat is uw retrieval CI-gate. Koppel het aan een snel subset dat is gebaseerd op codecoverage bij elke PR, en voer de volledige ‘golden set’ uit bij het langzamere release-gate. Blokkeer een merge wanneer een van tevoren geregistreerde metric zijn regressiebudget overschrijdt.
Het bijbehorende repository pinnt de exacte getallen hierboven vast.Recall@5 = 0.750, MRR = 0.625, nDCG@5 = 0.627) als een eenheidstest in tests/test_retrieval_metrics.py; Notitieboek 01 voert sweeps uit voor Recall@k / MRR / nDCG op een echte SciFact-index, en de in productie gebruikte harness bevindt zich in evaluation/retrieval.py.
Hybride fusing van retrieval-ranken en wederzijdse rangen
BM25 is een spaarzame lexicaal scoreerder die exacte-termovereenkomsten, termgewichting en lengte-normalisatie combineert. Hij is beschikbaar in rank_bm25Elasticsearch, OpenSearch en de meeste zoekmachines.
Reciproque rangfusie (Cormack, Clarke, en Buettcher, SIGIR 2009) combineert BM25 met dichte rangschikkingen op basis van positie. Het originele k=60 Een dergelijke instelling vormt een nuttige uitgangspunt. RRF is score-onafhankelijk, waardoor de normalisatie tussen verschillende rijbanen die bij lineaire interpolatie nodig is, wordt vermeden. Met een voldoende grote gemarkeerde dataset om een stabiele delta te kunnen bepalen, dient men ook een convexe combinatie te testen en de waarde van α af te stemmen.
Een hybridmodel retrieval in combinatie met een cross-encoder reranker verbetert vaak technische, loggen-gebaseerde en codecorpora. De voordelen zijn mogelijk beperkt bij corpora waarin semantiek een grote rol speelt. Meet de prestaties tegenover configuraties die uitsluitend gebruikmaken van dichte of spaarzame data, aangezien een slechte fusing-configuratie de prestaties van beide invoerbronnen kan verminderen.
De implementatie past in een paar regels.
from collections import defaultdict
# two retrieval lanes: dense embeddings and BM25.
dense = ["d3", "d7", "d1", "d4", "d2", "d9", "d10"]
sparse = ["d2", "d3", "d8", "d1", "d11", "d4", "d6"]
def rrf(rankings: list[list[str]], k: int = 60) -> list[tuple[str, float]]:
"""Reciprocal Rank Fusion (Cormack et al., SIGIR 2009).
score(d) = sum over rankings of 1 / (k + rank(d))
Score-agnostic: only rank position matters. k=60 is the canonical default.
"""
scores: dict[str, float] = defaultdict(float)
for ranking in rankings:
for rank, doc in enumerate(ranking, start=1):
scores[doc] += 1.0 / (k + rank)
return sorted(scores.items(), key=lambda kv: kv[1], reverse=True)
fused = rrf([dense, sparse], k=60)
for doc, score in fused[:5]:
print(f"{doc} score={score:.5f}")
# d3 score=0.03252 <- rank 1 dense, rank 2 sparse
# d2 score=0.03178 <- rank 5 dense, rank 1 sparse
# d1 score=0.03150
Let op wat RRF niet doet: het kijkt nooit naar de ruwe similariteitscores. Een dense retriever die een cosinuswaarde van 0,98 retourneert en een BM25-algoritme dat een score van 17,4 geeft, zijn niet direct vergelijkbaar. Als je ze normaliseert met z-scores of min-max-scaling, kan dit ertoe leiden dat de methode met de hoogste variatie in die batch wordt bevoordeeld.
RRF maakt uitsluitend gebruik van rang. Als een retriever een document op positie 2 plaatst, is die stem waard 1 / (60 + 2)ongeacht het ruwe scoreniveau dat dit heeft opgeleverd.
Hybride + RRF op SciFact: Notitieboek 02 vergelijkt dense met BM25 en RRF aan de hand van per-query verschillen. De voor productie gebruikte fuser bevindt zich in retrieval/hybrid_rrf.py; tests/test_rrf.py pinnt de canonieke versie vast d3 / d2 / d1 Bestelling plaatsen bij k=60.
Reranking
- ΔnDCG / ΔMRR: de enige betrouwbare reranker-meting — de verbetering ten opzichte van geen herrankering, op uw gouden dataset, op de diepte die uw applicatie daadwerkelijk gebruikt. Bereken dit door uw retrieval-metingen uit te voeren met en zonder reranker op identieke kandidaatdatasets.
- Cross-encoder versus bi-encoder: een bi-encoder embedt de query en het document apart (één vector per kant) en bepaalt de score via een dotproduct; een cross-encoder concateneert query+document en voert één enkele forward pass uit waarbij beide elementen gezamenlijk worden verwerkt. Cross-encoders geven ruimere mogelijkheden voor interactie tussen query en document, maar dit ten koste van een extra forward pass per kandidaat. Referentieimplementatie:
sentence-transformersCrossEncoder. Benchmark relevantie en latency met betrekking tot de genoemde hardware, batchgrootte en kandidaatdiepte; verplaats de resultaten van één model of een beheerde dienst niet naar een ander omgeving. - Lijstgewijs versus puntsgewijs: puntsgewijs worden elke (query, doc)-combinatie apart beoordeeld; lijstgewijs wordt de hele lijst met kandidaten gezamenlijk gewaardeerd zodat de model de kandidaten met elkaar kan vergelijken. Beoordeel beide methoden op dezelfde sets kandidaten. Stel elke scoredrempel af op basis van model en het corpus, in plaats van een gepubliceerd voorbeeld als universeel bruikbaar te beschouwen.
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
query = "How do I rotate database credentials in production?"
candidates = [
"Production database credentials are rotated via Vault every 30 days.",
"The new logo was unveiled at the all-hands meeting.",
"To rotate prod DB creds, run the `rotate-secrets` GitHub Action.",
]
scores = reranker.predict([(query, c) for c in candidates])
ranked = sorted(zip(candidates, scores), key=lambda x: -x[1])
for doc, score in ranked:
print(f"{score:+.3f} {doc}")
Een reranker is een veelbelovend kandidaat voor een eenvoudige RAG pipeline, maar dit garandeert geen succes. Meet de waarden ΔPrecision@1 en ΔnDCG op uw gouden dataset, en houd het alleen bij als het behaalde voordeel boven de latency en de kostenbegroting uitkomt. Vergelijk dit gemeten voordeel met kleinere retrieval-aanpassingen voordat u voor de volgende optimalisatie kiest.
ΔnDCG en ΔPrecision@1 afkomstig van een cross-encoder op SciFact: Notitieboek 03; module: retrieval/reranker.py.
Contextconstructie en het ‘verloren in het midden’-probleem
Dit is waar veel fouten van het type “goede retrieval, slechte antwoord” vandaan komen.
- Relevantie van de context: relevanciescore op basis van per-chunk RAGAS
ContextRelevancyof een cross-encoder, gegroepeerd als gemiddelde en als percentage van chunks onder een bepaalde drempelwaarde. - Contextutilisatie: van de in de context geplaatste chunks, hoeveel daarvan werden daadwerkelijk geciteerd of gebruikt in het antwoord. Bereken dit als \frac|\text{geciteerd chunks}|}{|\text{Geretrieven chunks}|Bereken $ voor een gemarkeerd voorbeeld. Stel de actierem op basis van de antwoordkwaliteit en de token-kosten in plaats van door een universele percentages te gebruiken.
- Detectie van verlies in het midden: synthetische eval waarbij de gouden chunk op posities {eerst, midden, laatst} in een lange context wordt geplaatst en de correctheid van het antwoord wordt gemeten. De U-vormige verslechtering is daadwerkelijk aanwezig en is gedocumenteerd in Liu et al. (TACL 2023). Moderne models presteren beter dan de models uit 2023, maar de vooringenomenheid blijft bestaan. Maatregelen: herordeer eerst de resultaten en rangschik daarna de top-k zodat de hoogst gecorrigeerde chunk op de eerste of laatste plaats komt (volgens LangChain’s)
LongContextReorderdoet precies dit), of comprimeer het middenste deel van chunks agressief. Meet dit met een positioneel gestrafde eval, en niet alleen met een algemene score. Een functionerende, uitvoerbare version van een positioneel gestrafde eval bevindt zich in Notitieboek 06 (module:evaluation/lost_in_middle.py). - Context compression: rapporteer de compressieratio (invoer tokens / uitvoer tokens) naast de correctheid van het antwoord. Hulpmiddelen hiervoor omvatten die van LangChain.
ContextualCompressionRetrieveren LongLLMLingua. Definieer van tevoren het maximale acceptabele verlies aan correctheid op basis van het risico van de applicatie en het budget van token, en wees configuraties die dit limiet overschrijden af.
Deel 5: Het false-exclusion-ratio van de filter
Deze metriek krijgt een eigen sectie omdat samengestelde retrieval-scores geen fout kunnen worden toegeschreven aan de filter.
Een strikte metadata-filter zoals tenant_id = X AND product = Y AND locale = en-US Dit kan de effectieve recall tot nul doen dalen. Een correct geïmplementeerde Recall@k herkent dit verlies, aangezien de noemer nog steeds bestaat uit de oorspronkelijke set relevante documenten. Het geeft echter geen indicatie of de filter, de retriever of de ranker de oorzaak is van het gemiste resultaat. De faithfulness kan er nog steeds goed uitzien, omdat deze de antwoord kwaliteiten evalueert op basis van de onvolledige, geraadpleegde context; model heeft immers trouw gezegd: “Ik weet het niet.”
De rode tak in de boom vertegenwoordigt de meest voorkomende fout: het juiste document bestaat wel, maar de filter verwijdert het al vóór retrieval.
De metriek
filter_false_exclusion_rate =
(# queries where all gold docs were excluded by metadata filter) /
(# queries with at least one gold doc)
Bij deze definitie op query-niveau worden catastrofale uitsluitingen meegeteld: er blijft geen relevante document over. Bij meervoudige ‘gold’-queries leidt standaard Recall@k nog steeds tot een gedeeltelijke verlies van informatie; voeg een uitsluitingsratio per document toe als die grens belangrijk is. Om een van deze ratios te berekenen, heb je (a) de echte document-ID’s voor elke eval query en (b) instrumentatie die de toepaste filterpredicaten logt, en niet alleen de uiteindelijke resultaten. Stel het doel vast op basis van de kosten van het uitsluiten van een geldig antwoord en de betrouwbaarheidsinterval van je productiesample.
Hier is een werkende implementatie. Deze vergelijkt de juiste standaard-recall met een ongeldige evaluator die de relevantie na het filteren opnieuw definiërt.
# A small worked example where hard filters remove relevant documents.
docs = [
{"id": "d1", "tenant": "acme", "locale": "en-US"},
{"id": "d2", "tenant": "acme", "locale": "en-GB"},
{"id": "d3", "tenant": "globex", "locale": "en-US"},
{"id": "d4", "tenant": "acme", "locale": "en-US"},
{"id": "d5", "tenant": "acme", "locale": "de-DE"},
]
queries = [
# the gold doc lives in en-GB but the dynamic filter forced en-US
{"qid": "q1", "gold": {"d2"}, "filter": lambda d: d["locale"] == "en-US"},
# the gold doc is correctly within the tenant filter
{"qid": "q2", "gold": {"d4"}, "filter": lambda d: d["tenant"] == "acme"},
# the gold doc is in a different tenant and gets dropped
{"qid": "q3", "gold": {"d3"}, "filter": lambda d: d["tenant"] == "acme"},
# the gold doc passes the filter (de-DE locale match)
{"qid": "q4", "gold": {"d5"}, "filter": lambda d: d["locale"] == "de-DE"},
]
def filter_false_exclusion_rate(queries, docs):
n_with_gold, n_excluded = 0, 0
for q in queries:
if not q["gold"]:
continue
n_with_gold += 1
survivors = {d["id"] for d in docs if q["filter"](d)}
if not (q["gold"] & survivors):
n_excluded += 1
return n_excluded / n_with_gold if n_with_gold else 0.0
rate = filter_false_exclusion_rate(queries, docs)
print(f"filter_false_exclusion_rate = {rate:.2%}")
# filter_false_exclusion_rate = 50.00%
# Correct Recall@k keeps the original gold set as its denominator.
def standard_recall_at_k(queries, docs, k=10):
recalls = []
for q in queries:
survivors = [d for d in docs if q["filter"](d)][:k]
survivor_ids = {d["id"] for d in survivors}
recalls.append(len(q["gold"] & survivor_ids) / len(q["gold"]))
return sum(recalls) / len(recalls) if recalls else 0.0
print(f"standard recall@10 = {standard_recall_at_k(queries, docs):.2%}")
# standard recall@10 = 50.00%
# INVALID: rebuilding the gold set after filtering changes the question.
# It drops queries whose relevant documents did not survive, then scores 100%.
def invalid_recall_over_filtered_gold(queries, docs, k=10):
recalls = []
all_doc_ids = {d["id"] for d in docs}
for q in queries:
all_survivors = {d["id"] for d in docs if q["filter"](d)}
filtered_gold = q["gold"] & all_doc_ids & all_survivors
if not filtered_gold:
continue
top_k_ids = set(list(all_survivors)[:k])
recalls.append(len(filtered_gold & top_k_ids) / len(filtered_gold))
return sum(recalls) / len(recalls) if recalls else 0.0
invalid = invalid_recall_over_filtered_gold(queries, docs)
print(f"INVALID recall (filtered gold) = {invalid:.2%}")
# INVALID recall (filtered gold) = 100.00%
assert rate == 0.5
assert standard_recall_at_k(queries, docs) == 0.5
assert invalid == 1.0
De helft van de zoekopdrachten verliest het gouden document door de filter, waardoor de correcte Recall@10 daalt tot 50%. Deze score geeft wel aan dat er een probleem is, maar kan dit niet specifiek toeschrijven aan een oorzaak. Het percentage valse uitsluitingen laat zien dat het predicaat al twee antwoorden heeft verwijderd voordat de retriever kon worden uitgevoerd. De opzettelijk ongeldige evaluator rapporteert 100% alleen omdat deze fouten worden buitengesloten uit zijn gouden dataset. Geen model kan een document herstellen dat al is gefilterd.
Het hierboven genoemde percentage van 50% wordt als een eenheidstest weergegeven in het bijbehorende repo: tests/test_filter_exclusion.py::test_50_percent_exclusion_rate. Notitieboek 04 het wordt uitgevoerd op SciFact met synthetische metadata, zodat je kunt zien hoe een echte filter de recall tot nul brengt; de runtime-meting (gecombineerd met de bijbehorende predicaten-precisie/recall-waarden) bevindt zich in evaluation/filter_exclusion.py.
Bijbehorende metric: predicatenprecisie en herinneringsratio
Wanneer het filteren dynamisch is (bijvoorbeeld wanneer een LLM filterpredicaten uit de query haalt), moet de predicatenextractor worden beschouwd als een classificatie model en op die manier worden geëvalueerd. Meet de precisie en recall van de predicaten aan de hand van een gelabeld dataset. (query, correct predicate) paren. Een foutkans van een predicaat komt niet direct overeen met dezelfde puntverlieswaarde bij retrieval recall; meet in plaats daarvan hoe vaak dergelijke fouten een gouden document uitsluiten. Zodra een harde filter het gouden document al heeft verwijderd, helpt geen enkele vorm van reranking meer.
Zachte versterking versus harde filtering
Deze metriek dwingt tot een ontwerpprioriteit. Gebruik harde filters wanneer de correctheid binair is: juridische jurisdictie, grenzen van ACL’s, en het onderscheid tussen gepubliceerde en conceptversies. Gebruik zachte versterkingen wanneer de relevantie op een schaal wordt beoordeeld: voorkeur voor locatie, recentheid en versie. Zonder meting van het uitsluitingspercentage is het moeilijk om de verkeerde keuze te herkennen.
De beslissingsregel is meetbaar:
For each filter predicate F:
hard_recall_F = retrieval_recall@k with F as a hard filter
soft_recall_F = retrieval_recall@k with F as a +0.X rerank boost
hard_precision = relevant_in_top_k / k under hard filter
soft_precision = relevant_in_top_k / k under soft boost
exclusion_rate = % of queries where the gold doc was filtered out (hard)
Use hard filter only if exclusion_rate < ε AND hard_precision >> soft_precision.
Otherwise prefer soft boost.
Kies ε op basis van de schade die voortvloeit uit een valse uitsluiting, het voordeel van meer precisie en de omvang van het evaluatiemonster. Een apart artikel in deze serie gaat dieper in op deze afweging.
Deel 6: Evaluatie van generatie
Retrieval-metrieken geven aan dat het systeem kan correct antwoorden. Ze geven echter niet aan dat dit daadwerkelijk is gebeurd. Generatiemetrieken vullen deze lacune op.
Getrouwheid en gefundeerdheid
RAGAS-getrouwheid het antwoord wordt opgesplitst in atomaire beweringen (korte, zelfstandige feitelijke uitspraken), waarna elke bewering wordt geverifieerd tegen de opgehaalde context met behulp van LLM judge:
\text{getrouwheid} = \frac|\text{Claimen ondersteund door de context}|}{|\text{totale claims}|}Het percentage ondersteunde claims vormt de score. Deze structuur is nuttiger dan één enkel getal, omdat deze aangeeft welke claims niet ondersteund worden. De productiecode bevindt zich in de ragas package — gebruik ziet er als volgt uit:
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision
samples = Dataset.from_dict({
"question": ["How many moons does Mars have?"],
"answer": ["Mars has two moons, Phobos and Deimos."],
"contexts": [["Mars has two moons named Phobos and Deimos."]],
"ground_truth": ["Mars has two moons."],
})
result = evaluate(samples, metrics=[faithfulness, answer_relevancy, context_precision])
print(result)
Hieronder staat dezelfde lus uitgewerkt met een deterministische vervanger judge, zodat u de volledige structuur van begin tot eind kunt zien.
def extract_claims(answer: str) -> list[str]:
# Production: an LLM call that decomposes the answer.
# Demo: split on sentence-final punctuation.
return [c.strip() for c in answer.replace("?", ".").replace("!", ".").split(".") if c.strip()]
def verify_claim(claim: str, context: str) -> bool:
# Production: an NLI (natural-language inference) model or LLM judge.
# Demo: a deterministic stand-in so the example runs offline.
entailed_pairs = {
"Mars has two moons": True,
"Phobos and Deimos orbit Mars": True,
"Mars has a thick atmosphere": False, # unsupported by context
"Curiosity landed in 2012": True,
}
for k, v in entailed_pairs.items():
if k.lower() in claim.lower() or claim.lower() in k.lower():
return v
words = [w.lower() for w in claim.split() if len(w) > 3]
return all(w in context.lower() for w in words) if words else False
context = (
"Mars has two moons, Phobos and Deimos. NASA's Curiosity rover "
"landed on Mars in 2012."
)
answer = (
"Mars has two moons. Phobos and Deimos orbit Mars. "
"Mars has a thick atmosphere. Curiosity landed in 2012."
)
claims = extract_claims(answer)
verdicts = [(c, verify_claim(c, context)) for c in claims]
faithfulness = sum(1 for _, ok in verdicts if ok) / len(verdicts)
for c, ok in verdicts:
print(f" [{'✓' if ok else '✗'}] {c}")
print(f"faithfulness = {faithfulness:.2f}")
# faithfulness = 0.75 (one unsupported claim about the atmosphere)
De structuur is van cruciaal belang. In productieomgevingen, verify_claim Het wordt een NLI model of een LLM aanroep. De overige stappen van harness blijven onveranderd: extraheren, verifiëren en aggregeren.
Einde-tot-einde extractie en verificatie van claims in gegenereerde SciFact-antwoorden: Notitieboek 05; module: evaluation/faithfulness.py. In dezelfde lus draait het repository ook een verificator in HHEM-stijl die verschillende families controleert, zodat u kunt zien welke judge-familie overeenkomt met welke andere.
Een speciaal ontworpen alternatief voor LLM als judge HHEM-2.1-Open (Hughes Hallucination Evaluatie Model, Vectara), een classifier die is gefine-tuned voor hallucination-detectie. De model-kaart documenteert de checkpoint, de standaard beslissingsgrens, evenals de resultaten op AggreFact en RAGTruth. Beschouw deze gegevens als bewijsmateriaal op een model-kaart, en niet als een garantie voor uw eigen corpus: kalibreer de drempelwaarde aan de hand van lokale labels en vergelijk deze met de door u gekozen judge vóór deployment.
Evaluatie van atoomfeiten
FActScore (Min et al., EMNLP 2023) splitst lange vormen van generatieprocesen op in atomaire feiten, haalt bewijsmateriaal op voor elk feit en geeft elk feit een label toe supported / not-supporteden geeft het ondersteunde fractiegedeelte weer:
Referentieimplementatie: shmsw25/FActScore. Het werkt uitstekend voor biografieën, samenvattingen en andere lange tekstuitvoerformaten. Wees echter voorzichtig: herhalende, triviale feiten kunnen de score verhogen, en “MontageLie”-aanvallen (waarbij echte feiten in een misleidende volgorde worden gepresenteerd) kunnen het systeem misleiden. VeriScore verwerkt claims met de benodigde modificatoren; de Kernel Een filter helpt om het toevoegen van onnodige feiten te voorkomen.
Precisie van citaties
Houd de precisie van citaties in de gaten (de geciteerde spans ondersteunen daadwerkelijk de bewering) en de herinneringsratio van citaties (de beweringen die geciteerd zouden moeten worden, zijn):
\text{cite\_precision} = \frac|\text{de geciteerde spans die een bewering ondersteunen}|}{|\text{geciteerd spans}|}, \quad \text{cite\_recall} = \frac|\text{Claimen met ten minste één onderbouwende geciteerde span}|}{|\text{claimen die geciteerd moeten worden}|}De TREC 2024 RAG Track definieert een reproduceerbaar protocol voor support evaluatie. Upadhyay et al. (SIGIR 2025) rapport dat GPT-4o het met mensen eens is judges 56% van de tijd bij een handmatige evaluatie vanaf nul, met een stijging tot 72% na post-editing. LLM Voorspellingen. Dit is nuttig als krachtvermeerker onder hun specifieke omstandigheden, maar niet als vervanging voor menselijke beoordeling in risicovolle situaties. Voor een geautomatiseerde benadering, ALCE (Gao et al., EMNLP 2023) implementeert citatieprecisie/citatierecall met verificatie gebaseerd op NLI.
Correctheid, volledigheid en weigering van antwoorden
- Correctheid van het antwoord versus ground truth: wanneer deze beschikbaar is, een exacte overeenkomst of token-F1 voor korte antwoordopdrachten (
evaluate.load("squad")), semantische similariteit voor open eindebert-score, embedding cosinus viasentence-transformers, of RAGASAnswerCorrectness). - Volledigheid via nuggets: een “nugget” is een enkel, atomair informatieonderdeel dat in elk correct antwoord moet voorkomen (bijvoorbeeld voor “Wanneer is het bedrijf opgericht?” kunnen de nuggets zijn)
{year: 1994, founder: Jane Doe}). De TREC-metingen AutoNuggetizer Het haalt de essentiële elementen van een correct antwoord uit een referentiebron en bepaalt vervolgens wat het aandeel is dat door het systeem wordt gedekt – er is een sterke correlatie met de manuele evaluaties bij 21 onderwerpen en 45 uitvoeringen tijdens TREC 2024. - Weerstandsgedrag: vragen waarvoor er geen antwoord in het corpus beschikbaar is, moeten leiden tot afzien van een antwoord in plaats van hallucination. Houd de precisie van het afzien-gedrag bij (de gevallen waarin het juist was om af te zien) en de recall van het afzien-gedrag (de vragen buiten het bereik die tot een weigering leidden). NoMIRACL Is de publieke benchmark; in uw eigen domein aanwezig? Markeer dan een deel van de buiten het bereik vallende query’s en houd de nauwkeurigheid van de afwijzing bij.
Verificatie na generatie
De goedkoopste verbeteringen op het gebied van betrouwbaarheid komen meestal voort uit deterministische post-checks, en niet uit grotere models-systemen.
- Controle van entiteiten grounding: elke genoemde entiteit in het antwoord moet voorkomen in de opgehaalde context (of daaruit afleidbaar zijn). Een eenvoudige regex-check gecombineerd met een exacte overeenkomstcontrole (of
spaCy’sentstegen een genormaliseerde contextstring vangt een verrassend groot deel van hallucinations op. - Verificatie van claims: haal de claims eruit, voer NLI uit tegen de context, en faal of markeer alles wat onder de drempel ligt. NLI-as-faithfulness models:
cross-encoder/nli-deberta-v3-large,MoritzLaurer/DeBERTa-v3-large-mnli-fever-anli-ling-wanli. Voegt latency toe. De moeite waard voor domeinen met hoge risico’s. - Zelfconsistentie (Wang et al., ICLR 2023): Voer meerdere generaties uit bij een temperatuur van meer dan 0; rapporteer het overeenstemmingspercentage (bijvoorbeeld het aandeel generaties dat overeenkomt met het meest waarschijnlijke antwoord, of de pairwise BERTScore); kies het aantal te genereren exemplaren op basis van de stabiliteit‑kostencurve en markeer antwoorden met lage overeenstemming voor menselijke beoordeling.
- Vertrouwensniveau calibration: verzamel de uitgesproken vertrouwensindicatie (“Hoe vertrouwd bent u, 0–1?”) en vergelijk deze met de daadwerkelijke correctheid op de eval-set. Teken een calibration-curve en geef het verwachte Calibration-foutpercentage weer: \text{ECE} = \sum_{m=1}^{M} \frac{|B_m|{n} |\text{acc}(B_m) - \text{conf}(B_m)|, waarbij de confidentiebinnensten zijn. Implementaties:
netcal,torchmetrics.CalibrationError. Een model die een zekerheid van 0,9 rapporteert, moet in ongeveer 90% van de vergelijkbare gevallen correct zijn; meet de afwijking in plaats van te veronderstellen dat dit het geval is bij calibration.
Deel 7: Evaluatie gebaseerd op ontologieën voor RAG
De hierboven genoemde standaardmetrieken dekken open corpora RAG. Systemen die zijn gebaseerd op een ontologie hebben meer nodig. Als uw RAG gegevens ophaalt uit een gestructureerde ontologie, taxonomie of kennisgrafiek (producten in een catalogus, condities in SNOMED, componenten in een BOM, beveiligingstechnieken in MITRE ATT&CK), zijn standaard RAG-metrieken noodzakelijk, maar voldoende niet. U moet ook de ontologielayer meten.
Precisie van entiteitenkoppeling
De eerste taak is het koppelen van een vermelding in een query aan een entiteit in de ontologie (“Aspirin” → wikidata:Q18216, “de 737” → aircraft:Boeing_737).
- Precisie/retentie/F1 op niveau van vermelding: standaard, vergeleken met de gouden referentie spans (berekenen met
seqevalof een span-set comparator). - Accuraatheid van onderscheiding: van de correct gedetecteerde vermeldingen, wat is het aandeel dat overeenkomt met het juiste entity-ID? Openbare referenties omvatten ReFinED, REL, en GENRE; benchmarks zoals AIDA-CoNLL en BELB Toon aan dat de resultaten verschillen per systeem en domein.
- NIL-beheer: nauwkeurigheid/retentie voor gevallen waarbij “entiteit niet in de ontologie voorkomt”. Meet de overkoppeling naar nabije, maar incorrecte entiteiten apart van het correcte afzien van actie.
Evaluatie met rekening houding met hiërarchie
Eenvoudige nauwkeurigheid behandelt het geval ‘voorspeld Sedan terwijl de werkelijkheid Hatchback is’ op dezelfde manier als ‘voorspeld Sedan terwijl de werkelijkheid Submarine is’. Deze fouten zijn echter niet gelijkwaardig.
-
Hiërarchische precisie/herinnering/F1 (Kosmopoulos et al., 2015): Krediteer de voorouders en afstammelingen in de ontologie-DAG. Met wordt het voorspelde node samen met al zijn voorouders aangeduid, en met het echte node samen met al zijn voorouders:
Implementeer met
networkxin de ontologiegrafiek; ziehierarchical-classifier-metricster referentie. -
Wu-Palmer similariteit tussen de voorspelde en de referentiële entiteit in de taxonomie (Wu & Palmer, 1994):
waarbij LCA de laagste gemeenschappelijke voorouder is in de taxonomie. Dit is standaard beschikbaar in NLTK voor WordNet.
from nltk.corpus import wordnet as wn; wn.synset("car.n.01").wup_similarity(wn.synset("truck.n.01"))); voor aangepaste taxonomieën, bereken je de LCA metnetworkx. -
Frequentie van verwarring tussen broers/zussen en ouders: houd apart bij hoe vaak er verwarring optreedt met broers/zussen, ouders en kinderen —
count_sibling / total_errors,count_parent / total_errors,count_descendant / total_errors. Gebruik geverifieerde voorbeelden om te testen of zustereerroren voortkomen uit ambiguïteit in de verwijzingen, en of ouderereerroren het gevolg zijn van overgeneralisatie.
Foutieve uitsluitingsratio van filters (herhaling, nu kritiek)
In ontologie-gebaseerde systemen komen harde filters vaak voort uit de ontologie zelf (“haal alleen documenten op die zijn gemarkeerd met categorie X”). De exclusieratio-metriek (gedefinieerd in Deel 5) Dit wordt een belangrijk signaal voor correctheid. Een verkeerde categorievoorspelling kan de recall tot nul brengen; de uitsluitingsgraad wijst aan dat deze verlies op het filter terug te voeren is.
Conformiteit van beperkte generatie
Wanneer uw uitvoer moet voldoen aan een ontologie (elk entiteitsnaam in het antwoord moet een geldig lid van de ontologie zijn; elke predicaat moet afkomstig zijn uit een gesloten woordenschat), meet dan:
- Schema-validiteitsratio: het percentage van de uitvoer dat wordt geanalyseerd en geverifieerd tegen het ontologieschema. Valideer met
jsonschemaofpydantic. JSONSchemaBench Is de publieke benchmark bedoeld voor algemene structured output-toepassingen? Voor schema’s die specifiek zijn voor een ontologie, moet u uw eigen validator bouwen. - Woordenschatconformiteit: het percentage genoemde entiteiten in de uitvoer dat bestaat uit geldige ontologieduiders — een eenvoudige controle op lidmaatschap van het gesloten woordenschatbestand.
- Semantische conformiteit: validiteit is noodzakelijk, maar niet voldoende. Een syntactisch correcte uitvoer kan een verkeerde, maar nog steeds geldige entiteit kiezen. Combineer conformiteit met de juistheid van de eindantwoord.
Constrained decoding frameworks (Overzichten, XGrammar, Leidraad, OpenAI Structured Outputs) zijn ontworpen om de validiteit van het schema af te dwingen. JSONSchemaBench Het vergelijkt de efficiëntie, de dekking en de kwaliteit tussen verschillende implementaties. Voer opnieuw de testgevallen uit die overeenkomen met uw schema’s en serving backend, aangezien zowel de dekking als latency afhankelijk zijn van beide.
Auditbaarheid
Voor ontologie-gebaseerde systemen waarbij antwoorden worden gecontroleerd:
- Volledigheid van citaties: het percentage feitelijke beweringen dat minstens één te verifiëren citaat bevat.
- Diepte van herkomst: het percentage citaten die terugleiden tot een brondocument met een stabiele ID, en niet alleen tot een chunk hash.
- Rate van reproduceerbaarheid: wanneer dezelfde query op een vaste snapshot wordt uitgevoerd, moet dit dezelfde uitkomst opleveren. Pin de model versie, runtime, de decoderingsconfiguratie en de seed, en stel vervolgens het vereiste herhalingspercentage in op basis van de auditieve eisen van workflow. Alleen een temperatuur van nul garandeert geen determinisme; fouten kunnen voortkomen uit de generatie, de serving runtime, of een eerder stadium in de keten.
Deel 8: Evaluatie op systeemniveau
Algemene kwaliteit van het antwoord
- LLM-als-judge (Zheng et al., NeurIPS 2023): Een schaalbare evaluatiemethode gebaseerd op model. G-Eval (een LLM-judge protocol waarbij model ervoor zorgt dat er zelf een chain-of-thought rubriek wordt gegenereerd voordat er wordt geëvalueerd) leidt een rubriek af uit een criterium in de natuurlijke taal en voert vervolgens de beoordeling uit met uitkomsten die gewogen zijn volgens logaritmische waarschijnlijkheden. De overeenstemming hangt af van de judge, de taak, het prompt en de calibration instellingen.
- Tweevoudige voorkeur: presenteer judge tegenover antwoord A en antwoord B; noteer de voorkeur. Dit voorkomt problemen met absolute scores bij calibration. MT-Bench Er werd gemeld dat de overeenstemming van GPT-4 judge boven de 80% ligt, zowel met menselijke voorkeuren als met overeenstemming tussen mensen, onder de benchmark voorwaarden; deze score mag niet worden overgedragen naar een ander domein zonder calibration.
LLM-as-judge vertoont echte vooringenomenheden:
- Positiebias: judges geeft de voorkeur aan het eerste of tweede antwoord, ongeacht de kwaliteit. Mitigatie: randomiseer de volgorde, of voer beide volgordes uit en neem het gemiddelde.
- Bijzonderheidsbias: judges kan lengte verwarren met kwaliteit. Een Gecontroleerde studie van 2026 Er werd heterogeen gedrag van de expansieparen waargenomen: drie judges gaven de voorkeur aan langere antwoorden, Claude gaf de voorkeur aan beknopte antwoorden, en GPT-4o bleef vrij neutraal. Alle vijf presteerden goed bij de tronkatiecontroles. Het resultaat valt binnen de grenzen van benchmark; informeer daarom uw judge over hoe om te gaan met volledigheid en vulling, en rapporteer vervolgens de prestaties onder lengtebeperking volgens uw eigen criteriën.
- Bias van zelfvoorkeur: GPT-4 geeft de voorkeur aan eigen uitvoer; deze bias staat in verband met de output-perplexiteit (judges geeft de voorkeur aan tekst die hen vertrouwd is). Vermindering: gebruik een andere familie van judge dan het systeem dat wordt geëvalueerd. Gebruik geen model op judge zelf.
Praktische aanpak: kies een judge uit calibration data-geëtiketteerde gegevens, randomiseer de volgorde van de antwoorden, maskereer de identiteiten van model en specificeer de lengtebeperking in de beoordelingscriteria. Herhaal gevallen alleen wanneer de toegevoegde voorbeelden de onzekerheid aanzienlijk verminderen. Bij evaluaties met hoge stakes moet je judges uit verschillende model-families vergelijken en de meningsverschillen analyseren ten opzichte van de menselijke labels.
Schema-gestuurde Reasoning voor judges
Vrije vorm van uitvoer is een van de oorzaken van variatie bij uitvoeringen van judge. Twee uitvoeringen op dezelfde vraag kunnen de beoordelingscriteria op verschillende manieren toepassen, waardoor er verschillende scores ontstaan. Schema-gestuurde Reasoning (SGR) Maak deze richtlijnen expliciet: definieer de evaluatiefasen als een Pydantic-schema, en gebruik vervolgens geconstrueerde uitvoer via Outlines, XGrammar, vLLM structured outputs, of OpenAI. response_format Dus elke uitvoering retourneert dezelfde velden in dezelfde volgorde.
Voor RAG eval splitst het schema het oordeel op in expliciete, controleerbare velden, in plaats van de model direct naar een getal te laten gaan:
from pydantic import BaseModel, Field
from typing import Literal
class FaithfulnessJudgment(BaseModel):
extracted_claims: list[str] = Field(
description="Atomic factual claims in the answer, one per item."
)
supported_claims: list[str] = Field(
description="Subset of extracted_claims that are entailed by the context."
)
unsupported_claims: list[str] = Field(
description="Subset that is NOT entailed by the context."
)
failure_mode: Literal[
"none", "fabrication", "overgeneralization", "wrong_entity", "stale_fact"
]
score: float = Field(ge=0.0, le=1.0)
rationale: str
De gestructureerde velden maken het mogelijk om de score weer te herstellen. len(supported) / len(extracted) En toon precies over welke beweringen twee judges het oneens waren. De Pydantic model maakt ook een verandering in de rubriek zichtbaar als een code‑diff. Door de uitvoer te beperken wordt alleen de vorm gegarandeerd, niet een onbevooroordeeld oordeel; daarom blijven positierandomisatie, cross‑family judges en menselijke calibration van toepassing.
Dit werkt voor elke op een rubriek gebaseerde judge, niet alleen voor de beoordeling van nauwkeurigheid. Zowel de paarwaardige voorkeursbeoordeling, de ondersteuning voor citaten als de correctheid bij weigeringen profiteren allemaal van dezelfde behandeling.
Een G-Eval / paarsgewijs / positiebias / interfamiliale judge harness komt voor in Notitieboek 07; module: evaluation/llm_judge.py. De benchmark-scanmake benchmark in de repo) verbindt drie frontier-tier models — gpt-5-mini, claude-haiku-4-5, gemini-2.5-flash — omgezet naar een rotatievolle judge paarvoor-paar A/B zodat elke model judges de andere twee, waardoor de zelfvoorkeur numeriek zichtbaar wordt.
Latency en kosten
- p50, p95, p99 op elke pipeline-fase. Kies het SLO-percentiel en de waarschuwingsdrempel op basis van de gebruikerservaring, het verkeersvolume en het foutbudget.
- Time-to-first-token versus de totale generatietijd. Gebruikers hechten belang aan TTFT voor een soepele streamer-UX.
- Fasenanalyse: retrieval, reranking, generatie en postverwerking. Gebruik trace om de oorzaak in het ‘tail’-gedeelte te achterhalen, in plaats van te veronderstellen welke fase dit veroorzaakt; noteer bij het vergelijken van verschillende uitvoeringen de reranker-apparatuur en de batchgrootte.
- Totaal $/query = embedding + retrieval + reranking + generatie + afgeschreven opslagkosten. Houd rekening met p50 en p99; het lange ‘tail’-gedeelte is waar het budget meestal wordt verbruikt.
- Cachehit-raten op het niveau van de embedding-cache, de retrieval-cache en de KV-cache. Stel aparte doelwaarden vast op basis van de waargenomen herhalingen, de invalidatiebeleid en de kosten die op elk niveau worden bespaard.
Een per-fase p50/p95/p99 met een gedetailleerde fasesplitsing is ingebouwd Notitieboek 08 en de runner bij evaluation/latency.py; Het rapport benchmark combineert latency met nauwkeurigheid in één enkele matrix die u opnieuw kunt uitvoeren. make benchmark.
A/B-testen
- Eenheid voor randomisatie: kies de eenheid uit de estimand, carryover en interference. Gebruik toewijzing per gebruiker of per session wanneer herhaalde blootstelling het gedrag kan veranderen of tot een inconsistente gebruikerservaring leidt. Toewijzing per query is alleen gerechtvaardigd wanneer deze effecten verwaarloosbaar zijn en de analyse models herhaalde observaties omvat.
- Primair, guardrails, exploratief metrisch materiaal: registreer dit van tevoren. Kies de primaire maatstaf uit het productresultaat; alternatieven voor tevredenheid omvatten thumbs, regeneraties en dwell-tijd. Beschouw latency en kosten als guardrails wanneer ze de gebruikerservaring beperken.
- Stekproefgrootte: voer eerst een power-analyse uit voordat je van start gaat, waarbij rekening wordt gehouden met het minimale effect dat waard is om te detecteren, de basisspanning, de toewijzingseenheid en de stopregel.
Deel 9: Opbouw van de testset
Een metriek is alleen zo goed als de testset waarop deze wordt uitgevoerd. Als uw gouden dataset drie intenties omvat en het productietraffic spans twaalf, meet Recall@10 alleen die drie intenties. Erger nog: een testset die te goed past bij eenvoudige vragen (“Wat is het restitutiebeleid van het bedrijf?”) kan een systeem goedkeuren dat faalt bij moeilijkere gevallen (“Voldoet een gedeeltelijke annulering onder de EU Digital Services Act van 2023, gefactureerd in EUR en afkomstig uit Ierland, aan de voorwaarden voor restitutie?”). De totale score stijgt, terwijl het systeem nog steeds een belangrijk deel van het productietraffic niet kan verwerken.
Hetzelfde probleem doet zich voor bij de ground truth. Als KMO’s de voor de hand liggende documenten hebben gelaagd maar de minder voorkomende, relevante documenten over het hoofd hebben gezien, zal Recall@k een retriever die ze wel heeft gevonden onterecht lage scores geven. Men optimaliseert dan richting de labels, en niet richting de waarheid.
Bouw eerst het testset op basis van de werkelijke verdeling en moeilijkheidsgraad van de vragen. Kies daarna metrics die reageren op de gewenste foutmodi, en stem het systeem hierop af.
Generatie van synthetische queries
Gebruik een LLM om vragen te genereren uit uw corpus:
- Per-chunk: “Genereer 3 vragen die een gebruiker zou kunnen stellen en waarop deze chunk antwoordt.”
- Multi-hop: neem twee chunks-voorbeelden, en maak een vraag die beide vereist.
- Adversarial: genereer vragen met afleidende entiteiten, bijna identieke formuleringen en dubbelzinnige verwijzingen.
RAGAS bevat een ingebouwde verdeling van vragensoorten (reasoning, conditioneel, meervoudig context). DataMorgana Het genereert configureerbare synthetische benchmarks-gegevens voor verschillende categorieën gebruikers en vragen. Synthetische gegevens zijn nuttig voor ‘cold start’-situaties en voor het uitvoeren van coverage-tests. Ze kunnen echter geen vervanging zijn voor echte gebruikersvragen.
Gouden dataset-constructie
Gedegenereerde gegevens vormen de basis voor de gouden set.
- Voorbeelden van echte gebruikersvragen (of gesimuleerde vragen indien nog voor de lancering), gegroepeerd naar intentie.
- Laat SME’s elke vraag beantwoorden en bepalen welk(ke) document(en) het antwoord bevatten.
- Bepaal de omvang van de set op basis van de dekkingsmatrix en het vertrouwensinterval dat nodig is voor beslissingen over de lancering; dekking is belangrijker dan het aantal gebruikte vragen.
- Herstel de dataset wanneer de lanceringssnelheid, signalen van afwijkingen, domeinrisico’s of annotatiecapaciteit dit rechtvaardigen.
Adversariale testsets
- Counterfactuals: vervang de belangrijkste entiteiten in de query. Haalt het systeem het juiste chunks op voor de gemodificeerde query?
- Distractors: queries waarin het corpus een plausibel, maar onjuist antwoord bevat dat niet geraadpleegd mag worden. Dit is precies wat RGB (Chen et al., AAAI 2024) voeren stresstests uit op: ruisbestendigheid, negatieve afwijzing, informatieintegratie en contrafactuele bestendigheid.
- Ontkenning en kwantificatoren: zoekopdrachten die “not”, “except” en “only” bevatten. Dichte retrievers hebben hier vaak moeite mee.
- Buiten het bereik: zoekopdrachten waarvoor er geen antwoord in het corpus is. Het systeem moet “Ik weet het niet” zeggen, in plaats van te hallucineren. NoMIRACL Het bevindt zich hier. Beoordeel afwezigheid expliciet op basis van uw productiequerytypen.
Dekking en continue evaluatie
- Maak een dekkingsmatrix aan: queryintentie × documenttype × ontologietak. Streef ernaar om per cel minstens één query te hebben. Lege cellen vertegenwoordigen onbeheerde gebieden waar regressies zich kunnen verbergen.
- Voer een beperkt en snel regressietestonderdeel uit op elke pull request, en het volledige testpakket op een langzamer tijdschema.
- Plan het volledige golden-set eval in overeenstemming met de releasecyclus en de kosten van evaluatie; release candidates vormen hierbij een logische controlepunt.
- Plan de evaluatie van drift op basis van het verkeersvolume, de verwachte veranderingen en het risico. Gebruik een rollend productieproefmonster en streef ernaar de resultaten te segmenteren op basis van feedback, in plaats van stilletjes de doeldistributie te wijzigen.
Deel 10: Productiemonitoring
Het eval-pakket dat u distribueert, beschrijft het systeem bij de lancering. Het verkeer in productie verandert daarna.
Impliciete en expliciete feedback
- Klik- en openratio van de geciteerde bronnen (indien uw gebruikersinterface deze weergeeft).
- Blijftijd bij het antwoord.
- Regeneratieratio: het percentage antwoorden dat de gebruiker opnieuw vraagt of waarbij hij het systeem vraagt om het opnieuw te genereren. Beschouw dit als een teken van ontevredenheid en pas het af aan de geanalyseerde gesprekken.
- Kopieer-/delen-/exportratio’s – een sterk positief signaal.
- Volgpatronen: vragen als “Weet u het zeker?” of “Maar wat gebeurt er met X?” duiden op wantrouwen.
- Duim omhoog/omlaag met optionele redencategorieën (verkeerd, onvolledig, afwijkend van het onderwerp, schadelijk, traag). In-linewijzigingen, wanneer uw interface dit toestaat, vormen het meest informatieve feedbacksignaal dat er bestaat.
Detectie van drift
- Query drift: houd de verdeling van queries embedding in de gaten ten opzichte van een referentieramen, met behulp van KL-divergentie, MMD of een detector gebaseerd op model. Geef een alarm af bij een verschuiving en voer vervolgens segmentatie- en debugwerkzaamheden uit.
- Embedding drift: fixeer een set monsters van vaste documenten; embed deze periodiek opnieuw en meet de cosinuscoëfficiënt ten opzichte van het oorspronkelijke embeddings. Zelfs kleine verschillen tussen versies van de provider model kunnen ongemerkt problemen veroorzaken bij retrieval. Gearchiveerde opslag van embedding in versies (waarbij elke versie onveranderlijk blijft volgens snapshots) is de meest kosteneffectieve manier om dit te verminderen.
- Performance drift: volg gedurende de tijd metrics die overeenkomen met die in productie (de regeneratierate per intent). Plotselinge sprongen duiden erop dat er iets mis is gegaan; langzame verschuivingen wijzen erop dat de omstandigheden zijn veranderd.
Schaduwevaluatie en human-in-the-loop
Voer het kandidaatstelsel parallel aan het productiesysteem uit, vergelijk de uitvoer offline en serveer deze niet aan gebruikers. Op deze manier worden regressies al vóór de lancering opgespoord. Dit kost extra inference, maar heeft geen invloed op de klanten.
Voor de review van human-in-the-loop (HITL):
- Plaats voorbeelden van output met lage betrouwbaarheid in een review-queue.
- Voeg een willekeurige steekproef van productietraffic toe voor een blinde review; stel het aantal voorbeelden in op basis van het verkeersvolume, het risiconiveau en de capaciteit van de reviewers.
- Weight geef veel voorbeelden met een negatieve beoordeling voor review.
- Gebruik de gereflecteerde output om de ‘golden set’ uit te breiden.
Het minimale guardrail-set
Geef alarm voor deze items, in volgorde van prioriteit:
- Faithfulness/HHEM-score lager dan de drempelwaarde in een rollende productiesample.
- p95 latency hoger dan de SLO.
- Foutloze uitsluitingsratio van filters boven de drempelwaarde (op basis van een sample).
- Regeneratieratio buiten een lokaal gekalibreerde controleband die rekening houdt met de venstergrootte, het verkeer, seizoensinvloeden en het budget voor valse alarmen.
- Kosten/per query boven het budget.
Wanneer een alarm wordt afgevuurd zonder een overeenkomstige code of een model-wijziging, wijst dit waarschijnlijk op drift. Als het alarm na een wijziging wordt afgevuurd, duidt dit meestal op een regressie. In beide gevallen krijg je al een signaal voordat er supportverzoeken binnenkomen.
Aandachtspunten
- De doelwaarden zijn lokaal van aard en niet universeel. Elke getalswaarde die in deze gids als illustratief wordt aangeduid, vertegenwoordigt een voorbeeldconfiguratie of een behaald resultaat, en niet een officiële release-threshold. Pas de thresholds aan op basis van uw specifieke domein, de betrokken risico’s, de onzekerheid in het evaluatiegegevensbestand en de verwachtingen van de gebruikers.
- De framework-ruimte ontwikkelt zich zeer snel. Versies van HHEM, namen van RAGAS-metingen, model-kaarten en de volgorde op de leaderboards kunnen na publicatie veranderen. Controleer altijd de gerelateerde bronnen en voer opnieuw benchmark uit voordat u iets committ.
- Nummers die aangeven in hoeverre LLM overeenkomt met judge, worden weergegeven met sterren. Het cijfer van 80% voor GPT-4 versus mens komt voort uit de omstandigheden van MT-Bench / Chatbot Arena. Op niche-domeinen en bij adversarische scenario’s daalt de overeenstemming sterk. Gebruik judges als hulpmiddel om de resultaten te versterken, maar niet als vervanging voor directe controle.
- Verbeteringen die door leveranciers worden aangeboden via benchmark, zijn vaak niet onafhankelijk reproduceerbaar. Voer eerst zelf tests uit met uw eigen gegevens voordat u een getal serieus neemt, vooral bij nieuwere rerankers- en OCR-systemen.
- Geen enkele metric kan dienen als vervanging voor het direct bekijken van de uitvoer. Plan regelmatig blinde reviews van willekeurige productievoorbeelden, afhankelijk van het verkeer, het risico en de beschikbare capaciteit van de reviewers. Metrics kunnen dit proces ondersteunen, maar ze vervangen het niet.
Wat komt eraan in deze serie
Dit was de index. De vervolgstukken zijn planning:
- Zachte boosts versus harde filters: een diepgaande analyse van het risico op valse uitsluiting door filters, inclusief code, echte productievoorbeelden en een beslissingsframework framework.
- Is Chunking de verborgen variabele?: een gecontroleerd experiment met recursieve, semantische, late en structurele chunking methoden op drie corpora.
- Selectie van Reranker in 2026: BGE versus Cohere versus ZeRank versus de huidige cross-encoder models, vergeleken wat betreft kosten, latency en prestatieverbetering.
- Ontologie-gebaseerde RAG: een end-to-end walkthrough: het opzetten van een volledige evaluatie harness voor een entiteit-gebaseerd retrieval systeem.
- LLM-als-Judge zonder de valkuil van zelfvoorkeur: praktische methoden voor onbevooroordeelde, geautomatiseerde evaluatie.
- Online evaluatie in productieomgevingen: instrumentatiepatronen, alarmbeleid en dashboards die echte regressies snel detecteren.
Referenties
Frameworks en benchmarks
- Es et al., Ragas: Geautomatiseerde evaluatie van Retrieval-versterkte generatie, 2023.
- RAGAS-documentatie en GitHub.
- Saad-Falcon e.a., ARES: Een geautomatiseerde evaluatie Framework voor Retrieval-versterkte generatiesystemen, NAACL 2024.
- TruLens, DeepEval, Arize Phoenix.
- Thakur et al., BEIR: Een heterogene Benchmark voor zero-shot evaluatie van informatie Retrieval Models, NeurIPS 2021.
- MTEB-lijst.
- TREC 2024 RAG Track.
- Pradeep e.a., Beginresultaten van de evaluatie van Nugget‑voorstellen voor de TREC 2024 RAG track met AutoNuggetizer Framework, 2024.
Retrieval en rangschikking
- Cormack, Clarke, Buettcher, Reciprocal Rank Fusion presteert beter dan Condorcet- en individuele rangleringsmethoden., SIGIR 2009.
- Gao et al., Precieze zero-shot dense Retrieval zonder relevanțielabels (HyDE), 2022.
- Jeong et al., Adaptive-RAG: Leren zich aanpassen aan Retrieval-verrijkte grote taalmodellen Models op basis van vraagcomplexiteit, NAACL 2024.
- Anthropic, Een introductie tot contextueel Retrieval, September 2024.
- Günther et al., Te late Chunking: Contextueel Chunk Embeddings met gebruik van langcontextuele Embedding Models, 2024.
- Sarthi e.a., RAPTOR: Recursieve abstractieverwerking voor boomgeorganiseerde Retrieval, 2024.
Generatie, getrouwheid, judges
- Min e.a., FActScore: Gedetailleerde atomaire evaluatie van de feitelijke nauwkeurigheid bij het genereren van lange tekstfragmenten, EMNLP 2023.
- Liu et al., Verloren in het midden: Hoe taal Models lange contexten gebruikt, TACL 2023.
- Chen et al., Benchmarking van grote taalmodellen Models in Retrieval-versterkte generatie (RGB), AAAI 2024.
- Vectara, HHEM-2.1-Open hallucination evaluatie model.
- Zheng et al., Het beoordelen van LLM als een Judge met MT-Bench en Chatbot Arena, NeurIPS 2023.
- Upadhyay et al., Beoordeling van ondersteuning voor de TREC 2024 RAG track: Vergelijking tussen menselijke en LLM Judges, SIGIR 2025.
- Thakur et al., NoMIRACL: Het herkennen wanneer je iets niet weet voor betrouwbare multilinguele Retrieval-geavanceerde generatie, 2023.
- Geng et al., JSONSchemaBench: Een rigoureuze Benchmark van Structured Outputs voor taal Models, 2025.
- Kosmopoulos et al., Evaluatiemethoden voor hiërarchische classificatie: een geïntegreerd overzicht en innovatieve benaderingen, 2015.
Drift en productieomgeving
- Kennelijk, Embedding Methoden voor het detecteren van drift.
Bijbehorende code
slavadubrov/rag-evals-demo— een uitvoerbaar harness voor elke metric in dit artikel over het SciFact-corpus, plus een chunking × embedding × LLM benchmark sweep. Notitieboeken 00–09, eenhets-tests die de hierboven beschreven werkvoorbeelden vastleggen, en een ingebouwde Qdrant-index zodat het zonder Docker kan draaien.