[Bugfix] Fix RoPE construction for deepseek-v4 sparse SWA layers (#54815)

Signed-off-by: Isotr0py <Isotr0py@outlook.com>

Isotr0py committed Sep 2, 2026 at 11:48 UTC 1d8d7a39652726a40068a42a8218cbac3af7b214
1 file changed +17 -1
vllm/models/deepseek_v4/common/rope.py
+17 -1
@@ -15,15 +15,31 @@ def build_deepseek_v4_rope(
15 compress_ratio: int,
16 ) -> RotaryEmbedding:
17 rope_parameters = config.rope_parameters
18 + # Newer checkpoints nest per-layer-type rope dicts ({"main", "compress"});
19 + # older ones ship a single flat dict shared by all layer types.
20 + if isinstance(rope_parameters.get("main"), dict) and isinstance(
21 + rope_parameters.get("compress"), dict
22 + ):
23 + key = "compress" if compress_ratio > 1 else "main"
24 + rope_parameters = dict(rope_parameters[key])
25 + else:
26 + rope_parameters = dict(rope_parameters)
27 +
28 rope_parameters["rope_theta"] = (
29 config.compress_rope_theta if compress_ratio > 1 else config.rope_theta
30 )
21 - if rope_parameters["rope_type"] != "default":
31 + if compress_ratio > 1 and rope_parameters["rope_type"] != "default":
32 + # YaRN applies only to compressor (CSA/HCA) layers.
33 rope_parameters["rope_type"] = (
34 "deepseek_yarn"
35 if rope_parameters.get("apply_yarn_scaling", True)
36 else "deepseek_llama_scaling"
37 )
38 + else:
39 + # Sliding-window layers use plain RoPE (theta=rope_theta, no YaRN).
40 + rope_parameters["rope_type"] = "deepseek_yarn"
41 + rope_parameters["factor"] = 1.0
42 + rope_parameters["original_max_position_embeddings"] = max_position_embeddings
43 rope_parameters["mscale"] = 0 # Disable mscale
44 rope_parameters["mscale_all_dim"] = 0 # Disable mscale
45 rope_parameters["is_deepseek_v4"] = True