Repository navigation
feat(pdf): add layout and tables with optional local OCR - #60
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
PDF extraction now reconstructs reading order, columns, headings/lists and ruled or borderless tables, including merged and wrapped cells. Optional versioned layout JSON exposes source words and semantic blocks/lines/cells linked to IR provenance. Tagged headings and ActualText are honored; repeated margin text can be suppressed.
Textless pages support opt-in local OCR using Rust Hayro rendering. Tesseract is the default;
pdf-ocr-ocrsadds Rust ocrs/RTen inference with explicit local ONNX paths. Rust, CLI, Node and Python expose the options; WASM gains text-layer PDF extraction, layout and tables. Python also gains structured document extraction.Why
PDFs need useful structured Markdown and source geometry across columns, tables and scanned pages. OCR uses local assets and works without Poppler; model downloads happen only through the separate pinned setup script.
Before / After
The optional ocrs backend scores 54.9% on the same scans, compared with Tesseract's 56.0%. Three fresh measured runs after warm-up, one inference thread: median document time 12.78s versus 4.28s; median sampled peak process-tree RSS 227.6 versus 36.2 MiB. Tesseract remains the default. Both return valid geometry; a generated fixture verifies known word positions. Public scan box comparisons measure agreement, not ground-truth localization accuracy.
Validation:
just pre-pr: formatting, Clippy, 825 default workspace tests, knowledge checks (including pinned okf-lint 0.1.1), script tests, examples and cargo-deny passed.cargo audit, documentation build and the core package publication dry-run passed. Ordinary benchmark results are saved alongside the OCR comparison.Usage:
--json --layoutfor geometry;--ocrfor Tesseract; build with--features pdf-ocr-ocrsand use--ocr --ocr-backend ocrswith both local model paths for Rust inference.Risk
High: PDF interpretation, reading-order heuristics and native image decoding are expanded. Table inference remains conservative. Rendering and RTen deadlines are cooperative; hostile documents still require host CPU/memory isolation. Inline, JBIG2, CCITT and DecodeParms-based OCR images fail explicitly pending bounded decoder support.
The optional default ocrs model supports Latin/English recognition. Its approximately 12 MB weights are separate CC-BY-SA 4.0 deployment assets with size/SHA256 pins and attribution; they are not embedded in packages. Extraction never downloads models or silently changes engines.
Breaking: exhaustive Rust
MarkkitBuilderliterals need the new PDF options. Builder methods/default update syntax remain valid. The IR source link is additive; the committed schema and all binding documentation are updated.Checklist