@@ -291,10 +291,14 @@ embedded text is trustworthy.
291291 - multipart with field name ` file ` or ` pdf ` .
292292- ** ` mode ` query** (default ` ocr ` ):
293293 - ` ocr ` — always render + OCR every page.
294- - ` geometric ` — use the PDF text layer for content; render only when
295- ` layout=1 ` or as a safety net.
294+ - ` geometric ` — prose comes ** only** from the PDF text layer; the page is
295+ ** never OCR'd** . A page with no usable text layer (image-only / scanned)
296+ returns empty prose — use ` auto ` or ` ocr ` for those. The page is still
297+ rendered for layout and table/formula recognition when requested (those
298+ are vision-recognized for born-digital pages too), so ` ?tables=1 ` /
299+ ` ?formulas=1 ` work in geometric mode and keep the exact text-layer prose.
296300 - ` auto ` — text layer when trusted (` text_layer_quality == "trusted" ` ),
297- OCR otherwise.
301+ OCR otherwise. This is the mode that recovers prose on image-only pages.
298302 - ` auto_verified ` — GPU only. Runs OCR, then cross-checks every
299303 detection against the PDF text layer; replaces matches with the
300304 native string (` source: "pdf" ` ). On CPU this aliases to ` auto ` .
@@ -304,6 +308,40 @@ embedded text is trustworthy.
304308 ` MAX_PDF_PAGES ` defaults to ` 2000 ` . Exceeding returns
305309 ` 400 PDF_TOO_LARGE ` with the limit echoed back in the message.
306310
311+ ### PDF → Markdown (` ?markdown=1 ` )
312+
313+ One call converts the whole PDF to the same faithful Markdown as
314+ ` POST /ocr/markdown ` , using the parallel page pipeline — no client-side
315+ page splitting. Available on both the GPU and CPU builds:
316+
317+ ``` bash
318+ curl -X POST ' http://localhost:8000/ocr/pdf?markdown=1' \
319+ --data-binary @paper.pdf -H ' Content-Type: application/pdf'
320+ ```
321+
322+ - Returns ` text/markdown ` : pages concatenated in order, each prefixed with an
323+ invisible ` <!-- page N --> ` marker (safe to render, easy to split on).
324+ - ` &as_pages=1 ` returns JSON instead — `{"pages":[ {"page_index":0,
325+ "markdown":"…"}, …] }` — for chunked/RAG consumers; per-page
326+ ` text_degraded ` / ` table_degraded ` / ` formula_degraded ` flags appear when set.
327+ - Implies ` layout=1&reading_order=1 ` (requires the layout model —
328+ ` 400 LAYOUT_DISABLED ` otherwise). In the default ` ocr ` mode, tables and
329+ formulas are recognized whenever their backends are loaded (→ HTML / LaTeX);
330+ pass ` tables=0 ` / ` formulas=0 ` to opt out.
331+ - ** Mode choice.** ` mode=ocr ` (default) renders and OCRs every page — best for
332+ scanned PDFs. ` mode=geometric ` reads a born-digital PDF's embedded text layer
333+ directly for the prose (exact text, faster, no OCR errors) while ** still**
334+ recognizing tables → HTML and formulas → LaTeX on the rendered image — so a
335+ born-digital paper exports exact text * and* structured math/tables. ` auto `
336+ picks per page: text layer when trustworthy, OCR otherwise.
337+ - Figure/chart crops are embedded as base64 ` data: ` URIs with their OCR'd text
338+ as alt text; tables come back as HTML, formulas as ` $…$ ` / ` $$…$$ ` LaTeX.
339+ - ` dpi ` , ` mode ` and ` autorotate ` work as usual. ` text=0 ` and ` images= ` are
340+ rejected (` 400 INVALID_PARAMETER ` ) — markdown needs the text, and the figure
341+ crops are already embedded.
342+ - Per-stage degradation is aggregated in the ` X-OCR-Degraded ` response header
343+ with page numbers (e.g. ` table(p3,p7) ` ), same contract as ` /ocr/markdown ` .
344+
307345### Inline page-image export
308346
309347` ?images=inline ` adds each rendered page back to the response as a
0 commit comments