Skip to content

feat: add LightOnOCR-3 presets and grounded output parsing - #4789

Open
PierreMesure wants to merge 7 commits into
docling-project:mainfrom
PierreMesure:feat/lightonocr-v3
Open

PierreMesure wants to merge 7 commits into
docling-project:mainfrom
PierreMesure:feat/lightonocr-v3

Conversation

@PierreMesure

@PierreMesure PierreMesure commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

LightOnOCR-3 adds block grounding, image descriptions, and chart tables, but Docling currently only has a LightOnOCR-2 preset. This adds the official 0.8B, 1B, and 4B models as lightonocr3_08b, lightonocr3_1b, and lightonocr3_4b presets. The existing lightonocr preset continues to use v2.

The new presets use the grounding prompt and a native LIGHTONOCR_MARKDOWN response format. The parser accepts markers on their own lines and inline with content, scales 0–1000 coordinates to the source page, and preserves Markdown text, HTML tables, image descriptions, and chart tables. It reuses the existing rich HTML fragment mapper. Empty-prompt transcription is also supported. Transformers decoding removes special tokens; local inference requires Transformers 5.5.4 or later.

Boxes remain block-level: derived children and list items do not receive synthetic coordinates. Continuation labels keep their base class without merging blocks. Separate captions are not linked by proximity. No unverified MLX export is configured.

Rebased onto main at 1ee1db0f648c4bd2d25146f5dd100d1b75d94d7d after #4964 merged. This branch uses the upstream heading and formula helpers without changing them. The LightOn mapper records raw heading depths when the pipeline maps a page, and the pipeline normalizes the joined document once. Direct mapper calls normalize their page by default. Regression tests cover pages with and without a depth-1 section.

The shared Markdown renderer and its tests remain identical to #4908. They include the currency-range fix: Price $5-$10 and $x$. keeps the price as text and creates only the x formula. Native inline parsing preserves tildes, alert markers, pipe-table text, and bare URLs. Full-page GFM table parsing stays enabled for LightOn.

Validation of current code on Python 3.12 with the locked docling-core 2.103.1:

Earlier validation included real 0.8B CPU inference through VlmConvertModel.process_images for grounding and empty-prompt transcription on a synthetic lease page, using Transformers 5.18.0, bfloat16, eight CPU threads, and compilation disabled. This inference was not rerun for the rebase. The 1B and 4B checkpoints, GPU/MLX inference, API-server inference, and the full repository suite were not run locally.

Fixes #4788.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ DCO Check Passed

Thanks @PierreMesure, all your commits are properly signed off. 🎉

@mergify

mergify Bot commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🟢 Merge protection satisfied — ready to merge.

Show 1 satisfied protection

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

@github-actions github-actions Bot added ai:ci-safe AI triage found no CI-safety concern (advisory) enhancement New feature or request ocr vlm-pipeline labels Oct 12, 2026
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

AI triage (advisory)

Checked commit 7173aab508. The analysis read the diff only. It did not run code from this pull request.

The PR adds three LightOnOCR-3 presets (lightonocr3_08b, lightonocr3_1b, lightonocr3_4b). It adds a LIGHTONOCR_MARKDOWN response format and a parser for grounded output with block bounding boxes. It also adds a math-aware Markdown parser helper, docs, and tests.

CI safety: no concern found. A maintainer must still approve CI.

2 related pull request(s) in the same code
PR State Signal Assessment
#4908 open changes the same code related: Both PRs add the same docling/utils/markdown_math.py helper and tests/test_markdown_math.py, so they will conflict on those files. This PR adds LightOnOCR-3 support, and the candidate fixes inline math for native VLM exports. They solve different problems.
#4934 open changes the same code related: Both PRs edit stage_model_specs.py and the CLI skill reference. This PR adds LightOnOCR-3 presets. The candidate adds an MLX engine for Nemotron 3.5 Parse. The changes are in different places and do different things.

The ai:* labels are advisory. They do not approve CI and they do not add tests:full. A new push runs this check again.

@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.27559% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
docling/utils/lightonocr_utils.py 95.45% 1 Missing and 2 partials ⚠️
docling/utils/markdown_math.py 93.61% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot removed the ai:ci-safe AI triage found no CI-safety concern (advisory) label Oct 19, 2026
@PierreMesure

Copy link
Copy Markdown
Contributor Author

Fixed the CI failure in 436888e.

The VLM job had one failure: TestPresetEngineIntegration.test_response_format_consistency did not include ResponseFormat.LIGHTONOCR_MARKDOWN in its explicit list of valid formats. The three new presets use that format, so the assertion failed. The code-checks / check and ci-status failures followed from this job.

The fix adds the missing format to that list. The existing test still checks presets across all three stage types. All 11 new LightOnOCR-3 tests already passed in the core CI job.

Local validation on Python 3.12:

  • Reproduced the same assertion failure before the fix.
  • Ran the full VLM suite selected by .github/scripts/pytest_marker_selection.py, with CI=true: 106 passed, 6 skipped. The skips match the original CI job.
  • Ran tests/test_lightonocr3_vlm.py, tests/test_chandra_vlm.py, tests/test_unlimited_ocr_markdown.py, tests/test_vlm_convert_model.py, and tests/test_vlm_pipeline_streaming.py: 76 passed.
  • UV_NO_SYNC=1 make validate: all applicable hooks passed, using the installed locked development environment.

Local Python 3.10 testing stopped at import because the locked SciPy wheel could not load on this Mac. Python 3.10 validation of the fix remains for Linux CI. No dependency or production-code changes were needed.

@github-actions github-actions Bot added the ai:ci-safe AI triage found no CI-safety concern (advisory) label Oct 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI first review (advisory): blocker found

This review covers the full diff at 436888e88f. It read the code and did not run it.

docling/utils/lightonocr_utils.py imports marko at module level, but marko is only in the optional format-markdown extra. A docling-slim[models-vlm-inline] install fails on the first page with a bare ModuleNotFoundError. Check this dependency first. The parser logic and tests look consistent with the existing Chandra mapper.

A maintainer makes the merge decision. This review never approves the pull request.

Comment thread docling/utils/lightonocr_utils.py Outdated
from collections.abc import Iterator
from pathlib import Path

import marko

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocker: marko is an optional dependency, but the new parser imports it with no guard

pyproject.toml lists marko only in the format-markdown extra. The models-vlm-inline extra does not include it. The lazy import in VlmPipeline._finalize_page_document (docling/pipeline/vlm_pipeline.py) runs this module on the first page.

Trigger: a docling-slim[models-vlm-inline] install, with no format-web or format-markdown, runs lightonocr3_*.

Result: inference runs on the page. Then parsing raises a bare ModuleNotFoundError: marko, and the conversion fails.

The repository already handles this case. MarkdownDocumentBackend raises an ImportError with an install hint. docling/utils/dots_utils.py:78-84 does the same.

Fix: import marko inside parse_lightonocr_markdown. On ImportError, raise a message that tells the user to run pip install 'docling-slim[format-markdown]'. You can also add format-markdown to the dependencies of models-vlm-inline. The full docling package is not affected, because it includes format-web.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in fa841f3.

The regression test blocks marko in a fresh interpreter, using the existing optional-dependency test helper. Before the fix, the parser import failed with ModuleNotFoundError. With the fix, the module imports successfully and a parsing call raises ImportError with pip install 'docling-slim[format-markdown]'. The original import error is preserved as the cause.

The import now runs inside parse_lightonocr_markdown, as suggested. The LightOnOCR-3 documentation also states the Markdown-extra requirement for slim installations. The dependency remains optional.

Validation on Python 3.12:

  • Optional-dependency tests selected with -k 'lightonocr or marko': 3 passed, including the new regression test.
  • LightOnOCR-3, Chandra, Unlimited OCR, VLM conversion, and streaming tests: 76 passed.
  • UV_NO_SYNC=1 make validate: all applicable hooks passed, including Ruff, ty, Tach, module coverage, and file-size checks.

Full Linux CI has not yet validated this commit.

@github-actions github-actions Bot added ai:review-changes AI first review suggests changes ai:ci-safe AI triage found no CI-safety concern (advisory) and removed ai:ci-safe AI triage found no CI-safety concern (advisory) ai:review-changes AI first review suggests changes labels Oct 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI first review (advisory): no blocker found

This review covers the changes since 436888e88f at fa841f325b. It read the code and did not run it.

The earlier blocker (module-level marko import failing on docling-slim[models-vlm-inline] installs) is fixed: marko is now imported lazily inside parse_lightonocr_markdown and raises an ImportError with the correct install hint. The regression test and docs update look consistent. No new issues found in the incremental changes.

Earlier findings

  • fixed (blocker): marko is an optional dependency but the new parser imports it with no guard

A maintainer makes the merge decision. This review never approves the pull request.

@github-actions github-actions Bot added ai:review-lgtm AI first review found no blocker or major issue (advisory) and removed ai:ci-safe AI triage found no CI-safety concern (advisory) labels Oct 19, 2026
@PierreMesure

Copy link
Copy Markdown
Contributor Author

Fixed three parser defects in 493f6fa:

  • LaTeX preservation: formula blocks bypass Markdown transformations and store LaTeX without outer math delimiters, so export adds exactly one pair. Inline math is protected from Markdown escaping and emphasis; code spans remain literal.
  • Section heading levels: grounded title blocks with Markdown section headings become section headers. Their levels are converted to Docling's title-relative numbering, so ## exports as ##. Formatted heading children keep one block-level coordinate owner.
  • Inline code fences: fence detection runs after extracting the grounding marker. A fence on the marker line now protects the code and ends before the next block. The following text keeps its label and coordinates instead of becoming code or a spurious picture.

Added 16 test cases to tests/test_lightonocr3_vlm.py, covering document structure, Markdown exports, coordinates, LaTeX escapes and multiline formulas, inline math versus code, and backtick/tilde fences. The initial regression run reproduced all three defect classes before the production fix.

Validation on Python 3.12:

  • Full VLM selection plus LightOnOCR-3, Chandra, Unlimited OCR, VLM conversion, streaming, and the missing-Markdown regression: 199 passed, 6 skipped.
  • Optional-dependency tests selected with -k 'marko or lightonocr': 3 passed.
  • UV_NO_SYNC=1 make validate: all applicable hooks passed, including Ruff, ty, Tach, module coverage, and file-size checks.

The shared Chandra mapper and dependency declarations are unchanged. Full Linux CI has not yet validated this commit.

@PierreMesure

Copy link
Copy Markdown
Contributor Author

Shared follow-up fixes are now tracked and implemented in focused PRs:

This PR now reuses the shared math renderer and delimiter normalizer in de76b6b. The HTML mapper correction is applied at the shared component, and the LightOn-only heading compensation has been removed. The shared implementations are identical to the corresponding follow-up PRs, so the math and heading logic need not remain duplicated in lightonocr_utils.py.

Validation of this refactor: 199 passed, 6 skipped across the VLM and related parser/pipeline tests, plus all applicable make validate hooks. Tests ran on Python 3.12. Full Linux CI has not yet validated this commit.

@github-actions github-actions Bot added ai:ci-safe AI triage found no CI-safety concern (advisory) ai:possible-duplicate AI triage: another PR may fix the same problem and removed ai:ci-safe AI triage found no CI-safety concern (advisory) ai:possible-duplicate AI triage: another PR may fix the same problem labels Oct 19, 2026
@PierreMesure

Copy link
Copy Markdown
Contributor Author

Kept the shared Markdown renderer and its tests identical to #4908 in ab79d5b. This addresses the confirmed GFM side effect reported on that PR: native inline parsing must preserve literal tildes and native block text. Full-page GFM parsing remains enabled for LightOn tables.

The shared-parser and LightOn test suites pass: 36 passed, 1 skipped. UV_NO_SYNC=1 make validate passes.

PierreMesure and others added 6 commits October 22, 2026 19:33
Signed-off-by: Pierre Mesure <pierre.mesure@statskontoret.se>
Include LIGHTONOCR_MARKDOWN in the explicit valid-format list so the LightOnOCR-3 presets pass the cross-stage consistency check.

Signed-off-by: Pierre Mesure <pierre@mesu.re>
Defer the marko import until parsing and report the format-markdown extra when it is missing. Add a cold-import regression test and document the requirement for slim installations.

Signed-off-by: Pierre Mesure <pierre@mesu.re>
Keep LaTeX literal during Markdown parsing and store formulas without export delimiters. Preserve section heading levels using Docling's title-relative levels, and track fences that start on grounding-marker lines.

Add regression cases for formula escapes and multiline content, heading exports and coordinates, inline math versus code, and both fence styles. Keep the shared Chandra mapper unchanged.

Signed-off-by: Pierre Mesure <pierre@mesu.re>
Move Markdown math rendering and delimiter normalization into shared helpers. Correct heading depth in the shared HTML mapper and remove the LightOn-only compensation. Coordinate with parser issues docling-project#4902, docling-project#4903, and docling-project#4904.

Signed-off-by: Pierre Mesure <pierre@mesu.re>
Signed-off-by: Pierre Mesure <pierre@mesu.re>
Signed-off-by: Pierre Mesure <pierre@mesu.re>
@github-actions github-actions Bot removed ai:ci-safe AI triage found no CI-safety concern (advisory) ai:possible-duplicate AI triage: another PR may fix the same problem labels Oct 22, 2026
@PierreMesure

PierreMesure commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (1ee1db0f) after #4964 merged. Removed the obsolete shared-helper changes. The mapper now supports normalize_heading_levels=False, the pipeline uses that mode, and LIGHTONOCR_MARKDOWN is included in the formats normalized once after joining pages. New tests cover standalone headings and two-page joins with and without a depth-1 section.

Synced the shared renderer and its tests with #4908, including the currency-range review fix, while retaining full-page GFM tables. Updated the heading documentation and PR description.

Validation: 193 passed, 2 skipped for the focused LightOn/shared/preset/optional-dependency suites; 267 passed, 1 skipped in a clean combined merge with #4908. make validate and hooks on all changed PR files pass. New CI is pending.

@cau-git, it's ready to review! 😊

@github-actions github-actions Bot added the ai:ci-safe AI triage found no CI-safety concern (advisory) label Oct 22, 2026
@cau-git

cau-git commented Oct 27, 2026

Copy link
Copy Markdown
Member

@PierreMesure Thanks, the integration follows the other VLM adapters well.

Before merge:

  1. markdown_math.py now differs from fix: preserve native VLM inline math through exports #4908 (parser cache, render_math fallback). Please merge fix: preserve native VLM inline math through exports #4908 first, then rebase and drop the copy here.
  2. Headings with math lose their text (## Theorem $x$ gives empty item.text). This is the same issue as in fix: preserve native VLM inline math through exports #4908 and docling-core#924.
  3. Please add the presets to docs/usage/model_catalog.md, and LightOnOCR to the list in "Heading depths in native layout output".
  4. Please add LightOn to tests/test_vlm_heading_exports.py instead of a separate heading test file.
  5. Optional: give chart pictures the OTHER_CHART class, like Nemotron 3.5, so chart data is kept. Optional: add one real model output under tests/data when you have one.

Since docling-core#924 is merged, #4908 should become mergeable and then this one too.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:ci-safe AI triage found no CI-safety concern (advisory) enhancement New feature or request ocr vlm-pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Official support for LightOnOCR-3

2 participants