Repository navigation
chore(models): share Qwen3.5/Qwen3.8 GatedDeltaNet, norm and shared expert in layers/ - #3860
Merged
Merged
Conversation
faresobeid
marked this pull request as ready for review
October 4, 2026 12:35
faresobeid
force-pushed
the
chore/share-qwen3-5-blocks
branch
from
October 11, 2026 12:57
ffa9892 to
c5e489b
Compare
…Norm and sigmoid-gated shared expert
samsja
force-pushed
the
chore/share-qwen3-5-blocks
branch
from
October 19, 2026 07:38
82816c8 to
1d66345
Compare
samsja
approved these changes
Oct 19, 2026
This was referenced Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Qwen3.8 Flash Next cloned three Qwen3.5 blocks. They now live once in
trainer/models/layers/, and both archs use them:layers/gated_delta_net.py::GatedDeltaNet(wasQwen3_5GatedDeltaNetand Qwen3.8GatedDeltaNet). It takes keyword args. Qwen3.5 passeshidden_act/output_gate_typefrom its config. Qwen3.8 passes"silu"/"sigmoid", the values it hardcoded before.layers/norms.py::ZeroCenteredRMSNorm(wasQwen3_5RMSNormand Qwen3.8RMSNorm).layers/mlp.py::SigmoidGatedFeedForward(wasQwen3_5SharedExpertandSigmoidOutputGatedFeedForward).The per-arch copies are deleted (
qwen3_5/{gated_delta_net,norm}.py,qwen3_8_flash_next/{gated_delta_net,norm}.py). State-dict keys, shapes and dtypes are unchanged for qwen3_5, qwen3_5_moe, the qwen3_5 VLM and qwen3_8.CP conv
cu_seqlens: Qwen3.5 passedcu_seqlensto the CP conv call and Qwen3.8 did not. Neither one is a bug. Whencp_contextis set, FLA'scausal_conv1dreturns early throughcausal_conv1d_cpand ignorescu_seqlens(fla 0.5.2,fla/modules/conv/causal_conv1d.py). The shared module keeps the Qwen3.5 single call. Qwen3.8 also passedinitial_state=None, output_final_state=Falseexplicitly. Those are the defaults, so the calls are the same.Behavior change
sigmoid(gate) * ffnand Qwen3.5 computesffn * sigmoid(gate). The product is the same, but autograd adds the two input-gradient terms in a different order. The shared module keeps the Qwen3.5 order. In a full CPU model, the largest weight-grad difference was about 3e-8.linear_attn, Qwen3.8 now registers parameters in the Qwen3.5 order (conv1d first). The keys are the same. Only the order of the state-dict /named_parameters()output changes, and the random init for a given seed. Models loaded from a checkpoint are not affected.What I ran
equiv_qwen38blocks.py). FLA kernels were replaced by pure-torch reference conv / gated-delta-rule / gated-norm, and every kernel call's kwargs were recorded. CP was faked with a stub context. Results:/tmp/prm-equiv/equiv.py check(CPU archs): all IDENTICAL.pytest tests/unit/train tests/unit/test_configs.py tests/unit/utils/test_weights.py -m "not gpu": 356 passed. The 2test_cpu_adamfailures are a missingninjain my env; they also fail on main.GPU checks (1×8 H200, SLURM job 2386)
prime_kernelshas noindexed_attention).-m gputests/unit/train/models/qwen3_5,test_qwen3_8_flash_next.pyandtest_cp_mamba.py: 11 passed. On main, the first two give 9 passed;test_cp_mambawas not part of the main run.Conflicts
#3833 rewrites the qwen3_5 / qwen3_8 modeling files. This PR touches only their imports and constructor calls, so expect a small rebase conflict there.
Note
Medium Risk
Touches core Qwen3.5/Qwen3.8 decoder paths (linear attention, norms, MoE shared expert) but is largely a refactor with stated bitwise equivalence for Qwen3.5 and near-identical Qwen3.8 behavior.
Overview
Consolidates duplicated Qwen3.5 and Qwen3.8 building blocks into shared
trainer/models/layers/modules and rewires both architectures to import them.GatedDeltaNetreplaces per-model linear-attention copies (Qwen3_5GatedDeltaNetand the Qwen3.8 local module), with explicit constructor kwargs (activation,output_gate_activation, etc.) instead of a Qwen3.5 config object.ZeroCenteredRMSNormandSigmoidGatedFeedForwardreplace arch-specific RMSNorm and sigmoid-gated shared-expert FFN implementations; Qwen3.5 dropsQwen3_5SharedExpertin favor of the shared MLP class.Per-arch files
qwen3_5/{gated_delta_net,norm}.pyandqwen3_8_flash_next/{gated_delta_net,norm}.pyare removed. Qwen3.8 MoE now usesSigmoidGatedFeedForwardfrom layers (localSigmoidOutputGatedFeedForwarddeleted). Intended checkpoint compatibility: state-dict keys unchanged; Qwen3.5/VLM behavior unchanged; Qwen3.8 forward matches with only minor autograd ordering on shared-expert input grads andlinear_attnparameter registration order for fresh inits.Reviewed by Cursor Bugbot for commit 1d66345. Bugbot is set up for automated code reviews on this repo. Configure here.