Chunking is the highest-leverage, least-measured decision in most RAG stacks. This playbook runs a matrix experiment — strategy × size × overlap — scored on retrieval and answer metrics against the pb-21 grounding set, so the chunker you ship is the one that won, not the one the tutorial used.
Tier: Core · Workflow area: RAG & Retrieval Engineering
context_recall/context_precision in pb-21 — both frequently trace to chunk boundaries slicing answers in half.langchain-text-splitters (or LlamaIndex node parsers), chonkie or a semantic splitter, Docling for layout-aware splitting of PDFs.Define the matrix. Strategies × parameters, pruned to what your corpus can use:
| Strategy | Sizes (tokens) | Overlap | Notes |
|---|---|---|---|
| Recursive (char/sep-aware) | 256 / 450 / 800 | 10%, 20% | The default to beat; ~400–512 + 10–20% overlap is the strong 2026 prior |
| Sentence-window | 3–5 sentences, window ±2 | — | Embed small, retrieve with neighbors attached |
| Semantic (embedding-drift boundary) | breakpoint percentile 90/95 | — | Splits where topic shifts; costs an embedding pass to chunk |
| Layout-aware (headings/tables) | section-bounded, max 800 | — | Requires Docling/unstructured structure from pb-18 |
Keep the total under ~12 configurations; beyond that you are fishing.
Hold everything else constant. Same embedding model, same top-k, same generator, same prompts as the baseline. One variable class per experiment — this is the same discipline as pb-20, applied to retrieval.
Re-map gold passages per configuration. The grounding set references document spans; a chunk is "gold" if it overlaps a gold span by ≥50% of the span. Automate this mapping — hand-relabeling per config is how these benchmarks die.
def is_gold(chunk, span): # both carry (doc_id, start_char, end_char)
if chunk.doc_id != span.doc_id: return False
inter = min(chunk.end, span.end) - max(chunk.start, span.start)
return inter / (span.end - span.start) >= 0.5
Score the matrix. For each config: recall@5, MRR, context_precision/context_recall + faithfulness via RAGAS, plus two often-decisive operational columns — index size (chunk count) and mean retrieved-context tokens per query (your per-query cost driver).
Check the context cliff. Add one deliberately oversized config (~2,500-token chunks). Published 2026 benchmarks and internal results consistently show retrieval quality falling off a cliff around this size — reproduce it on your corpus so the team stops proposing "just use bigger chunks."
Read results by document type, then decide. Slice metrics by corpus segment (prose vs tables vs code). It is common — and fine — to ship two chunkers routed by document type. Promote the winner only if it beats the baseline scorecard outside the bootstrap CI; ties go to the simpler strategy.
Semantic and layout-aware chunking win most often on heterogeneous, structured corpora (manuals, contracts, mixed reports) — one 2026 study measured topic-aligned chunking preferred in 87% of cases against a fixed-size baseline — but on homogeneous prose, well-tuned recursive splitting is regularly within noise of them at a fraction of the complexity.
RecursiveCharacterTextSplitter.from_tiktoken_encoder(...), SemanticChunker; LlamaIndex:SentenceWindowNodeParser, SemanticSplitterNodeParser, HierarchicalNodeParser (pairs with pb-25's parent-document retrieval).