RAG Knowledge Base Ingestion in Practice: How Parsing and Chunking Set the Ceiling on Retrieval Quality (2026 Edition)
Seven in ten "retrieval is inaccurate" cases trace back to ingestion, not the model. This article breaks down the full RAG ingestion pipeline: parser selection by document type (table structure preservation, OCR layout analysis, page-noise removal), the three-do/three-don’t cleaning layer, chunking strategy as a per-document-type decision table (heading hierarchy / clause-level / task-based / parent-child chunks), a three-number ingestion acceptance test (length distribution / number-integrity sampling / 20-question trial retrieval), three real project postmortems, and a copy-paste pre-ingestion checklist.【View the pre-ingestion checklist】
Introduction: The AI Misquoted a Contract Clause — Because Parsing Dropped a Column
Last month we took a firefighting engagement from a legaltech company: their contract Q&A knowledge base (12,000 historical contracts plus clause templates) had been live for a quarter, and legal staff were reporting that “answers are always half a sentence, and tables come back scrambled.”
The team’s first reaction was the usual one — suspect the model, suspect the retrieval. They swapped the embedding, tuned top-K, added a reranker. None of it worked.
We spent one day on the ingestion layer and found three problems:
- The penalty table in the contracts had been parsed into individual cells — each cell became its own chunk, with no column names and no row labels;
- Fixed 500-word chunking had split clause 4.2.1 into two chunks — the first half in one, the second half in the next, and retrieval hit whichever half by luck;
- Running headers and footers (“page 12 of 35 / Confidential”) had been ingested as knowledge — a batch of chunks was pure page noise.
We fixed ingestion and touched nothing downstream — no model change, no retrieval parameter change. Recall@5 on our 20-question trial set went from 58% to 89%.
This is not a rare case. Across the RAG projects we have delivered, roughly seven in ten “retrieval is inaccurate” cases trace their root cause to ingestion — lost structure in parsing, naive chunking, missing metadata. And the pattern is always the same: teams put 80% of their effort on the embedding-to-generation side and treat ingestion as “upload the files.”
The ceiling on retrieval quality is set at ingestion time. The model only determines how well it reads; ingestion determines what there is to read.
This article breaks down the full ingestion pipeline: parsing by document type, the three-do/three-don’t cleaning layer, chunking as a per-document-type decision table, the three numbers that make up pre-ingestion acceptance, plus three real project postmortems and a pre-ingestion checklist you can copy.
I. First, Get the Decomposition Right: Ingestion Is Four Stages, Not “Upload Files”
Ingestion is not one step. It is four stages, each with its own acceptance target:
Raw document → (1) Parse → (2) Clean → (3) Chunk → (4) Metadata → Vector store
| Stage | Responsibility | Typical failure | Downstream symptom |
|---|---|---|---|
| (1) Parse | Extract text and structure (headings/tables/lists) from PDF/Word/scans | Tables shattered, OCR garble, page numbers mixed in | ”Cells without column names” in results |
| (2) Clean | Remove page noise, normalize formats, merge broken paragraphs | ”Page 12 of 35 / Confidential” ends up in the base | Noise dilutes retrieval hits |
| (3) Chunk | Cut into self-contained chunks per document type | Fixed-size cutting splits clauses mid-sentence | Answers are always half a sentence |
| (4) Metadata | Attach source/number/page/permission to every chunk | Content without provenance | No filtering, no citation, no audit trail |
One stage failing poisons the whole chain: if parsing loses the tables, the smartest chunking is cooking with no rice; if chunking splits a clause, the most precise retrieval still serves a half-sentence. So each stage needs independent acceptance — you cannot wait until “the AI gave a wrong answer” and then debug upstream from the model, by which point you cannot tell which stage failed.
This is the first difference from how most teams work: they have launch acceptance (ask a few questions after go-live) but no ingestion-layer acceptance (the three numbers, 30 minutes, before data enters the base). The latter stops problems before they are stored; the former can only react after they become user complaints.
II. Parsing: Pick the Tool by Document Type, Not by “Most Accurate”
1. Classify Your Documents First
Choosing a parser starts with knowing what you hold. Most “parsing blew up” cases have one root cause: one tool applied to all document types.
| Document type | Characteristic | Parsing requirement | Typical scenario |
|---|---|---|---|
| (1) Digital documents | PDF/Word with text layer (text is selectable) | Structure extraction (headings/tables/lists) | Policies, Word contracts, born-digital PDFs |
| (2) Scanned documents | No text layer, OCR required | OCR + layout analysis + text-layer reconstruction | Scanned contracts, paper archives, hand-annotated files |
| (3) Table-heavy documents | Tables exceed 50% of the document | Table structure preservation (row/column relations must survive) | Financial statements, spec sheets, quotes, data appendices |
A single document can belong to multiple classes (scanned and table-heavy) — the highest-requirement class is what drives tool selection.
2. Tool Division by Type
The actual 2026 division of labor among mainstream tools (pull 20 of your own documents and benchmark them before deciding — never trust the public benchmark):
| Tool | Strength | Fits | Caveat |
|---|---|---|---|
| Unstructured | Broad format coverage, fast to integrate, HF ecosystem | Digital-document-dominated bases | Weak on complex table preservation |
| Docling | Strong layout analysis + table reconstruction, Markdown output | Scans mixed with tables | Moderate speed |
| MinerU | PDF-specialized; high table/formula/layout fidelity | Table-heavy or poor-quality scans | Strong on CJK OCR |
| PaddleOCR | Pure text recognition, high CJK accuracy | Text layer only (structure handled downstream) | No table structure output |
Three selection rules:
- Benchmark on your own 20 documents, not on public benchmarks — the public leader and your leader are frequently different tools. Three measured metrics: parse completeness (is everything that should be extracted present), structure preservation rate (are heading levels and table rows/columns correct), parse failure rate (how many need human intervention).
- Do not build your own parser — unless you are doing research. A custom parser costs 10x the tool in maintenance, and the tooling generation is six months. The legitimate place for custom code is the rule-patch layer (number recognition, specific header merging, running-header/footer removal rules) built on top of an off-the-shelf tool’s output, never a replacement for it.
- Score OCR confidence on scans — OCR output carries confidence scores; chunks below the threshold (typically 0.85) get flagged for human review instead of being ingested. Low-quality OCR chunks in the base surface as “the model occasionally answers with garbled characters or wrong digits” and are extremely hard to trace.
III. Cleaning: Three Dos, Three Don’ts
Between parse output and ingestion, the cleaning layer does three things and refuses three.
The three dos
① Remove page noise. Running headers/footers (page numbers, document IDs, confidentiality marks), repeated boilerplate (“final interpretation rights reserved by…”), and bookmarked table-of-contents entries are structure in the source document and pure noise in the base. Rule: regex-remove short lines that appear on more than 10% of pages and carry no business information. The removal rules live in code with a sample archive — “we think we cleaned it” is not reproducible and therefore not acceptable.
② Merge broken paragraphs. Parsers split a single sentence at page boundaries or visual blocks. The cleaning layer merges heuristically: previous block does not end in terminal punctuation/number, and the next block starts with a lowercase or ordinary character, merge them. For contracts, add number-break repair: when 4.2 and .1 Party A shall… land in separate blocks, reassemble 4.2.1 by number rule.
③ Normalize formats. Full-width/half-width characters, line endings, and invisible characters (zero-width spaces are extremely common in OCR output) get normalized. Zero-width characters are the hidden killer: invisible to the eye, yet they split “the same passage” into near-duplicate chunks with different embeddings — it surfaces as “the same content keeps getting retrieved twice.”
The three don’ts
- No aggressive content rewriting — cleaning deletes, it never rewrites. Rewriting “Clause 4.2” to “Penalty clause” or “polishing” colloquial policy text into formal prose changes the source semantics; RAG’s value is citing the real document, and a modified document cannot be traced back.
- No content-based pruning — “this paragraph looks unimportant” is a human judgment, not a cleaning rule. Deletion happens only by format rules (page numbers, repeated boilerplate), never by semantic judgment — semantic filtering belongs downstream in metadata filters, not hard-coded at ingestion.
- No one-time whole-base “cleaning mega-project” — cleaning rules evolve as document types do (new types bring new noise). Version the rules:
cleaning_rules_v2applies to newly ingested documents only; re-cleaning the old base is a full rebuild (dual-index cutover, see the freshness article).
IV. Chunking: One Decision Table per Document Type — “Self-Contained” Beats “Word Count”
1. The Core Principle: The Smallest Self-Contained Semantic Unit
The standard for a chunk is not “how many words” but “is it self-contained on its own” — self-contained = readable without context, and quotable directly as an answer fragment. Fixed-size chunking (one cut every 500 words) is the anti-pattern, because it is blind to semantic boundaries: when the front half of clause 4.2.1 and the back half land in separate chunks, retrieval hits the front half and the model receives “Party A shall” — with no “shall what, within how many days, do what.”
2. The Per-Type Chunking Decision Table
| Document type | Chunk unit | Typical size | Chunk header (required) |
|---|---|---|---|
| Policies / regulations | Heading hierarchy (H2/H3 sections) | 300–800 words | Doc title > section path |
| Contracts | Clause number (down to 4.2.1 level) | 100–400 words | Contract name + clause number |
| Manuals / SOPs | Task (one complete procedure step) | 200–600 words | Manual name > task name |
| FAQ / Q&A | One question + one answer | 50–300 words | The question verbatim as header |
| Tables | Small table whole / large table by row, each row carrying headers | By row count | Table name + section |
| Meeting minutes / reports | Agenda item / conclusion block | 200–500 words | Meeting name + date + item |
Four general rules:
- Header on every chunk: document title plus section/clause path at the top of each block. This is not aesthetics — it is the foundation of citation provenance (“per Contract XX, clause 4.2.1”) and part of the retrieval signal (when a user asks about penalties, “Clause 4.2.1 Liability for Breach” in the header is itself highly relevant text).
- Overlap of 50–100 words, or one semantic sentence: adjacent chunks overlap so a key sentence is not orphaned exactly at the cut point. Clause-level contract chunking needs no overlap (clauses are naturally self-contained); overlap mainly serves long sections cut by heading.
- Hard size boundaries: under 100 words, the chunk likely lacks context — merge with its predecessor; over 1000 words, precision is likely diluted — re-cut at the next-level boundary (paragraph/subheading). These are rules, not suggestions: encode them as validation in the chunker code and fail the build on violations.
- Parent-child chunking (advanced): small chunks (clauses/paragraphs) win retrieval; the parent chunk (whole section/whole task) supplies generation context. Precision and completeness both survive; the price is two indexes. Worth it when the base is “short clauses, long context” (contracts, regulations); unnecessary for FAQ-dominated bases.
3. Why Clause-Level Chunking Is the Winning Move for Contract Bases
Most teams process contracts with “500 words + 50 overlap” — for contracts, that is slicing every clause into 1.7 pieces. In legal settings, quoting the wrong clause is a fatal error (answering with the rights in 5.1 when asked about the obligations in 4.2), and clause-level chunking makes each chunk correspond exactly to one clause number:
- A retrieval hit is a complete clause, never a half;
- Citation provenance is the clause number itself;
- Contradiction detection gets a natural version key (the same clause number across contract versions makes diffs trivial).
Aligning the chunk unit with the business structure of the document is the highest-ROI step in the entire pipeline — higher ROI than swapping embeddings, tuning top-K, or adding a reranker. Those downstream knobs solve “does it read accurately”; chunking solves “is what it reads a complete thing” — and the latter is the precondition for the former.
V. Metadata: The Six Field Classes That Must Be Attached at Ingestion Time
Chunking decides “what each block is”; metadata decides “where each block came from and whether it may be used.” Metadata is not a later phase — retrieval-time filtering, citation provenance, and the entire deletion chain all depend on fields attached at this exact moment, because a “content-only chunk” in a vector store is the hardest thing to backfill (backfilling metadata means re-parsing the original documents).
Every chunk carries six field classes:
| Field | Purpose | What breaks without it |
|---|---|---|
source_id | Stable document identity (invariant under content/file-name change) | Delete/update chains break — “which chunks belong to this document” becomes unanswerable |
doc_title + section_path | Document name + section path | Citations cannot be traced (“per Contract XX, clause 4.2.1” cannot be written) |
chunk_type | clause / paragraph / table_row / faq / code | No per-type retrieval strategy (table chunks need header-anchored recall, FAQ chunks need whole-block citation) |
number (clause/item number) | Clause numbers (4.2.1) | Number retrieval (“what does clause 4.2 say”) fails; contradiction detection loses its comparison key |
page / page_range | Original page number(s) | Human review cannot locate the source; provenance chain breaks at the last mile |
created_at + permission marker | Ingestion time + visibility scope | Time filtering and permission filtering fail (see the access-control article: permission filtering depends on fields attached at ingestion) |
Two hard rules:
- Freeze the metadata schema before ingestion — a schema change means a full re-ingestion of the base. Spending half a day with legal/business confirming “what will we ever filter by” (department? confidentiality level? effective year?) before ingestion is two orders of magnitude cheaper than reworking it after.
- The
numberfield is the lifeline of contract/regulation bases — it bridges semantic retrieval and exact retrieval: “penalty clause” goes through vectors, “clause 4.2.1” goes through exact number matching, and the two merge at the retrieval layer. Withoutnumber, number-based questions can only be “guessed” by embeddings — and embeddings have very poor discriminative power for identifiers.
VI. Ingestion Acceptance: Three Numbers, Thirty Minutes
After ingestion completes and vectors are written, before retrieval is opened, run three numbers. These are the acceptance criteria for the ingestion layer — put them in the project acceptance document, because most RAG projects have only generation-layer acceptance (ask questions after launch, score the answers) and zero ingestion-layer acceptance, which is why “retrieval is inaccurate” always ends up blamed on the model.
Number 1: The chunk-length histogram
Plot the character length of every chunk and inspect three regions:
- Left tail (under 50 characters): batches of them mean incomplete cleaning — page numbers, bare clause-number lines, and empty headings became standalone chunks;
- Right tail (over 2000 characters): batches mean large blocks were never cut — long sections or large tables entered whole, and retrieval precision is dilution-guaranteed;
- Distribution shape: a healthy base shows one or two clear peaks (the dominant chunking units). Three or more scattered peaks mean chunking was not done per document type — one size for everything.
Pass/fail: main peak inside the target range (per the decision table), both tails under 5%. If it fails, go back to parsing/chunking. Do not proceed.
Number 2: Number-integrity sampling
Randomly pull 20 numbered clauses/items from documents that carry numbers, and verify by hand that each number is self-contained within a single chunk (number plus full content in the same chunk).
- Pass/fail: 18+ of 20 (90%) self-contained.
- Why this is the most critical number: number breaks are the direct cause of “half-sentence answers,” and they cannot be detected at the generation layer — given a half-clause, the model will do its best to complete it, the answer reads fluently, but the citation is wrong. Only inspecting the chunks themselves reveals it.
- While at it: verify the chunk header (doc title + section path) is genuinely present at the top of each block (5 chunks is enough).
Number 3: 20-question trial retrieval (recall@5)
Take 20 real high-frequency questions from the business side (the ones that will definitely be asked after launch), annotate each with the document + clause a correct answer must hit, and measure recall@5 (is the correct target in the top-5 results).
- Pass/fail: 70%+ → proceed to generation-layer integration; 50–70% → back to ingestion, triage each failure (parse loss? broken chunk? wrong metadata?); under 50% → the per-type chunking strategy is wrong, back to Section II.
- The critical discipline: at this step, when it fails, do not tune the model or retrieval parameters — touching downstream knobs before ingestion is accepted is building the second floor on sand. The “gains” you tune in will all evaporate once ingestion is fixed (we watched a team tune recall from 58% to 66%, then fix the ingestion layer — and land back at 58%. They had been tuning noise).
All three numbers passing is what makes the ingestion layer accepted. This is the only step in a RAG project where 30 minutes can stop 80% of production problems — the cost is nearly zero (one script + 20 annotated questions), and it is the precondition for every downstream tuning session.
VII. Three Real Projects, Ingestion-Layer Postmortems
Project A: Legaltech contract base (12,000 contracts + clause templates — the introduction case)
- Failure: a generic parser on tables shattered the penalty table into nameless cells; fixed 500-word chunking split clauses in half; running headers/footers were never cleaned. Swapping embeddings, tuning top-K, adding a reranker — none of it worked.
- Fix: table-structure-preserving parser (penalty table rebuilt whole) plus a rule-patch layer (page-noise regexes, clause-number-break merging); clause-level chunking (down to 4.2.1, header carries contract name + clause number);
numbermetadata field added. - Numbers: recall@5 on the 20-question trial set 58% → 89%; zero changes to model or retrieval parameters; legal’s “wrong clause quoted” feedback went to zero.
- Lesson: downstream parameters cannot heal upstream damage — with recall stuck at 58%, the team burned three weeks on embeddings and the reranker. The ingestion layer took one day.
Project B: Manufacturing QC knowledge base (2,000+ process standards, mostly scans, heavy parameter tables)
- Failure: scans through a generic parser — OCR text-layer quality was uneven, and low-confidence chunks were ingested anyway. The symptom: “the AI occasionally answers a parameter with a shifted digit” (0.05 answered as 0.5). Users could not tell whether the model or the base was wrong, so every complaint landed on the model.
- Fix: parser with layout analysis for scans + an OCR confidence threshold (under 0.85 → human-review queue; 7% of the first 1,200 documents entered the queue); parameter tables chunked “small tables whole, large tables by row with headers on every row”; zero-width-character removal added to cleaning (the hidden source of duplicate chunks from OCR output).
- Numbers: parameter-question accuracy 71% → 93% (after the review queue was worked); “occasional garbled characters” complaints went to zero.
- Lesson: the hidden cost of a scanned-document base is long-term contamination by low-confidence chunks — a 7% share of low-quality chunks expands at the user end into the overall impression “this AI is not trustworthy.” A confidence threshold plus a human-review queue is not polish; it is the standard equipment of any scanned base.
Project C: SaaS help-center base (FAQ-dominated, 15,000 Q&A entries, Markdown source)
- Failure: the team “gold-plated” — a full PDF parsing chain with layout analysis applied to Markdown FAQs, 400 ms per entry, 11 hours for a full rebuild. Ninety-five percent of the documents were clean, structured Markdown, and 90% of the parsing chain’s capability was wasted.
- Fix: per-type divide-and-conquer — Markdown/FAQs go through a lightweight direct reader (heading/QA blocks cut directly); only the supplementary PDFs use the full parsing chain; one Q&A per chunk, question verbatim as header.
- Numbers: ingestion time 11 h → 20 min; zero chunking failures; update cadence went from monthly to daily (ingestion became 30x cheaper, and only then could updates keep up).
- Lesson: parsing-chain complexity must match document-type complexity — most bases do not need the heaviest parser. “Using the heaviest hammer on the lightest nail” is slow and expensive, and it makes the update pipeline too costly for anyone to run (update cadence determines knowledge freshness — see the freshness article).
The common thread across all three: ingestion-layer problems can never be fixed downstream (model/retrieval) — they must be fixed at ingestion. The only variable is how long it takes to discover them: Project A took three weeks; Project B’s review mechanism kept the problem from reaching users at all; Project C avoided it at design time. The earlier the discovery, the lower the price.
VIII. Pre-Ingestion Checklist (Copy It)
| # | Check | Y/N | Note |
|---|---|---|---|
| 1 | Documents classified by type (digital / scanned / table-heavy); parser chosen per type | One tool for all types = failure precondition | |
| 2 | Benchmarked on 20 of your own documents (completeness / structure / failure rate) | Public benchmarks do not count | |
| 3 | OCR confidence threshold + human-review queue for scans | Hard-ingesting low-confidence chunks = long-term contamination | |
| 4 | Table structure preserved (small tables whole / large tables by row with headers) | Tables are 40–60% of enterprise-base failures | |
| 5 | Page-noise removal rules in code (regex + sample archive), not by hand | ”Looks clean” is not reproducible | |
| 6 | Zero-width / invisible characters removed | The hidden source of duplicate chunks | |
| 7 | Broken-paragraph / broken-clause-number merge rules exist | Half a clause = half an answer | |
| 8 | Chunking done per document type (decision table), not one fixed size | Chunk unit aligned with business structure | |
| 9 | Every chunk carries a header (doc title + section/clause path) | Dual value: provenance + retrieval signal | |
| 10 | Hard size boundaries enforced in code (under 100 words merge / over 1000 re-cut) | Rules, not suggestions | |
| 11 | Metadata schema frozen before ingestion (six field classes present) | Schema change = full re-ingestion | |
| 12 | Contract/regulation base has the number field | Exact number retrieval + contradiction-detection key | |
| 13 | Acceptance three numbers run: length histogram + 20-clause sampling + 20-question recall@5 | Below bar = no generation-layer integration | |
| 14 | Ingestion time acceptable (update cadence = f(ingestion cost)) | Expensive ingestion = nobody updates = stale base |
IX. When the Ingestion Layer Should Be Treated as an Engineering Budget
Some cold water — the ingestion layer is not “write a script.” In three situations a homegrown pipeline will probably fail:
- More than 3 document types, each with special structure (contracts + financial statements + drawings + mixed scans): per-type parsing rules, chunking units, and metadata schemas all differ; the divide-and-conquer effort far exceeds what “we’ll script it quickly” implies. At that point the ingestion layer is a subproject with its own budget, not a side script;
- Scanned documents over 30% and poor quality (phone photos, low-resolution scans, handwritten annotations): layout analysis + confidence management + a human-review process is a complete mechanism, not an OCR API call;
- Ingestion cost determines update cadence: if a full re-ingestion takes over an hour with no incremental mechanism (source_id + content hash), the base will be stale within 3 months — what you need then is ingestion-pipeline engineering (incremental indexing, idempotency, dual-index cutover; see the freshness article).
The decision rule: 2 or fewer document types + mostly digital + full-base ingestion under 1 hour — building it in-house is fine. If any one condition fails, budget the ingestion layer as engineering.
Further reading:
- Enterprise RAG Knowledge Base in Practice — the full pipeline methodology: this article is the deep dive into its ingestion side (parsing/cleaning/chunking/metadata)
- RAG Knowledge Base Freshness in Practice — ingestion quality sets the initial freshness: how source_id / idempotency / incremental indexing take over what this article produces
- RAG Knowledge Base Access Control in Practice — permission filtering depends on the metadata fields attached at ingestion: the same schema serves both
- Vector Database Selection Guide — the downstream: which store the chunks go into, HNSW parameters and filter performance
- Data Pipeline Engineering in Practice — idempotency / incremental / full-rebuild, the general methodology: an ingestion pipeline is a data pipeline
- LLM Evaluation in Practice — how the three ingestion numbers divide labor with generation-layer evaluation: recall@5 means different things in the two layers
- Long-Context LLMs vs RAG — the alternative ingestion route: whole-document injection vs chunked retrieval, and the cost decision tree
Need ingestion-layer design for your RAG base (parser selection, chunking rules, metadata schema) — or an ingestion-layer health check for an existing one? Contact us for a free assessment: bring 20 real documents and 20 high-frequency questions, and in 30 minutes we will run the three ingestion numbers and show you how many mines are waiting on the ingestion side of your current base.
FAQ
Which parser should I use? Unstructured vs Docling vs MinerU?
Classify your documents first, then pick a tool: (1) digital documents (PDF/Word with a text layer — text is selectable) use Unstructured or Docling, fast and cheap with adequate structure preservation; (2) scanned documents (no text layer, OCR required) need MinerU or Docling with layout analysis, where the core capability is layout detection plus table reconstruction — PaddleOCR fits when you only need a clean text layer; (3) table-heavy documents (financial statements, spec sheets, data appendices) should prioritize tools with strong table-structure preservation (MinerU / Docling) — tables are where generic parsers fail first. The selection criterion is not benchmark score: pull 20 real documents from your own corpus and measure three numbers — parse completeness, structure preservation rate, and parse failure rate. If none of them pass, consider rule patches (number recognition, header merging), not a custom parser — that is research-grade engineering.
How big should chunks be? 200 tokens? 500? 1000?
There is no universal number. The right approach is to define chunk size from the smallest self-contained semantic unit of each document type: policy/regulation documents by heading hierarchy (300–800 words per chunk), contracts by clause (down to 4.2.1, typically 100–400 words), operation manuals by task (one complete procedure step, 200–600 words), FAQs one question-and-answer per chunk. Two hard boundaries: a chunk under 100 words likely lacks context (retrieval hits but the answer is a fragment), over 1000 words likely dilutes retrieval precision (long chunks spread similarity across irrelevant content). The real question is not how many words, but is this chunk self-contained — meaning you can read it standalone and quote it directly as an answer fragment without knowing what the previous sentence said.
Tables come back with headers and data separated — I get rows of numbers with no column names. How do I fix that?
Three steps: (1) parsing layer — use a table-structure-aware parser (MinerU / Docling) that emits Markdown tables instead of scattered text; (2) chunking layer — small tables (under ~15 rows) stay whole, with the table title/context in the chunk header; large tables chunk by row, but every row chunk must carry the table header (row data without column names is meaningless on its own); (3) metadata layer — table chunks carry table name, section, and page number. The most common failure mode is a generic parser splitting a table into one-cell-per-chunk, so retrieval returns a cell with no column name and no row label — no model can infer that this column is unit price. In enterprise knowledge bases tables account for 40–60% of retrieval failures; fixing table handling saves far more effort than tuning retrieval parameters.
How do I validate parsing/chunking quality before launch?
Three numbers, runnable in 30 minutes before ingestion: (1) a histogram of chunk lengths — batches of abnormally short chunks (under 50 characters) or abnormally long ones (over 2000) mean incomplete cleaning (page noise) or unsplit large blocks; (2) number-integrity sampling — randomly pull 20 numbered clauses and verify each clause is self-contained within a single chunk (a clause number split across chunks is the #1 retrieval killer); (3) 20-question trial retrieval — run 20 real high-frequency questions and check recall@5 after ingestion completes; below 70%, do not start tuning the generation layer, go back to ingestion to locate the cause. These three numbers constitute ingestion-layer acceptance. Most RAG projects only have generation-layer acceptance (ask questions after launch and score answers), so "retrieval is inaccurate" forever gets blamed on the model.
Our knowledge base is already live and the chunking strategy is wrong. Can we change it?
Yes, at a price. Chunking strategy is a first-class decision: changing it means re-chunking and re-embedding every document — one full re-ingestion (use dual-index cutover if the embedding model is unchanged, see the freshness article). A small base (under 10k chunks) can run overnight; a large base (millions of chunks) needs a low-traffic window plus dual-index switch, never during peak load. The deeper lesson: chunking strategy should be decided before ingestion, based on the document-type distribution — look at what the Top 20 documents of your base actually are (contracts? policies? manuals?) and set chunking rules per type, rather than one size-500 rule for the whole base. The cost of deciding once is zero; the cost of changing once is a full-base rebuild.
This article comes from AI Enable Harness front-line delivery practice. Need a similar system or optimization service?
Subscribe to Updates
Get notified when new articles are published. No spam, occasional updates only.
Subscribe →