Parsing Effort for RAG
Retrieval can only find what indexing read. Every document a tenant indexes is read by the document parser, and the tenant's parsing effort decides how: from the text the document carries, with no model, or with the parser's vision model, which reads tables, charts and headings the way a person sees them. This guide is the one place that explains the levels; the rest of ingestion is in Indexing Well, and the parser itself in Document Parsing.
1The four levels#
| Level | How each page is read | Model | Cost per page | Choose it for |
|---|---|---|---|---|
Minimal (default) |
The text layer the file carries; OCR for scanned pages and pictures; Word, HTML and e-mail from their own structure | None | Milliseconds; a page read by OCR takes longer; any machine | Born-digital corpora, high volume, machines without a GPU |
Low |
The parser's model, the least time per page | The document parser | Seconds on a GPU | Large corpora of scans and mixed documents |
Medium |
The parser's model, a balance of time and fidelity | The document parser | Seconds on a GPU | Most business documents |
High |
The parser's model, the most faithful reading | The document parser | The most per page | Reports and papers where every table, chart and heading counts |
What the parser does inside each model level belongs to the parser and improves from one release to the next; a tenant's setting does not change when it does.
Whatever the level, a document is never slower to become searchable: it is always indexed at
once at Minimal, and a model level improves its pages afterwards (section 2). Minimal is the
reading every tenant had before the setting existed, word for word.
What a model level buys in a RAG answer: tables come back as tables (cells in their rows and columns, merged headers kept) instead of runs of numbers, a chart becomes the data table it plots, multi-column pages read in order, and headings are recognized from the page's typography rather than guessed, so chunks start and end where the document's sections do.
2What happens when a document is indexed#
- At once, at every level: the document is read at
Minimaland written. The call returns with the document full-text searchable (and semantically searchable once its embedding is done, as always). - At
Low,MediumorHigh: the server keeps the document's source and a background worker parses it again at the tenant's level, one document at a time, through the same completion slots as every request that runs a model. - When the parse finishes: the document's pages are replaced by the parsed ones, its
metadata and expiry kept, and it is embedded again. Search keeps answering
from the
Minimalpages until then.
The background parse respects the present, not the moment the document was queued:
- A document indexed again while it waits is parsed from its newest source; the older parse is dropped.
- A document deleted, or expired, is never parsed.
- A tenant set back to
Minimalstops parsing; what was already parsed stays. - A document whose parse fails is retried three times, then stays at
Minimal, still indexed.
Word documents, HTML pages, e-mails and plain text are read from their own structure at
Minimal and are not parsed again: the model would read a rendering of what the file already
states. PDFs, scans and images are.
3Which level for which corpus#
- Born-digital PDFs, Office files, e-mail, at volume:
Minimal. The text is already in the files; nothing a model reads would change the words, only the structure of tables and charts. - Scans, photos of documents, faxes:
Lowat least. OCR givesMinimalthe words, but not the tables or the reading order of a complex page. - Reports, filings, papers with tables and charts that answers must quote:
Medium, orHighwhen every figure matters. - No GPU: stay at
Minimal, or accept that a model level reads in minutes per page on the processor. The backlog then grows faster than it drains on a busy tenant (section 6 shows how to watch it; section 4 how to time a page first).
Two tenants are the way to run two levels: a level is tenant-wide, so a corpus that needs High
for one collection and Minimal for another is two tenants.
4Evaluate the levels in the Playground first#
The Playground reads a document exactly as a tenant would, so the level can be chosen on your own documents before a single one is indexed. Playground > Parse runs the same parser, with the same server OCR engine, as search indexing and its background parse.
How the Playground maps to a tenant
| Tenant setting | Playground: engine and level | What you see is |
|---|---|---|
parsing_effort: Minimal, enable_ocr: true (the defaults) |
Document parser, Minimal | The pages the tenant writes the moment the document is indexed |
parsing_effort: Minimal, enable_ocr: false |
Markdown converter, Fast | The same words (Document parser at Minimal always reads scans with OCR) |
parsing_effort: Low, Medium or High |
Document parser, Low, Medium or High | The pages that replace them once the background parse is done |
| None: search never reads this way | Markdown converter, Balanced or Accurate | The converter's own vision model, which search indexing does not use |
Markdown converter, Fast + OCR reads the same words as Document parser, Minimal:
it is the reading Minimal is built from, without the elements.
What is indexed is what the Markdown tab shows, page by page: its words feed full-text search (table cells included, never table tags) and its chunks the embeddings. The Reading view shows why a page reads the way it does: each element, its box on the page and its place in the reading order.
The Playground reads with the server's own settings; three tenant or collection settings can make a tenant's reading differ, and only on scanned pages or photos:
- A collection language (its full-text configuration, such as
french): the tenant gives OCR that language as a hint, the Playground lets the OCR engine choose. Born-digital pages read the same either way. - Reject photo noise turned off on the tenant: the Playground screens noise as the server is configured to (on by default), so a photo's stray "words" appear in the tenant's reading only.
- OCR turned off on the tenant: use Markdown converter, Fast (first table).
Figure images changes nothing in the indexed text; leave it as you like. A model level reads the same document the same way in the Playground and in the background parse; a reading made while the device serves many requests at once can differ in rare details.
Compare two levels on one document
- Open Playground > Parse and drop a document typical of the corpus (or start from a sample). Pick Document parser and the level the tenant has now (usually Minimal), then Parse.
- Select Compare: the Playground parses the same document at High (at Low when the first parse was High) and shows both pages side by side, with what changed, element by element. Each side switches to any level already run on that document; run Low or Medium first to add them.
- Read what answers will quote: tables (cells in their rows and columns), charts (a data table, or nothing), headings, the order of multi-column pages, and text on scanned pages.
- Note the time each parse shows, in total and per page: at a model level that is what every document costs the background parse, so it says how fast a backlog drains on this server.
When a model level reads your documents no better than Minimal, stay at Minimal: it costs nothing and is what the tenant reads already. Get code shows the parse on screen as an SDK call or a REST request, for a pipeline that parses outside search.
5Set the level#
When the tenant is provisioned:
curl -s "$LMKIT_URL/lmkit/v1/search/tenants" \
-H "Authorization: Bearer $LMKIT_API_KEY" -H "Content-Type: application/json" \
-d '{ "display_name": "Contracts", "enable_semantic_search": true, "parsing_effort": "High" }'
On an existing tenant, with the same update every tenant setting uses (omitted fields are left
as they are; local is the built-in cluster, GET /lmkit/v1/search/clusters lists yours):
curl -s -X PUT "$LMKIT_URL/lmkit/v1/search/clusters/local/tenants/$TENANT" \
-H "Authorization: Bearer $LMKIT_API_KEY" -H "Content-Type: application/json" \
-d '{ "parsing_effort": "Medium" }'
The tenant answers with parsing_effort and parsing_backlog. In the admin panel the level is
Search > (tenant) > Settings > Parsing, and the tenant's setup card shows it beside the
number of documents still waiting.
A new level applies to documents indexed from then on. To bring documents already indexed to
it, send them again without their content_hash (or with a new one): a document sent with
the hash it was indexed with is reported Unchanged and keeps its reading, which is what makes
a corpus sync cheap the rest of the time.
OCR stays a tenant setting of its own (enable_ocr, on by default) because every level reads a
scanned page with OCR first, at Minimal. A tenant that turned it off indexes scans as empty
pages at Minimal; a model level still reads them in the background.
6Watching the background parse#
parsing_backlog on the tenant counts the documents still waiting, and the worker appears on
the admin Scheduler page as search-parsing, with its last pass. The parser's model
(lmkit-doc-parser:1) downloads on first use like any model, visibly in the admin panel; a
server that cannot download it (no network, no room) pauses the parse and retries every ten
minutes, the documents staying searchable at Minimal meanwhile, and the server log says why.
An air-gapped server pulls it beforehand:
lmkit pull lmkit-doc-parser:1
On a farm. The source of a document waiting for its parse is kept on the node that indexed
it, and that node parses it: parsing_backlog counts the documents of the node that answers,
and each node drains its own. The pages it writes are shared like every indexed page, so every
node serves the parsed document. See Scaling Out for what is shared and
what is per node.
7Stated plainly#
Minimalreads exactly what indexing read before parsing efforts existed: same words, same page layout, same OCR flag. Moving a tenant to a model level changes the documents it indexes next, never the speed of indexing.- A model level never makes a document wait to be searchable; it makes its pages better later.
- Tables reach the index as HTML, so their spans survive; full-text search indexes their cells, never their tags.
- The level is per tenant, and so is the backlog. The same levels exist on
POST /lmkit/v1/document-parsingand in Playground > Parse (section 4), which reads a document exactly as the tenant will.