Chunking-strategieën kwantitatief vergelijken voor RAG
De keuze voor een chunking-strategie bepaalt in hoge mate het succes of falen van een Retrieval-Augmented Generation (RAG) pijplijn. Wanneer brondocumenten in te grote fragmenten worden opgedeeld, overspoelt irrelevante tekst het contextvenster van het taalmodel. Maak je fragmenten daarentegen te klein, dan verdwijnt de samenhang en ontbreken noodzakelijke randvoorwaarden om een vraag feitelijk te beantwoorden. Deze beslissing wordt in de praktijk te vaak genomen op basis van vuistregels of willekeurige standaarden zoals 500 tokens met 10% overlap.
Een doordachte architectuur vereist een kwantitatieve evaluatie: hoe presteert een specifieke splitsingsmethode op jouw corpus in termen van trefzekerheid, signaal-ruisverhouding en uiteindelijke antwoordkwaliteit? In dit artikel formuleren we een reproduceerbare meetopzet waarmee verschillende splitsingsstrategieën objectief met elkaar worden vergeleken. Voor een breder overzicht van de interactie tussen opzoek- en generatiestappen verwijzen we naar het fundament in het artikel over RAG-evaluatie, waarin de complete keten van zoektrap tot modelrespons wordt ontleed.
De afwegingen tussen vaste, semantische en structurele splitsing
Voordat we meetwaarden berekenen, is het noodzakelijk om de fundamentele splitsingsmechanismen te classificeren. Er bestaan grofweg vier dominante chunking-benaderingen, elk met specifieke aannames over tekststructuur en semantische dichtheid:
- Vaste vensters (Fixed-size chunking): De tekst wordt rigide gesplitst op een vooraf gedefinieerd aantal tokens of karakters (bijvoorbeeld 256 of 512 tokens), vaak met een schuivend overlapvenster van 10% tot 20%. Dit is computationeel goedkoop, maar snijdt zinnen of redeneringen willekeurig doormidden.
- Recursieve structurele splitsing (Recursive character chunking): Er wordt geprobeerd te splitsen langs natuurlijke grenzen, waarbij een hiërarchie van scheidingstekens (paragrafen
\n\n, regeleindes\n, zinnen.en spaties) wordt afgelopen totdat elk blok binnen de doelgrootte past. Dit behoudt grammaticale eenheden aanzienlijk beter dan vaste vensters. - Document-specifieke parsering (Structure-aware / Markdown chunking): De parser benut semantische metadata zoals HTML-koppen, Markdown-secties, tabelgrenzen of JSON-structuren. Fragmenten representeren zelfstandige subsecties waarin kopteksten vaak als contextuele prefix worden meegenomen.
- Semantische chunking (Embedding-based clustering): Zinnen worden opeenvolgend geanalyseerd. Er wordt een knip gemaakt op posities waar de cosinusovereenkomst tussen opeenvolgende zinsembeddings onder een bepaalde drempelwaarde duikt, wat wijst op een onderwerpverschuiving.
Wanneer documenten extreem lang en narratief van aard zijn, kan een chunking-strategie zelfs concurreren met direct inlezen via enorme contextvensters. Wie overweegt documenten in hun geheel aan te bieden zonder tussenliggende vectorindex, doet er goed aan het overzicht van modellen voor het samenvatten van lange documenten te raadplegen om de kosten en verwerkingslimieten van ongesplitste contexten te doorgronden.
Isolatie van de zoekfase versus de generatiefase
Een veelgemaakte methodologische fout is het beoordelen van chunking op basis van de uiteindelijke modelantwoorden alleen. Als een model faalt, kan dat liggen aan een slechte chunk (retrieval-fout), maar evengoed aan een redeneerfout van de generator of hallucinatie ondanks perfecte context. Om een chunking-strategie zuiver te kwantificeren, splitsen we de evaluatie op in twee geïsoleerde fasen:
1. Retrieval-kwaliteit (vóór het LLM): Worden de juiste passages teruggevonden uit de database? Bevatten de opgehaalde vectoren de brondata die nodig is om de vraag te beantwoorden?
2. Generatie-efficiëntie (door het LLM): Hoeveel ruis bevatten de opgehaalde brokken, en leidt de gefragmenteerde context tot coherentieverlies of onnodige tokenkosten?
Omdat de trefzekerheid van de retrieval-laag direct samenhangt met de gekozen vectorrepresentatie, moet de invloed van de chunkgrootte altijd worden geëvalueerd in combinatie met het gebruikte embeddingmodel. Zie ook de gids voor het evalueren van embedding-modellen om te verifiëren hoe de effectieve dimensies en contextcapaciteiten van embeddingsvectoren zich verhouden tot je chunklengte.
Kwantitatieve retrieval-statistieken: Recall, MRR en precisie
Om retrieval objectief te meten, is een gecureerde evaluatieset met paren van vragen en ground-truth documentpassages vereist. We definiëren een query $q$, een verzameling relevante document-ID's $R_q$, en een geordende lijst van $k$ opgehaalde chunks $K_q = [c_1, c_2, \dots, c_k]$.
| Metriek | Formule | Wat het meet bij chunking |
|---|---|---|
| Recall@k | $$\frac{|R_q \cap K_q|}{|R_q|}$$ | Of de vereiste informatie überhaupt aanwezig is in de top-$k$ resultaten. |
| Mean Reciprocal Rank (MRR) | $$\frac{1}{|Q|} \sum_{i=1}^{|Q|} \frac{1}{\text{rank}_i}$$ | Hoe hoog de eerste relevante chunk in de ranking verschijnt. |
| Context Precision | $$\frac{\sum_{r=1}^k P@r \cdot \mathbb{I}(c_r \in R_q)}{|R_q|}$$ | Of relevante chunks bovenaan staan en irrelevante chunks worden vermeden. |
| Context Token Efficiency | $$\frac{\text{Aantal relevante tokens in top-}k}{\text{Totaal aantal opgehaalde tokens}}$$ | De signaal-ruisverhouding binnen het contextvenster. |
Kleine chunks (bijv. 128 tokens) scoren vaak een hoge Context Precision en Context Token Efficiency, maar kunnen een lagere Recall@k opleveren als een argument over meerdere zinnen verspreid staat. Grote chunks (bijv. 1024 tokens) halen gemakkelijk een hoge Recall@k, maar drukken de Context Token Efficiency aanzienlijk omlaag doordat er honderden irrelevante tokens worden geïnjecteerd.
Illustratief voorbeeld: De onderstaande cijfers tonen een hypothetische vergelijking tussen drie splitsingsvarianten op een technisch testcorpus van 500 documenten.
| Strategie | Recall@3 | MRR | Context Token Efficiency | Gem. latency retrieval |
|---|---|---|---|---|
| Vast venster (128 tokens, overlap 20) | 0.68 | 0.54 | 78% | 12 ms |
| Recursief (512 tokens, overlap 50) | 0.89 | 0.76 | 52% | 15 ms |
| Structureel / Markdown-secties | 0.93 | 0.84 | 69% | 18 ms |
Contextfragmentatie en het meten van trouw
Wanneer een chunking-algoritme een document opsplitst, wordt de omringende context weggesneden. Dit introduceert het risico van contextfragmentatie: een chunk bevat bijvoorbeeld het antwoord "In dit geval bedraagt de opzegtermijn drie maanden", maar de voorwaarde "indien het contract vóór 2021 is getekend" staat in de voorafgaande paragraaf die niet is opgehaald.
Om te evalueren hoe gevoelig een chunking-strategie is voor fragmentatie, meten we de Faithfulness (Trouw) en Answer Relevance van het genererende model onder gecontroleerde omstandigheden. Een lage trouwscore wijst erop dat het generatieve model feiten moet verzinnen omdat randvoorwaarden ontbreken in de aangeleverde broktekst.
De beoordeling van trouw en feitelijke consistentie kan geautomatiseerd worden uitgevoerd met geijkte prompt-evaluatoren. Om de betrouwbaarheid van dergelijke beoordelingsmodellen te borgen, verwijzen we naar de systematiek in het artikel over LLM-as-a-Judge opzetten, waar methoden worden besproken om jury-bias en positievoorkeuren te corrigeren.
Valkuilen in het Nederlandse taalgebied
Bij het benchmarken van chunking op Nederlandstalige corpora treden specifieke taalkundige complicaties op die bij standaard Engelstalige evaluatieruns onzichtbaar blijven:
- Lange samenstellingen: Het Nederlands kent lange aaneengeschreven samenstellingen (zoals aansprakelijkheidsverzekeringsmaatschappij). Karaktergebaseerde splitsers die blind op lengte kappen, kunnen woorden middenin afbreken als de tokenizatiegrens niet gerespecteerd wordt.
- Juridische en ambtelijke zinsconstructies: Veel Nederlandstalige documenten (overheidsbeleid, contracten, CAO-teksten) hanteren tangconstructies waarbij de hoofdgedachte over tientallen woorden wordt uitgesmeerd. Splitsing op basis van een te kort vast venster (bijv. 150 tokens) knipt bijzinnen los van hun modale werkwoorden, wat leidt tot betekenisomkering.
- Afkortingen en interpunctie: Zinsdetectie op basis van eenvoudige regex-patronen (zoals een punt gevolgd door een spatie) faalt frequent bij gangbare Nederlandse afkortingen zoals m.b.t., t.a.v., art. en d.w.z. Dit veroorzaakt onbedoelde micro-chunks.
Tokenkosten, indexeertijd en opslagkwantificering
Een kwantitatieve evaluatie is niet compleet zonder de operationele kostenkant mee te wegen. Kleinere chunks met veel overlap leiden tot een explosie van het totale aantal vectoren in de database, wat de opslagkosten en de rekentijd voor het opbouwen van de index verhoogt. Bovendien beïnvloedt de totale chunkgrootte direct het aantal input-tokens per LLM-aanroep.
Voor een methodologische uitwerking van hoe tokenaantallen vertaald worden naar operationele budgetten, zie de methodiek voor het beheersen van evaluatiekosten. In onderstaande berekening leggen we vast hoe de datadichtheid en API-aanroepen schalen per splitsingsvariant.
# Voorbeeld: Formule voor vectorindex-omvang en API-overhead
# N = aantal brondocumenten
# W = gemiddeld aantal tokens per document
# C = chunk-grootte in tokens
# O = overlap in tokens
aantal_chunks = (W - O) / (C - O)
totale_index_vectoren = N * aantal_chunks
totale_invoer_tokens_per_rag_call = k * C
Als een corpus van 10.000 documenten van elk 2.000 tokens wordt gesplitst met $C=256$ en $O=50$, resulteert dat in circa 94.660 chunks. Kiest men voor $C=1024$ met $O=100$, dan daalt dit naar circa 20.550 chunks. Dit scheelt een factor 4,6 in database-grootte en initiële embedding-kosten.
Een reproduceerbaar experimenteel testprotocol
Om zelf een benchmark uit te voeren die bestand is tegen toevalsfluctuaties, hanteren we een gestandaardiseerd stappenplan. Hierbij worden alle variabelen buiten de chunking-methode strikt constant gehouden.
1. Bepaal de steekproefomvang
Zorg voor een representatieve set van minimaal 100 tot 250 testvragen met geverifieerde bronpassages. Om te berekenen of jouw steekproef statistisch voldoende onderscheidend vermogen biedt, kun je het statistische kader voor testgrootte raadplegen om betrouwbaarheidsintervallen rond je Recall-scores correct te interpreteren.
2. Zet alle overige parameters vast
Houd de volgende factoren identiek over alle testvarianten:
- Het embedding-model en de afstandsmetriek (bijv. cosinus-afstand).
- De vectorindex-configuratie (HNSW-parameters zoals
efSearchenM). - Het aantal opgehaalde resultaten ($k$).
- Het generatiemodel inclusief
temperature=0.0en een vaste seed. - De promptstructuur waarin de chunks aan het LLM worden gepresenteerd.
3. Voer het vergelijkend script uit
Hieronder staat een referentie-opzet in Python om retrieval-statistieken te loggen over verschillende chunking-configuraties:
from dataclasses import dataclass
from typing import List, Set
@dataclass
class RetrievalResult:
query_id: str
retrieved_chunk_ids: List[str]
ground_truth_chunk_ids: Set[str]
def calculate_metrics(results: List[RetrievalResult], k: int = 3):
total_recall = 0.0
total_mrr = 0.0
for res in results:
top_k = res.retrieved_chunk_ids[:k]
hits = [cid for cid in top_k if cid in res.ground_truth_chunk_ids]
# Recall@k
recall = len(hits) / max(1, len(res.ground_truth_chunk_ids))
total_recall += recall
# Reciprocal Rank
rr = 0.0
for rank, cid in enumerate(top_k, start=1):
if cid in res.ground_truth_chunk_ids:
rr = 1.0 / rank
break
total_mrr += rr
count = max(1, len(results))
return {
f"Recall@{k}": round(total_recall / count, 4),
"MRR": round(total_mrr / count, 4)
}
Beslisboom voor chunking-selectie
Nadat de kwantitatieve meetresultaten zijn verzameld, kan de definitieve architectuurkeuze worden vastgesteld aan de hand van onderstaande beslisregels:
- Gestructureerde markdown- of documentkaders: Kies altijd voor een structurele parser indien brondocumenten duidelijke tussenkopjes en tabellen bevatten. De meetbare winst in Context Precision weegt ruimschoots op tegen de iets complexere parsingstap.
- Kleine zinsbrokken met bovenliggende context (Parent-Child / Hierarchical): Wanneer vragen zeer specifieke feiten vereisen maar het antwoord brede context nodig heeft, splits dan in micro-chunks (100 tokens) voor indexering, maar stuur de bovenliggende paragraaf (500 tokens) mee naar de prompt. Dit combineert een hoge MRR met een hoge trouwscore.
- Recursief met dynamische drempel: Voor ongestructureerde proza presteert een recursieve splitser met een overlap van 15% consistent stabieler dan rigide vaste vensters, zonder de computationele traagheid van semantische clustering.
Door splitsingsparameters niet langer op intuïtie in te stellen maar structureel te meten via Recall@k, Context Token Efficiency en trouwscores, transformeer je de chunking-stap van een onzekere gok naar een geoptimaliseerde engineeringkeuze.


