Skip to content

Enable standard-ONNX Qwen3.8 Flash-Next export - #755

Merged
titaiwangms merged 11 commits into
mainfrom
feat/qwen38-standard-onnx
Oct 19, 2026
Merged

titaiwangms merged 11 commits into
mainfrom
feat/qwen38-standard-onnx

Conversation

@titaiwangms

@titaiwangms titaiwangms commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Enable standard-ONNX-only export for the existing Qwen3.8-Flash-Next text and image-text implementations with execution_provider="onnx-standard".

  • Replace unconditional fused MoE emission in standard mode with a single sparse expert-dispatch Scan. Select and optionally normalize routing probabilities in float32, then use model-dtype expert arithmetic and accumulation.
  • Gather one expert's packed weights at a time and skip experts without selected tokens. The compute graph does not grow with expert count and does not materialize token-by-top-k weight banks.
  • Preserve the fused MoE path for other execution providers, checkpoint parameter layouts, shared experts, tasks, and cache contracts.
  • Fail closed on unresolved custom operators or operators without an applicable standard ONNX schema. Validation covers nested graphs and function definitions and runs after optimization, opset lowering, and Transformers weight binding.
  • Preserve lexical image-token embeddings during cached decode when no new image features are supplied, matching the independent Hugging Face reference.
  • Use FP32 accumulation for the hyper-connection mean, retaining model-dtype products and results, and an FP32 QSA zero-bias comparison to avoid unsupported BF16 CUDA kernels.
  • Document the algorithm, resource limits, independent numerical evidence, and verification scope.

Qualification boundary and follow-up

This PR provides standard-operator graph support with layered, bounded validation; it does not claim exhaustive main/ngram qualification or complete official-checkpoint generation.

  • Main: official-weight component comparisons and a full-width four-layer composition (layers 0-3 of 48), with teacher-forced decode and heterogeneous state checks. This is not validation of every main layer or the complete main module.
  • Ngram/PLE: hash/history/EOS/padding/shard-mapping checks, selected official embedding rows, and the PLE core. These checks do not qualify all 128 complete ngram shards, the unchanged full-table graph, or an independently exported ngram component.
  • E2E: reduced/random-weight autoregressive text and image-text comparisons exist, with the historical BF16 caveat below. Complete official-checkpoint decoder/VLM E2E remains unqualified and requires separate resource planning; do not interpret this as an absence of all generation testing.
  • MTP: forward/export/cache execution is not implemented or numerically qualified. This is a functional gap, not an observed hardware failure; ordinary next-token generation does not require MTP.

The next-step design is tracked in #767: opt-in ngram/main separation, independent MTP forward qualification, shared-weight and state ownership, speculative rollback/replay, complete shard/layer coverage, and resource-gated full-checkpoint generation. Native GenAI execution and any required partition/offload work remain distinct follow-ons. The recorded QSA cutoff-tie discrepancy and BF16 vision restriction are not cleared by this PR. Official numerical receipts retain their pinned source revisions and do not automatically qualify current HEAD or future split/MTP graphs.

Verification

Verified in an isolated PR worktree, excluding unrelated local edits:

python -m pytest \
  tests/ep_optimization_test.py \
  src/mobius/models/qwen4_exp_test.py \
  src/mobius/_builder_test.py \
  src/mobius/integrations/transformers/_builder_test.py \
  -m "not integration" -q -rs --tb=short

267 passed, 3 skipped, 10 deselected. Scoped Ruff lint/format and git diff --check passed.

Coverage includes independent MoE references, routing ties and near-ties, normalization/scaling, FP16/BF16 CUDA expert dispatch, empty expert branches, constant-size expert compute graphs, text/image-text standard-domain checks, prefill/decode logits and cache parity, left padding, a nonzero image pipeline, reduced dense/FP8 streaming fixtures, and rejection of custom operators inserted at export boundaries.

The three skips identify unavailable ORT CPU BF16 kernels: two Expand(13) cases and one BF16 FLOAT8 DequantizeLinear case. Four reference-cast overflow warnings were reported.

Independent Hugging Face parity (historical pre-guard)

Historical pre-guard evidence: the command, counts, and reduced-model results below were recorded before the BF16 standard-ONNX vision export guard added in 704dd94e19bdd71b5608632e0bbcaa9d00b0fc21. They are not the current-head test matrix or counts. The current reduced image-text HF integration matrix covers FP32 CPU/CUDA only; BF16 standard-ONNX vision export is deliberately rejected and remains unqualified. The earlier reduced BF16 image-text passes are retained as historical observations, not as a claim that the current export path supports BF16 vision.

Using isolated Transformers source pinned to 598d8ba8baaec7fec5a22da0e2844c7bf4ea20e1 and tokenizers==0.23.1, with both Hub and Transformers offline:

python -m pytest src/mobius/models/qwen4_exp_test.py -q \
  -k "reduced_random_weight_huggingface or reduced_standard_huggingface or standard_moe_low_precision_execution_and_routing or multimodal_embedding_preserves_global_image_order" \
  --tb=short -rs

15 passed, 2 skipped, 163 deselected. Both skips are the expected CPU BF16 Expand gaps; there are no HF-reference or CUDA skips.

  • Random-weight reduced text models: FP32 CPU/CUDA and BF16 CUDA; ten-token prefill crossing the sparse-selection boundary, followed by six independent greedy decode steps.
  • Random-weight reduced image-text models: FP32 CPU/CUDA and BF16 CUDA; two nonzero images with different grid shapes through the actual ONNX vision -> embedding -> decoder pipeline, then three cached decode steps with no new images.
  • Compare independent HF vision features, fused embeddings, full logits, exact greedy token IDs, every exported convolution/recurrent/PLE/QSA state, and position history.
  • Check shapes and dtypes before comparing values. FP32 tolerance is rtol=atol=1e-3; BF16 tolerance is 1e-2. Recurrent state remains FP32.
  • CUDA EP sessions allow ordinary CPU handling/fallback for metadata and control flow; this is not a claim that every node executes on GPU.

Scoped MyPy is not green: the base and follow-up have the same 22 diagnostics, including the environment's missing onnxscript stub/import diagnostic. Comparing identical package layouts introduced no new diagnostic messages.

Official-weight component qualification (updated October 7, 2026)

These are additional, bounded component experiments, not a full-checkpoint run:

  • Mobius code: dbf12f4c820d1acfdbb122f930ecb8749e453d97.
  • Official checkpoint: Qwen/Qwen3.8-Flash-Next, revision de4b8e4d43b917e7706784d8bb445c9af86a3540.
  • Independent Transformers source: 598d8ba8baaec7fec5a22da0e2844c7bf4ea20e1.
  • This checkpoint revision is distinct from the f5d08274... revision in the existing test-case YAML; do not conflate the two.
  • CUDA FP32/FP16 comparisons use the same official BF16 source weights converted to the target dtype in both implementations. Ordinary CPU metadata/control-flow handling is allowed.
Official-weight component Cases CUDA FP32 CUDA FP16
Complete vision encoder: 27 layers, hidden 1152, 16 heads, intermediate 4304, output 2560 Nonzero landscape, portrait, square, and packed-two-image inputs using the official processor 4/4 passed; rtol=atol=1e-3; maximum absolute error 0.0006978660821914673 4/4 passed; rtol=atol=1e-2; maximum absolute error 0.006591796875
Complete layer-0 MoE: hidden 2560, 512 experts, top-10, expert/shared intermediate 640 Five nonzero synthetic hidden-state fixtures plus a zero-input control All passed; rtol=atol=1e-3; maximum full-output absolute error 3.5762786865234375e-7 All passed; rtol=atol=1e-2; maximum full-output absolute error 0.00048828125

Vision details: exact HTTP byte ranges supplied 333 tensors (897862112 bytes), without downloading the full checkpoint. The independent reference used native HF loading, preserving the nonpersistent FP32 rotary buffer.

MoE details: exact ranges supplied seven layer-0 weights (5045621760 bytes). The reference was the standalone HF Qwen4ExpTextSparseMoeBlock with eager expert execution and strict loading. All 2522810880 source parameter values were audited after conversion for exact graph binding and finiteness. Routing weights, routed output, shared output, shared contribution, and final output passed. Selected expert sets and order matched exactly for all five nonzero fixtures; tied expert identities differ on the zero control, while both final outputs are exactly zero.

The MoE serialized graph passed standard-only opset-24 validation, with one expert Scan, one If, and no remaining function definitions. Runtime profiling confirmed real CUDA dense computation: the FP32 single-fixture probe recorded 25 CUDA dense executions and zero CPU dense executions; FP16 across all six fixtures recorded 486 CUDA dense executions and zero CPU dense executions. Internal ORT optimization/fusion is allowed; the standard-only contract concerns the serialized graph.

BF16 is not qualified: the native-loader official vision comparison failed all four cases at rtol=atol=1e-2, with maximum absolute error 0.04052734375. The cause remains unresolved; a RoPE precision probe did not restore parity. BF16 investigation was deferred in favor of CUDA FP32/FP16. Reduced-model BF16 passes above do not override this production-size failure.

Cleanup: all experiment-owned downloaded weights, exported model binaries, isolated caches, and temporary worktrees were removed and their absence verified. The original checkout was preserved. Only small reports, logs, provenance, and harness scripts remain in session artifacts; these are not committed model payloads.

Retained evidence includes qwen38-real-vision-results.json, qwen38-fp16-vision-f16-native-loader-results.json, qwen38-real-vision-bf16-native-loader-results.json, qwen38-real-moe-results.json, and qwen38-real-moe-cleanup.json.

Official-weight FP32 CPU bounded qualification (October 13, 2026)

These additional component and reduced-layer experiments supersede the earlier pending statements for official-weight GDN, QSA, gated residual, and bounded PLE/ngram checks. They do not establish complete checkpoint, unchanged full-table, or generation qualification.

Provenance and gate

  • Model-source revision tested: 704dd94e19bdd71b5608632e0bbcaa9d00b0fc21.
  • Official checkpoint: Qwen/Qwen3.8-Flash-Next at de4b8e4d43b917e7706784d8bb445c9af86a3540.
  • Independent Transformers source: 598d8ba8baaec7fec5a22da0e2844c7bf4ea20e1.
  • Official BF16 source parameters were converted to FP32 for both implementations. Inference was offline, Torch was CPU-only, and ORT used only CPUExecutionProvider, with at most eight threads. Profiles confirmed CPU node execution.
  • Every floating output/state comparison retained atol=rtol=1e-3, strict shape/dtype/finiteness checks, and the per-element gate abs(onnx - hf) <= 0.001 + 0.001 * abs(hf). Integer indices, token history, and positions were compared exactly. No tolerance was relaxed.
  • Selected tensors came from pinned, validated HTTP 206 ranges. Parameter values after conversion and relevant post-fold initializers were audited, not merely their names/counts/dtypes. Saved/reloaded graphs passed recursive standard-domain/schema validation.
  • HF and ONNX maintained independent caches. The call counts below include correlated prefill/decode steps, not independent model samples.
Official-weight CPU scope Calls passing the fixed gate Maximum absolute error Evidence boundary
Production layer-0 GDN 19/19 Output 8.568167686462402e-8; conv 7.152557373046875e-7; recurrent 2.3283064365386963e-8 Synthetic nonzero activations; prefill, six-step decode, batch/padding, and chunked prefill
Production layer-3 QSA, initial run 51/57; 6 failures retained Output 0.005585193634033203 Includes the real 2048-token selection budget boundary, not just a reduced budget
QSA 2304/2560-token extension 86/88; 2 prefill-call failures retained Failing output 0.008429452776908875 All 14 target-context/following-decode calls and all 729 strict-cutoff query rows passed, max 3.5762786865234375e-7; neither complete schedule is an unconditional pass
Layer-0 attention/MLP gated residual 24/24 9.298324584960938e-6 Production-width stream mixing, gates, residual streams, and injection; batch 1/2, sequence 1/7/13
Final residual mixer, use_combine=False 18/18 1.5616416931152344e-5 Ordinary, wide, and near-zero nonzero streams; native grouped normalization included
Native ngram hash/history and shard mapping 14/14, exact 0 Cold/padded prefill, repeated ngrams, EOS in current/history, and six-step decode per chain
Bounded official-row embedding 14/14, exact 0 454 requested physical storage rows; sparse read-only storage substitution, not the unchanged complete table graph
PLE core 14/14 Output 5.364418029785156e-7; conv state 5.7220458984375e-6 Explicit sampled-row embedding boundary; native hidden-state gating, projections, causal convolution, and independent history/state chains
Complete production vision encoder 4/4 5.044043064117432e-6 Pinned official processor; landscape, portrait, square, and packed-two nonzero RGB images; no video/full VLM pipeline
Complete production layer-0 MoE 6/6 Full output 5.066394805908203e-7 Five nonzero activation fixtures plus zero control; hidden 2560, 512 experts, top-10, intermediate/shared 640
Official layers 0-3 hybrid composition with complete embedding/LM head 14/14 Full logits 3.337860107421875e-5; floating states 2.288818359375e-5 Original width/heads/expert geometry and 248320 vocabulary; two prefill chains plus six teacher-forced decode steps each; four layers and bounded row storage, not the complete 48-layer model

QSA known discrepancy: retained, not waived

At 2052 visible tokens there are 513 complete four-token blocks, from which the official policy selects 512. In the reproducible initial case, HF excluded block 334 and ORT excluded block 473; both differing blocks scored exactly zero in both implementations. Independent replays reproduced each saved output exactly. The initial run had seven differing selection masks and six full-output gate failures. The long-context extension also had two failing earlier prefill chunks, containing 33 failing query rows, all at exact-zero cutoff ties.

All tested strict-cutoff rows in the extension and all compared QSA key/value/index-key states passed. This narrows the observed discrepancy to tied selection in these fixtures; it does not prove all inputs are correct or declare either implementation mathematically wrong. The user deferred resolving this issue. QSA parity is not an unconditional pass, and the fixed numerical gate remains unchanged.

Composition and lookup limitations

  • The four-layer experiment derives layers 0-3 from the official 48-layer model: three linear-attention layers and one QSA layer. Both sides use their own state across teacher-forced decode, with full vocabulary logits and all heterogeneous states compared. It is not full-checkpoint greedy generation.
  • The isolated embedding fixture uses 454 requested official physical rows; the four-layer fixture uses 446. These are separate fixture counts, not exhaustive or additive table coverage. Storage reads are substituted with sparse official rows while retaining the tested hash/index/history/shard behavior. The PLE-core ONNX fixture has an explicit embedding input boundary.
  • The complete original ngram table was neither downloaded nor allocated. No unchanged complete table graph, all-128-shard qualification, or complete decoder/VLM E2E is claimed.
  • MoE expert sets/order matched for the non-tied nonzero fixtures. Expert IDs differ on the zero-score control, but both complete outputs are finite and exactly zero.
  • Setup/scaffold failures and rerun evidence were retained; no repository model arithmetic was changed to obtain passing comparisons. These are local experiments, not a claim that all scenarios were added to CI.

Evidence and cleanup

Locally retained reports, source weights, fixtures, profiles, scripts, and failure evidence:

  • /datadisks/disk5/titaiwang/mobius-qwen755-gdn-qsa-f32-cpu-9a3ab8ed/summary.json
  • /datadisks/disk5/titaiwang/mobius-qwen755-gdn-qsa-f32-cpu-9a3ab8ed/extension-long-cpu/summary.json
  • /datadisks/disk5/titaiwang/mobius-qwen755-residual-ple-f32-cpu-9a3ab8ed/summary.json
  • /datadisks/disk5/titaiwang/mobius-qwen755-remaining-f32-cpu-9a3ab8ed/summary.json

These paths are local provenance, not publicly downloadable attachments or committed model payloads. The final feasible batch received 23947429320 network bytes and retained 23947365728 bytes of new source weights. As requested, Torch/HF/reference weights were preserved, while newly generated ONNX/external-data exports and disposable temporary files were removed. Cleanup was subsequently checked independently; no new ONNX/external-data files remain in the completed final-batch root. Reproduction requires rebuilding exports using the retained harness/source weights. Earlier immutable summaries describe their original retention state; subsequent cleanup receipts record the deletions.

Subsequent model/cache cleanup (October 13, 2026): after explicit authorization, the remaining PR-owned model/source-weight payloads, runtime caches, and temporary data were removed from the three FP32 CPU experiment roots. All 14 identified target directories were verified absent. The cleanup removed 58 files totaling 24258381512 logical bytes (approximately 22.59 GiB). Reports, scripts, provenance, headers/manifests, profiles, case/failure fixtures, and sampled-row evidence were retained; metadata inside removed directories was relocated to preserved-evidence directories. The separate Qwen3.8-27B checkpoint, shared caches, and unrelated work were not touched. The preceding source-weight retention statement describes the earlier experiment state: reproduction now requires reacquiring the pinned source-weight ranges and rebuilding exports. Historical numerical receipts and their provenance are unchanged.

Remaining: complete 128-shard/full-table and all-48-main-layer coverage, complete official-checkpoint E2E/greedy-generation qualification, independent ngram export, MTP implementation/qualification, and the explicitly deferred QSA tied-selection discrepancy. The follow-up design is tracked in #767. The previously recorded production BF16 vision failure, GPU performance, and GenAI serving-ABI limitations are not cleared by these FP32 CPU results.

Review-only test cleanup: the mixed builder import in discussion 4170677378 was replaced by pytest dotted-path monkeypatching in f23db1a8f68b86226304278261109abfc24e2882; focused standard-ONNX tests: 21 passed, 26 deselected, with scoped Ruff lint/format and diff checks passing. This test-only commit does not change the model arithmetic measured at 704dd94e....

Scope and limitations

  • This provides standard-operator graph support, independent reduced-model evidence, bounded official-weight CUDA/FP32 CPU component results, and a four-layer official-weight CPU composition with sampled ngram storage. It is not complete official-checkpoint parity or semantic generation-quality validation.
  • Full-checkpoint execution, full-size BF16 qualification, GPU performance, and GenAI driver compatibility were not verified. Only the specified component byte ranges were downloaded; no complete checkpoint was downloaded.
  • Official-weight GDN, gated residual/final mixer, and bounded PLE/ngram CPU checks have now run as detailed above. QSA retains measured tied-selection failures at the unchanged numerical gate. The unchanged complete table graph, complete 48-layer checkpoint, and complete decoder/VLM generation remain unqualified.
  • Standalone official-weight MoE fixtures use synthetic activations. The four-layer fixture additionally exercises MoE in its independently executed official-weight layer chain, but not in the complete 48-layer model.
  • Sequential Scan visits every expert; existing FP8 QDQ bank reconstruction can still require O(E) runtime memory. QSA uses sparse selection with dense masked attention, not a dedicated block-sparse runtime kernel.
  • Standard-only validation intentionally rejects other architectures that still leak unresolved custom operators in this mode. Other execution providers are unchanged.
  • Video, MTP execution, GGUF payload enablement, GenAI engine integration, and paged-cache ABI changes are excluded.
  • Follow-up design and staged acceptance criteria for ngram/main separation, MTP, and full-checkpoint qualification are tracked in Qwen3.8-Flash-Next: standard-ONNX ngram/main separation, MTP, and staged qualification #767; publishing that design does not imply those capabilities are implemented.
  • Unrelated local paged-attention and VibeVoice branch changes are not included.

Use sequential sparse Scan replacing standard-mode fused MoE; add recursive post-weight schema/domain validation; preserve other EPs. Targeted tests: 263 passing with 3 BF16 capability skips.

Signed-off-by: titaiwang <titaiwang@microsoft.com>
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 2, 2026 23:28
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Performance Comparison

Comparing b1e9c8e9 → 1a90ec75

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 269 269 +0.0% ⚪
qwen3_5_text (hybrid-text-generation) model_size_bytes 458 KB 458 KB +0.0% ⚪
qwen3_5_text (hybrid-text-generation) num_nodes 131 131 +0.0% ⚪
qwen3_5_vl (hybrid-qwen-vl) model_size_bytes 977 KB 977 KB +0.0% ⚪
qwen3_5_vl (hybrid-qwen-vl) num_nodes 461 461 +0.0% ⚪
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.

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing b1e9c8e9 → 1a90ec75

Model Sub-model Changes Status
qwen model 0 ⚪
qwen (static-cache) model 0 ⚪

No architecture changes detected. ✅


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

Comment thread tests/ep_optimization_test.py Fixed

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

🔵 Needs a closer look

The recursive control-flow export is high-impact and full-checkpoint generation and cross-runtime performance remain unverified.

Review effort: Balanced
Findings: None

What changed in this PR

Enables portable standard-ONNX export for Qwen3.8 Flash-Next while retaining fused MoE paths for other providers.

Changes:

  • Adds sparse Scan-based standard-ONNX MoE dispatch.
  • Recursively validates standard operators after optimization, lowering, and weight binding.
  • Adds extensive structural, numerical, multimodal, and quantized-weight tests.
File Description
src/​mobius/​models/​qwen4_exp.py Implements standard sparse MoE dispatch.
src/​mobius/​_optimizations.py Adds recursive standard-ONNX validation.
src/​mobius/​_builder.py Validates packages after opset lowering.
src/​mobius/​integrations/​transformers/​_builder.py Validates after weight binding.
src/​mobius/​_execution_providers.py Disables fused MoE for standard ONNX.
src/​mobius/​models/​qwen4_exp_test.py Adds model and MoE coverage.
tests/​ep_optimization_test.py Tests validation boundaries and recursion.
docs/​design/​qwen4-exp-text-core.md Documents behavior and limitations.

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

Fix feature-presence image mixing during cached multimodal decode, preserving
lexical image-token embeddings when no new image features are supplied.
Accumulate hyper-connection means in BF16-safe FP32 and compare QSA zero
biases through portable kernels.

Add independent text and VLM logits, all-state, and token parity coverage
against reduced Hugging Face models across CPU-F32, CUDA-F32, and CUDA-BF16.
This validates reduced models only; it makes no official-checkpoint or GenAI
compatibility claim.

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

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.

🟡 Changes recommended

The newly enabled path accepts BF16 VLM exports despite documented production-size numerical failures.

1 open finding

🧠 Review effort: Balanced

Comment thread src/mobius/_execution_providers.py
titaiwangms and others added 2 commits October 12, 2026 21:20
Reject BF16 vision exports for official-weight Qwen4-Exp models after the
vision parity failures showed that the standard-ONNX path is not qualified.
Guard at vision forward using the actual cast patch-projection weight dtype,
so it also covers independent component builds under onnx-standard.
Preserve BF16 text exports and other execution providers. Adjust the
regression matrix and documentation to record the rejection and retained
coverage. This is a qualification guard, not a numerical fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: titaiwang <titaiwang@microsoft.com>
Remove the local module import and retain the pytest dotted patch target for the post-opset-lowering leak check. This addresses review discussion 4170677378; no model arithmetic changes.

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

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.

🟡 Changes recommended

Nested graph opset validation can approve operators against an opset that is not serialized, and the BF16 verification claim contradicts the submitted tests and guard.

1 open finding
1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Low severity Verification claim incorrectly reports unsupported BF16 pipeline success

src/​mobius/​models/​qwen4_exp_test.py:3198

The PR verification text says the reduced image-text pipeline passed BF16 on CUDA, but this added parity test contains only FP32 cases and the new export guard rejects every BF16 onnx-standard vision build. Please correct that verification claim so it does not report a BF16 pipeline result that the submitted code cannot produce; the later stated BF16 rejection is consistent with this test.

🧠 Review effort: Balanced

Comment thread src/mobius/_optimizations.py Outdated
Seed standard-ONNX validation from model and function imports, inheriting them unchanged through lexical subgraphs. Nested IR imports are not serialized and must not authorize unsupported operator versions. Add If, Scan, repeated-graph, function-scope, and save/reload regressions.

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

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.

🔵 Needs a closer look

Standard validation can incorrectly accept overloaded model-local operators as standard schemas.

0 open findings

1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Reject non-empty ONNX overloads during schema validation

src/​mobius/​_optimizations.py:264

This schema check ignores the ONNX overload field. A node/function such as ("", "Identity", "custom") passes because get_schema("Identity", ...) succeeds, even though that overloaded identifier is a model-local function rather than the standard Identity schema; if its body is otherwise standard, the advertised fail-closed validation accepts it. Include the overload in traversal and reject non-empty overloads (or otherwise prove that the exact operator identifier resolves to a standard schema).

🧠 Review effort: Balanced

Validate node and function overloads alongside their domain, operator name, and effective opset. Non-empty overloads identify model-local operators and must not be accepted as registered standard schemas. Extend recursive leak tests and save/reload regressions to cover overloaded calls and declared functions with otherwise standard bodies.

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

titaiwangms commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

Addressed the overview-only overload finding in Copilot review 5497959269 in commit 954e8f1.

Both node and function validation now require an empty overload before looking up the standard schema. Errors include the overload alongside the domain, operator name, and effective opset. This closes the case where a model-local Identity overload with a standard Neg body was accepted as the standard Identity operator. Non-empty overloads are valid ONNX constructs, but are rejected by this strict standard-only export profile; other EP profiles and empty-overload standard operators are unchanged.

Added eight regression cases covering overloaded identifiers in the main graph, If/Scan/GRAPHS subgraphs, function signatures and bodies, plus declared local-function calls and definitions before/after save/reload. The focused standard-ONNX suite passes 43 tests; the complete EP optimization test module passes 69 tests. Scoped Ruff lint/format and git diff --check pass. Temporary ONNX test artifacts are removed.

This finding has no inline review thread to resolve.

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.

🔵 Needs a closer look

The substantial control-flow export changes and acknowledged full-model and QSA parity limitations warrant final human review.

0 open findings

🧠 Review effort: Balanced

Comment thread src/mobius/_optimizations.py
Accept ai.onnx.ml schemas without treating ML imports as core-domain aliases.
Resolve each node's schema against the enclosing domain-specific opset, and
resolve retained function identifiers from model imports while validating
their bodies against function-local imports.

Add recursive positive and negative identifier cases, missing/invalid ML
imports, core aliases, a checker/ORT Normalizer roundtrip, and retained ML
function coverage through optimizer cleanup and serialization. Document the
schema and runtime-support boundary.

Validation: 104 EP optimization tests passed. Scoped Ruff lint/format and
git diff --check passed. Scoped MyPy retains the same five baseline errors,
with no new diagnostics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2d24442a-b68c-452f-8538-12f34b5bc4ea
Signed-off-by: titaiwang <titaiwang@microsoft.com>
@titaiwangms
titaiwangms requested review from xiaoyu-work and a balanced review from Copilot October 16, 2026 18:41

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.

🔵 Needs a closer look

Cross-dtype expert arithmetic, an unresolved rounding issue, and global export-validation changes require final human review.

1 open finding

🧠 Review effort: Balanced

Comment thread src/mobius/models/qwen4_exp.py Outdated
Evaluate the standard Qwen MoE SiLU activation as FP32 Exp/Div and cast it back before the model-dtype up product, preserving activation rounding and negative tails.

Add an independent torch.nn.functional.silu oracle with adversarial boundary inputs through the actual Scan/If dispatch on CPU FP32 and CUDA FP32/FP16/BF16, with graph optimization disabled and enabled. CPU FP16 numerical parity is explicitly excluded.

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

Copilot-Session: 2d24442a-b68c-452f-8538-12f34b5bc4ea
Signed-off-by: titaiwang <titaiwang@microsoft.com>

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.

🔵 Needs a closer look

Sparse low-precision execution and global export validation warrant human review, and CUDA test availability guards still need correction.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Add CUDA PyTorch and ONNX Runtime availability guards to tests

src/​mobius/​models/​qwen4_exp_test.py:1266

CUDA-enabled PyTorch can coexist with CPU-only ONNX Runtime. These cases then run instead of skipping and fail during session creation or at the CUDA-provider assertion, including in the non-integration suite. The same guard is missing in test_reduced_standard_huggingface_cached_logits_and_states (line 3217) and test_reduced_standard_huggingface_image_pipeline_and_decode (line 3314).

Use the combined guard from test_standard_moe_silu_boundary at all three sites:

if device == "cuda" and (
    not torch.cuda.is_available()
    or "CUDAExecutionProvider" not in ort.get_available_providers()
):
    pytest.skip("CUDA PyTorch and ORT are required")
1 resolved since last review

Review effort: Balanced

Require Torch CUDA and ORT CUDA at all three CUDA test entry points; add 9 unavailable-backend regressions; extend independent HF text/image CUDA FP16 coverage with typed cache helper, recurrent FP32, and three dtype units; record fixed HF 598d8ba and tokenizers 23.1 reused offline; document 25 passing focused CPU BF16 skips; 7 HF cases passed on both ORT 1.30/f1d07 and 1.32/f33; profile actual CUDA execution; not full checkpoint qualification.

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

Copilot-Session: 2d24442a-b68c-452f-8538-12f34b5bc4ea
Signed-off-by: titaiwang <titaiwang@microsoft.com>

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.

🔵 Needs a closer look

Cross-architecture validation and precision-sensitive expert execution warrant human review given the bounded numerical qualification.

No open issues 🎉

Review effort: Balanced

@titaiwangms
titaiwangms merged commit fd8b2fd into main Oct 19, 2026
25 of 27 checks passed
@titaiwangms
titaiwangms deleted the feat/qwen38-standard-onnx branch October 19, 2026 16:40
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.

3 participants