M06 · Document ingestion and chunking for RAG06-0122 min read

Lesson 37 of 106 · Module 7 of 14 · Week 3

Threads:The measurement threadThe infrastructure thread

Document parsing for RAG: PDFs, tables, and silent failures

Document parsing is the RAG stage that converts a file into plain text a machine can embed, and it is the only stage in the pipeline whose failures produce no error message. A parser that silently drops a scanned page, scrambles a two-column layout, or flattens a table into a row of orphaned numbers still returns a string, still embeds cleanly, and still gets indexed — so the corpus looks complete while the answers are wrong.

01

What document parsing for RAG is

Document parsing for RAG is the extraction of a machine-readable text representation from a source document, together with enough structure to make that text retrievable — reading order, headings, table boundaries, and page provenance. It is a lossy conversion by nature. The question is never whether you lose information but which information you lose and whether you noticed.

It helps to be precise about the three distinct things a parser is doing at once:

  1. Character recovery — getting the actual glyphs out. For a natively generated PDF this is a lookup in an embedded font map. For a scanned page it requires optical character recognition (OCR), because there are no characters in the file at all, only pixels.
  2. Reading-order reconstruction — deciding what sequence those characters belong in. A PDF stores text as positioned draw operations, not as a stream of sentences, so "the order the text appears in the file" and "the order a human reads it" are different orders that happen to coincide for simple single-column documents.
  3. Structure preservation — retaining the relationships that made the text meaningful: this number belongs to that column header, this paragraph sits under that section heading, this footnote attaches to that sentence.

Most parsing tutorials only do the first. Production RAG failures are overwhelmingly in the second and third.

The official NCA-GENL blueprint touches this directly. Objective 1.4 is "Curate and embed content datasets for RAGs" — curation is exactly this work, and it precedes embedding in the wording. Objective 2.3, "Conduct data analysis under the supervision of a senior team member," and the Data Analysis module's scope statement — "inspecting, cleansing, transforming, and modeling data" — put inspection and cleansing squarely in the tested territory. Objective 4.4, "Identify system data, hardware, or software components required to meet user needs," is where "do I need an OCR component in this pipeline?" lives. [OFFICIAL]

02

How document parsing works: text layers, layout analysis, and OCR

The mechanism is worth understanding in three tiers of depth, because the exam tests the first tier hard, the second tier occasionally, and the third tier almost never.

L1 — A PDF is a drawing, not a document

The single most useful intuition: a PDF is closer to a set of printing instructions than to a text file. Inside it are operators that say, in effect, set font F1 at 11 points, move to coordinate (72, 684), draw the glyphs "Quarterly", move to (128, 684), draw the glyphs "revenue". There is no paragraph object. There is often no space character — the space between two words can be a coordinate jump rather than a glyph. There is no notion of "this is a table"; a table is horizontal and vertical lines drawn near some text.

A parser therefore has to infer the document from the drawing. Every inference is a place where it can be wrong without knowing it. Word documents and HTML are structurally better off — they carry real paragraph, heading, and table elements — which is why format matters enormously to parsing quality and why "we support PDF" is a much weaker claim than it sounds.

L2 — The four-stage parsing mechanism

A capable document parser runs roughly these stages, and you should be able to name them:

StageWhat it doesWhat breaks it
Text-layer extractionReads embedded glyphs and their coordinates directly from the fileScanned pages have no text layer; broken font maps produce garbage characters
Layout analysisGroups positioned glyphs into lines, lines into blocks, blocks into a reading orderMulti-column layouts, sidebars, headers, footnotes, rotated text
OCR fallbackRuns optical character recognition on page images where no text layer existsLow-resolution scans, handwriting, skew, stamps over text, poor contrast
Structure extractionRecovers tables, headings, lists, and figure captions as distinct objectsBorderless tables, merged cells, multi-page tables, nested headers

Two things about this table matter more than the rest. First, OCR is a fallback, not a default — running OCR on a page that already has a clean text layer usually makes the text worse, not better, because OCR introduces recognition errors where none existed. Second, structure extraction is a separate capability from character recovery, and a parser can be excellent at one and useless at the other. A PDF library that gets every character right and returns a table as a single run-together line has recovered the characters and destroyed the meaning.

L3 — Reading order and the coordinate model

At the deepest tier: layout analysis is a geometry problem. The parser has a set of text blocks each with a bounding box, and it must produce a linear sequence. Common heuristics sort by vertical position then horizontal, which is correct for single-column prose and catastrophically wrong for two-column layouts — it produces "left column line 1, right column line 1, left column line 2, right column line 2", interleaving two unrelated arguments sentence by sentence. Better parsers detect column boundaries first (by finding vertical whitespace gutters that persist down the page) and then read each column fully before moving on.

You do not need to implement this for the exam. You need to recognise the symptom: retrieved chunks that read as grammatical fragments spliced together, where every other clause belongs to a different topic. That symptom is a reading-order failure, not an embedding failure, and no embedding model or reranker fixes it.

03

Native PDF vs scanned PDF vs HTML vs DOCX: what a parser can recover from each

This comparison is the highest-value asset in the lesson, because scenario questions describe a document type and ask what the pipeline needs.

Source formatCharacter recoveryReading orderTable structureComponent you needCharacteristic silent failure
Natively generated PDF (exported from a word processor)Reliable — glyphs and font maps are embeddedInferred; good for one column, fragile for twoInferred from ruling lines and alignmentPDF text extractorTwo-column interleaving; header/footer text injected mid-paragraph
Scanned PDF (page images, no text layer)Requires OCR; accuracy varies with scan qualityInferred from OCR output geometryVery fragileOCR engine plus layout analysisReturns an empty string. The page silently contributes nothing to the index
Hybrid PDF (some pages native, some scanned)Mixed per pageMixed per pageMixed per pagePer-page detection, then conditional OCRPartial corpus: chapters 1–4 index, chapter 5 vanishes
HTML web pageReliable — text is textExplicit in the DOM, but polluted by navigation, cookie banners, and boilerplateExplicit table elements, usually cleanHTML parser plus boilerplate removalNavigation menus and cookie notices become the most-repeated text in the corpus
DOCX / ODTReliableExplicit paragraph orderExplicit table objectsOffice-format readerTracked changes, comments, and hidden text extracted as if they were body text
Spreadsheets (XLSX / CSV)ReliableCell order is explicit but semantically ambiguousNative, but a sheet is not proseTabular reader plus a serialisation choiceA grid flattened into a sentence, losing which value belongs to which column
Slide decks (PPTX)ReliableWeak — slides are spatial, not linearSparsePresentation readerText boxes emitted in creation order rather than visual order; speaker notes silently merged with slide text
Email (EML / MSG)ReliableExplicitN/AMail parser plus quote strippingQuoted reply chains duplicate the same text dozens of times across the corpus

The row that decides architectures is the scanned PDF. Every other format degrades; a scanned PDF disappears. And because a corpus is usually assembled from whatever a business already has, hybrid corpora are the norm, not the exception — a policy archive spanning fifteen years will have native exports for recent documents and scans of the older ones.

04

Worked example: auditing a parser over a 400-page manual

Here is a constructed audit — the numbers below are invented for teaching and are not measured results — that shows the shape of the check you should actually run. Constructed scenario.

Suppose you ingest a single product manual: 400 pages, mixed content, exported to one PDF by a documentation team that scanned in three appendices from a 2009 printed edition.

text
Ingestion audit — constructed example, not measured

Source document
  pages                                 400
  pages with an embedded text layer      356
  pages that are images only              44   (the three scanned appendices)

Parser output, run 1 (text extractor only, no OCR)
  pages producing >50 characters         356
  pages producing 0 characters            44
  total extracted characters         812,000
  estimated tokens (chars / 4)       203,000

  → 11% of pages contributed nothing.
  → No error was raised. Zero exceptions. Exit code 0.

Parser output, run 2 (text extractor + OCR fallback on empty pages)
  pages producing >50 characters         398
  pages producing 0 characters             2   (two blank separator pages — correct)
  total extracted characters         903,000
  estimated tokens                   225,800

  → recovered ~91,000 characters, ~22,800 tokens
  → the two remaining zero-text pages are genuinely blank: verified by eye

The audit that found the problem is three numbers wide: pages in, pages producing text, characters per page. That is the entire diagnostic. You can compute it in a few lines and it catches the most expensive parsing failure there is.

Now the second half of the same audit, on structure rather than characters:

text
Structure audit — same constructed example

Tables in the source (counted by hand on a 20-page sample, extrapolated)
  ~68 tables across 400 pages

Tables in the parser output
  recognised as table objects                    19
  flattened into undelimited text                41
  partially captured (header lost)                8

  → 72% of tables lost their header-to-value binding.
  → Every one of them still produced text. Nothing errored.

A flattened table is the purest example of a silent parsing failure. Consider a specification table whose row reads Operating temperature | -10 °C | 45 °C. Flattened without delimiters it becomes Operating temperature -10 °C 45 °C, and with the column headers Minimum and Maximum stripped off the top of the table, nothing in the chunk records which number is the minimum. Ask "what is the maximum operating temperature?" and the retriever finds this chunk — it is genuinely the most relevant text in the corpus — and the model reads two numbers with no labels and picks one. The citation is correct. The provenance is correct. The answer is a coin flip.

05

Decision table: which parsing approach for which corpus

When to reach for each approach, and when not to:

Corpus descriptionApproachWhyWhen this is the wrong choice
Markdown, plain text, or clean HTML you controlDirect read, strip boilerplateStructure is already explicit; a heavy parser adds failure modesNever wrong, but does not generalise to a mixed corpus
Natively exported PDFs, single column, mostly proseText-layer extractor with a page-level character-count checkCheap, fast, high fidelity; the check catches the surprisesWrong if any page is scanned and you skip the check
Any corpus you did not personally producePer-page text-layer detection, conditional OCRHybrid corpora are the default case, and OCR-everything degrades good pagesOver-engineering only if you have verified every page has a text layer
Documents whose value is in tables (specs, financials, lab results)A parser with explicit table-structure extraction; serialise each table as Markdown or as one row-per-recordThe header-to-value binding is the informationWrong to rely on general text extraction here, however good its characters are
Multi-column academic PDFsLayout-aware parser with column detection; verify reading order on a sampleVertical-then-horizontal sorting interleaves columnsWrong to trust a naive extractor's clean-looking output
Scanned archives, decades old, low qualityOCR with a quality gate; route low-confidence pages to human review or exclude themBad OCR is worse than no text: it produces plausible wrong words that embed fineWrong to ingest silently at any confidence
Very large web-scale crawlsBatch curation tooling built for scale, with boilerplate removal and language filtering as pipeline stagesPer-document scripting does not survive millions of documentsWrong for a 200-document internal corpus, where it is pure overhead

That last row is where NVIDIA's named tool for this problem sits. NeMo Curator is NVIDIA's data-curation component for preparing datasets at scale, and its role in the stack map is exactly this: curation, as distinct from NeMo for build and customise, NeMo Retriever for retrieval, NeMo Guardrails for safety rails, Triton for serving, and NIM for packaged deployment. [NVIDIA-DOC] For the exam, the identity is what is tested: which tool curates data? NeMo Curator. Know it at that level, alongside the fact that the NVIDIA AI Blueprint for RAG is the reference workflow that shows the ingestion-to-answer path assembled end to end, and NeMo Retriever is the retrieval-accuracy component that consumes what your ingestion produced. [NVIDIA-DOC] Do not memorise configuration flags for any of them; the [FIELD] calibration on this exam is consistent that YAML-level depth does not appear and that high-level tool identity does.

06

Why document parsing is on the NCA-GENL exam

Document parsing serves four official objectives at once, which is unusual for a single ingestion topic and is why it earns a full lesson rather than a paragraph inside a RAG overview.

Objective (verbatim)How parsing serves it
1.4 Curate and embed content datasets for RAGsParsing is the first act of curation. You cannot curate text you have not extracted, and you cannot embed what the parser dropped
1.3 Build LLM use cases such as retrieval-augmented generation (RAG), chatbots, and summarizersA RAG use case built on a corpus that is 11% empty is a RAG use case that fails for one question in nine, unpredictably
2.3 Conduct data analysis under the supervision of a senior team memberThe page-count and character-count audit in §4 is data analysis on your own corpus, and it is exactly the inspect-and-cleanse work the module's scope statement describes
4.4 Identify system data, hardware, or software components required to meet user needs"This corpus contains scans, therefore this pipeline requires an OCR component" is the canonical form of this objective applied to RAG

[OFFICIAL] on the objective wording; the mapping is this course's reading of it.

How the questions get phrased. The exam is 50–60 multiple-choice questions in 60 minutes, which is roughly 60–70 seconds each, so questions are compact scenarios rather than long cases. [OFFICIAL] Expect forms like these:

  • "A team's RAG chatbot cannot answer questions about the company's 2011–2015 policy documents, although those documents are in the corpus and the pipeline reported no errors. What is the most likely cause?" — the keyed answer names scanned pages with no text layer and no OCR step.
  • "Which pipeline component is required to ingest a corpus of scanned contracts?" — OCR.
  • "A retrieved chunk contains correct numbers but the model attributes them to the wrong quantities. Which ingestion stage most likely failed?" — table-structure extraction, not embedding, not retrieval.
  • "Which NVIDIA component is intended for curating datasets at scale?" — NeMo Curator.
  • "Before embedding a document corpus, which step comes first?" — parsing/extraction, ahead of chunking, ahead of embedding, ahead of indexing. Component order is a repeatedly reported question shape for RAG. [FIELD]

Distractor families. Four recur, and recognising the family is faster than reasoning through each option:

  1. Downstream-fix distractors. The option proposes a bigger embedding model, a reranker, or a larger context window to solve a parsing problem. Tempting because those are all real techniques. Wrong because none of them can retrieve text that was never indexed.
  2. Tool-confusion distractors. NeMo Curator swapped for NeMo Retriever, NeMo Guardrails, TAO, or Triton. The stack-map discipline in this course exists for this family; [FIELD] reports consistently that NVIDIA-branded options are favoured when technically defensible, so the trap is picking an NVIDIA tool rather than the right one.
  3. Over-processing distractors. The option proposes running OCR on the entire corpus, or applying an aggressive classical-NLP cleanup (lowercasing, stop-word removal, stemming) before embedding. Both degrade a modern pipeline. OCR on a clean text layer adds errors; stripping case and stop words removes signal a contextual embedding model uses. See 02-05 for why that classical pipeline belongs to a different era of NLP than a transformer embedding model.
  4. Error-assumption distractors. The option assumes the pipeline would have raised an exception, and therefore concludes parsing is fine. The whole point of this lesson is that it would not have.
07

Common mistakes with document parsing for RAG

MistakeSymptom you actually seeUnderlying causeFix
Trusting a zero-exception ingestion run"It ingested fine" and then unanswerable questions about specific documentsParsers return empty strings rather than raising on unparseable pagesAssert on output: pages-in vs pages-with-text, characters per page, and fail the run when a page yields under a threshold
No OCR path for a hybrid corpusAn identifiable slice of the corpus — one date range, one department, one file source — is invisible to retrievalScanned pages have no text layer to extractDetect text-layer presence per page and route image-only pages to OCR
OCR applied indiscriminatelyRetrieved text has plausible but wrong words: 1 for l, rn for m, mangled unitsOCR recognition error introduced on pages that never needed itMake OCR conditional on an empty or near-empty text layer
Tables flattened to proseNumerically correct chunks, confidently wrong attributions of number to quantityHeader-to-value binding is destroyed by generic text extractionExtract tables as structured objects and serialise each with its headers — Markdown tables or one self-describing sentence per row
Reading order not verifiedRetrieved chunks read as spliced fragments; every other clause is off-topicMulti-column layout sorted vertically then horizontallyUse a layout-aware parser; eyeball extracted text against the rendered page for a sample of every distinct document template
Headers, footers, and page numbers left inThe same short string recurs thousands of times and starts winning retrievalRunning headers are drawn on every page and extracted on every pageStrip repeated per-page furniture at parse time — and see 06-04, where this becomes a corpus-level deduplication problem
Formulas, code, and figure text treated as proseChunks containing mathematical or code content are retrieved for unrelated queriesSymbol-heavy text tokenises into low-information fragments that sit oddly in embedding spaceDetect and either preserve these regions verbatim as distinct chunk types or exclude them, and record which you did
No provenance recorded during parsingYou cannot tell which file or page a retrieved chunk came from, so you cannot cite it or audit itProvenance is available at parse time and discarded before indexingCapture source file, page number, and section heading at parse time — the subject of 06-03
Parsing once, never againQuality drifts as new document templates enter the corpusThe audit was run at build time and never re-runMake the ingestion audit a recurring job with the same three counts, so a new template that parses badly is visible immediately
08

Why do document parsing failures stay silent instead of raising errors?

Because a parser's contract is to return a string, and an empty string is a valid string. There is no exception to raise: the file opened, the pages were read, the text-extraction call succeeded and produced zero characters, which is a correct description of a page containing no characters. The parser is not wrong. The pipeline's assumption — that a page yields text — is the thing that is wrong, and assumptions do not throw.

The same logic explains every other silent failure in the list. Interleaved columns are a valid string. A flattened table is a valid string. A cookie banner extracted as body text is a valid string. Every downstream stage accepts strings and produces something: the chunker chunks, the embedding model embeds — it will embed nonsense into a perfectly well-formed vector — the index indexes, the retriever retrieves, the generator generates. Not one of those stages has any way to know that the string it received does not represent the document.

The practical consequence is a rule worth carrying into every ingestion job you build: parsing must be validated by assertion on its output, not by the absence of errors. If you have not counted something, you have not checked anything.

09

Do I need OCR for my RAG corpus, and how do I know?

You need OCR if and only if some pages in your corpus contain text as pixels rather than as characters. The test is mechanical and takes one pass:

  1. For each page, extract the text layer and count the characters.
  2. Compare against the page's visual density — or simply flag any page under a low threshold, say 50 characters, since real content pages almost never fall below that.
  3. Render a handful of the flagged pages as images and look at them. If they contain visible text, you have image-only pages and you need OCR. If they are genuinely blank separators or full-page figures, you do not.

Two cautions. First, the answer is per page, not per corpus — the hybrid case in §3 is the common one, and a corpus-level "yes" leads to OCR-everything, which is the over-processing mistake. Second, OCR output needs its own quality gate. An OCR engine returns text with a confidence signal, and low-confidence text is actively dangerous in a RAG corpus: a wrong-but-plausible word embeds into a plausible region of vector space and gets retrieved for queries it should not match. Text you cannot trust is worse than text you do not have, because absence is at least honest.

10

What does a good ingestion audit measure?

Six numbers, all cheap, all computable without a model:

MeasurementWhat it catches
Pages in vs pages producing textMissing scans, unparseable pages, whole documents lost
Characters per page, as a distributionOutliers at both ends: near-empty pages and pages where a table collapsed into one enormous line
Tables counted by hand on a sample vs tables recognisedStructure loss, the most under-detected failure
Extracted tokens vs an independent estimate of document lengthSystematic loss you would otherwise never notice
Count of the most frequently repeated stringsHeaders, footers, boilerplate, navigation — the input to 06-04
Reading-order spot check on one page per document templateColumn interleaving

Templates, not documents, are the right sampling unit for the last one. A corpus of 4,000 documents may contain only six distinct layouts, and one spot check per layout is a complete audit of reading order — where 4,000 random spot checks would be both unaffordable and less informative.

The measurement thread in this course keeps insisting on the same idea in different clothes: 03-04 had you test retrieval quality by hand, 01-08 had you build an evaluation set before you had anything to evaluate. This is the same instruction pushed one stage earlier. The corpus is the earliest thing you can measure and the last thing anyone thinks to.

Glossary recap: the terms this lesson introduced

TermDefinition
Document parsingExtraction of machine-readable text plus recoverable structure from a source document, the first stage of a RAG ingestion pipeline
Text layerEmbedded character data in a PDF, with font maps and coordinates, that can be extracted without recognition
OCR (optical character recognition)Recognition of characters from page images, required when a page has no text layer, and a source of plausible-but-wrong text
Layout analysisGrouping positioned glyphs into lines, blocks, and a reading order
Reading orderThe linear sequence a human would read a page in, which a parser must infer from geometry
Structure extractionRecovery of tables, headings, and lists as distinct objects rather than as undifferentiated text
Silent failureA failure that produces valid-looking output and no error, so it is invisible to every downstream stage
Hybrid corpusA document set mixing native and scanned files, the normal case for any archive you did not create
BoilerplateRepeated non-content text — headers, footers, navigation, cookie notices — extracted alongside real content
Ingestion auditThe set of counts that verifies a parser's output against the source documents
NeMo CuratorNVIDIA's data-curation component for preparing datasets at scale [NVIDIA-DOC]

Key takeaways on document parsing for RAG

  • Parsing is the only RAG stage whose failures are silent. Every other stage errors, degrades measurably, or shows up in a metric. Parsing returns a valid string and moves on.
  • A PDF is a drawing, not a document. Paragraphs, reading order, and tables are inferred, and every inference is a place to be confidently wrong.
  • Scanned pages return an empty string, not an error. That is the single most expensive silent failure, and it hides in the age of a corpus rather than in its size.
  • OCR is a conditional fallback, not a default. Running it on clean text layers adds recognition errors; skipping it on image-only pages deletes content.
  • A flattened table keeps the numbers and destroys their meaning. The header-to-value binding is the information; preserve it as structure or serialise it into each row.
  • Validate by assertion, never by absence of errors. Pages in vs pages with text, characters per page, tables found vs tables present, and a reading-order spot check per document template.
  • Downstream tuning cannot recover upstream loss. No reranker, no larger context window, and no better embedding model retrieves text that was never indexed. This is the reasoning that kills the most common distractor family on this topic.
  • NeMo Curator is the NVIDIA answer to curation at scale, distinct from NeMo Retriever (retrieval accuracy) and from the AI Blueprint for RAG (reference workflow). Identity depth, not configuration depth. [NVIDIA-DOC]

Next: how parsed text becomes retrievable chunks

You now have text. It is one long string per document — possibly hundreds of thousands of characters — and nothing about it is retrievable yet, because retrieval works over pieces small enough for a single vector to represent faithfully. Deciding how big those pieces are, where to cut them, and whether they should overlap is a granularity decision that is entirely separate from how much text your model can read at once, and conflating those two things is one of the most common confusions in this whole subject.

Next: 06-02 Chunking strategies for RAG: fixed, recursive, and semantic — where chunk size is settled as a granularity decision, and the context window from 04-06 is settled as a ceiling that has nothing to do with it.