[Bugfix] Handle null RoPE parameters for NoPE layers (#55949)
Signed-off-by: Andreas Karatzas <akaratza@amd.com>
Andreas Karatzas committed
Sep 8, 2026 at 15:20 UTC
18615ad1ee11ae54a996a0c49dd6860630b3bca0
4 files changed
+75
-1
tests/test_config.py
+43
@@ -1533,6 +1533,49 @@ def test_get_and_verify_max_len(
1533
assert actual_max_len == expected_max_len
1534
1535
1536
+@pytest.mark.parametrize("max_model_len", [None, 1024])
1537
+@pytest.mark.parametrize(
1538
+ ("rope_parameters", "expected_max_len"),
1539
+ [
1540
+ ({"rope_type": "default"}, 4096),
1541
+ ({"rope_type": "linear", "factor": 2.0}, 8192),
1542
+ ({"rope_type": "longrope"}, 2048),
1543
+ ],
1544
+)
1545
+def test_get_and_verify_max_len_with_nope_layers(
1546
+ max_model_len, rope_parameters, expected_max_len
1547
+):
1548
+ """NoPE layers do not prevent deriving or scaling the context length."""
1549
+ from transformers import PretrainedConfig
1550
+
1551
+ from vllm.config.model import _get_and_verify_max_len
1552
+ from vllm.transformers_utils.model_arch_config_convertor import (
1553
+ ModelArchConfigConvertorBase,
1554
+ )
1555
+
1556
+ hf_config = PretrainedConfig(
1557
+ max_position_embeddings=4096,
1558
+ original_max_position_embeddings=2048,
1559
+ )
1560
+ hf_config.rope_parameters = {
1561
+ "full_attention": None,
1562
+ "sliding_attention": rope_parameters,
1563
+ }
1564
+ model_arch_config = ModelArchConfigConvertorBase(hf_config, hf_config).convert()
1565
+
1566
+ actual_max_len = _get_and_verify_max_len(
1567
+ hf_config=hf_config,
1568
+ model_arch_config=model_arch_config,
1569
+ tokenizer_config=None,
1570
+ max_model_len=max_model_len,
1571
+ disable_sliding_window=False,
1572
+ sliding_window=None,
1573
+ )
1574
+
1575
+ assert actual_max_len == (max_model_len or expected_max_len)
1576
+ assert hf_config.rope_parameters["full_attention"] is None
1577
+
1578
+
1579
class MockConfig:
1580
"""Simple mock object for testing maybe_pull_model_tokenizer_for_runai"""
1581
tests/transformers_utils/test_config.py
+23
@@ -18,6 +18,7 @@ from vllm.tokenizers import get_tokenizer
18
from vllm.transformers_utils import config as config_module
19
from vllm.transformers_utils.config import (
20
get_safetensors_params_metadata,
21
+ patch_legacy_rope_type,
22
try_get_generation_config,
23
)
24
from vllm.transformers_utils.configs.glm5_next import (
@@ -27,6 +28,28 @@ from vllm.transformers_utils.configs.glm5_next import (
28
)
29
30
31
+def test_patch_legacy_rope_type_preserves_nope_layers():
32
+ """NoPE layers stay disabled while later RoPE layers are normalized."""
33
+ rope_parameters = {
34
+ "full_attention": None,
35
+ "sliding_attention": {
36
+ "type": "mrope",
37
+ "mrope_section": [24, 20, 20],
38
+ },
39
+ }
40
+
41
+ patch_legacy_rope_type(rope_parameters)
42
+
43
+ assert rope_parameters == {
44
+ "full_attention": None,
45
+ "sliding_attention": {
46
+ "type": "mrope",
47
+ "rope_type": "default",
48
+ "mrope_section": [24, 20, 20],
49
+ },
50
+ }
51
+
52
+
53
def test_glm5_next_accepts_deepseek_sparse_attention_layers():
54
layer_types = ["linear_attention", "deepseek_sparse_attention"]
55
vllm/config/model.py
+7
@@ -2449,6 +2449,13 @@ def _get_and_verify_max_len(
2449
rope_parameters = getattr(hf_config, "rope_parameters", None)
2450
if rope_parameters and not is_rope_parameters_nested(rope_parameters):
2451
rope_parameters = {"": rope_parameters}
2452
+ if rope_parameters is not None:
2453
+ # Layers without RoPE do not contribute to context length scaling.
2454
+ rope_parameters = {
2455
+ layer_type: rp
2456
+ for layer_type, rp in rope_parameters.items()
2457
+ if rp is not None
2458
+ }
2459
2460
# NOTE(woosuk): Gemma3's max_model_len (128K) is already scaled by RoPE
2461
# scaling, so we skip applying the scaling factor again.
vllm/transformers_utils/config.py
+2
-1
@@ -541,7 +541,8 @@ def patch_legacy_rope_type(rope_parameters: dict[str, Any] | None) -> None:
541
# Handle nested rope_parameters in interleaved sliding attention models
542
if is_rope_parameters_nested(rope_parameters):
543
for rope_parameters_layer_type in rope_parameters.values():
544
- _patch_legacy_rope_type(rope_parameters_layer_type)
544
+ if rope_parameters_layer_type is not None:
545
+ _patch_legacy_rope_type(rope_parameters_layer_type)
546
else:
547
_patch_legacy_rope_type(rope_parameters)
548