@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 5576227bc1
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 10, 12:45 UTC

[Model] Standardize common vision encoders (#31947)

Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>

Cyrus Leung committed Jan 8, 2026 at 18:33 UTC 5576227bc132996d9e4ca279a8a8cf9e7b8a8ca4
19 files changed +254 -174
vllm/model_executor/models/clip.py
+57 -12
@@ -17,7 +17,7 @@ from transformers import (
17 from vllm.attention.layer import Attention
18 from vllm.attention.layers.mm_encoder_attention import MMEncoderAttention
19 from vllm.config import VllmConfig
20 -from vllm.config.multimodal import BaseDummyOptions
20 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
21 from vllm.distributed import divide, get_tensor_model_parallel_world_size
22 from vllm.model_executor.layers.activation import get_act_fn
23 from vllm.model_executor.layers.conv import Conv2dLayer
@@ -353,6 +353,7 @@ class CLIPAttention(nn.Module):
353 self,
354 config: CLIPTextConfig | CLIPVisionConfig,
355 quant_config: QuantizationConfig | None = None,
356 + multimodal_config: MultiModalConfig | None = None,
357 *,
358 prefix: str = "",
359 attn_cls: type[Attention] | type[MMEncoderAttention],
@@ -365,18 +366,24 @@ class CLIPAttention(nn.Module):
366 self.head_dim = self.embed_dim // self.num_heads
367 if self.head_dim * self.num_heads != self.embed_dim:
368 raise ValueError(
368 - "embed_dim must be divisible by num_heads "
369 - f"(got `embed_dim`: {self.embed_dim} and `num_heads`:"
370 - f" {self.num_heads})."
369 + f"embed_dim must be divisible by num_heads "
370 + f"(got `embed_dim`: {self.embed_dim} and "
371 + f"`num_heads`: {self.num_heads})."
372 )
373 self.scale = self.head_dim**-0.5
374
375 + use_data_parallel = (
376 + multimodal_config.mm_encoder_tp_mode == "data"
377 + if multimodal_config
378 + else False
379 + )
380 self.qkv_proj = QKVParallelLinear(
381 hidden_size=self.embed_dim,
382 head_size=self.head_dim,
383 total_num_heads=self.num_heads,
384 quant_config=quant_config,
385 prefix=f"{prefix}.qkv_proj",
386 + disable_tp=use_data_parallel,
387 )
388
389 self.out_proj = RowParallelLinear(
@@ -384,17 +391,29 @@ class CLIPAttention(nn.Module):
391 output_size=self.embed_dim,
392 quant_config=quant_config,
393 prefix=f"{prefix}.out_proj",
394 + disable_tp=use_data_parallel,
395 )
396
389 - self.tp_size = get_tensor_model_parallel_world_size()
397 + self.tp_size = (
398 + 1 if use_data_parallel else get_tensor_model_parallel_world_size()
399 + )
400 self.num_heads_per_partition = divide(self.num_heads, self.tp_size)
401
392 - self.attn = attn_cls(
393 - self.num_heads_per_partition,
394 - self.head_dim,
395 - self.scale,
396 - prefix=f"{prefix}.attn",
397 - )
402 + if attn_cls == MMEncoderAttention:
403 + self.attn = attn_cls(
404 + self.num_heads_per_partition,
405 + self.head_dim,
406 + self.scale,
407 + prefix=f"{prefix}.attn",
408 + multimodal_config=multimodal_config,
409 + )
410 + else:
411 + self.attn = attn_cls(
412 + self.num_heads_per_partition,
413 + self.head_dim,
414 + self.scale,
415 + prefix=f"{prefix}.attn",
416 + )
417
418 def forward(
419 self,
@@ -415,17 +434,26 @@ class CLIPMLP(nn.Module):
434 self,
435 config: CLIPTextConfig | CLIPVisionConfig,
436 quant_config: QuantizationConfig | None = None,
437 + multimodal_config: MultiModalConfig | None = None,
438 prefix: str = "",
439 ) -> None:
440 super().__init__()
441 +
442 self.config = config
443 + use_data_parallel = (
444 + multimodal_config.mm_encoder_tp_mode == "data"
445 + if multimodal_config
446 + else False
447 + )
448 self.activation_fn = get_act_fn(config.hidden_act)
449 +
450 self.fc1 = ColumnParallelLinear(
451 config.hidden_size,
452 config.intermediate_size,
453 bias=True,
454 quant_config=quant_config,
455 prefix=f"{prefix}.fc1",
456 + disable_tp=use_data_parallel,
457 )
458 self.fc2 = RowParallelLinear(
459 config.intermediate_size,
@@ -433,6 +461,7 @@ class CLIPMLP(nn.Module):
461 bias=True,
462 quant_config=quant_config,
463 prefix=f"{prefix}.fc2",
464 + disable_tp=use_data_parallel,
465 )
466
467 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
@@ -448,19 +477,27 @@ class CLIPEncoderLayer(nn.Module):
477 self,
478 config: CLIPTextConfig | CLIPVisionConfig,
479 quant_config: QuantizationConfig | None = None,
480 + multimodal_config: MultiModalConfig | None = None,
481 *,
482 prefix: str = "",
483 attn_cls: type[Attention] | type[MMEncoderAttention],
484 ) -> None:
485 super().__init__()
486 +
487 self.self_attn = CLIPAttention(
488 config,
489 quant_config=quant_config,
490 + multimodal_config=multimodal_config,
491 prefix=f"{prefix}.self_attn",
492 attn_cls=attn_cls,
493 )
494 self.layer_norm1 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
463 - self.mlp = CLIPMLP(config, quant_config=quant_config, prefix=f"{prefix}.mlp")
495 + self.mlp = CLIPMLP(
496 + config,
497 + quant_config=quant_config,
498 + multimodal_config=multimodal_config,
499 + prefix=f"{prefix}.mlp",
500 + )
501 self.layer_norm2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
502
503 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
@@ -491,6 +528,7 @@ class CLIPEncoder(nn.Module):
528 self,
529 config: CLIPTextConfig | CLIPVisionConfig,
530 quant_config: QuantizationConfig | None = None,
531 + multimodal_config: MultiModalConfig | None = None,
532 num_hidden_layers_override: int | None = None,
533 *,
534 prefix: str = "",
@@ -504,11 +542,13 @@ class CLIPEncoder(nn.Module):
542 num_hidden_layers = config.num_hidden_layers
543 else:
544 num_hidden_layers = num_hidden_layers_override
545 +
546 self.layers = nn.ModuleList(
547 [
548 CLIPEncoderLayer(
549 config=config,
550 quant_config=quant_config,
551 + multimodal_config=multimodal_config,
552 prefix=f"{prefix}.layers.{layer_idx}",
553 attn_cls=attn_cls,
554 )
@@ -618,6 +658,7 @@ class CLIPVisionTransformer(nn.Module):
658 self,
659 config: CLIPVisionConfig,
660 quant_config: QuantizationConfig | None = None,
661 + multimodal_config: MultiModalConfig | None = None,
662 *,
663 num_hidden_layers_override: int | None = None,
664 require_post_norm: bool | None = None,
@@ -637,6 +678,7 @@ class CLIPVisionTransformer(nn.Module):
678 self.encoder = CLIPEncoder(
679 config=config,
680 quant_config=quant_config,
681 + multimodal_config=multimodal_config,
682 num_hidden_layers_override=num_hidden_layers_override,
683 prefix=f"{prefix}.encoder",
684 attn_cls=MMEncoderAttention,
@@ -738,6 +780,7 @@ class CLIPVisionModel(nn.Module):
780 self,
781 config: CLIPVisionConfig,
782 quant_config: QuantizationConfig | None = None,
783 + multimodal_config: MultiModalConfig | None = None,
784 *,
785 num_hidden_layers_override: int | None = None,
786 require_post_norm: bool | None = None,
@@ -748,6 +791,7 @@ class CLIPVisionModel(nn.Module):
791 self.vision_model = CLIPVisionTransformer(
792 config=config,
793 quant_config=quant_config,
794 + multimodal_config=multimodal_config,
795 num_hidden_layers_override=num_hidden_layers_override,
796 require_post_norm=require_post_norm,
797 prefix=f"{prefix}.vision_model",
@@ -817,6 +861,7 @@ class CLIPEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
861 self.vision_model = CLIPVisionTransformer(
862 vision_config,
863 quant_config=quant_config,
864 + multimodal_config=multimodal_config,
865 prefix=maybe_prefix(prefix, "vision_model"),
866 )
867
vllm/model_executor/models/deepencoder.py
+3
@@ -19,6 +19,7 @@ import torch.nn.functional as F
19 from transformers import CLIPVisionConfig
20
21 from vllm.attention.layers.mm_encoder_attention import MMEncoderAttention
22 +from vllm.config import MultiModalConfig
23 from vllm.model_executor.layers.conv import Conv2dLayer
24 from vllm.model_executor.layers.quantization import QuantizationConfig
25 from vllm.model_executor.model_loader.weight_utils import default_weight_loader
@@ -608,6 +609,7 @@ class DeepCLIPVisionTransformer(nn.Module):
609 self,
610 config: CLIPVisionConfig,
611 quant_config: QuantizationConfig | None = None,
612 + multimodal_config: MultiModalConfig | None = None,
613 *,
614 num_hidden_layers_override: int | None = None,
615 prefix: str = "",
@@ -626,6 +628,7 @@ class DeepCLIPVisionTransformer(nn.Module):
628 self.transformer = CLIPEncoder(
629 config=config,
630 quant_config=quant_config,
631 + multimodal_config=multimodal_config,
632 num_hidden_layers_override=num_hidden_layers_override,
633 prefix=f"{prefix}.encoder",
634 attn_cls=MMEncoderAttention,
vllm/model_executor/models/deepseek_ocr.py
+1
@@ -397,6 +397,7 @@ class DeepseekOCRForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, Supports
397 self.vision_model = DeepCLIPVisionTransformer(
398 config=clip_vision_config,
399 quant_config=quant_config,
400 + multimodal_config=multimodal_config,
401 prefix=maybe_prefix(prefix, "vision_model"),
402 )
403
vllm/model_executor/models/hyperclovax_vision.py
+9 -10
@@ -6,7 +6,7 @@ from collections import defaultdict
6 from collections.abc import Iterable, Mapping, Sequence
7 from functools import partial
8 from itertools import accumulate
9 -from typing import Annotated, Any, Literal
9 +from typing import Annotated, Literal
10
11 import numpy as np
12 import torch
@@ -18,7 +18,7 @@ from transformers import BatchFeature, CLIPVisionConfig, SiglipVisionConfig
18 from transformers.modeling_utils import no_init_weights
19
20 from vllm.config import VllmConfig
21 -from vllm.config.multimodal import BaseDummyOptions
21 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
22 from vllm.model_executor.layers.quantization import QuantizationConfig
23 from vllm.multimodal import MULTIMODAL_REGISTRY
24 from vllm.multimodal.cache import BaseMultiModalProcessorCache
@@ -361,6 +361,7 @@ def _build_hcxvision_hf_processor(
361 def init_vision_tower_for_hcxvision(
362 vision_config,
363 quant_config: QuantizationConfig | None,
364 + multimodal_config: MultiModalConfig | None,
365 *,
366 use_nth_layer: int | None = None,
367 require_post_norm: bool | None = None,
@@ -378,6 +379,7 @@ def init_vision_tower_for_hcxvision(
379 return CLIPVisionModel(
380 vision_config,
381 quant_config=quant_config,
382 + multimodal_config=multimodal_config,
383 num_hidden_layers_override=num_hidden_layers,
384 require_post_norm=require_post_norm,
385 prefix=prefix,
@@ -386,6 +388,7 @@ def init_vision_tower_for_hcxvision(
388 return SiglipVisionModel(
389 vision_config,
390 quant_config=quant_config,
391 + multimodal_config=multimodal_config,
392 num_hidden_layers_override=num_hidden_layers,
393 require_post_norm=require_post_norm,
394 prefix=prefix,
@@ -597,18 +600,13 @@ class HCXVisionForCausalLM(nn.Module, SupportsMultiModal, SupportsPP):
600 "gate_up_proj": ["gate_proj", "up_proj"],
601 }
602
600 - def __init__(
601 - self,
602 - *,
603 - vllm_config: VllmConfig,
604 - prefix: str = "",
605 - **kwargs: Any | None,
606 - ) -> None:
603 + def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
604 super().__init__()
605
606 # init configs
607 config = vllm_config.model_config.hf_config
608 quant_config = vllm_config.quant_config
609 + multimodal_config = vllm_config.model_config.multimodal_config
610 # text_config
611 text_config = config.text_config
612 if text_config.model_type in ["gpt2", "hyperclovax", "llama"]:
@@ -631,7 +629,8 @@ class HCXVisionForCausalLM(nn.Module, SupportsMultiModal, SupportsPP):
629 with no_init_weights(): # weight will be loaded in from_pretrained
630 self.vision_model = init_vision_tower_for_hcxvision(
631 vision_config,
634 - quant_config,
632 + quant_config=quant_config,
633 + multimodal_config=multimodal_config,
634 use_nth_layer=getattr(config, "use_nth_layer", -1),
635 require_post_norm=False,
636 prefix=maybe_prefix(prefix, "vision_model"),
vllm/model_executor/models/isaac.py
+1 -1
@@ -1226,8 +1226,8 @@ class IsaacVisionEmbedding(nn.Module):
1226 self.transformer = Siglip2VisionTransformer(
1227 vision_cfg,
1228 quant_config=quant_config,
1229 - prefix=maybe_prefix(prefix, "0"),
1229 multimodal_config=multimodal_config,
1230 + prefix=maybe_prefix(prefix, "0"),
1231 )
1232 self.linear_fc1 = ColumnParallelLinear(
1233 hidden_dim,
vllm/model_executor/models/keye.py
+2
@@ -404,6 +404,7 @@ class KeyeSiglipAttention(nn.Module):
404 self.attn = MMEncoderAttention(
405 num_heads=self.num_heads,
406 head_size=self.head_dim,
407 + scale=self.scale,
408 num_kv_heads=self.num_kv_heads,
409 prefix=f"{prefix}.attn",
410 multimodal_config=multimodal_config,
@@ -511,6 +512,7 @@ class KeyeSiglipEncoderLayer(nn.Module):
512 self.mlp = SiglipMLP(
513 config,
514 quant_config=quant_config,
515 + multimodal_config=multimodal_config,
516 prefix=f"{prefix}.mlp",
517 )
518
vllm/model_executor/models/lightonocr.py
+3 -1
@@ -155,6 +155,7 @@ class LightOnOCRForConditionalGeneration(Mistral3ForConditionalGeneration):
155
156 def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
157 nn.Module.__init__(self)
158 +
159 config = vllm_config.model_config.hf_config
160 quant_config = vllm_config.quant_config
161 multimodal_config = vllm_config.model_config.multimodal_config
@@ -164,7 +165,8 @@ class LightOnOCRForConditionalGeneration(Mistral3ForConditionalGeneration):
165
166 self.vision_tower = init_vision_tower_for_llava(
167 config,
167 - quant_config,
168 + quant_config=quant_config,
169 + multimodal_config=multimodal_config,
170 require_post_norm=False,
171 prefix=maybe_prefix(prefix, "vision_tower"),
172 )
vllm/model_executor/models/llava.py
+7 -2
@@ -19,7 +19,7 @@ from transformers.models.llava import LlavaProcessor
19 from transformers.models.pixtral import PixtralProcessor
20
21 from vllm.config import VllmConfig
22 -from vllm.config.multimodal import BaseDummyOptions
22 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
23 from vllm.model_executor.layers.activation import get_act_fn
24 from vllm.model_executor.layers.linear import ColumnParallelLinear, RowParallelLinear
25 from vllm.model_executor.layers.quantization import QuantizationConfig
@@ -468,6 +468,7 @@ def _get_layer_index(feature_layer_index: int, num_hidden_layers: int) -> int:
468 def init_vision_tower_for_llava(
469 hf_config: LlavaLikeConfig,
470 quant_config: QuantizationConfig | None,
471 + multimodal_config: MultiModalConfig | None,
472 *,
473 require_post_norm: bool | None = None,
474 prefix: str = "",
@@ -481,6 +482,7 @@ def init_vision_tower_for_llava(
482 return CLIPVisionModel(
483 vision_config,
484 quant_config=quant_config,
485 + multimodal_config=multimodal_config,
486 num_hidden_layers_override=num_hidden_layers,
487 require_post_norm=require_post_norm,
488 prefix=prefix,
@@ -489,6 +491,7 @@ def init_vision_tower_for_llava(
491 return SiglipVisionModel(
492 vision_config,
493 quant_config=quant_config,
494 + multimodal_config=multimodal_config,
495 num_hidden_layers_override=num_hidden_layers,
496 require_post_norm=require_post_norm,
497 prefix=prefix,
@@ -497,6 +500,7 @@ def init_vision_tower_for_llava(
500 return PixtralHFVisionModel(
501 vision_config,
502 quant_config=quant_config,
503 + multimodal_config=multimodal_config,
504 num_hidden_layers_override=num_hidden_layers,
505 require_post_norm=require_post_norm,
506 prefix=prefix,
@@ -563,7 +567,8 @@ class LlavaForConditionalGeneration(
567 if multimodal_config.get_limit_per_prompt("image"):
568 self.vision_tower = init_vision_tower_for_llava(
569 config,
566 - quant_config,
570 + quant_config=quant_config,
571 + multimodal_config=multimodal_config,
572 require_post_norm=False,
573 prefix=maybe_prefix(prefix, "vision_tower"),
574 )
vllm/model_executor/models/llava_next.py
+3 -1
@@ -243,6 +243,7 @@ class LlavaNextForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsP
243
244 def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
245 super().__init__()
246 +
247 config = vllm_config.model_config.hf_config
248 quant_config = vllm_config.quant_config
249 multimodal_config = vllm_config.model_config.multimodal_config
@@ -270,7 +271,8 @@ class LlavaNextForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsP
271 # TODO: Optionally initializes this for supporting embeddings.
272 self.vision_tower = init_vision_tower_for_llava(
273 config,
273 - quant_config,
274 + quant_config=quant_config,
275 + multimodal_config=multimodal_config,
276 require_post_norm=False,
277 prefix=maybe_prefix(prefix, "vision_tower"),
278 )
vllm/model_executor/models/llava_next_video.py
+3 -1
@@ -321,6 +321,7 @@ class LlavaNextVideoForConditionalGeneration(nn.Module, SupportsMultiModal, Supp
321
322 def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
323 super().__init__()
324 +
325 config = vllm_config.model_config.hf_config
326 quant_config = vllm_config.quant_config
327 multimodal_config = vllm_config.model_config.multimodal_config
@@ -331,7 +332,8 @@ class LlavaNextVideoForConditionalGeneration(nn.Module, SupportsMultiModal, Supp
332 # Initialize the vision tower only up to the required feature layer
333 self.vision_tower = init_vision_tower_for_llava(
334 config,
334 - quant_config,
335 + quant_config=quant_config,
336 + multimodal_config=multimodal_config,
337 require_post_norm=False,
338 prefix=maybe_prefix(prefix, "vision_tower"),
339 )
vllm/model_executor/models/llava_onevision.py
+2 -1
@@ -511,7 +511,8 @@ class LlavaOnevisionForConditionalGeneration(nn.Module, SupportsMultiModal, Supp
511 # Initialize the vision tower only up to the required feature layer
512 self.vision_tower = init_vision_tower_for_llava(
513 config,
514 - quant_config,
514 + quant_config=quant_config,
515 + multimodal_config=multimodal_config,
516 require_post_norm=False,
517 prefix=maybe_prefix(prefix, "vision_tower"),
518 )
vllm/model_executor/models/minimax_vl_01.py
+2 -1
@@ -204,7 +204,8 @@ class MiniMaxVL01ForConditionalGeneration(nn.Module, SupportsMultiModal, Support
204 # TODO: Optionally initializes this for supporting embeddings.
205 self.vision_tower = init_vision_tower_for_llava(
206 config,
207 - quant_config,
207 + quant_config=quant_config,
208 + multimodal_config=multimodal_config,
209 require_post_norm=False,
210 prefix=maybe_prefix(prefix, "vision_tower"),
211 )
vllm/model_executor/models/mistral3.py
+5 -2
@@ -16,7 +16,7 @@ from transformers import (
16 from transformers.models.pixtral import PixtralProcessor
17
18 from vllm.config import VllmConfig
19 -from vllm.config.multimodal import BaseDummyOptions
19 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
20 from vllm.model_executor.layers.activation import get_act_fn
21 from vllm.model_executor.layers.layernorm import RMSNorm
22 from vllm.model_executor.layers.linear import ColumnParallelLinear, RowParallelLinear
@@ -395,6 +395,7 @@ def _get_layer_index(feature_layer_index: int, num_hidden_layers: int) -> int:
395 def init_vision_tower_for_llava(
396 hf_config: LlavaLikeConfig,
397 quant_config: QuantizationConfig | None,
398 + multimodal_config: MultiModalConfig | None,
399 *,
400 require_post_norm: bool | None = None,
401 prefix: str = "",
@@ -409,6 +410,7 @@ def init_vision_tower_for_llava(
410 return PixtralHFVisionModel(
411 vision_config,
412 quant_config=quant_config,
413 + multimodal_config=multimodal_config,
414 num_hidden_layers_override=num_hidden_layers,
415 require_post_norm=require_post_norm,
416 prefix=prefix,
@@ -472,7 +474,8 @@ class Mistral3ForConditionalGeneration(
474 if multimodal_config.get_limit_per_prompt("image"):
475 self.vision_tower = init_vision_tower_for_llava(
476 config,
475 - quant_config,
477 + quant_config=quant_config,
478 + multimodal_config=multimodal_config,
479 require_post_norm=False,
480 prefix=maybe_prefix(prefix, "vision_tower"),
481 )
vllm/model_executor/models/paddleocr_vl.py
+2 -42
@@ -38,10 +38,8 @@ from vllm.config import MultiModalConfig, VllmConfig
38 from vllm.config.multimodal import BaseDummyOptions
39 from vllm.distributed import parallel_state
40 from vllm.distributed import utils as dist_utils
41 -from vllm.model_executor.layers.activation import get_act_fn
41 from vllm.model_executor.layers.conv import Conv2dLayer
42 from vllm.model_executor.layers.linear import (
44 - ColumnParallelLinear,
43 QKVParallelLinear,
44 RowParallelLinear,
45 )
@@ -77,6 +75,7 @@ from vllm.utils.tensor_schema import TensorSchema, TensorShape
75
76 from .ernie45 import Ernie4_5ForCausalLM
77 from .interfaces import MultiModalEmbeddings, SupportsMRoPE, SupportsMultiModal
78 +from .siglip import SiglipMLP
79 from .utils import (
80 AutoWeightsLoader,
81 PPMissingLayer,
@@ -657,46 +656,6 @@ class SigLIPRotaryEmbedding(nn.Module):
656 return freqs
657
658
660 -class SiglipMLP(nn.Module):
661 - def __init__(
662 - self,
663 - config: PretrainedConfig,
664 - quant_config: QuantizationConfig | None = None,
665 - prefix: str = "",
666 - ) -> None:
667 - super().__init__()
668 -
669 - self.config = config
670 - self.activation_fn = get_act_fn(config.hidden_act)
671 - # Special handling for BNB and torchao quantization
672 - if quant_config and quant_config.get_name() in ["bitsandbytes", "torchao"]:
673 - quantizable = True
674 - else:
675 - # For other quantization, we require the hidden size to be a
676 - # multiple of 64
677 - quantizable = (
678 - config.hidden_size % 64 == 0 and config.intermediate_size % 64 == 0
679 - )
680 - self.fc1 = ColumnParallelLinear(
681 - config.hidden_size,
682 - config.intermediate_size,
683 - quant_config=quant_config if quantizable else None,
684 - prefix=f"{prefix}.fc1",
685 - )
686 - self.fc2 = RowParallelLinear(
687 - config.intermediate_size,
688 - config.hidden_size,
689 - quant_config=quant_config if quantizable else None,
690 - prefix=f"{prefix}.fc2",
691 - )
692 -
693 - def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
694 - hidden_states, _ = self.fc1(hidden_states)
695 - hidden_states = self.activation_fn(hidden_states)
696 - hidden_states, _ = self.fc2(hidden_states)
697 - return hidden_states
698 -
699 -
659 class SiglipEncoderLayer(nn.Module):
660 def __init__(
661 self,
@@ -720,6 +679,7 @@ class SiglipEncoderLayer(nn.Module):
679 self.mlp = SiglipMLP(
680 config,
681 quant_config=quant_config,
682 + multimodal_config=multimodal_config,
683 prefix=f"{prefix}.mlp",
684 )
685
vllm/model_executor/models/phi3v.py
+31 -31
@@ -29,7 +29,7 @@ from transformers import (
29 )
30
31 from vllm.config import VllmConfig
32 -from vllm.config.multimodal import BaseDummyOptions
32 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
33 from vllm.logger import init_logger
34 from vllm.model_executor.layers.quantization import QuantizationConfig
35 from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding
@@ -96,6 +96,7 @@ CLIP_VIT_LARGE_PATCH14_336_CONFIG = CLIPVisionConfig(
96 def _init_img_processor(
97 hf_config: PretrainedConfig,
98 quant_config: QuantizationConfig | None,
99 + multimodal_config: MultiModalConfig | None,
100 prefix: str = "",
101 ) -> CLIPVisionModel:
102 clip_config = CLIP_VIT_LARGE_PATCH14_336_CONFIG
@@ -109,7 +110,8 @@ def _init_img_processor(
110
111 img_processor = CLIPVisionModel(
112 clip_config,
112 - quant_config,
113 + quant_config=quant_config,
114 + multimodal_config=multimodal_config,
115 num_hidden_layers_override=num_hidden_layers,
116 prefix=prefix,
117 )
@@ -160,38 +162,15 @@ class Phi3VImageEmbeddingInputs(TensorSchema):
162 Phi3VImageInputs: TypeAlias = Phi3VImagePixelInputs | Phi3VImageEmbeddingInputs
163
164
163 -class Phi3ImageEmbeddingBase(nn.Module):
164 - def __init__(self) -> None:
165 - super().__init__()
166 - self.layer_idx: int
167 - self.type_feature: str
168 - self.img_processor: CLIPVisionModel
169 -
170 - def get_img_features(self, img_embeds: torch.FloatTensor) -> torch.FloatTensor:
171 - TYPE_FEATURE = self.type_feature
172 -
173 - # NOTE: we skip the step to select the vision feature layer since
174 - # this is already done inside the img_processor
175 - img_feature = self.img_processor(img_embeds)
176 -
177 - if TYPE_FEATURE == "patch":
178 - patch_feature = img_feature[:, 1:]
179 - return patch_feature
180 -
181 - if TYPE_FEATURE == "cls_patch":
182 - return img_feature
183 -
184 - raise NotImplementedError
185 -
186 -
165 # adapted from https://huggingface.co/microsoft/Phi-3-vision-128k-instruct/blob/main/image_embedding_phi3_v.py
188 -class Phi3HDImageEmbedding(Phi3ImageEmbeddingBase):
166 +class Phi3HDImageEmbedding(nn.Module):
167 """Phi3 Image embedding with HD transform."""
168
169 def __init__(
170 self,
171 config: PretrainedConfig,
172 quant_config: QuantizationConfig | None,
173 + multimodal_config: MultiModalConfig | None,
174 prefix: str = "",
175 ) -> None:
176 super().__init__()
@@ -200,7 +179,10 @@ class Phi3HDImageEmbedding(Phi3ImageEmbeddingBase):
179 hidden_size = config.n_embd if hasattr(config, "n_embd") else config.hidden_size
180
181 self.img_processor = _init_img_processor(
203 - config, quant_config, prefix=f"{prefix}.img_processor"
182 + config,
183 + quant_config=quant_config,
184 + multimodal_config=multimodal_config,
185 + prefix=f"{prefix}.img_processor",
186 )
187
188 image_dim_out = config.img_processor["image_dim_out"]
@@ -223,13 +205,29 @@ class Phi3HDImageEmbedding(Phi3ImageEmbeddingBase):
205
206 dim_projection = hidden_size
207 depth = 2
226 - layers = [nn.Linear(image_dim_out * 4, dim_projection)]
208 + layers: list[nn.Module] = [nn.Linear(image_dim_out * 4, dim_projection)]
209 for _ in range(1, depth):
210 layers.extend([nn.GELU(), nn.Linear(dim_projection, dim_projection)])
211 self.img_projection = nn.Sequential(*layers)
212
213 self.type_feature = config.img_processor.get("type_feature", "patch")
214
215 + def get_img_features(self, img_embeds: torch.FloatTensor) -> torch.FloatTensor:
216 + type_feature = self.type_feature
217 +
218 + # NOTE: we skip the step to select the vision feature layer since
219 + # this is already done inside the img_processor
220 + img_feature = self.img_processor(img_embeds)
221 +
222 + if type_feature == "patch":
223 + patch_feature = img_feature[:, 1:]
224 + return patch_feature
225 +
226 + if type_feature == "cls_patch":
227 + return img_feature
228 +
229 + raise NotImplementedError(type_feature)
230 +
231 def forward(
232 self, pixel_values: torch.FloatTensor, image_sizes: torch.Tensor
233 ) -> torch.FloatTensor:
@@ -582,6 +580,7 @@ class Phi3VForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, SupportsQuant)
580 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
581 super().__init__()
582 config = vllm_config.model_config.hf_config
583 + quant_config = vllm_config.quant_config
584 multimodal_config = vllm_config.model_config.multimodal_config
585 self.config = config
586 self.multimodal_config = multimodal_config
@@ -590,14 +589,15 @@ class Phi3VForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, SupportsQuant)
589 self.embed_tokens = VocabParallelEmbedding(
590 config.vocab_size,
591 config.hidden_size,
593 - quant_config=self.quant_config,
592 + quant_config=quant_config,
593 prefix=maybe_prefix(prefix, "model.embed_tokens"),
594 )
595
596 # TODO: Optionally initializes this for supporting input embeddings.
597 self.vision_embed_tokens = Phi3HDImageEmbedding(
598 config,
600 - self.quant_config,
599 + quant_config=quant_config,
600 + multimodal_config=multimodal_config,
601 prefix=maybe_prefix(prefix, "model.vision_embed_tokens"),
602 )
603
vllm/model_executor/models/pixtral.py
+38 -7
@@ -28,7 +28,7 @@ from transformers.models.pixtral.modeling_pixtral import (
28 from transformers.tokenization_utils_base import TextInput
29
30 from vllm.config import VllmConfig
31 -from vllm.config.multimodal import BaseDummyOptions
31 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
32 from vllm.distributed import divide, get_tensor_model_parallel_world_size
33 from vllm.model_executor.layers.activation import get_act_and_mul_fn
34 from vllm.model_executor.layers.conv import Conv2dLayer
@@ -1043,11 +1043,18 @@ class PixtralHFMLP(nn.Module):
1043 self,
1044 config: PixtralVisionConfig,
1045 quant_config: QuantizationConfig | None = None,
1046 + multimodal_config: MultiModalConfig | None = None,
1047 *,
1048 prefix: str = "",
1049 ) -> None:
1050 super().__init__()
1051
1052 + use_data_parallel = (
1053 + multimodal_config.mm_encoder_tp_mode == "data"
1054 + if multimodal_config
1055 + else False
1056 + )
1057 +
1058 assert config.intermediate_size is not None
1059 self.gate_up_proj = MergedColumnParallelLinear(
1060 input_size=config.hidden_size,
@@ -1055,6 +1062,7 @@ class PixtralHFMLP(nn.Module):
1062 bias=False,
1063 quant_config=quant_config,
1064 prefix=f"{prefix}.gate_up_proj",
1065 + disable_tp=use_data_parallel,
1066 )
1067 self.down_proj = RowParallelLinear(
1068 input_size=config.intermediate_size,
@@ -1062,6 +1070,7 @@ class PixtralHFMLP(nn.Module):
1070 bias=False,
1071 quant_config=quant_config,
1072 prefix=f"{prefix}.down_proj",
1073 + disable_tp=use_data_parallel,
1074 )
1075 self.act_and_mul = get_act_and_mul_fn(config.hidden_act)
1076
@@ -1077,6 +1086,7 @@ class PixtralHFAttention(nn.Module):
1086 self,
1087 config: PixtralVisionConfig,
1088 quant_config: QuantizationConfig | None = None,
1089 + multimodal_config: MultiModalConfig | None = None,
1090 *,
1091 prefix: str = "",
1092 ) -> None:
@@ -1085,10 +1095,14 @@ class PixtralHFAttention(nn.Module):
1095 self.config = config
1096 assert not config.hidden_size % config.num_attention_heads
1097 self.total_num_heads = config.num_attention_heads
1088 - tp_size = get_tensor_model_parallel_world_size()
1089 - self.n_heads = divide(config.num_attention_heads, tp_size)
1098 self.head_dim = config.hidden_size // config.num_attention_heads
1099 + assert self.total_num_heads * self.head_dim == config.hidden_size
1100
1101 + use_data_parallel = (
1102 + multimodal_config.mm_encoder_tp_mode == "data"
1103 + if multimodal_config
1104 + else False
1105 + )
1106 self.qkv_proj = QKVParallelLinear(
1107 hidden_size=config.hidden_size,
1108 head_size=self.head_dim,
@@ -1096,15 +1110,21 @@ class PixtralHFAttention(nn.Module):
1110 bias=False,
1111 quant_config=quant_config,
1112 prefix=f"{prefix}.qkv_proj",
1113 + disable_tp=use_data_parallel,
1114 )
1100 - assert self.total_num_heads * self.head_dim == config.hidden_size
1115 self.o_proj = RowParallelLinear(
1116 input_size=config.hidden_size,
1117 output_size=config.hidden_size,
1118 bias=False,
1119 quant_config=quant_config,
1120 prefix=f"{prefix}.o_proj",
1121 + disable_tp=use_data_parallel,
1122 + )
1123 +
1124 + self.tp_size = (
1125 + 1 if use_data_parallel else get_tensor_model_parallel_world_size()
1126 )
1127 + self.n_heads = divide(config.num_attention_heads, self.tp_size)
1128
1129 def forward(
1130 self,
@@ -1147,6 +1167,7 @@ class PixtralHFTransformerBlock(nn.Module):
1167 self,
1168 config: PixtralVisionConfig,
1169 quant_config: QuantizationConfig | None = None,
1170 + multimodal_config: MultiModalConfig | None = None,
1171 *,
1172 prefix: str = "",
1173 ) -> None:
@@ -1154,10 +1175,16 @@ class PixtralHFTransformerBlock(nn.Module):
1175
1176 self.attention_norm = RMSNorm(config.hidden_size, eps=1e-5)
1177 self.attention = PixtralHFAttention(
1157 - config, quant_config=quant_config, prefix=f"{prefix}.attention"
1178 + config,
1179 + quant_config=quant_config,
1180 + multimodal_config=multimodal_config,
1181 + prefix=f"{prefix}.attention",
1182 )
1183 self.feed_forward = PixtralHFMLP(
1160 - config, quant_config=quant_config, prefix=f"{prefix}.feed_forward"
1184 + config,
1185 + quant_config=quant_config,
1186 + multimodal_config=multimodal_config,
1187 + prefix=f"{prefix}.feed_forward",
1188 )
1189 self.ffn_norm = RMSNorm(config.hidden_size, eps=1e-5)
1190
@@ -1183,6 +1210,7 @@ class PixtralHFTransformer(nn.Module):
1210 self,
1211 config: PixtralVisionConfig,
1212 quant_config: QuantizationConfig | None = None,
1213 + multimodal_config: MultiModalConfig | None = None,
1214 *,
1215 num_hidden_layers_override: int | None = None,
1216 prefix: str = "",
@@ -1199,6 +1227,7 @@ class PixtralHFTransformer(nn.Module):
1227 PixtralHFTransformerBlock(
1228 config=config,
1229 quant_config=quant_config,
1230 + multimodal_config=multimodal_config,
1231 prefix=f"{prefix}.layers.{layer_idx}",
1232 )
1233 for layer_idx in range(num_hidden_layers)
@@ -1230,6 +1259,7 @@ class PixtralHFVisionModel(nn.Module):
1259 self,
1260 config: PixtralVisionConfig,
1261 quant_config: QuantizationConfig | None = None,
1262 + multimodal_config: MultiModalConfig | None = None,
1263 *,
1264 num_hidden_layers_override: int | None = None,
1265 require_post_norm: bool | None = None,
@@ -1249,7 +1279,8 @@ class PixtralHFVisionModel(nn.Module):
1279 self.ln_pre = RMSNorm(config.hidden_size, eps=1e-5)
1280 self.transformer = PixtralHFTransformer(
1281 config,
1252 - quant_config,
1282 + quant_config=quant_config,
1283 + multimodal_config=multimodal_config,
1284 num_hidden_layers_override=num_hidden_layers_override,
1285 prefix=f"{prefix}.transformer",
1286 )
vllm/model_executor/models/siglip.py
+73 -55
@@ -1,7 +1,6 @@
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 -import math
4 from collections.abc import Callable, Iterable, Mapping
5 from functools import cached_property
6 from typing import Annotated, Literal
@@ -19,7 +18,7 @@ from transformers import (
18 from vllm.attention.layers.encoder_only_attention import EncoderOnlyAttention
19 from vllm.attention.layers.mm_encoder_attention import MMEncoderAttention
20 from vllm.config import VllmConfig
22 -from vllm.config.multimodal import BaseDummyOptions
21 +from vllm.config.multimodal import BaseDummyOptions, MultiModalConfig
22 from vllm.distributed import divide, get_tensor_model_parallel_world_size
23 from vllm.model_executor.layers.activation import get_act_fn
24 from vllm.model_executor.layers.conv import Conv2dLayer
@@ -276,7 +275,7 @@ class SiglipEncoderInfo(VisionEncoderInfo[SiglipVisionConfig]):
275 return image_size // patch_size
276
277
279 -# Adapted from https://github.com/huggingface/transformers/blob/v4.43.3/src/transformers/models/siglip/modeling_siglip.py#L249 # noqa
278 +# Adapted from https://github.com/huggingface/transformers/blob/v4.57.3/src/transformers/models/siglip/modeling_siglip.py#L216
279 class SiglipVisionEmbeddings(nn.Module):
280 def __init__(self, config: SiglipVisionConfig):
281 super().__init__()
@@ -295,9 +294,7 @@ class SiglipVisionEmbeddings(nn.Module):
294
295 self.num_patches = (self.image_size // self.patch_size) ** 2
296 self.num_positions = self.num_patches
298 - self.position_embedding = VocabParallelEmbedding(
299 - self.num_positions, self.embed_dim
300 - )
297 + self.position_embedding = nn.Embedding(self.num_positions, self.embed_dim)
298 self.register_buffer(
299 "position_ids",
300 torch.arange(self.num_positions, dtype=torch.int64).expand((1, -1)),
@@ -307,50 +304,30 @@ class SiglipVisionEmbeddings(nn.Module):
304 def interpolate_pos_encoding(
305 self, embeddings: torch.Tensor, height: int, width: int
306 ) -> torch.Tensor:
310 - """
311 - This method is an adapted method for SigLIP (due to SigLIP not having
312 - class embedding unlike other ViTs) that allows the model to interpolate
313 - the pre-trained position encodings such that it can be usable on higher
314 - resolution images.
315 -
316 - Source:
317 - https://github.com/facebookresearch/dino/blob/de9ee3df6cf39fac952ab558447af1fa1365362a/vision_transformer.py#L174
318 - """
319 - position_embeddings = self.position_embedding.weight.unsqueeze(0)
307 num_patches = embeddings.shape[1]
321 - num_positions = position_embeddings.shape[1]
308 + num_positions = self.position_embedding.weight.shape[1]
309 if num_patches == num_positions and height == width:
323 - return position_embeddings
310 + return self.position_embedding(self.position_ids)
311 +
312 + patch_pos_embed = self.position_embedding.weight.unsqueeze(0)
313
314 dim = embeddings.shape[-1]
326 - height = height // self.patch_size
327 - width = width // self.patch_size
328 - # we add a small number to avoid floating point error
329 - # in the interpolation
330 - # see discussion at https://github.com/facebookresearch/dino/issues/8
331 - height, width = height + 0.1, width + 0.1
332 -
333 - patch_pos_embed = position_embeddings.reshape(
334 - 1, int(math.sqrt(num_positions)), int(math.sqrt(num_positions)), dim
315 +
316 + new_height = height // self.patch_size
317 + new_width = width // self.patch_size
318 +
319 + sqrt_num_positions = int(num_positions**0.5)
320 + patch_pos_embed = patch_pos_embed.reshape(
321 + 1, sqrt_num_positions, sqrt_num_positions, dim
322 )
323 patch_pos_embed = patch_pos_embed.permute(0, 3, 1, 2)
324 +
325 patch_pos_embed = nn.functional.interpolate(
326 patch_pos_embed,
339 - scale_factor=(
340 - height / math.sqrt(num_positions),
341 - width / math.sqrt(num_positions),
342 - ),
327 + size=(new_height, new_width),
328 mode="bicubic",
329 align_corners=False,
330 )
346 - if (
347 - int(height) != patch_pos_embed.shape[-2]
348 - or int(width) != patch_pos_embed.shape[-1]
349 - ):
350 - raise ValueError(
351 - "Width or height does not match with "
352 - "the interpolated position embeddings"
353 - )
331
332 patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim)
333 return patch_pos_embed
@@ -377,6 +354,7 @@ class SiglipAttention(nn.Module):
354 self,
355 config: SiglipVisionConfig | SiglipTextConfig,
356 quant_config: QuantizationConfig | None = None,
357 + multimodal_config: MultiModalConfig | None = None,
358 *,
359 prefix: str = "",
360 attn_cls: type[EncoderOnlyAttention] | type[MMEncoderAttention],
@@ -389,19 +367,25 @@ class SiglipAttention(nn.Module):
367 self.head_dim = self.embed_dim // self.num_heads
368 if self.head_dim * self.num_heads != self.embed_dim:
369 raise ValueError(
392 - f"embed_dim must be divisible by num_heads (got "
393 - "`embed_dim`: {self.embed_dim} and `num_heads`:"
394 - f" {self.num_heads})."
370 + f"embed_dim must be divisible by num_heads "
371 + f"(got `embed_dim`: {self.embed_dim} and "
372 + f"`num_heads`: {self.num_heads})."
373 )
374
375 self.scale = self.head_dim**-0.5
398 - self.dropout = config.attention_dropout
376 +
377 + use_data_parallel = (
378 + multimodal_config.mm_encoder_tp_mode == "data"
379 + if multimodal_config
380 + else False
381 + )
382 self.qkv_proj = QKVParallelLinear(
383 hidden_size=self.embed_dim,
384 head_size=self.head_dim,
385 total_num_heads=self.num_heads,
386 quant_config=quant_config,
387 prefix=f"{prefix}.qkv_proj",
388 + disable_tp=use_data_parallel,
389 )
390
391 self.out_proj = RowParallelLinear(
@@ -409,17 +393,29 @@ class SiglipAttention(nn.Module):
393 output_size=self.embed_dim,
394 quant_config=quant_config,
395 prefix=f"{prefix}.out_proj",
396 + disable_tp=use_data_parallel,
397 )
398
414 - self.tp_size = get_tensor_model_parallel_world_size()
399 + self.tp_size = (
400 + 1 if use_data_parallel else get_tensor_model_parallel_world_size()
401 + )
402 self.num_heads_per_partition = divide(self.num_heads, self.tp_size)
403
417 - self.attn = attn_cls(
418 - self.num_heads_per_partition,
419 - self.head_dim,
420 - self.scale,
421 - prefix=f"{prefix}.attn",
422 - )
404 + if attn_cls == MMEncoderAttention:
405 + self.attn = attn_cls(
406 + self.num_heads_per_partition,
407 + self.head_dim,
408 + self.scale,
409 + prefix=f"{prefix}.attn",
410 + multimodal_config=multimodal_config,
411 + )
412 + else:
413 + self.attn = attn_cls(
414 + self.num_heads_per_partition,
415 + self.head_dim,
416 + self.scale,
417 + prefix=f"{prefix}.attn",
418 + )
419
420 def forward(
421 self,
@@ -439,12 +435,19 @@ class SiglipMLP(nn.Module):
435 self,
436 config: SiglipVisionConfig | SiglipTextConfig,
437 quant_config: QuantizationConfig | None = None,
438 + multimodal_config: MultiModalConfig | None = None,
439 prefix: str = "",
440 ) -> None:
441 super().__init__()
442
443 self.config = config
444 + use_data_parallel = (
445 + multimodal_config.mm_encoder_tp_mode == "data"
446 + if multimodal_config
447 + else False
448 + )
449 self.activation_fn = get_act_fn(config.hidden_act)
450 +
451 # Special handling for BNB and torchao quantization
452 if quant_config and quant_config.get_name() in ["bitsandbytes", "torchao"]:
453 quantizable = True
@@ -454,17 +457,20 @@ class SiglipMLP(nn.Module):
457 quantizable = (
458 config.hidden_size % 64 == 0 and config.intermediate_size % 64 == 0
459 )
460 +
461 self.fc1 = ColumnParallelLinear(
462 config.hidden_size,
463 config.intermediate_size,
464 quant_config=quant_config if quantizable else None,
465 prefix=f"{prefix}.fc1",
466 + disable_tp=use_data_parallel,
467 )
468 self.fc2 = RowParallelLinear(
469 config.intermediate_size,
470 config.hidden_size,
471 quant_config=quant_config if quantizable else None,
472 prefix=f"{prefix}.fc2",
473 + disable_tp=use_data_parallel,
474 )
475
476 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
@@ -479,6 +485,7 @@ class SiglipEncoderLayer(nn.Module):
485 self,
486 config: SiglipVisionConfig | SiglipTextConfig,
487 quant_config: QuantizationConfig | None = None,
488 + multimodal_config: MultiModalConfig | None = None,
489 *,
490 prefix: str = "",
491 attn_cls: type[EncoderOnlyAttention] | type[MMEncoderAttention],
@@ -490,6 +497,7 @@ class SiglipEncoderLayer(nn.Module):
497 self.self_attn = SiglipAttention(
498 config,
499 quant_config=quant_config,
500 + multimodal_config=multimodal_config,
501 prefix=f"{prefix}.self_attn",
502 attn_cls=attn_cls,
503 )
@@ -497,6 +505,7 @@ class SiglipEncoderLayer(nn.Module):
505 self.mlp = SiglipMLP(
506 config,
507 quant_config=quant_config,
508 + multimodal_config=multimodal_config,
509 prefix=f"{prefix}.mlp",
510 )
511 self.layer_norm2 = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_eps)
@@ -524,6 +533,7 @@ class SiglipEncoder(nn.Module):
533 self,
534 config: SiglipVisionConfig | SiglipTextConfig,
535 quant_config: QuantizationConfig | None = None,
536 + multimodal_config: MultiModalConfig | None = None,
537 num_hidden_layers_override: int | None = None,
538 *,
539 prefix: str = "",
@@ -543,6 +553,7 @@ class SiglipEncoder(nn.Module):
553 SiglipEncoderLayer(
554 config,
555 quant_config=quant_config,
556 + multimodal_config=multimodal_config,
557 prefix=f"{prefix}.layers.{layer_idx}",
558 attn_cls=attn_cls,
559 )
@@ -647,6 +658,7 @@ class SiglipMultiheadAttentionPoolingHead(nn.Module):
658 self,
659 config: SiglipVisionConfig,
660 quant_config: QuantizationConfig | None = None,
661 + multimodal_config: MultiModalConfig | None = None,
662 prefix: str = "",
663 ) -> None:
664 super().__init__()
@@ -658,7 +670,10 @@ class SiglipMultiheadAttentionPoolingHead(nn.Module):
670 )
671 self.layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
672 self.mlp = SiglipMLP(
661 - config=config, quant_config=quant_config, prefix=f"{prefix}.mlp"
673 + config=config,
674 + quant_config=quant_config,
675 + multimodal_config=multimodal_config,
676 + prefix=f"{prefix}.mlp",
677 )
678
679 def forward(self, hidden_state: torch.Tensor) -> torch.Tensor:
@@ -683,6 +698,7 @@ class SiglipVisionTransformer(nn.Module):
698 self,
699 config: SiglipVisionConfig,
700 quant_config: QuantizationConfig | None = None,
701 + multimodal_config: MultiModalConfig | None = None,
702 *,
703 num_hidden_layers_override: int | None = None,
704 require_post_norm: bool | None = None,
@@ -698,6 +714,7 @@ class SiglipVisionTransformer(nn.Module):
714 self.encoder = SiglipEncoder(
715 config,
716 quant_config=quant_config,
717 + multimodal_config=multimodal_config,
718 num_hidden_layers_override=num_hidden_layers_override,
719 prefix=f"{prefix}.encoder",
720 attn_cls=MMEncoderAttention,
@@ -726,6 +743,7 @@ class SiglipVisionTransformer(nn.Module):
743 self.head = SiglipMultiheadAttentionPoolingHead(
744 config=config,
745 quant_config=quant_config,
746 + multimodal_config=multimodal_config,
747 prefix=f"{prefix}.head",
748 )
749
@@ -812,13 +830,11 @@ class SiglipVisionTransformer(nn.Module):
830
831
832 class SiglipVisionModel(nn.Module):
815 - config_class = SiglipVisionConfig
816 - main_input_name = "pixel_values"
817 -
833 def __init__(
834 self,
835 config: SiglipVisionConfig,
836 quant_config: QuantizationConfig | None = None,
837 + multimodal_config: MultiModalConfig | None = None,
838 *,
839 num_hidden_layers_override: int | None = None,
840 require_post_norm: bool | None = None,
@@ -829,7 +845,8 @@ class SiglipVisionModel(nn.Module):
845 self.quant_config = quant_config
846 self.vision_model = SiglipVisionTransformer(
847 config,
832 - quant_config,
848 + quant_config=quant_config,
849 + multimodal_config=multimodal_config,
850 num_hidden_layers_override=num_hidden_layers_override,
851 require_post_norm=require_post_norm,
852 prefix=f"{prefix}.vision_model",
@@ -1023,6 +1040,7 @@ class SiglipEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
1040 self.vision_model = SiglipVisionTransformer(
1041 vision_config,
1042 quant_config=quant_config,
1043 + multimodal_config=multimodal_config,
1044 prefix=maybe_prefix(prefix, "vision_model"),
1045 )
1046
vllm/model_executor/models/siglip2navit.py
+3 -5
@@ -11,7 +11,6 @@ from torch.nn import functional as F
11 from transformers import Siglip2VisionConfig
12 from transformers.configuration_utils import PretrainedConfig
13
14 -from vllm.attention.backends.registry import AttentionBackendEnum
14 from vllm.attention.layers.mm_encoder_attention import MMEncoderAttention
15 from vllm.config import MultiModalConfig
16 from vllm.distributed import divide, get_tensor_model_parallel_world_size
@@ -186,7 +185,6 @@ class Siglip2Attention(nn.Module):
185 multimodal_config: MultiModalConfig | None = None,
186 prefix: str = "",
187 use_data_parallel: bool = False,
189 - attn_backend_override: AttentionBackendEnum | None = None,
188 ):
189 super().__init__()
190 self.config = config
@@ -196,12 +194,11 @@ class Siglip2Attention(nn.Module):
194 if self.head_dim * self.num_heads != self.embed_dim:
195 raise ValueError(
196 f"embed_dim must be divisible by num_heads "
199 - f"(got `embed_dim`: {self.embed_dim} and `num_heads`:"
200 - f" {self.num_heads})."
197 + f"(got `embed_dim`: {self.embed_dim} and "
198 + f"`num_heads`: {self.num_heads})."
199 )
200 self.scale = self.head_dim**-0.5
201 self.dropout = config.attention_dropout
204 - self.is_causal = False
202
203 use_data_parallel = (
204 multimodal_config.mm_encoder_tp_mode == "data"
@@ -233,6 +230,7 @@ class Siglip2Attention(nn.Module):
230 self.attn = MMEncoderAttention(
231 num_heads=self.num_heads_per_partition,
232 head_size=self.head_dim,
233 + scale=self.scale,
234 prefix=f"{prefix}.attn",
235 multimodal_config=multimodal_config,
236 )
vllm/model_executor/models/tarsier.py
+9 -2
@@ -19,7 +19,7 @@ from transformers.models.llava import LlavaProcessor
19 from transformers.processing_utils import ProcessingKwargs, Unpack
20 from transformers.tokenization_utils_base import PreTokenizedInput, TextInput
21
22 -from vllm.config import VllmConfig
22 +from vllm.config import MultiModalConfig, VllmConfig
23 from vllm.model_executor.layers.activation import get_act_fn
24 from vllm.model_executor.layers.linear import ColumnParallelLinear, RowParallelLinear
25 from vllm.model_executor.layers.quantization import QuantizationConfig
@@ -346,6 +346,7 @@ def _build_tarsier_hf_processor(
346 def init_vision_tower_for_tarsier(
347 hf_config: TarsierHfConfig, # Use the Tarsier specific config protocol
348 quant_config: QuantizationConfig | None,
349 + multimodal_config: MultiModalConfig | None,
350 *,
351 require_post_norm: bool | None = None,
352 prefix: str = "",
@@ -377,6 +378,7 @@ def init_vision_tower_for_tarsier(
378 return CLIPVisionModel(
379 vision_config,
380 quant_config=quant_config,
381 + multimodal_config=multimodal_config,
382 num_hidden_layers_override=num_hidden_layers_to_init,
383 require_post_norm=require_post_norm,
384 prefix=prefix,
@@ -385,6 +387,7 @@ def init_vision_tower_for_tarsier(
387 return SiglipVisionModel(
388 vision_config,
389 quant_config=quant_config,
390 + multimodal_config=multimodal_config,
391 num_hidden_layers_override=num_hidden_layers_to_init,
392 require_post_norm=require_post_norm,
393 prefix=prefix,
@@ -414,12 +417,16 @@ class TarsierForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP)
417
418 def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
419 super().__init__()
420 +
421 config: TarsierHfConfig = vllm_config.model_config.hf_config
422 quant_config = vllm_config.quant_config
423 + multimodal_config = vllm_config.model_config.multimodal_config
424 +
425 self.config = config # Storing the Tarsier-specific HF config
426 self.vision_tower = init_vision_tower_for_tarsier(
427 config,
422 - quant_config,
428 + quant_config=quant_config,
429 + multimodal_config=multimodal_config,
430 require_post_norm=False,
431 prefix=maybe_prefix(prefix, "vision_tower"),
432 )