Add optional segment_boxes to /markdown and /html to skip re-analysis - #138
Merged
ali6parmak merged 1 commit intoJul 13, 2026
Merged
Conversation
Callers that already ran layout analysis on a document (e.g. via POST /) can now pass those segments back into /markdown and /html to skip a redundant re-analysis pass, mirroring the segment_boxes pattern /toc_from_xml already uses. - Both endpoints accept an optional segment_boxes form field (JSON list, same shape as POST /'s response); when present, analysis is skipped entirely and the given segments are converted directly. - Malformed segment_boxes JSON returns 422 via the existing catch_exceptions handling (no new error handling needed). - Unit tests for both use cases verify analysis is skipped when segment_boxes is provided and unchanged when it isn't (including fast mode). - End-to-end tests verify /markdown and /html output is identical with and without reusing segment_boxes, and that malformed payloads 4xx. In a downstream pipeline that already calls POST / for analysis, this cut markdown+html conversion from 3 HURIDOCS calls per document to 1, a ~60-67% reduction in end-to-end processing time.
Collaborator
|
Thanks for the PR, merging. |
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.
Motivation
Callers that already ran layout analysis on a document — most commonly via
POST /— have no way to reuse those segments when subsequently calling/markdownor/html. Today both endpoints always re-run analysisinternally, even when the caller already has an equivalent, freshly-computed
segment list in hand. For a pipeline that calls
POST /once and then/markdownand/or/htmlfor output, that's up to 3 analysis passes over thesame document where 1 would do.
This mirrors a pattern already in this codebase:
/toc_from_xmlaccepts asegment_boxesform field and skips analysis entirely, using the caller'ssegments directly. This PR extends the same idea to the two conversion
endpoints.
Design
segment_boxes: optional JSON-encoded list of segment dicts (same shape asPOST /'s response), added as aFormfield on/markdownand/html,parsed the same way
/toc_from_xmlalready parses its ownsegment_boxes.ConvertToMarkdownUseCase.execute/ConvertToHtmlUseCase.execute, whensegment_boxesis provided it's used as the analysis result directly(skipping both
analyze_pdf_layoutandanalyze_pdf_layout_fast); whenabsent, behavior is completely unchanged (including
fastmode routing).PDFAnalysisService, the conversion services, or theClean-Architecture layering —
segment_boxesflows in as a use-caseparameter, not a driver-level hack, consistent with
extract_toc,dpi, etc.segment_boxesraisesJSONDecodeError, already caughtby the existing
@catch_exceptionsdecorator and turned into a422, sono new error handling was needed.
Evidence
From pepng (a downstream consumer, not part of this PR) reprocessing the same
fixtures with and without segment reuse — end-to-end pipeline duration,
INGEST started→COMPLETE completed:table-bordered.pdftable-merged.pdftwocol-continuous.pdfThe engine's own logs confirm the skip (this PR adds the equivalent log
lines, matching
/toc_from_xml's existing logging style):Output was verified byte-for-byte identical with vs. without segment reuse
across three fixtures (
document.md,document.html,document.json).Test coverage
src/use_cases/markdown_conversion/test_convert_to_markdown_use_case.py,src/use_cases/html_conversion/test_convert_to_html_use_case.py, new inthis PR): analysis is skipped when
segment_boxesis given (asserted via aPDFAnalysisServicestub that raises if called), and unchanged (includingfast-mode routing) when it isn't.
src/tests/test_end_to_end.py, new in this PR, runagainst the real service):
/markdownand/htmloutput is identical with vs. without reusingsegment_boxesfrom a priorPOST /call, ontest_pdfs/regular.pdf.segment_boxes("not-json") returns422for bothendpoints, not
500.passing (
src/tests/test_end_to_end.py, includes the 4 new tests above):built natively on a DGX Spark (ARM64, NVIDIA GB10 GPU) via
docker build --build-arg BUILDER_IMAGE=nvidia/cuda:13.0.3-cudnn-devel-ubuntu24.04 --build-arg TORCH_INDEX_URL=https://download.pytorch.org/whl/cu130 --build-arg TORCH_CUDA_ARCH_LIST=12.0;12.1,run on a non-default port, verified against the live GPU-backed engine (not
mocked), then torn down.
black --check --line-length 125clean on all changed files.verified on aarch64 instead as that's the available hardware. No GPU-less
CPU-only run was attempted (out of scope — this change has no CPU/GPU
branching).
What wasn't run and why
test.yml, GitHub Actions, amd64) wasn't triggered —this is a fork branch, not yet a PR, so Actions haven't run. All tests
above were run manually against a natively-built image on aarch64
hardware instead.
for this change since
segment_boxesdoesn't interact with translation;the existing translation tests are part of the "full suite" pass above and
passed unmodified.