Skip to content

[Zamba2] Fix block_id to use hybrid order for num_mem_blocks>1 - #48150

Draft
aryansk wants to merge 1 commit into
huggingface:mainfrom
aryansk:fix/zamba2-mem-blocks-47994
Draft

[Zamba2] Fix block_id to use hybrid order for num_mem_blocks>1#48150
aryansk wants to merge 1 commit into
huggingface:mainfrom
aryansk:fix/zamba2-mem-blocks-47994

Conversation

@aryansk

@aryansk aryansk commented Aug 20, 2026

Copy link
Copy Markdown

CI

Fixes #47994

Problem

Zamba2Model(config) raises ValueError: tie_weights_keys before any weight is loaded for any config with num_mem_blocks > 1 (e.g. Zyphra/Zamba2-2.7B-instruct, num_mem_blocks=2, 54 layers, hybrids at [6,12,18,24,30,36,42,47,51]). Repro on main with torch.device("meta"):

from transformers import AutoConfig
from transformers.models.zamba2 import Zamba2Model
import torch
cfg = AutoConfig.from_pretrained("Zyphra/Zamba2-2.7B-instruct")  # num_mem_blocks=2
with torch.device("meta"):
    Zamba2Model(cfg)  # ValueError layers.12 <-> layers.47 adapter mismatch

Root cause in Zamba2Model.get_layers: block_id = layer_id % num_mem_blocks uses the global layer index, while the tie cycle just above advances once per hybrid layer, and Zamba2Attention/Zamba2MLP select adapter slots with i % num_mem_blocks == block_id where i runs over hybrid layers. For 2.7B the global rule yields [0,0,0,0,0,0,0,1,1] where the cycle expects [0,1,0,1,0,1,0,1,0]; layer 12 ends up tied to 47 with a disjoint adapter set, failing validation that was added to catch silent mis-ties.

Where num_mem_blocks == 1 (1.2B, the Zamba2Config default) both conventions are identical, so no currently-working config changes behavior.

Change

  • Track hybrid_layer_idx in Zamba2Model.get_layers and compute block_id = hybrid_layer_idx % config.num_mem_blocks (increment per hybrid). This makes structure, tie cycle and checkpoint agree.
  • Applied to the modular source src/transformers/models/zamba2/modular_zamba2.py and kept modeling_zamba2.py in sync (generated file; single logical fix in two files). Minimal diff: +3/-1 per file, no comment bloat.
  • Verified the 2.7B config now constructs with 531 params matching the published checkpoint's 531 tensors (per Zamba2: num_mem_blocks > 1 checkpoints cannot be constructed — block_id uses the global layer index while the tie cycle uses hybrid order #47994), and tie_weights_keys correctly alternates (6→18→30→42→51 share block 0, 12→24→36→47 share block 1).

Why this approach

  • The fix is exactly the hybrid-counter that the adapter logic already uses (range(num_fwd_mem_blocks) with i % num_mem_blocks == block_id). Alternatives like keeping global modulo would require changing both adapter selection and tie cycle, which diverges from the checkpoint layout. This keeps the checkpoint as ground truth.
  • Same functional fix as closed [Zamba2] Fix layer construction and weight tying for num_mem_blocks > 1 #48018 (which CI showed green), but the issue remains open after maintainer coordination note; this PR is scoped to the failing get_layers path and includes disclosure/differentiation below.

Testing

  • Reproduction script on meta device before/after:
    • Before: Zamba2Config(num_mem_blocks=2) raises ValueError for layers.12:layers.47 with mismatched gate_up_proj_adapter_list indices (0,2,4,6,8 vs 1,3,5,7).
    • After: construction succeeds, model._tied_weights_keys as above, per-layer block_id follows hybrid_idx % 2 (6:0,12:1,18:0,24:1,30:0,36:1,42:0,47:1,51:0), and Zamba2ForCausalLM also constructs. num_mem_blocks=1 regression still passes.
  • Focused model tests: pytest tests/models/zamba2/test_modeling_zamba2.py (with datasets/parameterized): 129 passed, 146 skipped (run in local venv, Python 3.13, torch). No failures in the Zamba2 common suite.
  • Style: ruff check src/transformers/models/zamba2/{modeling_zamba2,modular_zamba2}.pyAll checks passed!

Documentation and release impact

  • No documentation impact
  • Changelog/release note needed: fixes construction for published 2.7B/7B checkpoints; no API change.
  • No migration note (previously-unconstructible configs now work; working configs unchanged).

Review notes

Zamba2Model.get_layers previously computed block_id as
layer_id % num_mem_blocks using the global layer index, while the
tie cycle and the adapter selection (i % num_mem_blocks == block_id
where i iterates over hybrid layers) use hybrid-order. For configs
with num_mem_blocks>1 (e.g. Zyphra/Zamba2-2.7B with 9 hybrids at
[6,12,18,24,30,36,42,47,51] and num_mem_blocks=2) this mis-aligns
block ids ([0,0,0,0,0,0,0,1,1] vs expected [0,1,0,1,0,1,0,1,0]) and
causes tie_weights_keys validation to fail (layers.12 vs layers.47).

Track hybrid_layer_idx and compute
block_id = hybrid_layer_idx % num_mem_blocks so structure, tie
cycle and checkpoint agree. For num_mem_blocks==1 behavior is
identical. Fixes huggingface#47994.

Co-authored fix mirrors closed huggingface#48018; modular source updated and
generated modeling file kept in sync.

AI assistance disclosure: used Muse Spark for diagnosis and fix
with human verification (meta-device construction + Zamba2ModelTest
129 passed).
@github-actions

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: zamba2

@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 32375658356
Result: success | Grafana metrics are not available yet.

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.

Zamba2: num_mem_blocks > 1 checkpoints cannot be constructed — block_id uses the global layer index while the tie cycle uses hybrid order

1 participant