AI Engineering

Chunking Is a Product Decision: How Splitting Changes Answers

Where you cut a document decides which questions a retrieval system can answer. What headings, tables and PDFs need, with a chunk rule by document type.

5 min readBy BizHues Engineering

Working on this?

Talk it through with an engineer.

A 30-minute requirements call, no charge.

Book a call

Consider two engineers indexing the same HR handbook for a manufacturer with plants in Hosur, Pune and Sanand. One build answers leave questions correctly. The other mixes up the casual leave allowance for Pune with the one for Hosur, because the two sections sit a page apart and the split separated each allowance from its plant heading. Same model, same embeddings, same PDF; the only difference is where the text was cut.

The model only ever sees the chunks

A chunk is the unit the index stores and retrieval returns. In a RAG pipeline, the model never sees the handbook. It sees the five or six chunks that came back for this question and nothing else.

If the sentence that answers the question sits across a chunk boundary, the model receives half of it. If the chunk has lost the heading that said which plant it applies to, the model receives a rule with no scope. In both cases it still produces a fluent answer, because producing fluent text from whatever it is given is what it does. The model does not know a heading is missing. It only sees the chunk.

So chunking decides which questions the system can answer well. That makes it a product decision rather than a library setting, and it depends on the documents you hold and the questions people actually ask. We would rather spend a day reading chunks than a week comparing embedding models.

What fixed-size splitting breaks

The simplest splitter cuts every so many characters. It is fast, works on any text, and is the default in most frameworks. It also cuts through sentences, lists and tables, and it drops the heading above the cut.

The same handbook, two splitters
Fixed size
  • Cuts a table across two chunks
  • Separates the allowance from the plant heading
  • Overlap repairs some cuts, never the lost heading
Structure-aware
  • Splits at headings, then paragraphs
  • Keeps a small table whole with its caption
  • Prepends the heading path to every chunk

A structure-aware splitter is not a product you buy. It is a short set of rules written for your documents: where the headings are, what a table looks like once the text is extracted, which files need different treatment. For a handbook like this one it is a morning's work, and it changes the answers more than a model swap would.

Headings, tables and PDFs need their own rules

Headings

Headings carry the context a paragraph assumes. Here is a chunk from the fixed-size build:

"Employees are entitled to twelve days of casual leave per calendar year, credited quarterly."

On its own, that sentence is true for one plant and false for the other two. The structure-aware build stores the same text with its heading path in front:

"HR handbook > Leave > Pune plant > Casual leave. Employees are entitled to twelve days of casual leave per calendar year, credited quarterly."

Prepend the heading path before embedding, so both the vector and the model see it. It costs a few tokens per chunk, and for policies and manuals it is the most effective single change we know of.

Tables

A table row means nothing without its header, and a table split across two chunks cannot be reassembled by the model. Keep small tables in one chunk with their caption and header row. For large tables, such as a shift allowance schedule across grades and plants, write one chunk per row, with each row expressed as column and value pairs and the table title in front.

PDFs

PDF extraction returns text in the order the file stores it, which is not always reading order. Two-column layouts interleave, footers land in the middle of a paragraph, and a scanned circular contains no text at all until OCR runs. Read the extracted text for a sample of files before chunking anything. Nothing downstream can repair a scrambled page.

Overlap and metadata

Overlapping chunks repeat the last few sentences of the previous chunk, so a fact near a boundary appears whole in at least one of them. The cost is a larger index and the chance of retrieving two near-identical chunks for one question, so deduplicate by document and position before sending them to the model. Overlap patches boundary cuts. It does not replace splitting in the right place.

Metadata is what makes a chunk usable after retrieval: document id, version, section path, owner, date, language and audience. Retrieval can filter on these fields, so a question from a Pune employee gets only the Pune policy and only the current version, and the answer can cite a section instead of an unlabelled block of text. Decide the fields before indexing. Adding one later means re-indexing every document, including every circular issued since the handbook was first written.

A chunking rule by document type

Split at the smallest unit a person would quote to answer a question, and attach whatever that person would need to read the quote on its own.

Document type Split at Keep with each chunk
Policies, manuals Headings, then paragraphs Heading path, version
Tickets, chat threads One ticket or thread Product, status, date
Contracts One clause Clause number, parties, dates
Spreadsheets, large tables One row Table title, header row
Long reports Section, then paragraphs with overlap Section path, figure captions

When a document type is not on the list, ask its owner how they look things up in it. If the HR manager says "I search by circular number", the circular is the chunk and its number is metadata.

How chunking goes wrong

The most common mistake is accepting the framework default and never reading a single chunk. The second is judging chunking by reading answers instead of the retrieved chunks. The failure looks like a model problem, a fluent answer with the wrong number in it, so someone goes looking for a larger model when the fix was a heading.

Teams also re-chunk without a saved set of questions, so nobody can say whether the change helped. They apply one splitter to a corpus that mixes contracts, support tickets written in Hinglish and slide decks, each of which needs a different rule. And they forget that any chunking change invalidates the index. Every change means a full re-index and a re-run of the evaluation set, which is a reason to keep that evaluation set ready (the method is in measuring a RAG system).

Read ten chunks before tuning anything

  1. Take ten real questions from the intranet search log or the helpdesk queue.
  2. Run retrieval alone for each and print the chunks that come back.
  3. Read each chunk as the model would, with no document around it, and note what is missing.
  4. Turn each gap into a rule: a heading to prepend, a table to keep whole, a file type to OCR.
  5. Re-index, re-run the same ten, and compare.

The gaps you find in step three are the chunking rules you need to write. In the handbook above, the plant mix-up shows up on the second question.

Share this article
AI Engineering

Talk to an engineer

Have a requirement worth building?

Book a 30-minute call with an engineer, at no charge. Tell us the problem and the systems involved, and you leave with questions answered and a suggested first step, not a sales deck.