Skip to content

Qualify complete Qwen3.8-27B standard-only VLM export - #758

Open
titaiwangms wants to merge 5 commits into
mainfrom
test/qwen38-27b-standard-onnx
Open

titaiwangms wants to merge 5 commits into
mainfrom
test/qwen38-27b-standard-onnx

Conversation

@titaiwangms

@titaiwangms titaiwangms commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Goal and scope

Deliver the complete Qwen/Qwen3.8-27B vision-language package using standard ONNX operators only: 27-layer vision encoder, embedding/fusion, and the full 64-layer hybrid decoder (48 DeltaNet + 16 full-attention layers, dense MLP). Optional text-only export retains all hybrid decoder layers.

ModelBuilder/native operator equivalence and controlled performance remain deferred. Ordinary packaging and the existing --runtime ort-genai route are now covered by the bounded CUDA native qualification below; other runtime builds/platforms and full numerical equivalence remain unqualified. A complete real-weight standard-only artifact now exists; official FP16 numerical qualification is still failing.

Changes

  • Retain the initial text-only builder support, explicit FP32 recurrent-state contract, and Qwen3.5 fixed 1e-6 Q/K normalization epsilon.
  • Extend pinned-config construction and reduced CUDA qualification to the complete three-component VLM.
  • Cast processor-native FLOAT32 packed pixels to the model dtype inside the shared Qwen3/Qwen3.5 vision wrapper.
  • Recognize both image and video placeholders and use batch-global feature indices. The existing image_features input contains visual rows in flattened batch/token placeholder order; no new graph input is required.
  • Preserve FP32 learned-offset RMS normalization and 1 + weight scaling until the final activation cast. A nonzero learned-offset test reproduced premature FP16 rounding before the fix.
  • Document the packed-feature and state contracts, completed evidence, and remaining failures.

Offline and reduced-model evidence

Selection Result Scope
Full pinned-config graphs FP32/FP16 pass All 64 decoder + 27 vision layers; no real-weight allocation
Initial focused text/full-VLM qualification 34 passed, 0 skipped Recursive standard schemas/domains, package roundtrip, reduced CUDA parity
Related offline regressions 102 passed, 16 existing skips Separate selection, not additive with the later 102-test run
After learned-offset norm correction 102 passed, 0 skipped Affected RMS/dtype/attention/decoder components and focused Qwen qualification
Additional DeepStack sentinel regression 2 passed Two maps, B=2 reversed mixed-media order, and zero-media input
Scoped Ruff/format and whitespace Pass Changed source/tests

The 14 reduced VLM CUDA combinations cover FP32/FP16 text, multi-image, video, and mixed media, including two-row batches. Actual saved/reloaded ONNX vision outputs feed ONNX fusion and the hybrid decoder. Prefill plus four reused-state decode steps compare full logits, exact greedy IDs, and all convolution/recurrent/KV states. CUDA profiling requires actual matrix execution, not merely provider registration; it does not assert every node runs on CUDA.

Pixels are nonzero synthetic packed inputs. HF supplies explicit MRoPE positions. These tests do not establish official processor/host-position correctness or official-checkpoint accuracy. The earlier text-only stage's 361-test evidence and baseline-equivalent MyPy diagnostics are prior-stage results, not fresh full-VLM-revision checks.

Official complete checkpoint export

  • Source revision: 1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0.
  • Raw config SHA256: 191e0af232104ed8b65258cf3fb2b842e288008baca7633c11b82a1ac7203aab.
  • 18 official shards; 55,562,855,904 tensor bytes.
  • Complete corrected-source FP16 package: 54,779,987,399 bytes.
  • Components: decoder, vision_encoder, embedding, plus nine pinned processor/tokenizer/config assets.
  • Saved and reloaded all three components: recursive standard-domain/schema audit passed, zero local Functions, weights bound.
  • All three CUDA sessions loaded successfully.

The first serialization attempt timed out on strided folded tensors. A real production-matrix probe verified byte-identical output after C-contiguous conversion. The successful operational exporter copies only non-contiguous storage, verifies all bits/shapes/dtypes, then saves/reloads. No installed-library patch or generic Mobius serializer change is included.

All checkpoint/export/cache/temp payloads stay on disk5. Approved prior home experiment/download payloads were relocated (276 files, 121,376,498,834 bytes), with source symlinks and matching destination sizes verified. Repository/package fixtures were explicitly excluded. The original dirty checkout's branch, HEAD, 21 statuses and hashes were preserved.

Official runtime failures — not cleared

Environment: A100 CUDA, Transformers 5.15.0, PyTorch 2.13.0+cu130, ORT 1.30.0. Tolerance stayed rtol=atol=1e-2; failures were not hidden by changing it.

Stage Result
Official image vision Failed: 90 / 327,680 values outside tolerance (0.0275%)
Official text embedding Exact match
Corrected-source official text prefill logits Failed: 79,551 / 5,711,360 values outside tolerance (1.39%); max abs 0.091796875
Official greedy IDs / all states / cached generation Not completed: stopped at the preceding assertions
AI2D Paired 100- and 200-sample subsets completed; details below. Full 3,088-row test split not run.

Visual-only diagnosis strictly bound and checked all 333 official visual tensors. It reproduced extra FP16 rounding in separate MatMul/Add versus HF Linear, and in half-precision rotary arithmetic. Standard Gemm exactly matched the isolated QKV projection; FP32 rotary arithmetic matched locally. Their combined full-vision effect has not been established and neither is included as a claimed parity fix. Disabling optimization and wholesale FP32 execution also did not establish agreement with the original FP16 reference.

The learned-offset norm correction is independently grounded and tested but does not resolve the remaining full-decoder divergence. A per-layer numerical investigation remains necessary.

AI2D paired 100-sample evaluation (October 7, 2026)

The user selected a fixed 100-question comparison rather than the full 3,088-row benchmark.

  • Dataset: lmms-lab-encoder/ai2d, pinned revision c83a9b9692933aff8349157c88a413df9d02c4e5, test indices 0–99.
  • Protocol: pinned lmms-eval ai2d default MCQ prompt, filter and exact-match normalization at 08affba133b97b19351897f4d42081ead2b3412e; greedy generation with max_new_tokens=16.
  • Same pinned processor and original images, no manual resize; thinking disabled. ONNX uses the pinned HF MRoPE helper. Torch and ONNX generate independently with their own carried state, not teacher-forced shared tokens.
  • Complete FP16 Torch VLM versus the corrected standard-only three-graph ONNX package on separate A100s.
Metric Torch Standard-only ONNX
Correct answers 89 / 100 89 / 100
Subset accuracy 89.0% 89.0%
Invalid/unparseable responses 2 2
Median paired-evaluation generation latency 0.686 s 2.498 s

All 100 generated token sequences and decoded responses matched exactly. The valid-letter agreement metric is 98/100 because both models produced the same unparseable, 16-token-capped responses on indices 55 and 56; these were counted incorrect, not skipped. No sample was correct only in one backend. All 100 persisted records were independently re-scored and matched the summary.

This is a fixed-prefix subset result, not a full AI2D score or a general accuracy-equivalence claim. Logit parity remains failed: all 100 prefill last-position vocabulary comparisons exceeded the unchanged rtol=atol=1e-2; maximum absolute error across these comparisons was 0.453125. Task-answer agreement does not clear those numerical differences. The timings include each backend's current vision/decoder/cache-transfer path and are not optimized-runtime benchmarks.

Receipts: ai2d/first100/summary.json, ai2d/first100/predictions.jsonl, and ai2d/first100.log under the disk5 export task root. The initial pilot was blocked by transient GPU occupancy before producing any rows; it was retained as a failed receipt, and successful runs used explicitly distinct GPU UUIDs without terminating other processes.

AI2D paired 200-sample extension (October 7, 2026)

The same unchanged evaluator was run on test indices 0–199. This is HuggingFace generate() versus raw ONNX Runtime CUDA EP, with Python managing the three exported graphs and cache/position feeds. It is not an onnxruntime-genai compatibility test.

Metric Torch FP16 Standard-only ONNX FP16
Correct answers 175 / 200 174 / 200
Subset accuracy 87.5% 87.0%
Invalid/unparseable responses 3 3
Median paired-evaluation generation latency 0.730 s 2.971 s
  • Exact generated-token and decoded-response agreement: 199 / 200 (99.5%).
  • One backend disagreement: test index 124 (the 125th question), target C; Torch generated C ([34, 248046]), ONNX generated A ([32, 248046]). This is one Torch-correct/ONNX-wrong case and a 0.5 percentage-point subset accuracy gap.
  • The three identical unparseable responses, indices 55, 56 and 194, reached the pinned 16-token limit and were counted incorrect. There were no skipped/error rows.
  • Repeated first-100 token sequences, texts and parsed answers matched the previous run for each backend.
  • All targets, prompts and summary metrics were independently audited against the pinned dataset.
  • All 200 prefill last-position vocabulary comparisons still exceeded rtol=atol=1e-2; maximum absolute error was 0.462890625.

Receipts: ai2d/first200/summary.json, ai2d/first200/predictions.jsonl, and ai2d/first200.log under the disk5 task root. The evaluator SHA256 remained 0af276cb26c106f141d67e064732a74c186da9d097781446c62d89c7149b26cd.

At the October 7 raw-ORT stage, readiness was limited to an executable standard-ONNX export/evaluation candidate. The larger subset now demonstrates an actual answer difference, not only floating-point differences; it does not establish full Torch equivalence, a full AI2D score, or GenAI runtime readiness on their own; see the October 9 native qualification below. Numerical qualification remains unresolved.

Earlier standard-export review and exclusions (historical)

Five scoped static review roles reported no grounded Critical/Major implementation findings. The raised mixed-media DeepStack coverage gap was addressed by the two sentinel regressions. No Critical/Major findings were overruled; the corresponding findings ledger is empty.

Non-blocking questions retained: the source of remaining official FP16 decoder divergence, full DeepStack decoder parity, and caller correctness when token IDs are missing or visual rows are supplied in the wrong order. The pinned official config supplies explicit image/video IDs.

Not qualified: complete official numerical/generation accuracy, real-weight video/mixed-media and independent processor/host positions, the full AI2D test split, BF16, MTP, quantization, ModelBuilder/GenAI compatibility, or memory/throughput. The AI2D subset does not establish per-step full-state/full-logit parity or a production accuracy qualification.

Native ORT GenAI integration (October 9, 2026)

The scope now also includes ordinary ONNX packaging and the existing
--runtime ort-genai route, without a new Mobius CLI flag or automatically
adding fused/custom graph operators. The three existing standard-only ONNX
graphs and their weights are unchanged. A metadata-only overlay uses the
existing writer's ep="cuda" and og.Config provider APIs.

In the tested installed 0.16.0-dev build, decoder provider overrides did
not change explicit auxiliary CPU sessions. The qualified overlay therefore
writes CUDA session metadata for decoder, vision and embedding together;
capture and shared KV buffers stay off. This does not qualify other native
builds or CPU/DML execution.

Implementation also recognizes unwrapped qwen3_5_text VLM packages and
loads the local pinned HF processor assets. A grounded RGB producer fix
removes Normalize's BGR-to-RGB swap after DecodeImage already emits RGB;
PatchImage continues to own patch packing. No manual tensor flip, pixel
substitution, weight permutation or real-model rebuild was used.

The opt-in native toy checks sparse global KV slots 3/7, FP16 convolution
and FP32 recurrent states, state-driven [0,4,8] tokens, fresh-generator
reset, and every element of an asymmetric uniform RGB image before prefill.
The complete native toy suite passed all four tests. The proof is a local
operator attestation, not binary-identity verification; rerun it after any
native binary change.

Corrected-RGB native AI2D first 200

All 200 pinned examples completed with native GenAI image processing,
positions, caches and greedy generation, thinking disabled and 16 new
tokens. HF supplied only the unchanged chat template and independent
diagnostics, never model inputs. Torch/raw ORT below are the frozen October 7
references, not fresh reruns.

Metric Native GenAI CUDA Prior HF Torch Prior raw ORT CUDA
Correct answers 174/200 (87%) 175/200 (87.5%) 174/200 (87%)
Invalid native responses 3 - -
Exact native generated tokens - 199/200 198/200

Native IDs, image grids and pixel shapes equal HF for 172/200, not all
200. All 28 grid mismatches are explained by native smart-resize
half-away rounding versus HF ties-to-even rounding; both models predict
their respective observed grids for all 200 records. Index 130 has original
width 400: native resizes to 416, HF to 384 (factor 32), and native answers B
versus HF/raw ORT D. This coincidence is not proof that resizing alone caused
the answer difference. At index 124, native matches HF C while raw ORT
answered A.

Among the 172 shape-comparable records, maximum pixel absolute error is
0.0156863928 and minimum correlation is 0.9999995187. The 28 different-shape
records are not counted as pixel-parity passes. Runtime-side resize alignment
is deferred and explicitly documented; no unsupported metadata flag or
caller-side pre-resize workaround was introduced.

This is completed execution/task evidence, not preprocessing or full-logit
parity
, production accuracy, or a full 3,088-example AI2D score. The prior
official FP16 numerical blocker and unchanged 1e-2 tolerances remain.

Regression and review status

  • Combined affected selection: 605 passed, four opt-in native skips
    independently passed above, three uncached integration cases deselected.
  • Build/CI-focused selection: 2,000 passed, 52 existing skips.
  • Broad non-integration run: 10,572 passed, seven failed, 69 skipped.
    Four failures were a legacy fingerprint fixture still including the new
    unset state-policy field; its original-byte reference was corrected. The
    fifth required a real CUDA device for BF16 vision. All five focused
    reruns passed. The other two failures reproduce on the exact PR base in
    this environment: missing GenAI distribution metadata in the pinned
    0.15.2 evidence test, and a GGUF shard-identity mutation expectation.
    They are not claimed fixed or hidden by new skips.
  • Lintrunner and whitespace checks pass. Exact-PR-base benchmark comparison
    exits 0 with no warnings/blockers: Gemma2 105 -> 105 nodes; Qwen3.5 text
    127 -> 131, with the required Q/K epsilon retained. Only positively known
    FLOAT identity casts are removed; FP16/unknown-type FP32 math remains.
  • Five final targeted static reviewers reported no new grounded
    Critical/Major Mobius implementation findings.
ID Severity Raised by Finding Disposition
F1 Major Lead and static reviewers Unix-only resource imports break Windows collection Confirmed and fixed with POSIX guards and 11 offline regressions; actual Windows execution excluded
F2 Minor Code reviewer Dangling overlay destination bypasses freshness Confirmed and fixed before path resolution, with no-write regression
F3 Major Lead native diagnosis RGB decode followed by a second channel swap Confirmed and fixed at producer; native red/green pixel evidence
F4 Major QA and lead diagnosis 28 native/HF smart-resize grids differ Deferred external-runtime alignment, tracked in the design doc and rounding receipt; no preprocessing-parity claim

No Critical/Major finding was rejected. Attributed non-blocking questions
remain: critical/integration reviewers' binary-attestation automation and
inherited processor-load fallback policy; deep review's legacy text alias
numerical equivalence and unused ABI template computation; integration
review's future concurrent symlink replacement (no actual writer mutation);
deep review's future stale dtype annotations (not a current defect).

Not checked/qualified: actual Windows execution, broad CPU/DML, full official
logit/state parity, real-weight video/mixed-media, full AI2D, ModelBuilder,
PagedAttention/fused-MoE alignment, MTP/quantization, capture/serving or
controlled throughput. The local utility assumes operator-controlled paths
and receipts, not a hardened concurrent service.

Receipts remain on the qualification disk:
genai-integration/ai2d-native-rgb-fixed-first200-01/,
genai-integration/native-smart-resize-diagnosis.json,
genai-integration/review-f3-receipt.json, and
genai-integration/ci-benchmark-exact-comparison.txt.
The original dirty checkout is preserved. The superseded 54,779,725,653-byte
ONNX export was removed; the corrected 54,779,987,399-byte package is retained.

Input-size and repeated-inference findings (October 11, 2026)

The completed native AI2D200 result remains 174/200 (87%), compared with frozen HF 175/200 (87.5%) and raw ORT 174/200 (87%). Native/HF tokens matched 199/200 and native/raw tokens 198/200. AI2D used one process and one Model for all 200 questions, with a fresh Generator per question; it was not a per-question process-isolation run.

Observed native AI2D200 input Median Maximum
Prompt tokens, including image tokens 314.5 1,705
Image patch rows 1,064 6,580

Generation was capped at 16 tokens. These are bounds of the tested subset, not dataset-wide maxima or a validated deployment-safe limit.

A separate large-image memory diagnostic used 4,875 prompt tokens, 19,200 patch rows, and a 128-token cap. The first call completed; a second identical call on the same Model with a new Generator failed at decoder layer 3 Attention_node_335, requesting 4,563,000,320 bytes. After the first call, GPU usage was 81,133 MiB with only 20 MiB free; deleting the Generator and GC did not reduce usage while the Model stayed alive. Process exit restored 81,150 MiB free / 4 MiB used. The first call exactly matched the standalone tokens, text, processor tensors, and prompt.

This diagnostic used an isolated GenAI build, source 265917c09ffe68198a026e086d21e694cc938298, with a one-line last-token logits allocation correction and package-local $ORIGIN RPATH; actual loaded installed ORT SHA256 remained 5a2e81ad05259bce596e29d6361fe76750b6c2c9569b8cdddf709ab0d944b0ee. Graphs, weights, images, and generation policy were unchanged. It is not the installed GenAI binary used for AI2D200; the installed GenAI source origin is unknown. The external GenAI correction is not included in this Mobius PR and does not resolve repeated-inference OOM.

The decoder export has 16 standard Attention nodes, explicit FP16 masks, dynamic KV ports, and no TensorScatter. The inspected ORT unfused workspace formula exactly matches the allocation: 2 * align256(24 * 4875 * 4875 * 4) = 4,563,000,320. The local dispatch excludes Flash with an explicit mask and excludes MEA for a masked KV stride not divisible by four (4875 % 4 = 3). This strongly supports an unfused-workspace attribution, not a directly captured installed-binary dispatch trace; the inspected ORT source-to-binary correspondence remains unverified. Other large-image attempts also failed in the vision encoder.

The repeated-inference memory blocker is reproducible, but live tensor ownership, arena retention, and fragmentation are not yet distinguished. A KV-cache leak is not proven, and static TensorScatter cache has not been A/B tested. Deployment requires validated processor-output limits, generation/concurrency budgets, and repeated mixed-size request testing, rather than assuming a successful isolated inference or AI2D subset qualifies serving stability.

Per the narrowed publication scope, no MMMU accuracy result is claimed. Existing official FP16 numerical parity failures, native/HF resize differences, and incomplete historical L4/L5 CI remain open; this update does not declare merge/deployment readiness. Detailed evidence and historical CI disposition are recorded in docs/design/qwen38-27b-standard-onnx.md. Qualification-disk receipts include genai-runtime-fix-01/probes/candidate-case56-repeat01/{receipt,execution}.json and the unchanged AI2D200 artifacts.

Add the public text-only mapping for the Qwen3.8-27B qwen3_5 composite,
preserve its explicit FP32 recurrent-state policy, and apply the fixed HF
Qwen3.5 L2 normalization epsilon of 1e-6.  The offline evidence covers
full-config standard graphs and reduced CUDA own-state parity with synthetic
weights.  This does not qualify official weights or a full checkpoint.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: titaiwang <titaiwang@microsoft.com>
@titaiwangms
titaiwangms requested review from a team and a balanced review from Copilot October 7, 2026 01:09
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Performance Comparison

Comparing 26a712b2 → 0c2b2a6c

Model Metric Baseline Current Delta
bert (feature-extraction) model_size_bytes 359 KB 359 KB +0.0% ⚪
bert (feature-extraction) num_nodes 68 68 +0.0% ⚪
falcon model_size_bytes 364 KB 364 KB +0.0% ⚪
falcon num_nodes 66 66 +0.0% ⚪
gemma2 model_size_bytes 428 KB 428 KB +0.0% ⚪
gemma2 num_nodes 105 105 +0.0% ⚪
gpt2 model_size_bytes 324 KB 324 KB +0.0% ⚪
gpt2 num_nodes 54 54 +0.0% ⚪
llama model_size_bytes 425 KB 425 KB +0.0% ⚪
llama num_nodes 60 60 +0.0% ⚪
llama (static-cache) model_size_bytes 425 KB 425 KB +0.0% ⚪
llama (static-cache) num_nodes 56 56 +0.0% ⚪
mamba (ssm-text-generation) model_size_bytes 296 KB 296 KB +0.0% ⚪
mamba (ssm-text-generation) num_nodes 94 94 +0.0% ⚪
phi3 model_size_bytes 421 KB 421 KB +0.0% ⚪
phi3 num_nodes 58 58 +0.0% ⚪
phi3 (static-cache) model_size_bytes 421 KB 421 KB +0.0% ⚪
phi3 (static-cache) num_nodes 54 54 +0.0% ⚪
qwen2 model_size_bytes 425 KB 425 KB +0.0% ⚪
qwen2 num_nodes 60 60 +0.0% ⚪
qwen2 (static-cache) model_size_bytes 425 KB 425 KB +0.0% ⚪
qwen2 (static-cache) num_nodes 56 56 +0.0% ⚪
qwen3_5_moe (hybrid-text-generation) model_size_bytes 506 KB 506 KB +0.0% ⚪
qwen3_5_moe (hybrid-text-generation) num_nodes 265 269 +1.5% ⚪
qwen3_5_text (hybrid-text-generation) model_size_bytes 458 KB 458 KB +0.0% ⚪
qwen3_5_text (hybrid-text-generation) num_nodes 127 131 +3.1% ⚪
qwen3_5_vl (hybrid-qwen-vl) model_size_bytes 977 KB 977 KB +0.0% ⚪
qwen3_5_vl (hybrid-qwen-vl) num_nodes 450 461 +2.4% ⚪
t5 (seq2seq) model_size_bytes 836 KB 836 KB +0.0% ⚪
t5 (seq2seq) num_nodes 176 176 +0.0% ⚪
whisper (speech-to-text) model_size_bytes 1008 KB 1008 KB +0.0% ⚪
whisper (speech-to-text) num_nodes 128 128 +0.0% ⚪

No performance regressions.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The text-only routing map omits the registered qwen3_5_vl_text model type, causing the public builder to reject that valid route.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Qualifies Qwen3.8-27B’s unquantized, text-only standard-ONNX export path.

Changes:

  • Adds Qwen3.5 text-only routing and pinned Qwen3.8 configuration.
  • Preserves configured recurrent-state precision and corrects Qwen3.5 DeltaNet normalization.
  • Adds graph, serialization, CUDA parity, and documentation coverage.
File Description
testdata/​configs/​qwen3_8-27b.json Adds the pinned official configuration.
src/​mobius/​tasks/​_causal_lm.py Documents mixed cache dtypes.
src/​mobius/​tasks/​_cache_utils.py Applies configured recurrent-state dtype.
src/​mobius/​models/​qwen38_standard_test.py Adds structural and numerical qualification tests.
src/​mobius/​models/​qwen35.py Adds Qwen-specific DeltaNet epsilon.
src/​mobius/​components/​_gated_deltanet.py Preserves legacy dtype fallback.
src/​mobius/​_registry.py Adds Qwen3.5 text-only routing aliases.
src/​mobius/​_configs/​_base.py Extracts and validates state dtype policy.
docs/​design/​qwen38-27b-standard-onnx.md Documents scope, ABI, and evidence.
docs/​cli_reference.md Documents CLI support and limitations.
CHANGELOG.md Records qualification and compatibility changes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/mobius/_registry.py
Comment on lines +1196 to +1198
"qwen3_5": "qwen3_5_text",
"qwen3_5_vl": "qwen3_5_text",
"qwen3_5_text": "qwen3_5_text",
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing 26a712b2 → 0c2b2a6c

Model Sub-model Changes Status
bert (feature-extraction) model 0 ⚪
falcon model 0 ⚪
gemma2 model 0 ⚪
gemma4 (gemma4) decoder 0 ⚪
gemma4 (gemma4) embedding 0 ⚪
gemma4 (gemma4) vision_encoder 0 ⚪
gemma4_text model 0 ⚪
gpt2 model 0 ⚪
llama model 0 ⚪
llama (static-cache) model 0 ⚪
mamba (ssm-text-generation) model 0 ⚪
phi3 model 0 ⚪
phi3 (static-cache) model 0 ⚪
qwen model 0 ⚪
qwen (static-cache) model 0 ⚪
qwen2 model 0 ⚪
qwen2 (static-cache) model 0 ⚪
qwen2_moe model 0 ⚪
qwen2_moe (static-cache) model 0 ⚪
qwen3 model 0 ⚪
qwen3 (static-cache) model 0 ⚪
qwen3_5_moe (hybrid-text-generation) model 33 🔴
qwen3_5_text (hybrid-text-generation) model 33 🔴
qwen3_5_vl (hybrid-qwen-vl) decoder 56 🔴
qwen3_5_vl (hybrid-qwen-vl) embedding 7 🟡
qwen3_5_vl (hybrid-qwen-vl) vision_encoder 35 🟡
qwen3_moe model 0 ⚪
qwen3_moe (static-cache) model 0 ⚪
qwen3_next (hybrid-text-generation) model 1 🔴
t5 (seq2seq) decoder 0 ⚪
t5 (seq2seq) encoder 0 ⚪
whisper (speech-to-text) decoder 0 ⚪
whisper (speech-to-text) encoder 0 ⚪
qwen3_5_moe (hybrid-text-generation) / model — 33 change(s)

Op summary: 265 → 269 nodes

--- base
+++ head
@@ -42,11 +42,15 @@
 Concat
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape

Added nodes:

  • + CastLike
  • + Add
  • + CastLike
  • + Add

Connectivity changes:

  • node[4] Unsqueeze: input_ids [78, 11] → [79, 11]
  • node[7] Sub: input_ids [81, 80] → [82, 81]
  • node[8] Slice: input_ids [78, 82, 81, 11] → [79, 83, 82, 11]
  • node[9] Unsqueeze: input_ids [83, 12] → [84, 12]
  • node[10] GreaterOrEqual: input_ids [84, 79] → [85, 80]
  • node[12] Cast: input_ids [86] → [87]
  • node[13] And: input_ids [87, 85] → [88, 86]
  • node[14] Where: input_ids [88, 13, 14] → [89, 13, 14]
  • node[15] Cast: input_ids [89] → [90]
  • node[16] Unsqueeze: input_ids [90, 11] → [91, 11]
  • node[18] RMSNormalization: input_ids [75, 92] → [76, 93]
  • node[19] Shape: input_ids [93] → [94]
  • node[21] MatMul: input_ids [93, 95] → [94, 96]
  • node[23] MatMul: input_ids [93, 97] → [94, 98]
  • node[25] MatMul: input_ids [93, 99] → [94, 100]
  • node[27] MatMul: input_ids [93, 101] → [94, 102]
  • node[28] Transpose: input_ids [96] → [97]
  • node[30] CastLike: input_ids [104, 23] → [105, 23]
  • node[32] Expand: input_ids [105, 106] → [106, 107]
  • node[33] CausalConvWithState: input_ids [103, 23, 107, 3] → [104, 23, 108, 3]
  • node[34] Transpose: input_ids [108] → [109]
  • node[36] Split: input_ids [110, 111] → [111, 112]
  • node[37] Shape: input_ids [93] → [94]
  • node[39] Concat: input_ids [94, 115, 116] → [95, 116, 117]
  • node[41] Concat: input_ids [94, 115, 118] → [95, 116, 119]
  • node[42] Reshape: input_ids [112, 117] → [113, 118]
  • node[43] ReduceSumSquare: input_ids [120, 24] → [121, 24]

Interface changes:

  • output[0]: dtype UNKNOWN → FLOAT; shape [] → ['?', '?', '256']; output[2]: dtype UNKNOWN → FLOAT; output[3]: dtype UNKNOWN → FLOAT; output[4]: dtype UNKNOWN → FLOAT

Initializer changes:

  • count 68 → 69; dtype distribution: FLOAT: 61 → 62
qwen3_5_text (hybrid-text-generation) / model — 33 change(s)

Op summary: 127 → 131 nodes

--- base
+++ head
@@ -42,11 +42,15 @@
 Concat
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape

Added nodes:

  • + CastLike
  • + Add
  • + CastLike
  • + Add

Connectivity changes:

  • node[4] Unsqueeze: input_ids [50, 11] → [51, 11]
  • node[7] Sub: input_ids [53, 52] → [54, 53]
  • node[8] Slice: input_ids [50, 54, 53, 11] → [51, 55, 54, 11]
  • node[9] Unsqueeze: input_ids [55, 12] → [56, 12]
  • node[10] GreaterOrEqual: input_ids [56, 51] → [57, 52]
  • node[12] Cast: input_ids [58] → [59]
  • node[13] And: input_ids [59, 57] → [60, 58]
  • node[14] Where: input_ids [60, 13, 14] → [61, 13, 14]
  • node[15] Cast: input_ids [61] → [62]
  • node[16] Unsqueeze: input_ids [62, 11] → [63, 11]
  • node[18] RMSNormalization: input_ids [47, 64] → [48, 65]
  • node[19] Shape: input_ids [65] → [66]
  • node[21] MatMul: input_ids [65, 67] → [66, 68]
  • node[23] MatMul: input_ids [65, 69] → [66, 70]
  • node[25] MatMul: input_ids [65, 71] → [66, 72]
  • node[27] MatMul: input_ids [65, 73] → [66, 74]
  • node[28] Transpose: input_ids [68] → [69]
  • node[30] CastLike: input_ids [76, 23] → [77, 23]
  • node[32] Expand: input_ids [77, 78] → [78, 79]
  • node[33] CausalConvWithState: input_ids [75, 23, 79, 3] → [76, 23, 80, 3]
  • node[34] Transpose: input_ids [80] → [81]
  • node[36] Split: input_ids [82, 83] → [83, 84]
  • node[37] Shape: input_ids [65] → [66]
  • node[39] Concat: input_ids [66, 87, 88] → [67, 88, 89]
  • node[41] Concat: input_ids [66, 87, 90] → [67, 88, 91]
  • node[42] Reshape: input_ids [84, 89] → [85, 90]
  • node[43] ReduceSumSquare: input_ids [92, 24] → [93, 24]

Interface changes:

  • output[0]: dtype UNKNOWN → FLOAT; shape [] → ['?', '?', '256']; output[2]: dtype UNKNOWN → FLOAT; output[3]: dtype UNKNOWN → FLOAT; output[4]: dtype UNKNOWN → FLOAT

Initializer changes:

  • count 40 → 41; dtype distribution: FLOAT: 33 → 34
qwen3_5_vl (hybrid-qwen-vl) / decoder — 56 change(s)

Op summary: 153 → 157 nodes

--- base
+++ head
@@ -67,11 +67,15 @@
 Concat
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape
 Reshape
 ReduceSumSquare
+CastLike
+Add
 Sqrt
 Div
 Reshape

Added nodes:

  • + CastLike
  • + Add
  • + CastLike
  • + Add

Connectivity changes:

  • node[1] Reshape: input_ids [3, 52] → [3, 53]
  • node[2] Transpose: input_ids [53] → [54]
  • node[4] Gather: input_ids [54, 55] → [55, 56]
  • node[6] Slice: input_ids [57, 12, 13, 14] → [58, 12, 13, 14]
  • node[8] Concat: input_ids [59, 58] → [60, 59]
  • node[10] Expand: input_ids [61, 60] → [62, 61]
  • node[11] Reshape: input_ids [62, 60] → [63, 61]
  • node[12] Gather: input_ids [63, 14] → [64, 14]
  • node[13] Squeeze: input_ids [64, 14] → [65, 14]
  • node[14] Gather: input_ids [8, 65] → [8, 66]
  • node[15] Gather: input_ids [9, 65] → [9, 66]
  • node[16] Gather: input_ids [63, 15] → [64, 15]
  • node[17] Squeeze: input_ids [68, 14] → [69, 14]
  • node[18] Gather: input_ids [8, 69] → [8, 70]
  • node[19] Gather: input_ids [9, 69] → [9, 70]
  • node[20] Gather: input_ids [63, 16] → [64, 16]
  • node[21] Squeeze: input_ids [72, 14] → [73, 14]
  • node[22] Gather: input_ids [8, 73] → [8, 74]
  • node[23] Gather: input_ids [9, 73] → [9, 74]
  • node[24] Where: input_ids [10, 70, 66] → [10, 71, 67]
  • node[25] Where: input_ids [11, 74, 76] → [11, 75, 77]
  • node[26] Where: input_ids [10, 71, 67] → [10, 72, 68]
  • node[27] Where: input_ids [11, 75, 78] → [11, 76, 79]
  • node[29] Unsqueeze: input_ids [80, 15] → [81, 15]
  • node[32] Sub: input_ids [83, 82] → [84, 83]
  • node[33] Slice: input_ids [80, 84, 83, 15] → [81, 85, 84, 15]
  • node[34] Unsqueeze: input_ids [85, 16] → [86, 16]
  • node[35] GreaterOrEqual: input_ids [86, 81] → [87, 82]
  • node[37] Cast: input_ids [88] → [89]
  • node[38] And: input_ids [89, 87] → [90, 88]
  • node[39] Where: input_ids [90, 18, 19] → [91, 18, 19]
  • node[40] Cast: input_ids [91] → [92]
  • node[41] Unsqueeze: input_ids [92, 15] → [93, 15]
  • node[43] RMSNormalization: input_ids [0, 94] → [0, 95]
  • node[44] Shape: input_ids [95] → [96]
  • node[46] MatMul: input_ids [95, 97] → [96, 98]
  • node[48] MatMul: input_ids [95, 99] → [96, 100]
  • node[50] MatMul: input_ids [95, 101] → [96, 102]
  • node[52] MatMul: input_ids [95, 103] → [96, 104]
  • node[53] Transpose: input_ids [98] → [99]
  • node[55] CastLike: input_ids [106, 28] → [107, 28]
  • node[57] Expand: input_ids [107, 108] → [108, 109]
  • node[58] CausalConvWithState: input_ids [105, 28, 109, 4] → [106, 28, 110, 4]
  • node[59] Transpose: input_ids [110] → [111]
  • node[61] Split: input_ids [112, 113] → [113, 114]
  • node[62] Shape: input_ids [95] → [96]
  • node[64] Concat: input_ids [96, 117, 118] → [97, 118, 119]
  • node[66] Concat: input_ids [96, 117, 120] → [97, 118, 121]
  • node[67] Reshape: input_ids [114, 119] → [115, 120]
  • node[68] ReduceSumSquare: input_ids [122, 29] → [123, 29]

Interface changes:

  • output[0]: dtype UNKNOWN → FLOAT; shape [] → ['?', '?', '256']; output[2]: dtype UNKNOWN → FLOAT; output[3]: dtype UNKNOWN → FLOAT; output[4]: dtype UNKNOWN → FLOAT

Initializer changes:

  • count 44 → 45; dtype distribution: FLOAT: 32 → 33
qwen3_5_vl (hybrid-qwen-vl) / embedding — 7 change(s)

Op summary: 46 → 52 nodes

--- base
+++ head
@@ -12,14 +12,20 @@
 Gather
 Constant
 Equal
+Constant
+Equal
+Or
 Unsqueeze
 Cast
+Reshape
 Constant
 CumSum
 Constant
 Sub
 Constant
 Clip
+Shape
+Reshape
 CastLike
 Constant
 Shape

Added nodes:

  • + Constant
  • + Equal
  • + Or
  • + Reshape
  • + Shape
  • + Reshape

Connectivity changes:

  • node[42] Concat: input_ids [47] → [46, 47]
qwen3_5_vl (hybrid-qwen-vl) / vision_encoder — 35 change(s)

Op summary: 251 → 252 nodes

--- base
+++ head
@@ -1,3 +1,4 @@
+Cast
 Reshape
 Conv
 Reshape

Added nodes:

  • + Cast

Modified attributes:

  • node[93] Constant: value_int: 0 → None, value_ints: None → [1, 0]
  • node[127] Constant: value_int: 1 → 0
  • node[202] Constant: value_int: 1 → 0

Connectivity changes:

  • node[10] Mul: input_ids [61, 66] → [64, 66]
  • node[21] Unsqueeze: input_ids [67, 8] → [77, 7]
  • node[39] Mul: input_ids [90, 95] → [93, 95]
  • node[50] Unsqueeze: input_ids [96, 8] → [106, 7]
  • node[60] Gather: input_ids [115, 8] → [116, 7]
  • node[64] Gather: input_ids [13, 118] → [12, 119]
  • node[65] Gather: input_ids [12, 119] → [13, 119]
  • node[66] Gather: input_ids [13, 119] → [12, 120]
  • node[81] Unsqueeze: input_ids [127, 8] → [137, 7]
  • node[103] CastLike: input_ids [125, 159] → [125, 160]
  • node[112] Mul: input_ids [163, 166] → [165, 166]
  • node[119] Mul: input_ids [163, 168] → [165, 168]
  • node[123] Reshape: input_ids [182, 20] → [176, 20]
  • node[130] Unsqueeze: input_ids [151, 7] → [190, 8]
  • node[137] Unsqueeze: input_ids [196, 7] → [197, 8]
  • node[140] CastLike: input_ids [22, 183] → [21, 184]
  • node[143] Unsqueeze: input_ids [183, 7] → [203, 23]
  • node[145] Unsqueeze: input_ids [158, 7] → [185, 7]
  • node[151] Add: input_ids [88, 211] → [211, 25]
  • node[160] Add: input_ids [212, 220] → [220, 31]
  • node[178] CastLike: input_ids [125, 238] → [125, 239]
  • node[187] Mul: input_ids [242, 245] → [244, 245]
  • node[194] Mul: input_ids [242, 247] → [244, 247]
  • node[198] Reshape: input_ids [261, 20] → [255, 20]
  • node[205] Unsqueeze: input_ids [151, 7] → [269, 8]
  • node[212] Unsqueeze: input_ids [275, 7] → [276, 8]
  • node[215] CastLike: input_ids [22, 262] → [21, 263]
  • node[218] Unsqueeze: input_ids [262, 7] → [282, 23]
  • node[220] Unsqueeze: input_ids [237, 7] → [264, 7]
  • node[226] Add: input_ids [221, 290] → [290, 44]
  • node[235] Add: input_ids [291, 299] → [299, 50]
qwen3_next (hybrid-text-generation) / model — 1 change(s)

Op summary: 565 → 565 nodes

No op-sequence changes.

Interface changes:

  • output[0]: dtype UNKNOWN → FLOAT; shape [] → ['?', '?', '256']; output[2]: dtype UNKNOWN → FLOAT; output[4]: dtype UNKNOWN → FLOAT; output[6]: dtype UNKNOWN → FLOAT; output[7]: dtype UNKNOWN → FLOAT; output[8]: dtype UNKNOWN → FLOAT

Legend: ⚪ No change · 🔵 Minor (attrs/inits) · 🟡 Moderate (nodes added/removed) · 🔴 Major (interface changed)

Publish the complete Qwen3.8-27B standard-only VLM graph with reduced qualification coverage. Update processor casting and global image/video offsets, and use FP32 learned normalization where required. Record the remaining official FP16 parity failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: titaiwang <titaiwang@microsoft.com>
@titaiwangms titaiwangms changed the title Qualify Qwen3.8-27B standard-only text export Qualify complete Qwen3.8-27B standard-only VLM export Oct 7, 2026
titaiwangms and others added 3 commits October 8, 2026 11:36
Publish metadata-only packaging and the existing runtime route with local processor and RGB double-swap root fixes while preserving global mixed caches.

Correct GGUF unset policy fingerprint handling and mandatory Qwen4 FP32 state. Restore DeltaNet output dtype and skip only known FLOAT identity casts without changing precision or epsilon.

Qualification notes: native-first 200 completes 174, HF 175, with 28 diagnosed resize-grid differences deferred runtime-side and FP16 parity unresolved. No readiness or all-CI-green claim.

Signed-off-by: titaiwang <titaiwang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Record the approved native AI2D results, numerical and historical CI context, and repeated-inference input-memory findings. Explicitly preserve the numerical, memory, and qualification limitations: task-answer agreement is evidence for this tested subset, not deployment qualification or a claim of full numerical parity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: titaiwang <titaiwang@microsoft.com>

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants