Skip to content

Fix L4/L5 golden regressions across 7 broken models - #436

Merged
justinchuby merged 1 commit into
mainfrom
fix/l4l5-broken-models
Jul 30, 2026
Merged

Fix L4/L5 golden regressions across 7 broken models#436
justinchuby merged 1 commit into
mainfrom
fix/l4l5-broken-models

Conversation

@justinchuby

Copy link
Copy Markdown
Member

Summary

An L4/L5 golden-test regression sweep on main (CI had not run for a while) found 7 models failing at build or run time. This PR root-causes and fixes each one, then verifies L4 (prefill argmax) and L5 (generation) on GPU (CUDA EP).

Fixes

Model Root cause Fix
diffllama-0.3b create_padding_mask returns 4D [B,1,S,Sk], but attention re-Unsqueezed it → rank-5 bias broke ORT Split Add the already-4D pad bias directly
gemma-4-e2b/e4b audio (1) op.Range got 1-D [1] limit from op.Shape; (2) mask-downsample Slice used INT64_MAX ends → shape inference derived 2^62 length → Reshape overflow at load (1) squeeze limit to scalar at both Range sites; (2) bound Slice ends to the dynamic time dim
gemma-4-e2b-it-assistant Generic Attention path built sliding-window bias from full buffer-width mask (kv_len+1) while K is only shared KV (kv_len) → inconsistent total_sequence_length Slice mask to kv_len first
qwen3-asr / qwen3-asr-en thinker_config ships as a plain dict, so text_config-unwrap in build() missed it → decoder hidden_size=0 Convert dict via _dict_to_pretrained_config before unwrapping
nemotron-h-nano-4b build() without trust_remote_code mis-detected layer_types as linear_attention (TypeError) Add trust_remote_code + clear None-guard in linear_attention_dims; documented skip_reason (HF ref needs trust_remote_code + mamba-ssm CUDA kernels, unavailable in CI — same as jamba/granitemoehybrid; prior golden was generated with the wrong native config)
sensevoice-small audio-ctc L4/L5 not wired into the e2e harness (custom LFR-fbank + language_id, FunASR reference, no golden generator) documented skip_reason

Verification (GPU, CUDA EP)

  • L4 + L5 PASS: diffllama-0.3b, qwen3-asr, qwen3-asr-en, gemma-4-e2b-it-audio, gemma-4-e4b-it-audio, gemma-4-e2b-it-assistant
  • SKIP (documented): nemotron-h-nano-4b, sensevoice-small
  • Regression sanity (unchanged, still pass): gemma-4-e2b, llama-3_2-1b, qwen3-0_6b

Notes

  • No protobuf ops; onnx_ir APIs only.
  • ruff format / ruff check clean.
  • The nemotron-h build fixes are genuine improvements (correct mamba2 layer types); only the golden comparison is skipped until a valid reference can be generated.

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

@github-actions

Copy link
Copy Markdown

Performance Comparison

Comparing 9b22d8d18c4c8b

Model Metric Baseline Current Delta
bert (feature-extraction) model_size_bytes 359 KB 359 KB +0.0%
bert (feature-extraction) num_nodes 60 60 +0.0%
falcon model_size_bytes 364 KB 364 KB +0.0%
falcon num_nodes 68 68 +0.0%
gemma2 model_size_bytes 428 KB 428 KB +0.0%
gemma2 num_nodes 107 107 +0.0%
gpt2 model_size_bytes 388 KB 388 KB +0.0%
gpt2 num_nodes 54 54 +0.0%
llama model_size_bytes 425 KB 425 KB +0.0%
llama num_nodes 62 62 +0.0%
llama (static-cache) model_size_bytes 425 KB 425 KB +0.0%
llama (static-cache) num_nodes 58 58 +0.0%
mamba (ssm-text-generation) model_size_bytes 296 KB 296 KB +0.0%
mamba (ssm-text-generation) num_nodes 98 98 +0.0%
phi3 model_size_bytes 421 KB 421 KB +0.0%
phi3 num_nodes 60 60 +0.0%
phi3 (static-cache) model_size_bytes 421 KB 421 KB +0.0%
phi3 (static-cache) num_nodes 56 56 +0.0%
qwen2 model_size_bytes 425 KB 425 KB +0.0%
qwen2 num_nodes 62 62 +0.0%
qwen2 (static-cache) model_size_bytes 425 KB 425 KB +0.0%
qwen2 (static-cache) num_nodes 58 58 +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 275 275 +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 129 129 +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 413 413 +0.0%
t5 (seq2seq) model_size_bytes 836 KB 836 KB +0.0%
t5 (seq2seq) num_nodes 166 166 +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.

Pull request overview

This PR fixes multiple L4/L5 golden regressions by addressing model-specific build/runtime issues across several architectures, plus documenting intentional golden-test skips where a valid HF reference cannot be produced in CI.

Changes:

  • Fix attention-mask/bias shape handling in DiffLlama and Gemma4 assistant to satisfy ORT Attention/KV-shape constraints.
  • Fix Gemma4 audio masking/downsampling and Range scalar-limit issues to avoid shape-inference overflow and runtime errors.
  • Improve config resolution for composite configs (e.g., Qwen3-ASR thinker_config dict) and harden linear-attention cache config validation; document skip reasons for unsupported CI golden generation cases.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
testdata/cases/speech/sensevoice-small.yaml Adds skip_reason documenting why SenseVoice audio-ctc L4/L5 isn’t currently runnable in the e2e harness.
testdata/cases/causal-lm/nemotron-h-nano-4b.yaml Enables trust_remote_code and documents golden-generation skip due to unavailable HF reference dependencies in CI.
src/mobius/tasks/_cache_utils.py Adds explicit validation/error messaging when linear-attention cache dims are requested but config fields are unset.
src/mobius/models/diffllama.py Fixes padding-mask bias rank/broadcasting by adding already-4D bias directly to attention scores.
src/mobius/components/_gemma4_audio.py Fixes Range limit rank and bounds Slice ends to dynamic lengths to prevent shape-inference overflow.
src/mobius/components/_gemma4_assistant.py Slices buffer-width attention mask to shared-KV length to avoid inconsistent total_sequence_length failures.
src/mobius/_builder.py Converts dict-valued composite sub-configs to PretrainedConfig to reliably unwrap text_config.

Comment on lines 49 to +52
head_k_dim = config.linear_key_head_dim
head_v_dim = config.linear_value_head_dim
conv_kernel = config.linear_conv_kernel_dim
missing = [
@github-actions

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing 9b22d8d18c4c8b

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)

An L4/L5 golden-test regression sweep found seven models failing at build
or run time. Root-cause and fix each:

- diffllama: create_padding_mask now returns a 4D bool [B,1,S,Sk] mask, but
  DiffLlamaAttention still unsqueezed it again, producing a rank-5 bias that
  broke ORT Split. Add the (already-4D) pad bias directly.

- gemma-4 audio encoder (e2b + e4b): (1) op.Range got a 1-D [1] limit from
  op.Shape; squeeze to a scalar at both Range sites. (2) the mask-downsample
  Slice uses an INT64_MAX "to-the-end" sentinel with step 2; onnx-shape-
  inference < 0.3.1 did not normalize the sentinel for strided slices and
  derived a 2^62 extent that overflowed the downstream Reshape at load. Bump
  the dependency to onnx-shape-inference>=0.3.1 (which normalizes a positive-
  sentinel end to ceil(dim/step)) and keep the natural [INT64_MAX] slice.

- gemma-4 assistant drafter: the generic Attention path built the sliding-
  window bias from the full buffer-width attention_mask (kv_len + 1) while K
  is only the shared KV (kv_len), so ORT rejected an inconsistent
  total_sequence_length. Slice the mask to kv_len first.

- qwen3-asr / qwen3-asr-en: thinker_config ships as a plain dict, so the
  text_config-unwrap branch in build() missed it and the decoder config kept
  hidden_size=0. Convert the dict via _dict_to_pretrained_config before
  unwrapping text_config.

- nemotron-h: build() without trust_remote_code mis-detected layer_types as
  linear_attention (TypeError). Add trust_remote_code and a clear None-guard
  in linear_attention_dims. The build now succeeds with correct mamba2 layer
  types, but the HF reference needs trust_remote_code custom modeling plus
  mamba-ssm CUDA kernels that are unavailable in CI golden generation (same
  as jamba-v0_1 / granitemoehybrid-tiny), and the previously committed golden
  was generated without trust_remote_code (wrong native config). Documented
  skip_reason added until a valid golden can be produced.

- sensevoice-small: audio-ctc L4/L5 is not wired into the e2e harness (custom
  LFR-fbank input_features + language_id, FunASR reference, no audio-ctc
  golden generator). Documented skip_reason added.

Verified on GPU (CUDA EP): diffllama, qwen3-asr, qwen3-asr-en,
gemma-4-e2b-it-audio, gemma-4-e4b-it-audio, gemma-4-e2b-it-assistant all pass
L4 and L5; nemotron-h and sensevoice-small skip. Regression-checked
gemma-4-e2b, llama-3_2-1b, qwen3-0_6b (unchanged, still pass).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: justinchuby <justinchuby@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 16:31
@justinchuby
justinchuby force-pushed the fix/l4l5-broken-models branch from 18c4c8b to db9a470 Compare July 30, 2026 16:32
@justinchuby
justinchuby merged commit 195b207 into main Jul 30, 2026
13 of 25 checks passed
@justinchuby
justinchuby deleted the fix/l4l5-broken-models branch July 30, 2026 16:36

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.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/mobius/tasks/_cache_utils.py:69

  • The new missing list check doesn't narrow the Optional[int] config fields for mypy, so key_dim = head_k_dim * num_k_heads (and similar) will still be typed as Optional[int] * Optional[int] under strict_optional, causing a type-check failure. Also, the docstring still says it raises TypeError, but the new code raises ValueError.
    missing = [
        name
        for name, value in (
            ("linear_num_key_heads", num_k_heads),
            ("linear_num_value_heads", num_v_heads),
            ("linear_key_head_dim", head_k_dim),
            ("linear_value_head_dim", head_v_dim),
            ("linear_conv_kernel_dim", conv_kernel),
        )
        if value is None
    ]
    if missing:
        raise ValueError(
            "Linear-attention cache inputs requested but the following config "
            f"fields are unset: {', '.join(missing)}. This usually means the "
            "architecture's layer_types were mis-detected as 'linear_attention' "
            "(e.g. a hybrid model built without trust_remote_code)."
        )

Copilot AI review requested due to automatic review settings July 30, 2026 16:37

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.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/mobius/tasks/_cache_utils.py:64

  • This guard now raises ValueError, but the function docstring (above) documents a TypeError for missing required config fields. To keep the public contract consistent (and avoid surprises for callers that may be catching TypeError), consider raising TypeError here instead, or update the docstring in a follow-up.
        raise ValueError(

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