[Qwen3.8] Support Qwen3.8 on branch v0.5.15 - #22
Conversation
Signed-off-by: apinge <tong.qiu2@amd.com>
There was a problem hiding this comment.
Pull request overview
Adds Qwen3.8 text-only support on v0.5.15 through Qwen3.5-compatible model changes and ROCm RMSNorm paths.
Changes:
- Registers text-only Qwen configurations.
- Refactors dense/MoE model support and weight loading.
- Adds ROCm Triton Gemma RMSNorm dispatch.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Findings |
|---|---|
python/sglang/srt/utils/hf_transformers/common.py |
Critical import failure because text config classes are not re-exported. |
python/sglang/srt/models/qwen3_5.py |
Critical incompatibility with the MTP integration and MoE configuration handling. |
python/sglang/srt/layers/layernorm.py |
Critical AITER ABI mismatch; moderate empty-batch and batch-invariant handling issues. |
Suppressed comments (7)
python/sglang/srt/models/qwen3_5.py:1741
- Fused checkpoint names retain a suffix such as
.weight(and FP8 scale variants), so these checks never match keys like...experts.gate_up_proj.weight: the string does not end withexperts.gate_up_proj.is_fused_expertconsequently stays false, causing packed routed-expert tensors to bypass splitting/distribution; the remapped shared slotexperts.{num_experts}.gate_up_proj.*is missed as well. Match the base substrings and the remapped shared slot explicitly.
if name.endswith("experts.gate_up_proj") or name.endswith(
"experts.down_proj"
):
python/sglang/srt/models/qwen3_5.py:1889
- With pipeline parallelism,
make_layersleavesPPMissingLayerplaceholders outside this rank's range, and those placeholders have nomlp. When EPLB evaluates this lazy property, the comprehension therefore raisesAttributeErrorinstead of returning the local expert weights. Iterate only overstart_layer:end_layerand guard themlplookup.
self._routed_experts_weights_of_layer = LazyValue(
lambda: {
layer_id: layer.mlp.get_moe_weights()
for layer_id, layer in enumerate(self.model.layers)
if isinstance(layer.mlp, Qwen2MoeSparseMoeBlock)
python/sglang/srt/models/qwen3_5.py:1383
- For MoE inputs this coercion discards the original
model_type:Qwen3_5MoeTextConfigbecomesQwen3_5TextConfig. The MTP implementation passes the target text config to this class and has explicit MoE expert loading, but the resultingQwen3_5Modelnow builds dense MLPs instead ofQwen2MoeSparseMoeBlock, so MoE MTP weights cannot load or execute. Derivemoefrom the input model type or preserve the subclass.
config = _coerce_qwen3_5_text_config(config, moe=False)
python/sglang/srt/models/qwen3_5.py:1382
qwen3_5_mtp.py:99-103still constructs this class withis_nextn=True, but the new constructor no longer accepts that argument. Every Qwen3.5 MTP model therefore raisesTypeErrorduring initialization. Preserve the parameter and forward it toQwen3_5Model, which already supports it.
) -> None:
python/sglang/srt/models/qwen3_5.py:1389
- This wrapper changes the parameter namespace from the old body-only layout to
model.*. Existing body-only callers do not account for that extra nesting: MTP rewritesmtp.layers.*tomodel.layers.*(qwen3_5_mtp.py:287-290), and MiniCPM stripsmodel.language_model.tolayers.*(minicpmv.py:1581-1584). Consequently their LLM weights no longer matchparams_dictand remain at initialization values. Keep the backbone layout compatible or update both callers' name remapping together with this wrapper.
self.model = Qwen3_5Model(
config, quant_config, prefix=add_prefix("model", prefix)
python/sglang/srt/models/qwen3_5.py:1447
- This new forward applies the LM head and returns
LogitsProcessorOutput, but the class is still used as a body-only model by bothqwen3_5_mtp.py:197-208andMiniCPMV4_6.forward(minicpmv.py:1446-1457), which each apply their own logits processor. Those callers will either process logits twice or fail when treating the result as hidden states. Keep this class body-only for those integrations (and let the outer model own the head), or switch both callers toQwen3_5Modeland update their loading paths.
return self.logits_processor(
input_ids, hidden_states, self.lm_head, forward_batch, aux_hidden_states
)
python/sglang/srt/models/qwen3_5.py:1405
- The new text-only wrapper owns
capture_aux_hidden_states, butset_dflash_layers_to_capturewas left onQwen3_5Modeland is not delegated here.ModelRunner.init_aux_hidden_state_capture()calls this method on the registered top-level model for DFLASH (model_runner.py:1055-1061), so enabling DFLASH with a text-only Qwen3.5 model now raises the missing-methodValueError. Add a wrapper method that sets the flag and delegates toself.model.
self.capture_aux_hidden_states = False
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Signed-off-by: apinge <tong.qiu2@amd.com>
modification in
|
|
@sammysun0711 About gemma rmsnorm I profiled current version. In decode, because The profile is 8k in 1conc. |


Motivation
Support Qwen3.8-2.4T-A95B-FP8 on this v0.5.15 branch. This change partially references the implementation in branch qwen3_8_mi308x
Modifications
Change the backbone from
Qwen3_5ForCausalLMtoQwen3_5Modelto allow the Qwen3.8 text-only checkpoint to be initialized directly as a causal LM.Accuracy Tests
Speed Tests and Profiling
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ci