Add LayoutLM v1 document-question-answering support (impira/layoutlm-invoices) - #1096
Add LayoutLM v1 document-question-answering support (impira/layoutlm-invoices)#1096ssss141414 wants to merge 10 commits into
Conversation
37278b0 to
175b8e7
Compare
c3bb569 to
4c0ec9a
Compare
APPROVE — PR #1096 independent final reviewReviewed state
12-file engineering assessment
The full diff was read line-by-line. The design is generalized, minimally scoped for Outcome L1, and consistent across auto-config, explicit recipes, and perf. No production Structured bbox invariantsIndependent final-SHA runtime verification regenerated default inputs and ran CPU ONNX inference against exact fp32, exact fp16, and recipe-free fp32 artifacts. For all three paths:
The tester's six-path repair validation additionally covers auto-config/Optimum, exact fp32 Independent local quality gatesAll commands were actually executed from the isolated exact-SHA checkout with the repository environment:
The exact invocations were the current workflow-parity Ruff/mypy commands and each complete non-hardware pytest partition. The checkout retained no tracked modification; only ignored reviewer evidence was created. Artifact and runtime rerun evidenceArtifact structure and precision:
Independent bounded semantic-input artifact perf reruns:
The slower fp16 CPU result is reported without a speedup claim; fp16's validated benefit here is the halved external weight data. Exact-SHA GitHub checksThe live PR
No exact-SHA check is queued, in progress, cancelled, skipped, or failed. Threads, comments, and reviewsThe GitHub conversation gates were executed and then rechecked live after the final-SHA checks:
There is no unresolved external feedback to route. PR body, draft, and label state
Lane A methodology commit verification
Final dispositionAPPROVE. The exact PR SHA is green locally and on GitHub, the 12-file change is engineering-sound, every applicable bbox-generation path now enforces the real relational input contract, exact fp32/fp16 runtime evidence passes, the PR remains a correctly labeled draft, all discussion counts are zero, and the Lane A methodology correction is present at the cited exact commit. |
19177bc to
37805dc
Compare
REQUEST_CHANGES - PR #1096 independent final reviewReviewed state
Actionable findings
Independent validation
GitHub gate
Owner routing: finding 1 -> producer (then tester reruns metric/focused/commands evidence and learner/explainer refresh downstream claims as needed); finding 2 -> explainer with tester-owned Analyze command/provenance retained. |
|
Addressed both blocking items in commit
|
APPROVE - PR #1096 independent reviewer iteration 2Reviewed state
Prior findings closure
Independent validation
GitHub gate
No owner actions remain. This is a skill-level normal-comment approval only; it does not change GitHub review state or authorize moving the PR out of draft. |
|
|
||
| from .metrics import ANLSMetric | ||
|
|
||
| input_names = set((getattr(self.model, "io_config", None) or {}).get("input_names", [])) |
There was a problem hiding this comment.
load_native_hf_model() returns a plain Hugging Face module, which does not expose io_config. For --runtime pytorch, this therefore produces an empty set and every document-QA evaluation fails at the bbox check even though LayoutLMForQuestionAnswering.forward accepts bbox. Please fall back to inspecting the native model's forward signature when io_config is unavailable (the keypoint evaluator already uses this ONNX-config-or-forward-signature pattern).
There was a problem hiding this comment.
Fixed in 4513fee267ad15d8244619d1ef308d302a057366. Native document-QA input discovery now falls back to forward signature inspection when io_config is absent, filters optional training/alternative arguments, and retains evaluator-provided bbox and fallback token_type_ids.
Independent final-SHA smoke with impira/layoutlm-invoices processed one real DocVQA row: prediction DORAL, ANLS 1.0; the native forward received input_ids, bbox, attention_mask, and token_type_ids. The focused evaluator suite and full CI partitions also passed.
| f"Tokenizer did not produce declared model input '{input_name}'." | ||
| ) | ||
| with torch.no_grad(): | ||
| outputs = self.model(**model_inputs) |
There was a problem hiding this comment.
The assembled tensors need to be moved to self.config.pipeline_device before this call. With --runtime pytorch --device gpu, the native loader places the model on CUDA, but the tokenizer outputs, bbox, and fallback token_type_ids created above remain on CPU, so inference fails with a device-mismatch error. Moving each assembled tensor (or constructing the new tensors directly on the target device) preserves CPU/WinML behavior and enables GPU evaluation.
There was a problem hiding this comment.
Fixed in 4513fee267ad15d8244619d1ef308d302a057366. All assembled inputs are moved to config.pipeline_device after bbox and fallback token_type_ids are created. The regression covers a non-CPU (meta) target, and the independent real CPU smoke observed all four forwarded tensors on CPU.
Validation: 6,154 ordinary CI tests passed; Ruff passed; mypy passed across 443 source files; sealed independent evidence reverified 53/53 files.
Summary
This PR adds stock LayoutLM v1 document-question-answering support for
impira/layoutlm-invoices, including metadata-derived export/input handling, a bounded document-QA evaluator with ANLS, and verified CPU recipes for fp32 and fp16. The committed scope is Effort L2 / Outcome L2, and tester validation at candidate29f169eae33406bd4072a9d67d3a7d4b28985c53reached the Goal L3 ceiling withL3 PASSand full planned tuple coverage. Support is intentionally limited to the stockLayoutLMForQuestionAnsweringcontiguous start/end span head; a custom non-consecutive-token classifier head is not implemented or claimed.Model metadata
What the model does
This English LayoutLM v1 checkpoint scores extractive answers in invoices and other documents. A caller supplies OCR-derived token IDs, normalized token bounding boxes, an attention mask, and token-type IDs; the concrete Transformers class returns per-token start and end logits. Image/PDF decoding, OCR, token-box alignment, and answer decoding are outside this neural forward path.
fdf56765f8bdf236b2bd45d23347066475aa730aidentify invoice/document question answering, DocVQA/SQuAD2.0 fine-tuning,model_type=layoutlm, andLayoutLMForQuestionAnswering; Transformers 5.14.1 exposes the four-input forward signature andQuestionAnsweringModelOutput(verified).Primary user stories
verified).verified).Supported tasks
document-question-answering: declared by the checkpoint's Hugging Face metadata and model-card frontmatter (verifiedon the checkpoint surface).question-answering: Transformers selectsLayoutLMForQuestionAnswering; WinML maps LayoutLM QA to the canonical exporter and emitsstart_logits/end_logitswhile the contribution supplies document-aware preprocessing and evaluation (verifiedon the Transformers and WinML surfaces).Model architecture
hidden_size=768, 12 layers, 12 heads,intermediate_size=3072, GELU) and Transformers 5.14.1 LayoutLM constructors (verified).Validation and support evidence
1. Baseline
2b9ec0e9e57bba8003d25eaff85f8c7c9e30d75a, WinML0.3.0.FULL-RERUN. Main had moved from the previous validated baseline, and changes reached runtime/configuration/dependency, Eval, Analyze, and quality-gate surfaces, so the planner refreshed the complete baseline instead of reusing stale measurements.WINML-ONLYfor that task.AutoModelForNextSentencePrediction; Transformers rejectedLayoutLMConfig. The build exited 2 after 26.502 s and produced no ONNX model. A diagnostic explicit-QA build also failed after 33.68 s during input generation/export withindex out of range in self.BLOCKED-NO-ARTIFACT; neither baseline build produced a complete model to benchmark.document-question-answeringwas unsupported and exited 2. The existingquestion-answeringschema exited 0 but required text-only SQuAD question/context/id/answers columns and was incompatible with OCR words, boxes, and images.logitsoutput. The shipped recipes replace these values with the metadata-derived document-QA contract detailed below.2. Goal
L2.L3.L2.FULL-RERUN; no downstream role changed the committed E/G/O tiers.3. Outcome
L2.L3 PASS.full; no planned(EP, device, precision)tuple was deferred.29f169eae33406bd4072a9d67d3a7d4b28985c53.examples/recipes/impira_layoutlm-invoices/cpu/cpu/question-answering_fp32_config.jsonandexamples/recipes/impira_layoutlm-invoices/cpu/cpu/question-answering_fp16_config.json.src/winml/modelkit/.tests/unit/commands/,tests/unit/eval/,tests/unit/export/, andtests/unit/loader/.layoutlm-009throughlayoutlm-014record separate fp32/fp16 CPU build/perf/parity evidence, complete component mapping, operator/rule classification, fallback task and input-contract behavior, and the bounded strict-boundary ANLS 0.0 smoke. They remain in the separate skill knowledge lane, not this product PR.4. Per-EP/device/precision results and Functional smoke Eval
Goal ladder
L0 build and structure
input_ids [1,512],bbox [1,512,4],attention_mask [1,512],token_type_ids [1,512]->start_logits [1,512],end_logits [1,512]input_ids [1,512],bbox [1,512,4],attention_mask [1,512],token_type_ids [1,512]->start_logits [1,512],end_logits [1,512]L0/L1/L2 and component/op Analyze were executed at
be919c416b51949a77aacdb16725d6cec8f33360and reused with verified no-impact provenance. The tester verified 95 source-integrity entries with zero mismatches and proved that the changes through final candidate29f169eae33406bd4072a9d67d3a7d4b28985c53did not touch graph, config, recipe, or runtime-producing paths. L3, strict ANLS boundary evidence, affected evaluator regressions, current-SHA CI partitions, Ruff, mypy, license, and the exact public pinned-rules Analyze sequence were rerun or revalidated for the final semantic binding.L1 perf
L2 named-input parity
Parity used named
input_ids,bbox,attention_mask, andtoken_type_idsinputs for pinned DocVQA row 0, question ID 9951.Functional smoke Eval
Verdict:
PASS. This is one-row end-to-end operability evidence only; it is not representative accuracy and is not a benchmark-quality claim.29f169eae33406bd4072a9d67d3a7d4b28985c53; FP32 onCPUExecutionProviderthrough ONNX Runtime.pixparse/docvqa-single-page-questions, revision33136ef456fa5a3fe68568d6e31dda4eeff95b9b, default config, train split, filedata/train-00000-of-00036.parquet, row group 0, row 0, question ID 9951.7 - 1 - 99/addition; prediction logit score-13.570242881774902.ANLS=0.0. The evaluator, document inputs, contiguous OCR-span prediction, and strict-boundary metric path operated end to end; the low value is model output quality on this single row, not a failed smoke.< 0.5retains similarity; distance>= 0.5scores0.0. Revalidated cases were distance0.3333333333333333-> direct similarity0.6666666666666667/ aggregate0.6667; distance0.5->0.0; and distance0.75->0.0.input_ids [1,512],bbox [1,512,4],attention_mask [1,512],token_type_ids [1,512].max_windows=1; windows processed 1;doc_stride=128;top_k=1;max_answer_words=64.n_samples=1, skipped 0, windows processed 1.5. Delta
The recipes were structurally compared with the frozen generated baseline after removing
_notefields. They are changed, not identical.examples/recipes/README.mdremains untouched./loader/tasknext-sentence-predictiondocument-question-answering/loader/model_classAutoModelForNextSentencePredictionLayoutLMForQuestionAnswering/export/input_tensors/*/shape/1514512/export/input_tensors/1/value_range/111001/export/input_tensors/3/value_range/121type_vocab_size=1; only token type 0 is legal./export/output_tensorslogitsstart_logits,end_logits/export/compatibility/transformers_attentioneagereager/eval/quantnullRecipe-free acceptance also passed: the generalized code path produced a four-input, two-output fp32 ONNX model without relying on a checkpoint-specific recipe override. The recipes remain exact evidence artifacts for the two verified CPU precision tuples.
Bug fix explanation: task resolution and task-boundary normalization
impira/layoutlm-invoicesresolution selected next-sentence prediction and failed before export; an early broad QA suffix implementation also regressed four sibling task-resolution cases.loader/resolution.pyadds fallback-onlyForQuestionAnsweringsuffix inference witharchitecture-suffixprovenance and restores the existing string return contract;loader/task.pymaps publicdocument-question-answeringto canonicalquestion-answeringonly at loader/export boundaries. The final repair also narrows evaluator tokenizer typing without runtime behavior change.impira/layoutlm-invoicesor any checkpoint ID.*ForQuestionAnsweringheads use the fallback.question-answering / LayoutLMForQuestionAnswering / architecture-suffix; all final quality partitions passed.Bug fix explanation: LayoutLM metadata-derived export and runtime inputs
index out of range in self; generated sequence length 514, token type 1, and unusable bbox bounds violated this checkpoint's embedding constraints.type_vocab_size=1,max_2d_position_embeddings, or concrete QA output contract.models/hf/layoutlm.pyderives usable sequence length, token-type range, bbox range, QA I/O, and concrete model-class mapping; the QA runtime wrapper forwardsbboxonly when the ONNX graph declares it; registration modules expose the mapping.Bug fix explanation: bbox and integer-range generation
core/model_input_generator.pyandonnx/io.pygenerate ordered positive-area coordinates for declared rank-3 bbox tensors ending in dimension 4;commands/perf.pypreserves high-exclusive semantics when calling inclusive generators.Bug fix explanation: document-QA evaluation and strict ANLS boundary
document-question-answeringhad no WinML evaluator/schema, and the first ANLS implementation incorrectly awarded0.5at exact normalized edit distance0.5for predictionaband referencea.similarity >= 0.5condition made the canonical strict distance boundary inclusive.normalized_levenshtein_similaritynow retains similarity only for normalized edit distance< 0.5(equivalently similarity> 0.5), while evaluator/schema/default-dataset registrations expose the first-class task.0.0canonically.test_anls_uses_strict_normalized_distance_thresholdcovers distance0.3333333333333333->0.6666666666666666, exact distance0.5->0.0, and distance0.75->0.0; tester boundary evidence passed the same three cases. The affected document-QA file passed 12 tests, the Eval partition passed 637 tests with one non-failing warning, and the final one-row smoke remainedANLS=0.0at29f169eae33406bd4072a9d67d3a7d4b28985c53.6. Analyze summary - component level and op level
ANALYZE-PARTIAL-SUCCESS: the retained fp32 and fp16 central-rule analyses exited 1 because four emitted GPU rows had no rule data; both JSON payloads remained parseable and complete for all seven emitted rows. This is static rule-backed compatibility analysis, not runtime execution. The exact public r4 sequence independently verified pinnedv0.3.0rules acquisition and produced 12 complete result rows with exit 1 under the same partial-success semantics.Component-level summary
Op-level summary
Rule-less GPU rows for CUDA, MIGraphX, TensorRT, and DML had no rule data; they are not runtime failures and are the reason the retained two-artifact Analyze status remains
ANALYZE-PARTIAL-SUCCESSwith exit code 1 for each artifact.7. Reproduce commands