Skip to content

Add native GPT-OSS MXFP4 QMoE export - #719

Open
titaiwangms wants to merge 7 commits into
mainfrom
titaiwang/gptoss-mxfp4-qmoe
Open

Add native GPT-OSS MXFP4 QMoE export#719
titaiwangms wants to merge 7 commits into
mainfrom
titaiwang/gptoss-mxfp4-qmoe

Conversation

@titaiwangms

@titaiwangms titaiwangms commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • preserve official GPT-OSS MXFP4 expert weights instead of dequantizing and requantizing them
  • losslessly repack GPT-OSS [E, N, K/32, 16] blocks into the native QMoE [E, K, N/2] layout
  • emit com.microsoft::QMoE with GPT-OSS routing, expert biases, global scales, and SwiGLU semantics
  • stream indexed safetensors one expert projection at a time so GPT-OSS 120B does not require an eager second copy of all expert weights
  • keep integer-affine GPTQ/AWQ/Olive QMoE and unquantized GPT-OSS paths unchanged

Runtime requirements

Native GPT-OSS MXFP4 export currently requires:

  • the CUDA execution provider
  • FP16 or BF16 activations
  • an ONNX Runtime build with FP4 QMoE enabled using CUDA 12.8 or newer

Unsupported execution providers and dtypes fail before graph construction or weight I/O.

Draft validation remaining

The implementation blockers are resolved. Before marking this PR ready, the
remaining work is runtime qualification with official checkpoints:

  • export an official GPT-OSS 20B and 120B checkpoint and record peak host
    memory, temporary disk use, output size, and wall time
  • run prefill and cached decode on A100 with a pinned FP4-QMoE-enabled ONNX
    Runtime build
  • characterize both the SM80 fused path and forced full-dequant fallback,
    including numerical parity and peak GPU memory

Validation

  • native nibble repacking is byte-exact across chunk boundaries
  • E8M0 bytes 0x00 through 0xfe are preserved and 0xff is rejected
  • cross-shard block/scale pairs are streamed and transformed without invoking the eager checkpoint loader
  • graph construction emits the expected FP4 QMoE inputs, attributes, routing, biases, and global scales
  • existing integer QMoE, generic streaming, configuration, builder, and unquantized GPT-OSS tests pass
  • the resulting FP4 QMoE contract was exercised against ONNX Runtime CUDA with numerical parity to the GPT-OSS reference computation

Preserve official GPT-OSS MXFP4 expert weights during QMoE export and stream indexed safetensors one projection at a time.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Performance Comparison

Comparing 014812f6c88112

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 265 +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 127 127 +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 450 450 +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 Sep 1, 2026

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing 014812f6c88112

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 0
qwen3_5_text (hybrid-text-generation) model 0
qwen3_5_vl (hybrid-qwen-vl) decoder 0
qwen3_5_vl (hybrid-qwen-vl) embedding 0
qwen3_5_vl (hybrid-qwen-vl) vision_encoder 0
qwen3_moe model 0
qwen3_moe (static-cache) model 0
qwen3_next (hybrid-text-generation) model 0
t5 (seq2seq) decoder 0
t5 (seq2seq) encoder 0
whisper (speech-to-text) decoder 0
whisper (speech-to-text) encoder 0

No architecture changes detected.


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

Apply the existing streaming save policy and revalidate E8M0 scales when lazy sources are materialized.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
Emit the required ONNX IR version and prevent streaming safetensors output from overwriting lazy source shards through directory, symlink, component-layout, or hard-link aliases.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
Comment thread src/mobius/_model_package_test.py Fixed
Comment thread src/mobius/_model_package_test.py Fixed
Comment thread src/mobius/_ir_utils.py Outdated
Comment thread src/mobius/_ir_utils.py Outdated
Comment thread src/mobius/_ir_utils.py Outdated
Align native MXFP4 attention and KV-cache behavior with the ORT GenAI model builder, and keep graph capture consistent with the effective shared-buffer contract.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
@titaiwangms
titaiwangms marked this pull request as ready for review September 3, 2026 23:24
@titaiwangms
titaiwangms requested review from a team and a lite review from Copilot September 3, 2026 23:24

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

It modifies core export/weight-loading/serialization paths and introduces a new native FP4 runtime-dependent execution slice that needs final qualification on official checkpoints and the targeted ORT CUDA build.

Pull request overview

This PR adds a native export path for GPT-OSS MXFP4 MoE checkpoints that preserves the original FP4 expert codes/scales (no dequant/requant), repacks them into ORT’s native com.microsoft::QMoE FP4 layout, and introduces a bounded-memory streaming safetensors loader so very large checkpoints (e.g., 120B) can be exported without holding an eager second copy of expert weights in host RAM.

Changes:

  • Implement native GPT-OSS MXFP4 export: lossless FP4 nibble repacking, E8M0 byte validation, native QMoE emission, and direct GroupQueryAttention path for the supported CUDA slice.
  • Add native MXFP4 safetensors streaming: new transformed streaming sources, plan validation, and ModelPackage.save() collision guards to prevent overwriting lazily-read source shards.
  • Make export/config more robust: infer minimum ONNX IR version from graph dtypes (IR12 for FLOAT8E8M0), introduce QuantizedWeightFormat, and resolve ORT GenAI graph-capture settings based on the finalized KV-cache contract.
File summaries
File Description
src/mobius/tasks/_task_test.py Adds unit coverage for _make_model() IR version floor behavior (IR11 vs IR12).
src/mobius/tasks/_base.py Sets model ir_version via minimum_ir_version(graph) instead of hard-coding 11.
src/mobius/models/gptoss.py Implements native MXFP4 QMoE export, repacking/validation, and direct GQA path for supported builds.
src/mobius/models/gptoss_test.py Expands unit tests for repacking, native MXFP4 preprocessing/graph emission, and CUDA GQA parity checks.
src/mobius/models/base.py Gates quantized-linear factory selection on QuantizedWeightFormat.INTEGER_AFFINE.
src/mobius/integrations/transformers/_gptoss_weights.py Adds bounded-memory native MXFP4 safetensors streaming planner + binder.
src/mobius/integrations/transformers/_gptoss_weights_test.py Adds extensive tests for streaming transforms, save collision guards, and roundtrip portability.
src/mobius/integrations/transformers/_builder.py Validates native GPT-OSS MXFP4 export contract early and routes weight loading to streaming.
src/mobius/integrations/transformers/_builder_test.py Tests streaming selection and early contract failures (EP/dtype).
src/mobius/integrations/ort_genai/genai_config.py Resolves decoder graph capture only after KV-cache/search settings are finalized.
src/mobius/integrations/ort_genai/genai_config_test.py Adds coverage for graph-capture resolution vs share-buffer and beam settings.
src/mobius/integrations/ort_genai/ep_config.py Ensures DML graph capture can be explicitly disabled (emit option key).
src/mobius/integrations/ort_genai/ep_config_test.py Adds tests for DML graph-capture default vs explicit disable behavior.
src/mobius/integrations/ort_genai/auto_export_test.py Updates/extends tests to ensure capture tracks KV-cache contract.
src/mobius/integrations/_weight_loading.py Adds StreamingTransformedWeightSource + synthesized targets support, and threads it through streaming validation/binding.
src/mobius/components/_moe.py Refactors QMoE gate realization into a reusable helper for routing adapters.
src/mobius/_weight_utils.py Prevents integer-affine QMoE logic from claiming MXFP4 configs.
src/mobius/_model_package.py Adds streaming-save collision protection, freezes component filters, and adds E8M0 safetensors compatibility shim + lock.
src/mobius/_model_package_test.py Adds tests for E8M0 safetensors save compatibility, predicate freezing, and streaming collision checks.
src/mobius/_ir_utils.py Introduces dtype inspection helpers and minimum_ir_version() (IR12 floor for FLOAT8E8M0).
src/mobius/_configs/_quantization.py Adds QuantizedWeightFormat enum and weight-format normalization + MXFP4 parsing.
src/mobius/_configs/init.py Re-exports QuantizedWeightFormat.
src/mobius/_configs_test.py Adds tests for weight-format defaults, normalization, and transformers MXFP4 parsing.
Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Lite

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

Comment thread src/mobius/models/gptoss_test.py Outdated

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

ONNX saves can corrupt hard-linked lazy sources, and native QMoE execution lacks automated parity coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

src/mobius/models/gptoss_test.py:106

  • This test helper introduces explicit protobuf construction through onnx.helper/onnx.TensorProto, which this repository prohibits even in tests. Build the parity graph with onnx_ir (ir.Value, ir.Node, ir.Graph, and ir.Model) and serialize that model instead.
    tensor = onnx.helper.make_tensor_value_info
    inputs = [
        tensor("query", onnx.TensorProto.FLOAT16, [batch, query_length, 16]),
        tensor("key", onnx.TensorProto.FLOAT16, [batch, query_length, 8]),
        tensor("value", onnx.TensorProto.FLOAT16, [batch, query_length, 8]),
  • Files reviewed: 23/23 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread src/mobius/_model_package.py Outdated
Comment thread src/mobius/models/gptoss.py
Resolve the latest main conflicts while preserving native GPT-OSS MXFP4 streaming and GQA support. Adopt universal IR 12, harden source-safe transactional serialization, and restore explicit dense dequantization across CLI entry points.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
Execute the emitted CUDA QMoE with production-repacked checkpoint tensors and compare routing, clipped SwiGLU, and bias semantics against an independent decoder for prefill and decode-shaped inputs.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
Test the shared build boundary after local config exports stopped using the removed private config and module-building helpers.

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

Copilot-Session: 1d9a8b1f-9b83-4a52-bfe4-92437196e1c1
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