Skip to content

Fix GLM-5.2 packed KV-cache layout - #559

Merged
justinchuby merged 4 commits into
mainfrom
copilot/glm-52-fix-invalid-squeeze
Aug 23, 2026
Merged

Fix GLM-5.2 packed KV-cache layout#559
justinchuby merged 4 commits into
mainfrom
copilot/glm-52-fix-invalid-squeeze

Conversation

Copilot AI commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

GLM-5.2 declared standard multi-head KV-cache inputs while DSA expected packed single-head caches, causing an invalid Squeeze and incomplete output shape inference.

  • Cache wiring

    • Use the dedicated GlmMoeDsaTask.
    • Declare per-layer packed cache widths for full and shared indexers:
      key:   [B, 1, T, H*(nope+rope) + optional_index_dim]
      value: [B, 1, T, H*value_dim]
      
  • Regression coverage

    • Build co-located GLM tests through the production task.
    • Assert symmetric past/present cache shapes for both full and shared layers.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI and others added 3 commits August 23, 2026 04:18
Declare the DSA decoder's per-layer packed cache widths through the causal LM task so the unpacking Squeeze operates on its intended singleton head axis. Register and type the IndexShare custom op, and add tiny-config and cache-layout regression coverage.

Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
The DSA graph requires the pkg.nxrt IndexShare runtime kernel, which stock ORT used by synthetic parity does not register. Keep graph/checker and dedicated DSA tests active while treating this as a capability skip.

Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
Adopt main's dedicated GlmMoeDsaTask implementation from #560 and retain focused production-task cache layout regression coverage.

Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix invalid Squeeze in glm_moe_dsa model Fix GLM-5.2 packed KV-cache layout Aug 23, 2026
Copilot AI requested a review from justinchuby August 23, 2026 04:35
@justinchuby
justinchuby marked this pull request as ready for review August 23, 2026 04:40
@justinchuby
justinchuby requested review from a team and a lite review from Copilot August 23, 2026 04:40
@github-actions

Copy link
Copy Markdown

🏗️ Architecture Diff

Comparing d33c33be0b6893

Model Sub-model Changes Status

No architecture changes detected.


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

@justinchuby
justinchuby merged commit bed2983 into main Aug 23, 2026
22 of 23 checks passed
@justinchuby
justinchuby deleted the copilot/glm-52-fix-invalid-squeeze branch August 23, 2026 04:41
@github-actions

Copy link
Copy Markdown

Performance Comparison

Comparing d33c33be0b6893

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 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 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 264 264 +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 126 126 +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 428 428 +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.

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 updates the co-located GLM-5.2 DSA graph-build tests to exercise the production GlmMoeDsaTask path and adds a regression assertion that the KV-cache I/O is declared using the packed single-head layout expected by DSA.

Changes:

  • Switch the test build path from the generic "text-generation" task to the dedicated "glm-moe-dsa" task.
  • Add a regression test that asserts past/present KV-cache shapes are symmetric and use [B, 1, T, packed_width] with per-layer packed widths derived from the config.

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

Comment on lines +259 to +262
cache_inputs = {value.name: list(value.shape) for value in onnx_model.graph.inputs[3:]}
cache_outputs = {
value.name: list(value.shape) for value in onnx_model.graph.outputs[1:]
}
justinchuby added a commit that referenced this pull request Aug 23, 2026
## Root cause

`_DeepSeekMoEFFN.__init__` (src/mobius/models/deepseek.py) accepted
`linear_class`
but only forwarded it to `_SharedExpertMLP`, not to the `MoELayer` that
builds
the routed-expert dense loop-over-experts fallback:

```python
self.moe = MoELayer(config, gate=gate)  # linear_class silently dropped
```

Consequence: a quantized config correctly quantized attention, dense
FFN, and
the shared expert, but every routed MoE expert's gate/up/down
projections
stayed plain float `MatMul`. This both loses quantization for the routed
experts and breaks the `fuse_dense_moe_to_qmoe` post-hoc rewrite, which
only
pattern-matches a quantized `MatMulNBits` dense-fallback shape — so a
quantized DeepSeek-V2/V3 config would silently fail to fuse into QMoE
for its
routed experts.

DeepSeek-V4 is unaffected: its `DeepSeekV4MoE` uses `expert_factory` to
build
`_DeepSeekV4Expert`, which independently recomputes its quantized class
from
`config.quantization` per-expert rather than relying on `MoELayer`'s
`linear_class` forwarding — verified via review, no matching fix needed
there.

## Fix

One line: thread `linear_class` through to the routed-expert `MoELayer`:

```python
self.moe = MoELayer(config, gate=gate, linear_class=linear_class)
```

## Tests

Added `test_deepseek_moe_ffn_linear_class_reaches_routed_experts` in
`deepseek_test.py`, which isolates the assertion on `module.moe.experts`
(routed) separately from `module.shared_experts` (already worked before
this
fix), rather than relying on an aggregate creation count — so it can't
pass
for the wrong reason.

- Verified the new test **fails** on pre-fix code (`assert False` at the
  routed-experts isinstance check) and **passes** post-fix.
- Full suite: `PYTHONPATH=src python3 -m pytest src/` → **3249 passed, 9
  skipped**, no failures.
- `ruff check` / `ruff format --check` on changed files: clean.
- Independently reviewed (separate reviewer pass over the diff);
verdict:
  **Approve**, no findings.

## Scope

Deliberately minimal and focused: does not touch GLM-5.2 registration,
DeepSeek-V4 QMoE export, YaRN, or any other follow-up — those are
tracked/
landed separately (#548, #550, #555, #559, #560).

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

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

glm_moe_dsa (GLM-5.2) emits an invalid Squeeze; ORT cannot load the model

4 participants