feat(vit-gpt2): add CPU image-captioning recipes - #1122
Conversation
|
Independent pre-PR review: APPROVE. Scope is coherent: the nested-config JSON fix is generic and regression-tested; all four CPU recipes parse and retain the auto-config export/optimizer/loader contract; genuine FP16 is evidenced by initializer dtypes; encoder and decoder pass L0-L3 in both CPU precisions; and examples/recipes/README.md is untouched. Coverage annotation: partial because this host exposes CPU runtime only. All 26 required EP/device/precision tuples are nevertheless enumerated, and static analysis is not represented as accelerator runtime validation. |
6ea6dd9 to
c60f91e
Compare
c60f91e to
17b8002
Compare
REQUEST_CHANGESI independently reviewed PR #1122 at head Blocking issue
Reviewed scope and engineering resultThe live exact-head diff contains 10 files (the supplied six-file expectation is stale): three shared source files, three regression files, and four CPU recipes. Task normalization is gated by registered composite support; processor composition is capability-based; caption caps apply only to multi-reference rows; explicit/unregistered task behavior and OCR scalar semantics are preserved. No shared-source model-ID branch exists. All four recipes have the correct target paths, eager attention, exact encoder/decoder identities, fp32 The three threads resolved by removal are substantiated: Independent reruns
All used the existing locked venv with Frozen L0-L3 and Analyze evidence
GitHub and handoff stateImmediately before publication: PR is OPEN/DRAFT with Handoff hashes verified: charter |
17b8002 to
4679e50
Compare
Summary
Adds current-main CPU support for
nlpconnect/vit-gpt2-image-captioning, a ViT/GPT-2 image-captioning composite, with FP32 and materially realized FP16 encoder/decoder recipes. The L2 contribution generalizes task normalization, multimodal processor composition, and bounded caption evaluation; the final tester reached L3 PASS with full coverage of the committed CPU FP32/FP16 component tuples.examples/recipes/README.mdremains unchanged.Model metadata
What the model does
An image-captioning encoder-decoder model that transforms one RGB image into an English natural-language caption: a ViT encoder produces visual patch states and a cross-attentive GPT-2 causal decoder generates caption tokens.
VisionEncoderDecoderModelwith nested ViT and GPT-2 components; real-image PyTorch and split-ONNX generation both produced English captions. Confidence: verified.Primary user stories
generated_textcaptions as output. Confidence: verified.Supported tasks
image-to-text; Optimum registersvision-encoder-decoderforimage-to-textandimage-to-text-with-past; WinML registers theimage-to-textcomposite and emitsimage-feature-extractionplustext2text-generationcomponents. Confidence: verified.TasksManagerauto-detection returnsimage-text-to-text, while the prior WinML ONNX export boundary rejected that alias. Confidence: verified.Model architecture
VisionEncoderDecoderModel, WinMLVisionDecoderWrapper, and final encoder/decoder ONNX graph contracts and hierarchy tags. The matching 768-wide encoder and decoder require no projection module. Confidence: verified.Validation and support evidence
Baseline
The full current-main baseline was rerun at
e564a6375d6cd2b596fb3d21d918f07824b349e0using WinML0.2.0package metadata (0.3.0in the sourcepyproject.toml), Python 3.11.9, Transformers 5.14.1, Optimum 2.1.0, ONNX 1.18.0, and ONNX Runtime Windows ML 1.24.5.202604171637.image-text-to-text; WinML had no matching exporter composite, and build exited 2 after 27.214 s. This established a capability floor, not a reason to stop at L0.image-to-textconfig: PASS, emitting exactly animage-feature-extractionencoder andtext2text-generationdecoder. Diagnostic component builds passed in 79.696 s and 149.209 s with no semantic CLI overrides.a herd of giraffes and zebras grazing in a field; ONNX generateda herd of giraffes standing in a field; exact tokens differed but both were semantically coherent.AutoProcessorresolved to a tokenizer-onlyTokenizersBackend, not aProcessorMixin, so no metric was emitted.image-to-textandimage-to-text-with-past; WinML additionally exposedfeature-extractionandtext2text-generationfor the composite.Goal
Success required encoder and decoder builds for CPU FP32 and FP16; material FP16 realization; complete named decoder inputs, 12 KV layers, and 24 present outputs; perf for every artifact; tensor/KV/generation parity reporting; one deterministic 1-2-row COCO smoke with all fan-out dimensions capped; and component- plus op-level static analysis for every artifact. The charter was not re-issued and the ceiling was not downgraded.
Outcome
L2 shipped; L3 PASS; coverage: full. All committed CPU FP32/FP16 encoder and decoder tuples passed L0 and L1, L2 passed for both precisions, and exactly one bounded L3 functional smoke passed. There are no deferred tuples and no final blockers.
The PR contains four recipe paths and exactly these six source/test paths:
src/winml/modelkit/loader/resolution.pysrc/winml/modelkit/inference/pipeline.pysrc/winml/modelkit/eval/image_to_text_evaluator.pytests/unit/loader/test_detect_task_and_class.pytests/unit/inference/test_pipeline.pytests/unit/eval/test_image_to_text_evaluator.pyThe four model findings
vision-encoder-decoder-005throughvision-encoder-decoder-008capture processor/recipe/KV contracts, FP32/FP16 realization and perf, numeric parity plus coherent generation divergence, and static component/EP findings. They are maintained separately in the draft Lane A skill PR #217 at commit0bef530285b785641504038232b03b0be45c3009. That PR also records methodology finding_meta-109; methodology was updated with paired tester/reviewer guidance for deterministic static-provider analysis without changing this PR's tester verdicts.Per-EP/device/precision results and Functional smoke Eval
All four ONNX artifacts passed checker validation at IR 8 / opset 17. FP32 initializers were encoder
{FLOAT: 200, INT64: 6}and decoder{FLOAT: 254, INT64: 43, BOOL: 1}; FP16 initializers were encoder{FLOAT16: 200, INT64: 6}and decoder{FLOAT16: 254, INT64: 43, BOOL: 1}. Decoder artifacts retained 12 past-key/value layers and 24 present outputs. Schema-v2 model precision wasfp32/fp16; benchmark precision wasautofor FP32 andfp16for FP16.Assembled greedy generation also passed: FP32 took 2.8438051999546587 s (3.868056785385786 tokens/s) and FP16 took 3.172113100066781 s (3.4677199875907396 tokens/s). Component latencies above are not summed or mislabeled as end-to-end caption latency.
L2 numeric parity: PASS. FP32 encoder cosine was 0.9999999999987601, logits cosine 0.9999999999999883, and minimum present-KV cosine 0.9999999999997096. FP16 encoder cosine was 0.999999639303887, logits cosine 0.9999999921532873, and minimum present-KV cosine 0.9999997401972208. In both precisions, generation first diverged at token index 8: PyTorch selected token 5671 (
monitor) and produceda desk with a computer and a monitor; WinML selected token 5118 (chair) and produceda desk with a computer and a chair. Token sequences were not exact; both captions were coherent, and the divergence is reported rather than hidden.Functional smoke Eval: PASS. Exactly one final-candidate FP32 CPU run used
LIME-DATA/COCO-Caption2017revisionb14474455722b8c56eb7cdeb3f6be76fca1bba7a, streamingtrain, deterministic first two rows with no shuffle. It processed 2 and skipped 0. Caps were one candidate prompt, one beam, one frame/crop, generation length 32, and five references per image. Input schema, reference-label semantics, and generated-caption semantics were verified. It emitted CIDEr 0.8427 and CER 0.6316. This single bounded run is end-to-end operability evidence only, not representative accuracy or benchmark quality. The former blocker was tokenizer-onlyAutoProcessor; generalized image-processor/tokenizer composition removed it.Delta
Recipe paths:
examples/recipes/nlpconnect_vit-gpt2-image-captioning/cpu/cpu/image-to-text_fp32_config_encoder.jsonexamples/recipes/nlpconnect_vit-gpt2-image-captioning/cpu/cpu/image-to-text_fp32_config_decoder.jsonexamples/recipes/nlpconnect_vit-gpt2-image-captioning/cpu/cpu/image-to-text_fp16_config_encoder.jsonexamples/recipes/nlpconnect_vit-gpt2-image-captioning/cpu/cpu/image-to-text_fp16_config_decoder.jsonBoth FP32 recipes are identical to current auto-config. The FP16 recipes are identical except
/quantchanges fromnullto the complete current generated FP16 block (mode=fp16,fp16_keep_io_types=true) for the required precision contract. Shared invariants remain: eager Transformers attention, no eval block, no SROIE reference, and the decoder's 12 past-key/value layers plus 24 present outputs. Recipe invocation used no recipe-owned semantic CLI overrides; FP16 used only the current--precision fp16selector. No-recipe inspect/config/build/eval acceptance passed, reducibility is consistent with the charter, andexamples/recipes/README.mdis untouched.Bug fix explanation
image-text-to-text, which WinML could not export as the registered image-captioning composite; Eval then failed before processing becauseAutoProcessorsupplied only tokenizer behavior.AutoProcessorobject always carried image preprocessing, tokenization, decoding, and decoder-start behavior.resolve_tasknormalizes auto-detectedimage-text-to-texttoimage-to-textonly for model types with a registered WinML composite._ImageToTextProcessor,_load_image_to_text_processor,_pipeline_component_kwargs, andcreate_pipelinepreserve completeProcessorMixinobjects or composeAutoImageProcessorwith the tokenizer-only result, validate required capabilities, and usedecoder_start_token_idfor empty caption prompts.WinMLImageToTextEvaluator.computebounds multi-reference caption generation to 32 new tokens and one beam while preserving scalar OCR behavior.image-text-to-text; WinML's public composite remainsimage-to-text; complete processors are returned unchanged; non-empty prompts preserve tokenizer output; scalar OCR calls and CER semantics remain unchanged. Intentional changes are alias normalization for registered composites and bounded caption smoke generation.There is no stale
scripts/e2e_evalchange in this contribution.Analyze summary - component level and op level
PASS: complete component- and op-level static rule analysis was recovered for all four final artifacts. This is static compatibility analysis, not runtime execution or accelerator validation.
Component-level summary
Addunsupported,ScatterND/Whereunknown. QNN GPU:Concat/Gatherpartial,LessOrEqualunsupported,ScatterND/Whereunknown. QNN NPU:Gatherpartial,ScatterND/Whereunknown. NvTensorRTRTX GPU:ScatterND/Whereunknown.Graph-support nodes outside repeated module scopes remain an explicit partial semantic region.
runtime.generationis runtime-only; no ONNX node mapping is fabricated for it.Op-level summary
Rule-less EP groups CPU, CUDA, MIGraphX, TensorRT, and DML have all operator types unknown; this is not a runtime failure claim.
Reproduce commands