VLM: support passing --mm-process-config for all models (#18467)

This commit is contained in:
Wenyao Gao
2026-04-12 17:08:05 +08:00
committed by GitHub
parent f1eb4ca90c
commit 4dfc8e1c3f
7 changed files with 331 additions and 6 deletions
@@ -184,6 +184,11 @@ class BaseMultimodalProcessor(ABC):
self.server_args = server_args
self.transport_mode = transport_mode
mm_process_config = self.server_args.mm_process_config
self.image_config = mm_process_config.get("image", {})
self.video_config = mm_process_config.get("video", {})
self.audio_config = mm_process_config.get("audio", {})
# Resolve tokenizer: some processors (e.g. InternVL) pass a tokenizer
# directly as _processor rather than a processor that wraps a tokenizer.
if hasattr(self._processor, "tokenizer"):
@@ -381,8 +386,12 @@ class BaseMultimodalProcessor(ABC):
"""
if images:
kwargs["images"] = images
if self.image_config:
kwargs.setdefault("images_kwargs", {}).update(self.image_config)
if videos:
kwargs["videos"] = videos
if self.video_config:
kwargs.setdefault("videos_kwargs", {}).update(self.video_config)
if audios:
if self._processor.__class__.__name__ in {
"Gemma3nProcessor",
@@ -394,10 +403,12 @@ class BaseMultimodalProcessor(ABC):
}:
# Note(Xinyuan): for gemma3n, ref: https://github.com/huggingface/transformers/blob/ccf2ca162e33f381e454cdb74bf4b41a51ab976d/src/transformers/models/gemma3n/processing_gemma3n.py#L107
kwargs["audio"] = audios
kwargs["audio_kwargs"] = {}
kwargs.setdefault("audio_kwargs", {})
kwargs["audio_kwargs"].setdefault("truncation", False)
else:
kwargs["audios"] = audios
if self.audio_config:
kwargs.setdefault("audio_kwargs", {}).update(self.audio_config)
processor = self._processor
if (
@@ -292,8 +292,12 @@ class Ernie4_5_VLImageProcessor(SGLangBaseProcessor):
"""
if images:
kwargs["images"] = images
if self.image_config:
kwargs.setdefault("images_kwargs", {}).update(self.image_config)
if videos:
kwargs["videos"] = videos
if self.video_config:
kwargs.setdefault("videos_kwargs", {}).update(self.video_config)
processor = self._processor
if (
@@ -57,8 +57,10 @@ class MiDashengLMMultimodalProcessor(BaseMultimodalProcessor):
kwargs["videos"] = videos
if audios:
kwargs["audio"] = audios
kwargs["audio_kwargs"] = {}
kwargs.setdefault("audio_kwargs", {})
kwargs["audio_kwargs"].setdefault("truncation", False)
if self.audio_config:
kwargs["audio_kwargs"].update(self.audio_config)
processor = self._processor
result = processor.__call__(
@@ -267,9 +267,6 @@ class QwenVLImageProcessor(SGLangBaseProcessor):
self.audio_start_token_id = getattr(hf_config, "audio_start_token_id", None)
self.audio_token_id = getattr(hf_config, "audio_token_id", None)
self.image_config = server_args.mm_process_config.get("image", {})
self.video_config = server_args.mm_process_config.get("video", {})
self.mm_tokens = MultimodalSpecialTokens(
image_token="<|vision_start|><|image_pad|><|vision_end|>",
image_token_id=hf_config.image_token_id,
+21
View File
@@ -762,6 +762,8 @@ class ServerArgs:
# Normalize load balancing defaults early (before dummy-model short-circuit).
self._handle_load_balance_method()
# Validate mm_process_config before dummy-model early return.
self._handle_multimodal()
# Validate SSL arguments early (before dummy-model short-circuit).
self._handle_ssl_validation()
@@ -938,18 +940,37 @@ class ServerArgs:
"--enable-http2 requires the 'granian' package. "
'Install it with: pip install "sglang[http2]"'
)
if self.enable_ssl_refresh:
raise ValueError(
"--enable-ssl-refresh is not supported with --enable-http2. "
"Granian does not support SSL certificate hot-reloading. "
"Use Uvicorn (the default) or handle certificate rotation externally."
)
if self.tokenizer_worker_num > 1:
raise ValueError(
"--enable-http2 does not yet support --tokenizer-worker-num > 1. "
"Multi-worker HTTP/2 support will be added in a future release."
)
def _handle_multimodal(self):
"""Validate mm_process_config structure before model loading."""
if self.mm_process_config is not None:
if not isinstance(self.mm_process_config, dict):
raise TypeError(
f"mm_process_config must be a dict, "
f"but got {type(self.mm_process_config)}"
)
for key in ("image", "video", "audio"):
if key in self.mm_process_config and not isinstance(
self.mm_process_config[key], dict
):
raise TypeError(
f"mm_process_config['{key}'] must be a dict, "
f"but got {type(self.mm_process_config[key])}"
)
def _handle_deprecated_args(self):
# Handle deprecated tool call parsers
deprecated_tool_call_parsers = {"qwen25": "qwen", "glm45": "glm"}