Skip to content

[lora] Support GDN in_proj_ba adapters for Qwen3.5 - #30499

Merged
yushengsu-thu merged 1 commit into
sgl-project:sglang-milesfrom
yushengsu-thu:sgl-lora-qwen3.5
Jul 8, 2026
Merged

yushengsu-thu merged 1 commit into
sgl-project:sglang-milesfrom
yushengsu-thu:sgl-lora-qwen3.5

Conversation

@yushengsu-thu

@yushengsu-thu yushengsu-thu commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Qwen3.5's GatedDeltaNet (GDN) has two packed input projections: in_proj_qkvz (already LoRA-supported) and in_proj_ba — the delta-rule β/α gate projections. LoRA adapter weights covering in_proj_ba are currently silently dropped at load time (not in _KNOWN_LORA_TARGET_MODULES, warning only). An adapter trained against the fused megatron-side in_proj (Megatron-Bridge exports it split 4-way as in_proj_qkv/z/b/a) therefore serves base weights for the β/α slices — a quiet train/serve mismatch for RL.

Modifications

  • models/qwen3_5.py: add in_proj_ba to supported_lora_modules + get_hidden_dim (2 * linear_num_value_heads)
  • lora/utils.py: register in_proj_ba in _KNOWN_LORA_TARGET_MODULES, get_stacked_multiply (=2), and in_proj_b/in_proj_ain_proj_ba name normalization
  • lora/lora.py: new _normalize_in_proj_ba (split b+a concat, merged repeat×2); extend _normalize_in_proj_qkvz to accept the 2-way in_proj_qkv + in_proj_z layout emitted by Megatron-Bridge adapter export (shared lora_A repeated ×3 for the q|k|v slices) — previously only the 4-way PEFT layout and pre-merged form were handled

MergedColumnParallelLinearWithLoRA wraps the base layer generically (2-equal-slice path, same as gate_up) — no layer/mem-pool/manager changes needed.

Validation

  • Normalization unit checks: MB 2-way qkvz, b+a split, merged ba, and 4-way PEFT regression — all pass
  • End-to-end RL (miles) on Qwen/Qwen3.5-35B-A3B, 8×H200 TP2/EP8 colocate, LoRA on attention + MoE experts + shared expert + GDN in_proj/out_proj: rollout-vs-train logprob_abs_diff = 0.0100, zero adapter weights skipped

CI States

Latest PR Test (Base): ❌ Run #28927579933
Latest PR Test (Extra): ❌ Run #28978966210

Model coverage

Also covers Qwen3.6 with no additional changes: Qwen3.6 checkpoints declare the same Qwen3_5(Moe)ForConditionalGeneration architectures / qwen3_5* model_type, so they dispatch to qwen3_5.py and pick up this LoRA support directly. Verified with a 10-step LoRA RL run on Qwen/Qwen3.6-35B-A3B (full target set incl. GDN in_proj_qkvz/in_proj_ba/out_proj): rollout↔train logprob_abs_diff 0.010 at step 0, KL ≤ 0.004, reward 0.19 → 0.47, zero adapter weights skipped.

Qwen3.5's GatedDeltaNet has two packed input projections: in_proj_qkvz
(supported) and in_proj_ba (the delta-rule beta/alpha gates). Adapters
covering in_proj_ba were silently dropped at load time, so a LoRA
trained on the fused megatron in_proj served base weights for the
b/a slices (a quiet train/serve mismatch for RL).

- qwen3_5.py: add in_proj_ba to supported_lora_modules and
  get_hidden_dim (out dim = 2 * linear_num_value_heads)
- lora/utils.py: register in_proj_ba (known targets, stacked_multiply=2,
  in_proj_b/in_proj_a name normalization)
- lora/lora.py: new _normalize_in_proj_ba (b+a concat / merged repeat);
  extend _normalize_in_proj_qkvz to accept the 2-way in_proj_qkv +
  in_proj_z layout emitted by Megatron-Bridge adapter export (repeat the
  shared A 3x for the q|k|v slices)

MergedColumnParallelLinearWithLoRA wraps the base layer generically; no
layer/mem-pool changes needed.

Validated end-to-end with miles RL on Qwen/Qwen3.5-35B-A3B (8xH200,
TP2/EP8, colocate): rollout-vs-train logprob_abs_diff 0.0100 with LoRA
on attention + MoE experts + shared expert + GDN in_proj/out_proj; no
adapter weights skipped.

Signed-off-by: Yusheng Su <yushengsu.thu@gmail.com>
@yushengsu-thu
yushengsu-thu requested a review from Ying1123 as a code owner July 8, 2026 08:08
Copilot AI review requested due to automatic review settings July 8, 2026 08:08

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request adds support for normalizing and stacking in_proj_ba weights for GatedDeltaNet (GDN) layers, such as those in Qwen 3.5, and adds support for 2-way split in_proj_qkv and in_proj_z weights. The changes span LoRA weight normalization, utility functions, and the Qwen 3.5 model definition. Feedback suggests updating get_hidden_dim in qwen3_5.py to use config.linear_num_value_heads_cpu when running on CPU to avoid shape mismatches when loading LoRA adapters.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread python/sglang/srt/models/qwen3_5.py
@yushengsu-thu

Copy link
Copy Markdown
Collaborator Author

Additional end-to-end evidence: 10-step LoRA RL run (miles, GRPO/gsm8k) on Qwen/Qwen3.6-35B-A3B (same Qwen3_5* architecture/classes) with the full target set including GDN in_proj_qkvz + in_proj_ba + out_proj: step-0 rollout↔train logprob_abs_diff 0.010, KL ≤ 0.004 across 10 steps, reward 0.19 → 0.47, zero adapter weights skipped.

@yushengsu-thu
yushengsu-thu merged commit 2fdb655 into sgl-project:sglang-miles Jul 8, 2026
112 of 142 checks passed
yueming-yuan pushed a commit that referenced this pull request Jul 14, 2026
Signed-off-by: Yusheng Su <yushengsu.thu@gmail.com>
yueming-yuan pushed a commit that referenced this pull request Jul 14, 2026
Signed-off-by: Yusheng Su <yushengsu.thu@gmail.com>
yueming-yuan pushed a commit that referenced this pull request Jul 14, 2026
Signed-off-by: Yusheng Su <yushengsu.thu@gmail.com>
yueming-yuan pushed a commit that referenced this pull request Jul 14, 2026
Signed-off-by: Yusheng Su <yushengsu.thu@gmail.com>
martingiovannigeyer pushed a commit to martingiovannigeyer/sglang that referenced this pull request Jul 18, 2026
Add _normalize_in_proj_ba to LoRAAdapter: split in_proj_b + in_proj_a
adapter weights are concatenated into in_proj_ba, and already-merged
in_proj_ba adapters get their shared lora_A replicated 2x across the
stacked b/a slots. Extend _normalize_in_proj_qkvz with the 2-way
Megatron-Bridge split (in_proj_qkv + in_proj_z, qkv A block repeated 3x),
register in_proj_ba in the LoRA utils, and wire it into Qwen3_5ForCausalLM.

Ported from the sglang-miles branch (original PR sgl-project#30499).
Kh4L pushed a commit to Kh4L/sglang that referenced this pull request Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants