forked from Karylab-cklius/vllm
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0dd86f6c3 | ||
|
|
01f19dee7f | ||
|
|
2c06cf3486 | ||
|
|
e6f710a87f | ||
|
|
c245d35ff4 | ||
|
|
f8ac0c7cf0 |
@@ -439,6 +439,7 @@ th {
|
||||
| `Mamba2ForCausalLM` | Mamba2 | `mistralai/Mamba-Codestral-7B-v0.1`, etc. | | ✅︎ |
|
||||
| `MiMoForCausalLM` | MiMo | `XiaomiMiMo/MiMo-7B-RL`, etc. | ✅︎ | ✅︎ |
|
||||
| `MiMoV2FlashForCausalLM` | MiMoV2Flash | `XiaomiMiMo/MiMo-V2-Flash`, etc. | | ✅︎ |
|
||||
| `MiMoV2ProForCausalLM` | MiMoV2Pro | `XiaomiMiMo/MiMo-V2.5-Pro`, etc. | | ✅︎ |
|
||||
| `MiniCPMForCausalLM` | MiniCPM | `openbmb/MiniCPM-2B-sft-bf16`, `openbmb/MiniCPM-2B-dpo-bf16`, `openbmb/MiniCPM-S-1B-sft`, etc. | ✅︎ | ✅︎ |
|
||||
| `MiniCPM3ForCausalLM` | MiniCPM3 | `openbmb/MiniCPM3-4B`, etc. | ✅︎ | ✅︎ |
|
||||
| `MiniMaxForCausalLM` | MiniMax-Text | `MiniMaxAI/MiniMax-Text-01-hf`, etc. | | |
|
||||
@@ -590,6 +591,7 @@ These models primarily accept the [`LLM.generate`](./generative_models.md#llmgen
|
||||
| `LlavaNextVideoForConditionalGeneration` | LLaVA-NeXT-Video | T + V | `llava-hf/LLaVA-NeXT-Video-7B-hf`, etc. | | ✅︎ |
|
||||
| `LlavaOnevisionForConditionalGeneration` | LLaVA-Onevision | T + I<sup>+</sup> + V<sup>+</sup> | `llava-hf/llava-onevision-qwen2-7b-ov-hf`, `llava-hf/llava-onevision-qwen2-0.5b-ov-hf`, etc. | | ✅︎ |
|
||||
| `MiDashengLMModel` | MiDashengLM | T + A<sup>+</sup> | `mispeech/midashenglm-7b` | | ✅︎ |
|
||||
| `MiMoV2OmniForCausalLM` | MiMo-V2.5-Omni | T + I<sup>E+</sup> + V<sup>E+</sup> + A<sup>+</sup> | `XiaomiMiMo/MiMo-V2.5-Omni` | | ✅︎ |
|
||||
| `MiniCPMO` | MiniCPM-O | T + I<sup>E+</sup> + V<sup>E+</sup> + A<sup>E+</sup> | `openbmb/MiniCPM-o-2_6`, etc. | ✅︎ | ✅︎ |
|
||||
| `MiniCPMV` | MiniCPM-V | T + I<sup>E+</sup> + V<sup>E+</sup> | `openbmb/MiniCPM-V-2` (see note), `openbmb/MiniCPM-Llama3-V-2_5`, `openbmb/MiniCPM-V-2_6`, `openbmb/MiniCPM-V-4`, `openbmb/MiniCPM-V-4_5`, etc. | ✅︎ | |
|
||||
| `MiniMaxVL01ForConditionalGeneration` | MiniMax-VL | T + I<sup>E+</sup> | `MiniMaxAI/MiniMax-VL-01`, etc. | | ✅︎ |
|
||||
|
||||
@@ -594,6 +594,9 @@ _TEXT_GENERATION_EXAMPLE_MODELS = {
|
||||
"MiMoV2FlashForCausalLM": _HfExamplesInfo(
|
||||
"XiaomiMiMo/MiMo-V2-Flash", trust_remote_code=True
|
||||
),
|
||||
"MiMoV2ProForCausalLM": _HfExamplesInfo(
|
||||
"XiaomiMiMo/MiMo-V2.5-Pro", trust_remote_code=True, is_available_online=False
|
||||
),
|
||||
"Dots1ForCausalLM": _HfExamplesInfo("rednote-hilab/dots.llm1.inst"),
|
||||
}
|
||||
|
||||
@@ -1069,6 +1072,9 @@ _MULTIMODAL_EXAMPLE_MODELS = {
|
||||
"MiDashengLMModel": _HfExamplesInfo(
|
||||
"mispeech/midashenglm-7b", trust_remote_code=True
|
||||
),
|
||||
"MiMoV2OmniForCausalLM": _HfExamplesInfo(
|
||||
"XiaomiMiMo/MiMo-V2.5-Omni", trust_remote_code=True, is_available_online=False
|
||||
),
|
||||
"MiniCPMO": _HfExamplesInfo(
|
||||
"openbmb/MiniCPM-o-2_6",
|
||||
trust_remote_code=True,
|
||||
@@ -1552,6 +1558,18 @@ _SPECULATIVE_DECODING_EXAMPLE_MODELS = {
|
||||
trust_remote_code=True,
|
||||
speculative_model="XiaomiMiMo/MiMo-7B-RL",
|
||||
),
|
||||
"MiMoV2MTPModel": _HfExamplesInfo(
|
||||
"XiaomiMiMo/MiMo-V2.5-Pro",
|
||||
trust_remote_code=True,
|
||||
speculative_model="XiaomiMiMo/MiMo-V2.5-Pro",
|
||||
is_available_online=False,
|
||||
),
|
||||
"MiMoV2OmniMTPModel": _HfExamplesInfo(
|
||||
"XiaomiMiMo/MiMo-V2.5-Omni",
|
||||
trust_remote_code=True,
|
||||
speculative_model="XiaomiMiMo/MiMo-V2.5-Omni",
|
||||
is_available_online=False,
|
||||
),
|
||||
"NemotronHMTPModel": _HfExamplesInfo(
|
||||
"nvidia/Nemotron-Super-Placeholder",
|
||||
speculative_model="nvidia/Nemotron-Super-Placeholder",
|
||||
|
||||
@@ -5,6 +5,8 @@ Unit tests for MultiModalRegistry.supports_multimodal_inputs and
|
||||
Qwen2.5-VL visual component loading behavior.
|
||||
"""
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from vllm.multimodal import MULTIMODAL_REGISTRY
|
||||
@@ -32,3 +34,17 @@ def test_supports_multimodal_inputs(model_id, limit_mm_per_prompt, expected):
|
||||
limit_mm_per_prompt=limit_mm_per_prompt,
|
||||
)
|
||||
assert MULTIMODAL_REGISTRY.supports_multimodal_inputs(ctx.model_config) is expected
|
||||
|
||||
|
||||
def test_create_processor_error_uses_served_model_name():
|
||||
model_config = SimpleNamespace(
|
||||
is_multimodal_model=False,
|
||||
model="/path/to/model/weights",
|
||||
served_model_name="friendly-model-name",
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="friendly-model-name is not a multimodal model",
|
||||
):
|
||||
MULTIMODAL_REGISTRY.create_processor(model_config)
|
||||
|
||||
@@ -521,6 +521,7 @@ class ModelConfig:
|
||||
if dict_overrides:
|
||||
self._apply_dict_overrides(hf_config, dict_overrides)
|
||||
self.hf_text_config = get_hf_text_config(self.hf_config)
|
||||
self.model_arch_config = self.get_model_arch_config()
|
||||
self.attention_chunk_size = getattr(
|
||||
self.hf_text_config, "attention_chunk_size", None
|
||||
)
|
||||
@@ -528,7 +529,6 @@ class ModelConfig:
|
||||
self.hf_image_processor_config = get_hf_image_processor_config(
|
||||
self.model, hf_token=self.hf_token, revision=self.revision
|
||||
)
|
||||
self.model_arch_config = self.get_model_arch_config()
|
||||
|
||||
architectures = self.architectures
|
||||
registry = self.registry
|
||||
|
||||
@@ -34,6 +34,7 @@ logger = init_logger(__name__)
|
||||
MTPModelTypes = Literal[
|
||||
"deepseek_mtp",
|
||||
"mimo_mtp",
|
||||
"mimo_v2_mtp",
|
||||
"glm4_moe_mtp",
|
||||
"glm4_moe_lite_mtp",
|
||||
"glm_ocr_mtp",
|
||||
@@ -332,6 +333,48 @@ class SpeculativeConfig:
|
||||
}
|
||||
)
|
||||
|
||||
if (arch := hf_config.architectures[0]) in (
|
||||
"MiMoV2ProForCausalLM",
|
||||
"MiMoV2OmniForCausalLM",
|
||||
):
|
||||
from vllm.model_executor.models.mimo_v2_mtp import (
|
||||
_MIMO_V2_PRO_NUM_MTP_LAYERS,
|
||||
)
|
||||
|
||||
mtp_arch_maps = {
|
||||
"MiMoV2ProForCausalLM": "MiMoV2MTPModel",
|
||||
"MiMoV2OmniForCausalLM": "MiMoV2OmniMTPModel",
|
||||
}
|
||||
|
||||
hf_config.model_type = "mimo_v2_mtp"
|
||||
# vLLM currently supports only the first MiMo-V2 MTP layer.
|
||||
n_predict = _MIMO_V2_PRO_NUM_MTP_LAYERS
|
||||
hf_config.update(
|
||||
{
|
||||
"num_hidden_layers": 0,
|
||||
"n_predict": n_predict,
|
||||
"num_nextn_predict_layers": n_predict,
|
||||
"architectures": [mtp_arch_maps[arch]],
|
||||
}
|
||||
)
|
||||
|
||||
if hf_config.architectures[0] == "MiMoV2FlashForCausalLM":
|
||||
from vllm.model_executor.models.mimo_v2_mtp import (
|
||||
_MIMO_V2_FLASH_NUM_MTP_LAYERS,
|
||||
)
|
||||
|
||||
hf_config.model_type = "mimo_v2_mtp"
|
||||
# vLLM currently supports only the first MiMo-V2 MTP layer.
|
||||
n_predict = _MIMO_V2_FLASH_NUM_MTP_LAYERS
|
||||
hf_config.update(
|
||||
{
|
||||
"num_hidden_layers": 0,
|
||||
"n_predict": n_predict,
|
||||
"num_nextn_predict_layers": n_predict,
|
||||
"architectures": ["MiMoV2MTPModel"],
|
||||
}
|
||||
)
|
||||
|
||||
if hf_config.architectures[0] == "Glm4MoeForCausalLM":
|
||||
hf_config.model_type = "glm4_moe_mtp"
|
||||
n_predict = getattr(hf_config, "num_nextn_predict_layers", None)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Scheduler-side logic for the NIXL connector."""
|
||||
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Any
|
||||
@@ -88,6 +89,12 @@ class NixlConnectorScheduler:
|
||||
if vllm_config.scheduler_config.disable_hybrid_kv_cache_manager:
|
||||
logger.info("Hybrid Memory Allocator is enabled with NIXL")
|
||||
|
||||
if os.environ.get("VLLM_NIXL_ABORT_REQUEST_TIMEOUT") is not None:
|
||||
logger.warning(
|
||||
"VLLM_NIXL_ABORT_REQUEST_TIMEOUT is deprecated and will be "
|
||||
"removed in release 0.22.0."
|
||||
)
|
||||
|
||||
# Background thread for handling new handshake requests.
|
||||
self._nixl_handshake_listener_t: threading.Thread | None = None
|
||||
self._stop_event = threading.Event()
|
||||
|
||||
@@ -1120,7 +1120,12 @@ class QKVParallelLinear(ColumnParallelLinear):
|
||||
# Special case for Quantization.
|
||||
# If quantized, we need to adjust the offset and size to account
|
||||
# for the packing.
|
||||
if (
|
||||
if isinstance(param, BlockQuantScaleParameter):
|
||||
weight_block_size = getattr(self, "weight_block_size", None)
|
||||
shard_size, shard_offset = adjust_block_scale_shard(
|
||||
weight_block_size, shard_size, shard_offset
|
||||
)
|
||||
elif (
|
||||
isinstance(param, (PackedColumnParameter, PackedvLLMParameter))
|
||||
and param.packed_dim == param.output_dim
|
||||
):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import math
|
||||
from collections.abc import Callable
|
||||
from functools import partial
|
||||
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
@@ -33,28 +34,46 @@ from vllm.v1.attention.backend import AttentionMetadata
|
||||
from vllm.v1.attention.backends.linear_attn import LinearAttentionMetadata
|
||||
|
||||
|
||||
@CustomOp.register("minimax_text01_rmsnorm_tp")
|
||||
class MiniMaxText01RMSNormTP(CustomOp):
|
||||
name = "MiniMaxText01RMSNormTP"
|
||||
|
||||
def __init__(self, hidden_size: int, eps: float = 1e-6) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hidden_size: int,
|
||||
eps: float = 1e-6,
|
||||
*,
|
||||
weight_shard_world_size: int | None = None,
|
||||
weight_shard_rank: int | None = None,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.tp_world = get_tensor_model_parallel_world_size()
|
||||
self.tp_rank = get_tensor_model_parallel_rank()
|
||||
self.weight = nn.Parameter(torch.ones(int(hidden_size / self.tp_world)))
|
||||
self.weight_shard_world = weight_shard_world_size or self.tp_world
|
||||
self.weight_shard_rank = (
|
||||
self.tp_rank if weight_shard_rank is None else weight_shard_rank
|
||||
)
|
||||
|
||||
self.weight.weight_loader = self.weight_loader
|
||||
self.weight = nn.Parameter(torch.ones(hidden_size // self.weight_shard_world))
|
||||
self.weight.weight_loader = partial(
|
||||
self.weight_loader,
|
||||
shard_world_size=self.weight_shard_world,
|
||||
shard_rank=self.weight_shard_rank,
|
||||
)
|
||||
self.variance_epsilon = eps
|
||||
|
||||
@staticmethod
|
||||
def weight_loader(
|
||||
param: nn.Parameter,
|
||||
loaded_weight: torch.Tensor,
|
||||
shard_world_size: int | None = None,
|
||||
shard_rank: int | None = None,
|
||||
) -> None:
|
||||
tp_world = get_tensor_model_parallel_world_size()
|
||||
tp_rank = get_tensor_model_parallel_rank()
|
||||
if shard_world_size is None:
|
||||
shard_world_size = get_tensor_model_parallel_world_size()
|
||||
if shard_rank is None:
|
||||
shard_rank = get_tensor_model_parallel_rank()
|
||||
|
||||
shard_size = loaded_weight.shape[0] // tp_world
|
||||
shard = slice(tp_rank * shard_size, (tp_rank + 1) * shard_size)
|
||||
shard_size = loaded_weight.shape[0] // shard_world_size
|
||||
shard = slice(shard_rank * shard_size, (shard_rank + 1) * shard_size)
|
||||
param.data.copy_(loaded_weight[shard])
|
||||
|
||||
def _forward(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+22
-2
@@ -6,6 +6,7 @@ from itertools import islice
|
||||
import torch
|
||||
from torch import nn
|
||||
|
||||
from vllm.compilation.decorators import support_torch_compile
|
||||
from vllm.config import (
|
||||
CacheConfig,
|
||||
VllmConfig,
|
||||
@@ -268,7 +269,7 @@ class MiMoV2Attention(nn.Module):
|
||||
self.total_num_heads * self.v_head_dim,
|
||||
hidden_size,
|
||||
bias=False,
|
||||
quant_config=quant_config,
|
||||
quant_config=quant_config if "mtp.layers" not in prefix else None,
|
||||
reduce_results=True,
|
||||
prefix=f"{prefix}.o_proj",
|
||||
)
|
||||
@@ -440,6 +441,7 @@ class MiMoV2FlashDecoderLayer(nn.Module):
|
||||
return self.config.hybrid_layer_pattern[self.layer_id] == 1
|
||||
|
||||
|
||||
@support_torch_compile
|
||||
class MiMoV2Model(nn.Module):
|
||||
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
|
||||
super().__init__()
|
||||
@@ -603,7 +605,13 @@ class MiMoV2Model(nn.Module):
|
||||
|
||||
if expert_matched:
|
||||
continue
|
||||
|
||||
# Support fused qkv_proj checkpoint (Pro format)
|
||||
if "qkv_proj" in name:
|
||||
if name in params_dict:
|
||||
param = params_dict[name]
|
||||
loaded_weight = loaded_weight.chunk(tp_size, dim=0)[tp_rank]
|
||||
default_weight_loader(param, loaded_weight)
|
||||
continue
|
||||
stacked_matched = False
|
||||
for param_name, weight_name, shard_id in stacked_params_mapping:
|
||||
if weight_name not in name:
|
||||
@@ -662,6 +670,11 @@ class MiMoV2Model(nn.Module):
|
||||
|
||||
|
||||
class MiMoV2FlashForCausalLM(nn.Module, SupportsPP, MixtureOfExperts):
|
||||
packed_modules_mapping = {
|
||||
"qkv_proj": ["q_proj", "k_proj", "v_proj"],
|
||||
"gate_up_proj": ["gate_proj", "up_proj"],
|
||||
}
|
||||
|
||||
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
|
||||
super().__init__()
|
||||
config = vllm_config.model_config.hf_config
|
||||
@@ -718,3 +731,10 @@ class MiMoV2FlashForCausalLM(nn.Module, SupportsPP, MixtureOfExperts):
|
||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||
loader = AutoWeightsLoader(self)
|
||||
return loader.load_weights(weights)
|
||||
|
||||
|
||||
class MiMoV2ProForCausalLM(MiMoV2FlashForCausalLM):
|
||||
packed_modules_mapping = {
|
||||
"qkv_proj": ["qkv_proj"],
|
||||
"gate_up_proj": ["gate_proj", "up_proj"],
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
"""Inference-only MiMo-V2 MTP (Multi-Token Prediction) draft model.
|
||||
|
||||
Supports both MiMo-V2-Pro and MiMo-V2-Flash checkpoints.
|
||||
|
||||
Checkpoint weight layout (model.mtp.layers.{idx}.*):
|
||||
enorm - RMSNorm for token embeddings
|
||||
hnorm - RMSNorm for previous hidden states
|
||||
eh_proj - ReplicatedLinear(hidden*2 -> hidden)
|
||||
input_layernorm - pre-attention RMSNorm
|
||||
self_attn.* - attention weights; format differs by variant:
|
||||
Pro: fused qkv_proj [Q;K;V] concatenated
|
||||
Flash: separate q_proj, k_proj, v_proj
|
||||
pre_mlp_layernorm - post-attention / pre-MLP RMSNorm
|
||||
mlp.* - dense MLP (gate_proj / up_proj / down_proj)
|
||||
final_layernorm - norm applied before logit computation
|
||||
"""
|
||||
|
||||
from collections.abc import Iterable
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from transformers import PretrainedConfig
|
||||
|
||||
from vllm.config import VllmConfig
|
||||
from vllm.distributed import (
|
||||
get_tensor_model_parallel_rank,
|
||||
get_tensor_model_parallel_world_size,
|
||||
)
|
||||
from vllm.model_executor.layers.layernorm import RMSNorm
|
||||
from vllm.model_executor.layers.linear import ReplicatedLinear
|
||||
from vllm.model_executor.layers.logits_processor import LogitsProcessor
|
||||
from vllm.model_executor.layers.quantization import QuantizationConfig
|
||||
from vllm.model_executor.layers.vocab_parallel_embedding import (
|
||||
ParallelLMHead,
|
||||
VocabParallelEmbedding,
|
||||
)
|
||||
from vllm.model_executor.model_loader.weight_utils import default_weight_loader
|
||||
from vllm.sequence import IntermediateTensors
|
||||
|
||||
from .interfaces import (
|
||||
MultiModalEmbeddings,
|
||||
SupportsMultiModal,
|
||||
_require_is_multimodal,
|
||||
)
|
||||
from .mimo_v2 import MiMoV2Attention, MiMoV2MLP
|
||||
from .utils import _merge_multimodal_embeddings, maybe_prefix
|
||||
|
||||
# MiMo-V2 checkpoints contain multiple MTP layers, but vLLM currently supports
|
||||
# only the first layer and only one speculative token.
|
||||
_MIMO_V2_PRO_NUM_MTP_LAYERS = 1
|
||||
_MIMO_V2_FLASH_NUM_MTP_LAYERS = 1
|
||||
|
||||
|
||||
class MiMoV2MTPLayer(nn.Module):
|
||||
"""Single MTP predictor layer for MiMo-V2 (Pro and Flash).
|
||||
|
||||
Mirrors the single-layer MiMo-V2 nextn reference implementation.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: PretrainedConfig,
|
||||
prefix: str,
|
||||
quant_config: QuantizationConfig | None = None,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
|
||||
# Predictor head components
|
||||
self.enorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
|
||||
self.hnorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
|
||||
self.eh_proj = ReplicatedLinear(
|
||||
config.hidden_size * 2, config.hidden_size, bias=False
|
||||
)
|
||||
|
||||
# MTP uses the SWA attention configuration
|
||||
# implementation.
|
||||
swa_rope_theta = getattr(
|
||||
config,
|
||||
"swa_rope_theta",
|
||||
getattr(config, "rope_theta", 1000000),
|
||||
)
|
||||
sliding_window_size = getattr(config, "sliding_window_size", -1)
|
||||
|
||||
self.input_layernorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
|
||||
self.self_attn = MiMoV2Attention(
|
||||
hidden_size=config.hidden_size,
|
||||
num_heads=config.swa_num_attention_heads,
|
||||
num_kv_heads=config.swa_num_key_value_heads,
|
||||
head_dim=config.swa_head_dim,
|
||||
v_head_dim=getattr(config, "swa_v_head_dim", None),
|
||||
v_scale=getattr(config, "attention_value_scale", None),
|
||||
sliding_window_size=sliding_window_size,
|
||||
attention_bias=config.attention_bias,
|
||||
add_swa_attention_sink_bias=getattr(
|
||||
config, "add_swa_attention_sink_bias", False
|
||||
),
|
||||
layer_id=0,
|
||||
rope_theta=swa_rope_theta,
|
||||
max_position_embeddings=getattr(config, "max_position_embeddings", 32768),
|
||||
quant_config=quant_config,
|
||||
partial_rotary_factor=getattr(config, "partial_rotary_factor", 1.0),
|
||||
prefix=f"{prefix}.self_attn",
|
||||
)
|
||||
self.pre_mlp_layernorm = RMSNorm(
|
||||
config.hidden_size, eps=config.layernorm_epsilon
|
||||
)
|
||||
self.mlp = MiMoV2MLP(
|
||||
hidden_size=config.hidden_size,
|
||||
intermediate_size=config.intermediate_size,
|
||||
hidden_act=config.hidden_act,
|
||||
quant_config=quant_config,
|
||||
prefix=f"{prefix}.mlp",
|
||||
)
|
||||
self.final_layernorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
inputs_embeds: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
previous_hidden_states: torch.Tensor,
|
||||
) -> torch.Tensor:
|
||||
# Combine token embedding and previous hidden state
|
||||
h, _ = self.eh_proj(
|
||||
torch.cat(
|
||||
[self.enorm(inputs_embeds), self.hnorm(previous_hidden_states)], dim=-1
|
||||
)
|
||||
)
|
||||
|
||||
# Transformer block with fused residual norms
|
||||
residual = h
|
||||
h = self.input_layernorm(h)
|
||||
h = self.self_attn(positions=positions, hidden_states=h)
|
||||
h, residual = self.pre_mlp_layernorm(h, residual)
|
||||
h = self.mlp(h)
|
||||
h = h + residual
|
||||
|
||||
return self.final_layernorm(h)
|
||||
|
||||
|
||||
class _MiMoV2MTPLayers(nn.Module):
|
||||
"""Thin wrapper so parameter paths match checkpoint: model.mtp.layers.*"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: PretrainedConfig,
|
||||
num_mtp_layers: int,
|
||||
quant_config: QuantizationConfig | None,
|
||||
prefix: str,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.layers = nn.ModuleDict(
|
||||
{
|
||||
str(i): MiMoV2MTPLayer(
|
||||
config=config,
|
||||
prefix=f"{prefix}.{i}",
|
||||
quant_config=quant_config,
|
||||
)
|
||||
for i in range(num_mtp_layers)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class MiMoV2MultiTokenPredictor(nn.Module):
|
||||
def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
|
||||
super().__init__()
|
||||
|
||||
config = vllm_config.model_config.hf_config
|
||||
spec_cfg = vllm_config.speculative_config
|
||||
assert spec_cfg is not None
|
||||
if spec_cfg.num_speculative_tokens != 1:
|
||||
raise ValueError(
|
||||
"MiMo-V2 MTP in vLLM only supports num_speculative_tokens=1."
|
||||
)
|
||||
num_mtp_layers = 1
|
||||
|
||||
self.num_mtp_layers = num_mtp_layers
|
||||
|
||||
self.embed_tokens = VocabParallelEmbedding(
|
||||
config.vocab_size,
|
||||
config.hidden_size,
|
||||
)
|
||||
|
||||
self.mtp = _MiMoV2MTPLayers(
|
||||
config=config,
|
||||
num_mtp_layers=num_mtp_layers,
|
||||
quant_config=vllm_config.quant_config,
|
||||
prefix=maybe_prefix(prefix, "mtp.layers"),
|
||||
)
|
||||
|
||||
self.logits_processor = LogitsProcessor(config.vocab_size)
|
||||
|
||||
def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
|
||||
return self.embed_tokens(input_ids)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
positions: torch.Tensor,
|
||||
previous_hidden_states: torch.Tensor,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
spec_step_idx: int = 0,
|
||||
) -> torch.Tensor:
|
||||
assert spec_step_idx == 0, "MiMo-V2 MTP only supports one speculative token."
|
||||
if inputs_embeds is None:
|
||||
inputs_embeds = self.embed_input_ids(input_ids)
|
||||
return self.mtp.layers[str(spec_step_idx)](
|
||||
inputs_embeds, positions, previous_hidden_states
|
||||
)
|
||||
|
||||
def compute_logits(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
lm_head: ParallelLMHead,
|
||||
spec_step_idx: int = 0,
|
||||
) -> torch.Tensor:
|
||||
assert spec_step_idx == 0, "MiMo-V2 MTP only supports one speculative token."
|
||||
return self.logits_processor(lm_head, hidden_states)
|
||||
|
||||
|
||||
class MiMoV2MTP(nn.Module):
|
||||
def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
|
||||
super().__init__()
|
||||
self.config = vllm_config.model_config.hf_config
|
||||
self.model = MiMoV2MultiTokenPredictor(
|
||||
vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
|
||||
)
|
||||
self.lm_head = ParallelLMHead(
|
||||
self.config.vocab_size,
|
||||
self.config.hidden_size,
|
||||
prefix=maybe_prefix(prefix, "lm_head"),
|
||||
)
|
||||
|
||||
def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
|
||||
return self.model.embed_input_ids(input_ids)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
input_ids: torch.Tensor | None,
|
||||
positions: torch.Tensor,
|
||||
hidden_states: torch.Tensor,
|
||||
intermediate_tensors: IntermediateTensors | None = None,
|
||||
inputs_embeds: torch.Tensor | None = None,
|
||||
spec_step_idx: int = 0,
|
||||
) -> torch.Tensor:
|
||||
assert spec_step_idx == 0, "MiMo-V2 MTP only supports one speculative token."
|
||||
return self.model(
|
||||
input_ids, positions, hidden_states, inputs_embeds, spec_step_idx
|
||||
)
|
||||
|
||||
def compute_logits(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
spec_step_idx: int = 0,
|
||||
) -> torch.Tensor | None:
|
||||
assert spec_step_idx == 0, "MiMo-V2 MTP only supports one speculative token."
|
||||
return self.model.compute_logits(hidden_states, self.lm_head, spec_step_idx)
|
||||
|
||||
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
|
||||
tp_rank = get_tensor_model_parallel_rank()
|
||||
tp_size = get_tensor_model_parallel_world_size()
|
||||
|
||||
stacked_params_mapping = [
|
||||
("gate_up_proj", "gate_proj", 0),
|
||||
("gate_up_proj", "up_proj", 1),
|
||||
# Flash format: separate projections → fused qkv_proj
|
||||
("qkv_proj", "q_proj", "q"),
|
||||
("qkv_proj", "k_proj", "k"),
|
||||
("qkv_proj", "v_proj", "v"),
|
||||
]
|
||||
|
||||
params_dict = dict(self.named_parameters())
|
||||
loaded_params: set[str] = set()
|
||||
|
||||
for name, loaded_weight in weights:
|
||||
if "rotary_emb.inv_freq" in name:
|
||||
continue
|
||||
|
||||
# Only load MTP-related weights, shared embeddings, and lm_head
|
||||
if (
|
||||
"model.mtp" not in name
|
||||
and "model.embed_tokens" not in name
|
||||
and not name.startswith("lm_head")
|
||||
):
|
||||
continue
|
||||
|
||||
# Support fused qkv_proj checkpoint (Pro format).
|
||||
# The checkpoint is stored pre-sharded for TP=8 as
|
||||
# [Q_rank0, K_rank0, V_rank0, Q_rank1, ...], so splitting along
|
||||
# dim 0 with chunk(tp_size) gives each rank its Q+K+V slice for
|
||||
# both the FP8 weight and the block weight_scale_inv. This matches
|
||||
# how the main model loads the same layout.
|
||||
if "qkv_proj" in name:
|
||||
if name in params_dict:
|
||||
param = params_dict[name]
|
||||
loaded_weight = loaded_weight.chunk(tp_size, dim=0)[tp_rank]
|
||||
default_weight_loader(param, loaded_weight)
|
||||
loaded_params.add(name)
|
||||
continue
|
||||
|
||||
# gate_proj/up_proj → gate_up_proj stacking (both formats);
|
||||
# Flash: q_proj/k_proj/v_proj → qkv_proj merging.
|
||||
stacked_matched = False
|
||||
for param_name, weight_name, shard_id in stacked_params_mapping:
|
||||
if weight_name not in name:
|
||||
continue
|
||||
name_rewritten = name.replace(weight_name, param_name)
|
||||
if (
|
||||
name_rewritten.endswith(".bias")
|
||||
and name_rewritten not in params_dict
|
||||
):
|
||||
continue
|
||||
if name_rewritten not in params_dict:
|
||||
continue
|
||||
param = params_dict[name_rewritten]
|
||||
weight_loader = getattr(param, "weight_loader", default_weight_loader)
|
||||
weight_loader(param, loaded_weight, shard_id)
|
||||
loaded_params.add(name_rewritten)
|
||||
stacked_matched = True
|
||||
break
|
||||
|
||||
if stacked_matched:
|
||||
continue
|
||||
|
||||
if name.endswith(".bias") and name not in params_dict:
|
||||
continue
|
||||
if name not in params_dict:
|
||||
continue
|
||||
|
||||
param = params_dict[name]
|
||||
# attention_sink_bias is head-parallel; slice by tp
|
||||
if "attention_sink_bias" in name:
|
||||
total_heads = loaded_weight.shape[0]
|
||||
heads_per_rank = total_heads // tp_size
|
||||
loaded_weight = loaded_weight.narrow(
|
||||
0, tp_rank * heads_per_rank, heads_per_rank
|
||||
)
|
||||
|
||||
weight_loader = getattr(param, "weight_loader", default_weight_loader)
|
||||
weight_loader(param, loaded_weight)
|
||||
loaded_params.add(name)
|
||||
|
||||
return loaded_params
|
||||
|
||||
|
||||
class MiMoV2OmniMTP(MiMoV2MTP, SupportsMultiModal):
|
||||
def embed_input_ids(
|
||||
self,
|
||||
input_ids: torch.Tensor,
|
||||
multimodal_embeddings: MultiModalEmbeddings | None = None,
|
||||
*,
|
||||
is_multimodal: torch.Tensor | None = None,
|
||||
) -> torch.Tensor:
|
||||
inputs_embeds = self._embed_text_input_ids(
|
||||
input_ids,
|
||||
self.model.embed_input_ids,
|
||||
is_multimodal=is_multimodal,
|
||||
)
|
||||
|
||||
if multimodal_embeddings is None or len(multimodal_embeddings) == 0:
|
||||
return inputs_embeds
|
||||
|
||||
is_multimodal = _require_is_multimodal(is_multimodal)
|
||||
|
||||
inputs_embeds = _merge_multimodal_embeddings(
|
||||
inputs_embeds=inputs_embeds,
|
||||
multimodal_embeddings=multimodal_embeddings,
|
||||
is_multimodal=is_multimodal,
|
||||
)
|
||||
|
||||
return inputs_embeds
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ from vllm.compilation.decorators import support_torch_compile
|
||||
from vllm.config import CacheConfig, ModelConfig, VllmConfig
|
||||
from vllm.distributed import (
|
||||
get_pp_group,
|
||||
get_tensor_model_parallel_rank,
|
||||
get_tensor_model_parallel_world_size,
|
||||
)
|
||||
from vllm.model_executor.layers.attention import Attention
|
||||
@@ -220,9 +221,21 @@ class MiniMaxM2Attention(nn.Module):
|
||||
self.q_norm = MiniMaxText01RMSNormTP(
|
||||
self.head_dim * self.total_num_heads, eps=rms_norm_eps
|
||||
)
|
||||
self.k_norm = MiniMaxText01RMSNormTP(
|
||||
self.head_dim * self.total_num_kv_heads, eps=rms_norm_eps
|
||||
)
|
||||
if self.total_num_kv_heads >= tp_size:
|
||||
self.k_norm = MiniMaxText01RMSNormTP(
|
||||
self.head_dim * self.total_num_kv_heads, eps=rms_norm_eps
|
||||
)
|
||||
else:
|
||||
# KV heads are replicated across TP ranks; shard k_norm weight by
|
||||
# total_num_kv_heads rather than tp_size to avoid incorrect sharding.
|
||||
num_kv_head_replicas = tp_size // self.total_num_kv_heads
|
||||
self.k_norm = MiniMaxText01RMSNormTP(
|
||||
self.head_dim * self.total_num_kv_heads,
|
||||
eps=rms_norm_eps,
|
||||
weight_shard_world_size=self.total_num_kv_heads,
|
||||
weight_shard_rank=get_tensor_model_parallel_rank()
|
||||
// num_kv_head_replicas,
|
||||
)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
|
||||
@@ -171,7 +171,8 @@ _TEXT_GENERATION_MODELS = {
|
||||
"MptForCausalLM": ("mpt", "MPTForCausalLM"),
|
||||
"MPTForCausalLM": ("mpt", "MPTForCausalLM"),
|
||||
"MiMoForCausalLM": ("mimo", "MiMoForCausalLM"),
|
||||
"MiMoV2FlashForCausalLM": ("mimo_v2_flash", "MiMoV2FlashForCausalLM"),
|
||||
"MiMoV2FlashForCausalLM": ("mimo_v2", "MiMoV2FlashForCausalLM"),
|
||||
"MiMoV2ProForCausalLM": ("mimo_v2", "MiMoV2ProForCausalLM"),
|
||||
"NemotronForCausalLM": ("nemotron", "NemotronForCausalLM"),
|
||||
"NemotronHForCausalLM": ("nemotron_h", "NemotronHForCausalLM"),
|
||||
"NemotronHPuzzleForCausalLM": ("nemotron_h", "NemotronHForCausalLM"),
|
||||
@@ -468,6 +469,7 @@ _MULTIMODAL_MODELS = {
|
||||
),
|
||||
"MantisForConditionalGeneration": ("llava", "MantisForConditionalGeneration"),
|
||||
"MiDashengLMModel": ("midashenglm", "MiDashengLMModel"),
|
||||
"MiMoV2OmniForCausalLM": ("mimo_v2_omni", "MiMoV2OmniForCausalLM"),
|
||||
"MiniMaxVL01ForConditionalGeneration": (
|
||||
"minimax_vl_01",
|
||||
"MiniMaxVL01ForConditionalGeneration",
|
||||
@@ -570,6 +572,8 @@ _MULTIMODAL_MODELS = {
|
||||
_SPECULATIVE_DECODING_MODELS = {
|
||||
"ExtractHiddenStatesModel": ("extract_hidden_states", "ExtractHiddenStatesModel"),
|
||||
"MiMoMTPModel": ("mimo_mtp", "MiMoMTP"),
|
||||
"MiMoV2MTPModel": ("mimo_v2_mtp", "MiMoV2MTP"),
|
||||
"MiMoV2OmniMTPModel": ("mimo_v2_mtp", "MiMoV2OmniMTP"),
|
||||
"EagleLlamaForCausalLM": ("llama_eagle", "EagleLlamaForCausalLM"),
|
||||
"EagleLlama4ForCausalLM": ("llama4_eagle", "EagleLlama4ForCausalLM"),
|
||||
"EagleMiniCPMForCausalLM": ("minicpm_eagle", "EagleMiniCPMForCausalLM"),
|
||||
|
||||
@@ -207,7 +207,8 @@ class MultiModalRegistry:
|
||||
Create a multi-modal processor for a specific model and tokenizer.
|
||||
"""
|
||||
if not model_config.is_multimodal_model:
|
||||
raise ValueError(f"{model_config.model} is not a multimodal model")
|
||||
model_name = model_config.served_model_name or model_config.model
|
||||
raise ValueError(f"{model_name} is not a multimodal model")
|
||||
|
||||
model_cls = self._get_model_cls(model_config)
|
||||
factories = model_cls._processor_factory
|
||||
|
||||
@@ -66,6 +66,13 @@ MISTRAL_CONFIG_NAME = "params.json"
|
||||
|
||||
logger = init_logger(__name__)
|
||||
|
||||
if Version(version("transformers")) < Version("5.0.0"):
|
||||
logger.warning(
|
||||
"Support for Transformers v4 is deprecated. The Transformers v4 codepath will "
|
||||
"become unmaintained in vLLM v0.22.0 and will be removed in vLLM v0.24.0. "
|
||||
"Please upgrade to Transformers v5: pip install --upgrade transformers"
|
||||
)
|
||||
|
||||
|
||||
class LazyConfigDict(dict):
|
||||
def __getitem__(self, key):
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
|
||||
from transformers import PretrainedConfig
|
||||
|
||||
|
||||
class Mimo_VLVisionConfig(PretrainedConfig):
|
||||
model_type = "mimovl"
|
||||
base_config_key = "vision_config"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
depth=28,
|
||||
hidden_size=1280,
|
||||
hidden_act="silu",
|
||||
intermediate_size=4608,
|
||||
num_heads=32,
|
||||
in_channels=3,
|
||||
patch_size=16,
|
||||
spatial_merge_size=2,
|
||||
temporal_patch_size=2,
|
||||
tokens_per_second=2,
|
||||
window_size=128,
|
||||
out_hidden_size=2048,
|
||||
fullatt_block_indexes=None,
|
||||
initializer_range=0.02,
|
||||
kv_channels=64, # HACK
|
||||
qk_channels=64,
|
||||
num_query_groups=4,
|
||||
num_key_value_heads=8,
|
||||
vit_window_attn_types=None,
|
||||
visual_token_window_size=64,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.depth = depth
|
||||
self.hidden_size = hidden_size
|
||||
self.hidden_act = hidden_act
|
||||
self.intermediate_size = intermediate_size
|
||||
self.num_heads = num_heads
|
||||
# Support GQA: if num_key_value_heads is not provided,
|
||||
# default to num_heads (MHA)
|
||||
if num_key_value_heads is None:
|
||||
num_key_value_heads = num_heads
|
||||
self.num_key_value_heads = num_key_value_heads
|
||||
self.in_channels = in_channels
|
||||
self.patch_size = patch_size
|
||||
self.spatial_merge_size = spatial_merge_size
|
||||
self.temporal_patch_size = temporal_patch_size
|
||||
self.tokens_per_second = tokens_per_second
|
||||
self.window_size = window_size
|
||||
self.fullatt_block_indexes = (
|
||||
fullatt_block_indexes
|
||||
if fullatt_block_indexes is not None
|
||||
else [7, 15, 23, 31]
|
||||
)
|
||||
self.out_hidden_size = out_hidden_size
|
||||
self.initializer_range = initializer_range
|
||||
self.kv_channels = kv_channels
|
||||
self.qk_channels = qk_channels
|
||||
self.num_query_groups = num_query_groups
|
||||
self.vit_window_attn_types = vit_window_attn_types or [-1] * depth
|
||||
self.visual_token_window_size = visual_token_window_size
|
||||
@@ -445,6 +445,37 @@ class MimoMTPModelArchConfigConvertor(ModelArchConfigConvertorBase):
|
||||
return getattr(self.hf_text_config, "num_nextn_predict_layers", 0)
|
||||
|
||||
|
||||
def _strip_mimo_v2_attention_chunk_size(
|
||||
hf_config: PretrainedConfig, hf_text_config: PretrainedConfig
|
||||
) -> None:
|
||||
# MiMo-V2-Flash's config.json sets `attention_chunk_size=128` but the
|
||||
# architecture does not actually use chunked local attention. Leaving it
|
||||
# set makes vLLM disable the hybrid KV cache manager
|
||||
for cfg in (hf_text_config, hf_config):
|
||||
if cfg is not None and hasattr(cfg, "attention_chunk_size"):
|
||||
delattr(cfg, "attention_chunk_size")
|
||||
|
||||
|
||||
class MimoV2ModelArchConfigConvertor(ModelArchConfigConvertorBase):
|
||||
def __init__(self, hf_config: PretrainedConfig, hf_text_config: PretrainedConfig):
|
||||
super().__init__(hf_config, hf_text_config)
|
||||
_strip_mimo_v2_attention_chunk_size(hf_config, hf_text_config)
|
||||
|
||||
|
||||
class MimoV2MTPModelArchConfigConvertor(ModelArchConfigConvertorBase):
|
||||
def __init__(self, hf_config: PretrainedConfig, hf_text_config: PretrainedConfig):
|
||||
super().__init__(hf_config, hf_text_config)
|
||||
_strip_mimo_v2_attention_chunk_size(hf_config, hf_text_config)
|
||||
|
||||
def get_num_hidden_layers(self) -> int:
|
||||
n = getattr(self.hf_text_config, "num_nextn_predict_layers", None)
|
||||
if n is not None:
|
||||
return n
|
||||
# Fall back to n_predict set by hf_config_override
|
||||
n = getattr(self.hf_text_config, "n_predict", None)
|
||||
return n if n is not None else 0
|
||||
|
||||
|
||||
class GLM4MoeMTPModelArchConfigConvertor(ModelArchConfigConvertorBase):
|
||||
def get_num_hidden_layers(self) -> int:
|
||||
return getattr(self.hf_text_config, "num_nextn_predict_layers", 0)
|
||||
@@ -511,6 +542,10 @@ MODEL_ARCH_CONFIG_CONVERTORS = {
|
||||
"qwen3_next_mtp": Qwen3NextMTPModelArchConfigConvertor,
|
||||
"qwen3_5_mtp": Qwen3_5MTPModelArchConfigConvertor,
|
||||
"mimo_mtp": MimoMTPModelArchConfigConvertor,
|
||||
"mimo_v2_pro": MimoV2ModelArchConfigConvertor,
|
||||
"mimo_v2_flash": MimoV2ModelArchConfigConvertor,
|
||||
"mimo_v2_mtp": MimoV2MTPModelArchConfigConvertor,
|
||||
"mimo_v2_omni_mtp": MimoV2MTPModelArchConfigConvertor,
|
||||
"glm4_moe_mtp": GLM4MoeMTPModelArchConfigConvertor,
|
||||
"glm_ocr_mtp": GLM4MoeMTPModelArchConfigConvertor,
|
||||
"ernie_mtp": ErnieMTPModelArchConfigConvertor,
|
||||
|
||||
@@ -27,6 +27,7 @@ __all__ = [
|
||||
"IsaacProcessor",
|
||||
"KimiAudioProcessor",
|
||||
"KimiK25Processor",
|
||||
"MiMoOmniProcessor",
|
||||
"MistralCommonPixtralProcessor",
|
||||
"MistralCommonVoxtralProcessor",
|
||||
"NanoNemotronVLProcessor",
|
||||
@@ -57,6 +58,7 @@ _CLASS_TO_MODULE: dict[str, str] = {
|
||||
"IsaacProcessor": "vllm.transformers_utils.processors.isaac",
|
||||
"KimiAudioProcessor": "vllm.transformers_utils.processors.kimi_audio",
|
||||
"KimiK25Processor": "vllm.transformers_utils.processors.kimi_k25",
|
||||
"MiMoOmniProcessor": "vllm.transformers_utils.processors.mimo_v2_omni",
|
||||
"MistralCommonPixtralProcessor": "vllm.transformers_utils.processors.pixtral",
|
||||
"MistralCommonVoxtralProcessor": "vllm.transformers_utils.processors.voxtral",
|
||||
"NanoNemotronVLProcessor": "vllm.transformers_utils.processors.nano_nemotron_vl",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1381,7 +1381,9 @@ def unify_hybrid_kv_cache_specs(kv_cache_spec: dict[str, KVCacheSpec]):
|
||||
block_size=spec.block_size,
|
||||
num_kv_heads=spec.num_kv_heads,
|
||||
head_size=spec.head_size,
|
||||
head_size_v=spec.head_size_v,
|
||||
dtype=spec.dtype,
|
||||
kv_quant_mode=spec.kv_quant_mode,
|
||||
sliding_window=spec.sliding_window,
|
||||
page_size_padded=spec.page_size_padded,
|
||||
)
|
||||
|
||||
@@ -1344,6 +1344,7 @@ class SpecDecodeBaseProposer:
|
||||
"Exaone4_5_ForConditionalGeneration",
|
||||
"GlmOcrForConditionalGeneration",
|
||||
"HunYuanVLForConditionalGeneration",
|
||||
"MiMoV2OmniForCausalLM",
|
||||
"Qwen2_5_VLForConditionalGeneration",
|
||||
"Qwen3_5ForConditionalGeneration",
|
||||
"Qwen3_5MoeForConditionalGeneration",
|
||||
|
||||
Reference in New Issue
Block a user