Fix rope config compatibility and VL/transformers-fallback weight loading (#31575)

Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
vikram singh shekhawat
2026-08-17 14:53:59 +08:00
committed by GitHub
co-authored by Claude Sonnet 4.5
parent 0099107e8b
commit f7a404e9c3
7 changed files with 190 additions and 8 deletions
+4 -3
View File
@@ -9,12 +9,13 @@ from sglang.srt.managers.schedule_batch import MultimodalDataItem
from sglang.srt.mem_cache.multimodal_cache import EmbeddingResult, MultiModalStaticCache
from sglang.srt.multimodal.evs import EVSEmbeddingResult
from sglang.srt.runtime_context import get_parallel, get_schedule
from sglang.srt.utils import is_hip, is_npu
from sglang.srt.utils import is_hip, is_npu, is_xpu
from sglang.srt.utils.async_probe import maybe_assert_sum
from sglang.utils import logger
_is_hip = is_hip()
_is_npu = is_npu()
_is_xpu = is_xpu()
embedding_cache: Optional[MultiModalStaticCache] = None
@@ -510,9 +511,9 @@ def _get_chunked_prefill_embedding(
is_per_image = all(len(item.offsets) == 1 for item in embedding_items_per_req)
if is_per_image:
if _is_hip or _is_npu:
if _is_hip or _is_npu or _is_xpu:
# ROCm CI regressed with one large cross-request ViT batch; keep
# the previous per-request path on HIP while CUDA uses batching.
# the previous per-request path on HIP/NPU/XPU while CUDA uses batching.
chunk = _get_chunked_embedding_by_item(
data_embedding_func,
embedding_items_per_req,
+2 -2
View File
@@ -44,6 +44,7 @@ from sglang.srt.model_executor.forward_batch_info import ForwardBatch, PPProxyTe
from sglang.srt.models.deepseek_v2 import DeepseekV2MLP as Ernie4_5_VLMoeMLP
from sglang.srt.runtime_context import get_parallel
from sglang.srt.utils import add_prefix, make_layers
from sglang.srt.utils.hf_transformers.common import get_rope_config
logger = logging.getLogger(__name__)
@@ -368,8 +369,7 @@ class Ernie4_5_VLMoeDecoderLayer(nn.Module):
prefix: str = "",
):
super().__init__()
rope_theta = config.rope_parameters["rope_theta"]
rope_scaling = config.rope_parameters
rope_theta, rope_scaling = get_rope_config(config)
rope_is_neox_style = getattr(config, "rope_is_neox_style", False)
freq_allocation = getattr(config, "freq_allocation", 20)
max_position_embeddings = getattr(config, "max_position_embeddings", 131072)
+2 -1
View File
@@ -49,6 +49,7 @@ from sglang.srt.model_executor.runner import get_is_capture_mode
from sglang.srt.model_loader.weight_utils import default_weight_loader
from sglang.srt.runtime_context import get_parallel, get_stream
from sglang.srt.utils import add_prefix, is_cuda, make_layers
from sglang.srt.utils.hf_transformers.common import get_rope_config
_is_cuda = is_cuda()
@@ -100,7 +101,7 @@ class Olmo2Attention(nn.Module):
self.q_size = self.num_heads * self.head_dim
self.kv_size = self.num_kv_heads * self.head_dim
self.max_position_embeddings = config.max_position_embeddings
self.rope_theta = config.rope_parameters["rope_theta"]
self.rope_theta, _ = get_rope_config(config)
# Attention input projection. Projects x -> (q, k, v)
self.qkv_proj = QKVParallelLinear(
+7 -1
View File
@@ -337,7 +337,10 @@ class QWenLMHeadModel(nn.Module):
for param_name, weight_name, shard_id in stacked_params_mapping:
if weight_name not in name:
continue
name = name.replace(weight_name, param_name)
temp_name = name.replace(weight_name, param_name)
if temp_name not in params_dict:
continue
name = temp_name
# Skip loading extra bias for GPTQ models.
if name.endswith(".bias") and name not in params_dict:
continue
@@ -349,6 +352,9 @@ class QWenLMHeadModel(nn.Module):
# Skip loading extra bias for GPTQ models.
if name.endswith(".bias") and name not in params_dict:
continue
# Skip visual encoder weights (e.g. Qwen-VL-Chat transformer.visual.*)
if name not in params_dict:
continue
param = params_dict[name]
weight_loader = getattr(param, "weight_loader", default_weight_loader)
weight_loader(param, loaded_weight)
+47
View File
@@ -1345,6 +1345,22 @@ class MultiModalMixin:
super().__init__(*args, **kwargs)
self._mm_padding_pattern = MultiModalityDataPaddingPatternMultimodalTokens()
# transformers v5 flattened SigLIP/CLIP (dropped the "vision_model"
# wrapper); older checkpoints still ship "vision_tower.vision_model.*"
# keys, so remap them when the live model lacks that sub-module.
vt = getattr(self.model, "vision_tower", None)
if vt is not None and not any(
name == "vision_model" for name, _ in vt.named_children()
):
self.weight_mapper = (
WeightsMapper(
orig_to_new_prefix={
"vision_tower.vision_model.": "model.vision_tower.",
}
)
| self.weight_mapper
)
def _uses_mrope_positions(self) -> bool:
rope_scaling = getattr(self.text_config, "rope_scaling", None)
if isinstance(rope_scaling, Mapping) and "mrope_section" in rope_scaling:
@@ -1497,6 +1513,14 @@ class MultiModalMixin:
):
mm_inputs = forward_batch.mm_inputs
target_device = next(self.model.parameters()).device
# 5D features (num_images, num_patches, C, H, W) can't be flattened
# here: anyres models pad num_patches per HF processor call, so a
# flattened concat would leave stray padding rows once items with
# different tile counts are combined. Defer them and pad to the
# batch-wide max instead -- the model's own get_image_features
# re-derives each image's real patch count from image_sizes and
# slices the padding back out.
pending_5d_features: dict = {}
for batch_idx in range(len(mm_inputs or [])):
mm_input = mm_inputs[batch_idx]
@@ -1519,6 +1543,11 @@ class MultiModalMixin:
feature = item.feature
if isinstance(feature, torch.Tensor):
feature = feature.to(device=target_device)
if feature.dim() == 5:
pending_5d_features.setdefault(feature_key, []).append(
feature
)
continue
if feature_key not in kwargs:
kwargs[feature_key] = feature
elif isinstance(feature, torch.Tensor) and isinstance(
@@ -1528,6 +1557,24 @@ class MultiModalMixin:
[kwargs[feature_key], feature], dim=0
)
for feature_key, tensors in pending_5d_features.items():
max_patches = max(t.shape[1] for t in tensors)
padded = []
for t in tensors:
if t.shape[1] < max_patches:
pad = t.new_zeros(
(t.shape[0], max_patches - t.shape[1], *t.shape[2:])
)
t = torch.cat([t, pad], dim=1)
padded.append(t)
combined = torch.cat(padded, dim=0)
if feature_key in kwargs:
kwargs[feature_key] = torch.cat(
[kwargs[feature_key], combined], dim=0
)
else:
kwargs[feature_key] = combined
return kwargs
def _forward_hidden_states(
@@ -365,7 +365,8 @@ def get_rope_config(config):
"""
rope_params = getattr(config, "rope_parameters", None)
if rope_params is not None:
return rope_params["rope_theta"], rope_params
rope_theta = rope_params.get("rope_theta", getattr(config, "rope_theta", 10000))
return rope_theta, rope_params
return getattr(config, "rope_theta", 10000), getattr(config, "rope_scaling", None)