Chunking a mixed corpus
Our knowledge base is 40% PDFs with tables, 30% Confluence pages, 20% source code, 10% support tickets. One chunking configuration is used for all of it and quality is poor everywhere. What do you change?
The constraint. Chunk size is not a hyperparameter to tune globally. It is a consequence of the document's structure, and these four corpora have nothing structurally in common. A fixed 512-token recursive splitter destroys tables, splits functions from their signatures, and merges unrelated tickets.
Per-corpus treatment.
| Corpus | Unit | Failure if you get it wrong |
|---|---|---|
| PDF with tables | Layout-detected block; tables kept whole, serialized to Markdown | A table split across chunks yields rows without headers — the single worst retrieval artifact |
| Confluence | Heading hierarchy, with the heading path prepended to each chunk | Orphaned sections that read as authoritative but lack scope |
| Source code | Syntactic unit: function, class, or module, from a parser | Half a function retrieved is worse than nothing |
| Tickets | Whole ticket, never split; embed a summary, retrieve the thread | Splitting a conversation destroys resolution context |
The pattern underneath. Retrieve small, provide large. Embed a precise unit for matching, then expand to its natural container before it reaches the model — the parent section, the full function, the entire ticket. This decouples matching granularity from grounding granularity, and it removes most of the chunk-size argument.
Also prepend context to every chunk: document title, heading path, and for tables the caption and column headers. A chunk that cannot identify itself cannot be reranked well.
Stack. Docling for PDFs when per-page cost matters and the documents are local; LlamaParse or Reducto when the documents are genuinely messy and the accuracy is worth the invoice. Chonkie for the chunking strategies themselves — token, semantic, recursive, late. Tree-sitter for code, not a text splitter. Unstructured if the format spread is wider than these four.
Where answers fail. Proposing "semantic chunking" as a universal answer. It is a reasonable default for prose and actively wrong for code and tables.