Repository navigation
fix: preserve native VLM inline math through exports - #4908
PierreMesure wants to merge 4 commits into
Conversation
|
✅ DCO Check Passed Thanks @PierreMesure, all your commits are properly signed off. 🎉 |
Merge Protections🟢 Merge protection satisfied — ready to merge. Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
|
Combined the changes from #4906, #4907, #4908, and #4909 in an isolated worktree and ran the focused parser suites together: 119 passed, 1 skipped on Python 3.12. The skipped case requires an external Ollama server. The Nemotron changes overlap in the imports and section-header emission block. When rebasing after the other PRs land, retain all shared-helper imports, the corrected heading-level conversion from #4906, and the returned heading item used for inline math here. Those combined paths passed the test run. Each PR currently targets |
AI triage (advisory)Checked commit The PR adds a shared math-aware Markdown renderer in CI safety: no concern found. A maintainer must still approve CI. 2 related pull request(s) in the same code
The |
There was a problem hiding this comment.
AI first review (advisory): blocker found
This review covers the full diff at 1d0bce45a7. It read the code and did not run it.
The shared renderer adds the marko gfm extension. gfm changes plain text that has no math, and the PR does not say so. Check that tildes and GFM block elements cannot corrupt text that now takes the math or emphasis path.
A maintainer makes the merge decision. This review never approves the pull request.
| return marko.Markdown( | ||
| parser=InlineParser if inline_only else marko.Parser, | ||
| extensions=[ | ||
| "gfm", |
There was a problem hiding this comment.
blocker: The gfm extension strips ~ characters and turns the text between them into strikethrough
The gfm extension of marko adds Strikethrough with the pattern (?<!~)(~|~~)([^~]+)\1(?!~). A single ~ is enough to trigger it. The renderer outputs <del>…</del>, and docling/utils/chandra_utils.py maps del to strikethrough formatting.
Trigger: a DOTS or Nemotron text block with two ~ and any math or emphasis, for example about ~5 m and ~10 m, where $x$ is the length. The output has no ~, and the text 5 m and is struck through. The block text changes, so content is lost. The base code did not load gfm, so this is a regression. Strikethrough is also a new formatting claim that the model did not make.
The extension also adds Table, Alert, and Url (autolink). InlineParser.__init__ filters the block elements, but marko calls add_element for extension elements after __init__. So Table and Alert are active again with inline_only=True. Native list and heading blocks can then be reshaped by pipe-table or > [!NOTE] text. A bare www. or http:// string becomes an <a> link.
Fix: remove "gfm" from extensions. Add Strikethrough explicitly only if DOTS needs ~~text~~. Add a regression test with two tildes and a math span, and assert that the ~ characters stay.
There was a problem hiding this comment.
Confirmed. In both DOTS and Nemotron, about ~5 m and ~10 m, where $x$ is the length exported with unintended strikethrough. GFM also registered Table and Alert after the inline parser had filtered block elements.
Fixed in 6372eeb. The shared renderer now loads GFM only for full Markdown pages. Native inline blocks keep literal tildes, pipe-table text, alert markers, and bare URLs. Full-page table parsing still works.
Added seven test cases. Six reproduce the regressions and failed before the fix; the seventh checks full-page tables with math. The targeted DOTS/Nemotron suite passes (67 tests). The combined four-PR suite passes (129 passed, 1 skipped). UV_NO_SYNC=1 make validate passes. The shared module and its tests are identical in #4789 (ab79d5b).
There was a problem hiding this comment.
AI first review (advisory): no blocker found
This review covers the changes since 1d0bce45a7 at 6372eebe65. It read the code and did not run it.
The earlier GFM finding is fixed. gfm now loads only for full-page parsing, so native inline blocks keep literal tildes, pipe tables, alert markers and bare URLs. The inline-only path is the same as the base DOTS parser setup, plus the math element. I found no new defect in the new changes.
Earlier findings
- fixed (blocker): The
gfmextension strips~characters and turns the text between them into strikethrough
A maintainer makes the merge decision. This review never approves the pull request.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
geoHeil
left a comment
There was a problem hiding this comment.
Reviewed 6372eebe65217caef506ab480040c70434defc3b. One blocker remains in markdown_math.py.
A native block with Price $5-$10 and $x$. creates formulas 5- and x in both DOTS and Nemotron. Export changes the price to Price $5-$ 10 and $x$ .. Base preserves the price text. Keep currency ranges as text. Add a cross-adapter regression that checks the formula list and the exported price.
The prior GFM fix is correct. Local parser tests: 58 passed. Current CI is green. Codecov patch coverage is 97.01493%.
Local make check stops on file-length violations that already exist on base. The other read-only checks pass. I made no source or reference-data changes.
Share a math-aware Markdown renderer between DOTS and Nemotron. Keep code and currency literal and retain each native block as its coordinate owner. Fixes 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>
6372eeb to
6992439
Compare
|
Confirmed the currency-range blocker and fixed it in 6992439. Added eight cross-adapter cases for hyphen/en-dash ranges, decimals, and thousands separators, plus a shared-renderer case that includes numeric math. Six cross-adapter cases failed before the fix. All now pass. Rebased onto current main ( |
|
#4789 adds the same Small points:
|
geoHeil
left a comment
There was a problem hiding this comment.
Reviewed 699243912782f59fe273ebe16d40573095fa3e46. One blocker remains: titles and section headings with math lose their text in chunk heading metadata. See the inline finding.
The earlier currency and GFM findings are fixed. Local focused parser, export, and heading suites: 115 passed. CI passes at this head. The new export tests do not check chunk metadata, so they do not catch the remaining defect.
Local make check stops on file-length failures already present on base. The other read-only checks complete; ty reports warnings. Model inference and the full repository test suite were not run locally. No source or reference data changed.
|
Thanks both for the review! Let's merge this one first, I'll address your comments now. |
Signed-off-by: Pierre Mesure <pierre@mesu.re>
|
@dolfim-ibm Following up on your review: #4908 should land before #4789, once the core heading dependency below is resolved. Then #4789 can rebase and drop its copies of the shared renderer and tests. The shared files currently differ because of the review fixes in this PR. The parser changes are in e219b3a:
The heading finding is tracked in docling-core#925, with the fix in docling-core#924. It preserves serialized heading metadata and consumes the inline children so they do not become body chunks. This PR still needs a core release containing that fix, a dependency/lock update, and the four prepared cross-adapter chunk metadata regressions. Local focused validation: 118 tests pass with locked core 2.103.1; 122 pass with the companion core fix and the four prepared regressions. Changed-file validation hooks pass. The PR description now records the dependency and merge order. |
Nemotron Parse 2.0 and DOTS stored inline LaTeX as ordinary text, so Markdown export escaped subscripts or interpreted math asterisks as emphasis. Both adapters now use a shared math-aware renderer and the rich HTML mapper to produce formula items while preserving native block types, coordinates, surrounding text, code, and escaped currency.
Native inline blocks keep literal tildes, pipe-table text, alert markers, and bare URLs. GFM loads only for full Markdown pages. Non-math Nemotron regions keep their existing conversion path. Plain code-only DOTS blocks keep their literal-text behavior. The branch retains the upstream heading normalization and formula helpers from #4964 and the DOTS fixes for escaping, line breaks, and setext headings.
Currency ranges such as
Price $5-$10 and $x$.remain text and create only thexformula. Numeric math such as$5$and$2+2$still parses as math. DOTS literal protection now shares the same math delimiter rules. Parser instances are reused per thread and mode to avoid concurrent document state leaks. The math renderer falls back to escaped literal text when a match is unavailable.Remaining heading dependency: docling-core#924 preserves rich title and section-heading context in hierarchical chunks and prevents heading children from becoming body chunks. The heading blocker remains open with locked docling-core 2.103.1. After that fix is released, update the minimum core dependency and lock, and add the four prepared DOTS/Nemotron Title/Section-header chunk metadata regressions. Those tests pass with the companion fix and fail with locked core; they are not included in this branch yet.
Land this PR before LightOnOCR #4789. Rebase #4789 to use the shared renderer and tests from this PR; the shared files currently differ because of these review fixes.
Resolves #4904. Related to #2352; this addresses VLM response conversion, not formula recognition in the standard PDF pipeline.
Validation on Python 3.12.10:
Checklist: