From faa4b76afae3660efc8a5d48a8c7c2d37e0ffb05 Mon Sep 17 00:00:00 2001 From: Isotr0py Date: Fri, 15 May 2026 12:30:26 +0800 Subject: [PATCH] [Model] Support InternS2 Preview (#42705) Signed-off-by: Isotr0py Co-authored-by: zxy <46674730+CUHKSZzxy@users.noreply.github.com> --- docs/models/supported_models.md | 1 + tests/models/registry.py | 5 +++ vllm/config/speculative.py | 11 ++++++ .../model_executor/models/interns2_preview.py | 38 +++++++++++++++++++ vllm/model_executor/models/registry.py | 4 ++ vllm/v1/spec_decode/llm_base_proposer.py | 1 + 6 files changed, 60 insertions(+) create mode 100644 vllm/model_executor/models/interns2_preview.py diff --git a/docs/models/supported_models.md b/docs/models/supported_models.md index 454ab08debc..d9df96bea44 100644 --- a/docs/models/supported_models.md +++ b/docs/models/supported_models.md @@ -575,6 +575,7 @@ These models primarily accept the [`LLM.generate`](./generative_models.md#llmgen | `IsaacForConditionalGeneration` | Isaac | T + I+ | `PerceptronAI/Isaac-0.1` | ✅︎ | ✅︎ | | `InternS1ForConditionalGeneration` | Intern-S1 | T + IE+ + VE+ | `internlm/Intern-S1`, `internlm/Intern-S1-mini`, etc. | ✅︎ | ✅︎ | | `InternS1ProForConditionalGeneration` | Intern-S1-Pro | T + IE+ + VE+ | `internlm/Intern-S1-Pro`, etc. | ✅︎ | ✅︎ | +| `InternS2PreviewForConditionalGeneration` | Intern-S2-Preview | T + IE+ + VE+ | `internlm/Intern-S2-Preview`, etc. | ✅︎ | ✅︎ | | `InternVLChatModel` | InternVL 3.5, InternVL 3.0, InternVideo 2.5, InternVL 2.5, Mono-InternVL, InternVL 2.0 | T + IE+ + (VE+) | `OpenGVLab/InternVL3_5-14B`, `OpenGVLab/InternVL3-9B`, `OpenGVLab/InternVideo2_5_Chat_8B`, `OpenGVLab/InternVL2_5-4B`, `OpenGVLab/Mono-InternVL-2B`, `OpenGVLab/InternVL2-4B`, etc. | ✅︎ | ✅︎ | | `InternVLForConditionalGeneration` | InternVL 3.0 (HF format) | T + IE+ + VE+ | `OpenGVLab/InternVL3-1B-hf`, etc. | ✅︎ | ✅︎ | | `KananaVForConditionalGeneration` | Kanana-V | T + I+ | `kakaocorp/kanana-1.5-v-3b-instruct`, etc. | | ✅︎ | diff --git a/tests/models/registry.py b/tests/models/registry.py index 8ab8d79ac78..af2a6ba4e59 100644 --- a/tests/models/registry.py +++ b/tests/models/registry.py @@ -988,6 +988,11 @@ _MULTIMODAL_EXAMPLE_MODELS = { "internlm/Intern-S1-Pro", trust_remote_code=True, ), + "InternS2PreviewForConditionalGeneration": _HfExamplesInfo( + "internlm/Intern-S2-Preview", + trust_remote_code=True, + is_available_online=False, + ), "InternVLChatModel": _HfExamplesInfo( "OpenGVLab/InternVL2-1B", extras={ diff --git a/vllm/config/speculative.py b/vllm/config/speculative.py index 91c6c1cfcc8..47d35f4ff4b 100644 --- a/vllm/config/speculative.py +++ b/vllm/config/speculative.py @@ -467,6 +467,17 @@ class SpeculativeConfig: "architectures": ["Qwen3_5MoeMTP" if is_moe else "Qwen3_5MTP"], } ) + if hf_config.model_type == "intern_s2_preview": + text_config = getattr(hf_config, "text_config", None) + is_moe = getattr(text_config, "model_type", None) == "qwen3_5_moe_text" + hf_config.model_type = "qwen3_5_mtp" + n_predict = getattr(text_config, "mtp_num_hidden_layers", None) + hf_config.update( + { + "n_predict": n_predict, + "architectures": ["Qwen3_5MoeMTP" if is_moe else "Qwen3_5MTP"], + } + ) if hf_config.model_type == "longcat_flash": hf_config.model_type = "longcat_flash_mtp" n_predict = getattr(hf_config, "num_nextn_predict_layers", 1) diff --git a/vllm/model_executor/models/interns2_preview.py b/vllm/model_executor/models/interns2_preview.py new file mode 100644 index 00000000000..6efc98aabc1 --- /dev/null +++ b/vllm/model_executor/models/interns2_preview.py @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +from collections.abc import Iterable + +import torch +from transformers import AutoProcessor + +from vllm.multimodal import MULTIMODAL_REGISTRY + +from .qwen3_5 import Qwen3_5MoeForConditionalGeneration +from .qwen3_vl import ( + Qwen3VLDummyInputsBuilder, + Qwen3VLMultiModalProcessor, + Qwen3VLProcessingInfo, +) +from .utils import AutoWeightsLoader + + +class InternS2PreviewProcessingInfo(Qwen3VLProcessingInfo): + def get_hf_config(self): + return self.ctx.get_hf_config() + + def get_hf_processor(self, **kwargs: object) -> AutoProcessor: + return self.ctx.get_hf_processor(**kwargs) + + +@MULTIMODAL_REGISTRY.register_processor( + Qwen3VLMultiModalProcessor, + info=InternS2PreviewProcessingInfo, + dummy_inputs=Qwen3VLDummyInputsBuilder, +) +class InternS2PreviewForConditionalGeneration(Qwen3_5MoeForConditionalGeneration): + def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]: + loader = AutoWeightsLoader( + self, + skip_prefixes=["mtp.", "model.time_series.", "time_series."], + ) + return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper) diff --git a/vllm/model_executor/models/registry.py b/vllm/model_executor/models/registry.py index bafeb73e4c0..513185e127c 100644 --- a/vllm/model_executor/models/registry.py +++ b/vllm/model_executor/models/registry.py @@ -435,6 +435,10 @@ _MULTIMODAL_MODELS = { "interns1_pro", "InternS1ProForConditionalGeneration", ), + "InternS2PreviewForConditionalGeneration": ( + "interns2_preview", + "InternS2PreviewForConditionalGeneration", + ), "Idefics3ForConditionalGeneration": ( "idefics3", "Idefics3ForConditionalGeneration", diff --git a/vllm/v1/spec_decode/llm_base_proposer.py b/vllm/v1/spec_decode/llm_base_proposer.py index b8f344d863b..8c9f2f7baef 100644 --- a/vllm/v1/spec_decode/llm_base_proposer.py +++ b/vllm/v1/spec_decode/llm_base_proposer.py @@ -1218,6 +1218,7 @@ class SpecDecodeBaseProposer: "Exaone4_5_ForConditionalGeneration", "GlmOcrForConditionalGeneration", "HunYuanVLForConditionalGeneration", + "InternS2PreviewForConditionalGeneration", "MiMoV2OmniForCausalLM", "Qwen2_5_VLForConditionalGeneration", "Qwen3_5ForConditionalGeneration",