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 15, 03:30 UTC
[Core] [Bugfix] [Multimodal] Fix multimodal profiling and generation for SFT/PTQed models (#20058)
Signed-off-by: Kyle Sayers <kylesayrs@gmail.com>
Kyle Sayers committed
Jun 30, 2025 at 13:26 UTC
d8cf819a9a337a578b7dfc7642617921cc468c17
41 files changed
+207
-38
docs/contributing/model/multimodal.md
+7
@@ -538,11 +538,13 @@ return a schema of the tensors outputted by the HF processor that are related to
538
prompt: str,
539
mm_data: Mapping[str, object],
540
mm_kwargs: Mapping[str, object],
541
+ tok_kwargs: Mapping[str, object],
542
) -> BatchFeature:
543
processed_outputs = super()._call_hf_processor(
544
prompt=prompt,
545
mm_data=mm_data,
546
mm_kwargs=mm_kwargs,
547
+ tok_kwargs=tok_kwargs,
548
)
549
550
image_patches = processed_outputs.get("image_patches")
@@ -566,6 +568,11 @@ return a schema of the tensors outputted by the HF processor that are related to
568
Our [actual code](gh-file:vllm/model_executor/models/fuyu.py) has special handling
569
for text-only inputs to prevent unnecessary warnings from HF processor.
570
571
+ !!! note
572
+ The `_call_hf_processor` method specifies both `mm_kwargs` and `tok_kwargs` for
573
+ processing. `mm_kwargs` is used to both initialize and call the huggingface
574
+ processor, whereas `tok_kwargs` is only used to call the huggingface processor.
575
+
576
This lets us override [_get_mm_fields_config][vllm.multimodal.processing.BaseMultiModalProcessor._get_mm_fields_config] as follows:
577
578
```python
tests/multimodal/test_processing.py
+1
@@ -1086,6 +1086,7 @@ def test_hf_processor_kwargs(model_id, call_kwargs, expected_kwargs):
1086
prompt="",
1087
mm_data={},
1088
mm_kwargs=call_kwargs,
1089
+ tok_kwargs={},
1090
)
1091
1092
assert out_kwargs == expected_kwargs
vllm/entrypoints/llm.py
+8
@@ -481,6 +481,13 @@ class LLM:
481
# Use default sampling params.
482
sampling_params = self.get_default_sampling_params()
483
484
+ tokenization_kwargs: dict[str, Any] = {}
485
+ truncate_prompt_tokens = None
486
+ if isinstance(sampling_params, SamplingParams):
487
+ truncate_prompt_tokens = sampling_params.truncate_prompt_tokens
488
+ _validate_truncation_size(self.llm_engine.model_config.max_model_len,
489
+ truncate_prompt_tokens, tokenization_kwargs)
490
+
491
self._validate_and_add_requests(
492
prompts=parsed_prompts,
493
params=sampling_params,
@@ -488,6 +495,7 @@ class LLM:
495
lora_request=lora_request,
496
prompt_adapter_request=prompt_adapter_request,
497
guided_options=guided_options_request,
498
+ tokenization_kwargs=tokenization_kwargs,
499
priority=priority,
500
)
501
vllm/entrypoints/utils.py
+4
@@ -171,6 +171,10 @@ def _validate_truncation_size(
171
tokenization_kwargs["truncation"] = True
172
tokenization_kwargs["max_length"] = truncate_prompt_tokens
173
174
+ else:
175
+ if tokenization_kwargs is not None:
176
+ tokenization_kwargs["truncation"] = False
177
+
178
return truncate_prompt_tokens
179
180
vllm/inputs/preprocess.py
+22
-7
@@ -265,7 +265,8 @@ class InputPreprocessor:
265
prompt: Union[str, list[int]],
266
mm_data: MultiModalDataDict,
267
mm_processor_kwargs: Optional[Mapping[str, object]],
268
- lora_request: Optional[LoRARequest],
268
+ tokenization_kwargs: Optional[dict[str, Any]] = None,
269
+ lora_request: Optional[LoRARequest] = None,
270
return_mm_hashes: bool = False,
271
) -> MultiModalInputs:
272
"""
@@ -280,15 +281,19 @@ class InputPreprocessor:
281
if mm_processor_kwargs is None:
282
mm_processor_kwargs = {}
283
283
- return mm_processor.apply(prompt, mm_data, mm_processor_kwargs,
284
- return_mm_hashes)
284
+ return mm_processor.apply(prompt,
285
+ mm_data,
286
+ hf_processor_mm_kwargs=mm_processor_kwargs,
287
+ tokenization_kwargs=tokenization_kwargs,
288
+ return_mm_hashes=return_mm_hashes)
289
290
async def _process_multimodal_async(
291
self,
292
prompt: Union[str, list[int]],
293
mm_data: MultiModalDataDict,
294
mm_processor_kwargs: Optional[Mapping[str, object]],
291
- lora_request: Optional[LoRARequest],
295
+ tokenization_kwargs: Optional[dict[str, Any]] = None,
296
+ lora_request: Optional[LoRARequest] = None,
297
return_mm_hashes: bool = False,
298
) -> MultiModalInputs:
299
"""
@@ -302,8 +307,11 @@ class InputPreprocessor:
307
if mm_processor_kwargs is None:
308
mm_processor_kwargs = {}
309
305
- return mm_processor.apply(prompt, mm_data, mm_processor_kwargs,
306
- return_mm_hashes)
310
+ return mm_processor.apply(prompt,
311
+ mm_data,
312
+ hf_processor_mm_kwargs=mm_processor_kwargs,
313
+ tokenization_kwargs=tokenization_kwargs,
314
+ return_mm_hashes=return_mm_hashes)
315
316
def _process_embeds(
317
self,
@@ -338,6 +346,7 @@ class InputPreprocessor:
346
def _process_tokens(
347
self,
348
parsed_content: TokensPrompt,
349
+ tokenization_kwargs: Optional[dict[str, Any]] = None,
350
lora_request: Optional[LoRARequest] = None,
351
return_mm_hashes: bool = False,
352
) -> Union[TokenInputs, MultiModalInputs]:
@@ -350,6 +359,7 @@ class InputPreprocessor:
359
prompt_token_ids,
360
multi_modal_data,
361
parsed_content.get("mm_processor_kwargs"),
362
+ tokenization_kwargs=tokenization_kwargs,
363
lora_request=lora_request,
364
return_mm_hashes=return_mm_hashes,
365
)
@@ -367,6 +377,7 @@ class InputPreprocessor:
377
async def _process_tokens_async(
378
self,
379
parsed_content: TokensPrompt,
380
+ tokenization_kwargs: Optional[dict[str, Any]] = None,
381
lora_request: Optional[LoRARequest] = None,
382
return_mm_hashes: bool = False,
383
) -> Union[TokenInputs, MultiModalInputs]:
@@ -379,6 +390,7 @@ class InputPreprocessor:
390
prompt_token_ids,
391
multi_modal_data,
392
parsed_content.get("mm_processor_kwargs"),
393
+ tokenization_kwargs=tokenization_kwargs,
394
lora_request=lora_request,
395
return_mm_hashes=return_mm_hashes,
396
)
@@ -408,6 +420,7 @@ class InputPreprocessor:
420
prompt_text,
421
multi_modal_data,
422
parsed_content.get("mm_processor_kwargs"),
423
+ tokenization_kwargs=tokenization_kwargs,
424
lora_request=lora_request,
425
return_mm_hashes=return_mm_hashes,
426
)
@@ -442,6 +455,7 @@ class InputPreprocessor:
455
prompt_text,
456
multi_modal_data,
457
parsed_content.get("mm_processor_kwargs"),
458
+ tokenization_kwargs=tokenization_kwargs,
459
lora_request=lora_request,
460
return_mm_hashes=return_mm_hashes,
461
)
@@ -860,7 +874,8 @@ class InputPreprocessor:
874
"returned until they are supported on vLLM V1.")
875
# Encoder-decoder model requires special mapping of
876
# input prompts to encoder & decoder
863
- return self._process_encoder_decoder_prompt(prompt)
877
+ return self._process_encoder_decoder_prompt(
878
+ prompt, tokenization_kwargs)
879
880
if is_explicit_encoder_decoder_prompt(prompt):
881
raise ValueError("Cannot pass encoder-decoder prompt "
vllm/model_executor/models/aya_vision.py
+2
@@ -185,11 +185,13 @@ class AyaVisionMultiModalProcessor(
185
prompt: str,
186
mm_data: Mapping[str, object],
187
mm_kwargs: Mapping[str, object],
188
+ tok_kwargs: Mapping[str, object],
189
) -> BatchFeature:
190
processed_outputs = super()._call_hf_processor(
191
prompt,
192
mm_data,
193
mm_kwargs,
194
+ tok_kwargs,
195
)
196
hf_processor = self.info.get_hf_processor(**mm_kwargs)
197
image_processor = hf_processor.image_processor
vllm/model_executor/models/blip2.py
+2
@@ -454,6 +454,7 @@ class Blip2MultiModalProcessor(BaseMultiModalProcessor[Blip2ProcessingInfo]):
454
prompt: str,
455
mm_data: Mapping[str, object],
456
mm_kwargs: Mapping[str, object],
457
+ tok_kwargs: Mapping[str, object],
458
) -> BatchFeature:
459
if not mm_data:
460
# HF processor always adds placeholders even when there's no image
@@ -465,6 +466,7 @@ class Blip2MultiModalProcessor(BaseMultiModalProcessor[Blip2ProcessingInfo]):
466
prompt=prompt,
467
mm_data=mm_data,
468
mm_kwargs=mm_kwargs,
469
+ tok_kwargs=tok_kwargs,
470
)
471
472
def _get_mm_fields_config(
vllm/model_executor/models/chameleon.py
+2
@@ -107,6 +107,7 @@ class ChameleonMultiModalProcessor(
107
prompt: str,
108
mm_data: Mapping[str, object],
109
mm_kwargs: Mapping[str, object],
110
+ tok_kwargs: Mapping[str, object],
111
) -> BatchFeature:
112
if not mm_data:
113
prompt_ids = self.info.get_tokenizer().encode(prompt)
@@ -117,6 +118,7 @@ class ChameleonMultiModalProcessor(
118
prompt=prompt,
119
mm_data=mm_data,
120
mm_kwargs=mm_kwargs,
121
+ tok_kwargs=tok_kwargs,
122
)
123
124
def _apply_hf_processor_tokens_only(
vllm/model_executor/models/deepseek_vl2.py
+5
-1
@@ -204,12 +204,13 @@ class DeepseekVL2MultiModalProcessor(
204
prompt: str,
205
mm_data: Mapping[str, object],
206
mm_kwargs: Mapping[str, object],
207
+ tok_kwargs: Mapping[str, object],
208
) -> BatchFeature:
209
if mm_data:
210
processed_outputs = self.info.ctx.call_hf_processor(
211
self.info.get_hf_processor(**mm_kwargs),
212
dict(prompt=prompt, **mm_data),
212
- mm_kwargs,
213
+ dict(**mm_kwargs, **tok_kwargs),
214
)
215
pixel_values = processed_outputs["pixel_values"]
216
# split pixel values into patches corresponding to each image
@@ -278,6 +279,7 @@ class DeepseekVL2MultiModalProcessor(
279
prompt: Union[str, list[int]],
280
mm_data_items: MultiModalDataItems,
281
hf_processor_mm_kwargs: Mapping[str, object],
282
+ tokenization_kwargs: Mapping[str, object],
283
*,
284
return_mm_hashes: bool,
285
) -> tuple[list[int], MultiModalKwargs, Optional[MultiModalHashes], bool]:
@@ -290,6 +292,7 @@ class DeepseekVL2MultiModalProcessor(
292
prompt=prompt,
293
mm_data_items=mm_data_items,
294
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
295
+ tokenization_kwargs=tokenization_kwargs,
296
return_mm_hashes=return_mm_hashes,
297
)
298
@@ -297,6 +300,7 @@ class DeepseekVL2MultiModalProcessor(
300
prompt=prompt,
301
mm_data_items=mm_data_items,
302
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
303
+ tokenization_kwargs=tokenization_kwargs,
304
return_mm_hashes=return_mm_hashes,
305
)
306
vllm/model_executor/models/florence2.py
+3
-1
@@ -794,6 +794,7 @@ class Florence2MultiModalProcessor(
794
prompt_text: str,
795
mm_items: MultiModalDataItems,
796
hf_processor_mm_kwargs: Mapping[str, object],
797
+ tokenization_kwargs: Mapping[str, object],
798
) -> bool:
799
return False
800
@@ -828,10 +829,11 @@ class Florence2MultiModalProcessor(
829
prompt: str,
830
mm_data: Mapping[str, object],
831
mm_kwargs: Mapping[str, object],
832
+ tok_kwargs: Mapping[str, object],
833
) -> BatchFeature:
834
if mm_data:
835
processed_outputs = super()._call_hf_processor(
834
- prompt, mm_data, mm_kwargs)
836
+ prompt, mm_data, mm_kwargs, tok_kwargs)
837
else:
838
hf_processor = self.info.get_hf_processor()
839
tokenizer = hf_processor.tokenizer
vllm/model_executor/models/fuyu.py
+2
@@ -153,6 +153,7 @@ class FuyuMultiModalProcessor(BaseMultiModalProcessor[FuyuProcessingInfo]):
153
prompt: str,
154
mm_data: Mapping[str, object],
155
mm_kwargs: Mapping[str, object],
156
+ tok_kwargs: Mapping[str, object],
157
) -> BatchFeature:
158
if not mm_data:
159
# Avoid warning from HF logger for text-only input
@@ -164,6 +165,7 @@ class FuyuMultiModalProcessor(BaseMultiModalProcessor[FuyuProcessingInfo]):
165
prompt=prompt,
166
mm_data=mm_data,
167
mm_kwargs=mm_kwargs,
168
+ tok_kwargs=tok_kwargs,
169
)
170
171
image_patches = processed_outputs.get("image_patches")
vllm/model_executor/models/gemma3_mm.py
+2
@@ -259,11 +259,13 @@ class Gemma3MultiModalProcessor(BaseMultiModalProcessor[Gemma3ProcessingInfo]):
259
prompt: str,
260
mm_data: Mapping[str, object],
261
mm_kwargs: Mapping[str, object],
262
+ tok_kwargs: Mapping[str, object],
263
) -> BatchFeature:
264
processed_outputs = super()._call_hf_processor(
265
prompt,
266
mm_data,
267
mm_kwargs,
268
+ tok_kwargs,
269
)
270
271
# HF processor pops the `num_crops` kwarg, which is needed by vLLM
vllm/model_executor/models/glm4v.py
+1
@@ -481,6 +481,7 @@ class GLM4VMultiModalProcessor(BaseMultiModalProcessor[GLM4VProcessingInfo]):
481
prompt_text: str,
482
mm_items: MultiModalDataItems,
483
hf_processor_mm_kwargs: Mapping[str, object],
484
+ tokenization_kwargs: Mapping[str, object],
485
) -> bool:
486
return False
487
vllm/model_executor/models/granite_speech.py
+2
@@ -141,6 +141,7 @@ class GraniteSpeechMultiModalProcessor(
141
prompt: str,
142
mm_data: Mapping[str, object],
143
mm_kwargs: Mapping[str, object],
144
+ tok_kwargs: Mapping[str, object],
145
) -> BatchFeature:
146
mm_data = dict(mm_data)
147
audios = mm_data.pop("audios", [])
@@ -153,6 +154,7 @@ class GraniteSpeechMultiModalProcessor(
154
prompt=prompt,
155
mm_data=mm_data,
156
mm_kwargs=mm_kwargs,
157
+ tok_kwargs=tok_kwargs,
158
)
159
160
if "audio" in mm_data:
vllm/model_executor/models/h2ovl.py
+3
@@ -490,6 +490,7 @@ class H2OVLMultiModalProcessor(
490
prompt: Union[str, list[int]],
491
mm_data_items: MultiModalDataItems,
492
hf_processor_mm_kwargs: Mapping[str, object],
493
+ tokenization_kwargs: Mapping[str, object],
494
*,
495
return_mm_hashes: bool,
496
) -> tuple[list[int], MultiModalKwargs, Optional[MultiModalHashes], bool]:
@@ -502,6 +503,7 @@ class H2OVLMultiModalProcessor(
503
prompt=prompt,
504
mm_data_items=mm_data_items,
505
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
506
+ tokenization_kwargs=tokenization_kwargs,
507
return_mm_hashes=return_mm_hashes,
508
)
509
@@ -509,6 +511,7 @@ class H2OVLMultiModalProcessor(
511
prompt=prompt,
512
mm_data_items=mm_data_items,
513
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
514
+ tokenization_kwargs=tokenization_kwargs,
515
return_mm_hashes=return_mm_hashes,
516
)
517
vllm/model_executor/models/idefics3.py
+2
@@ -326,6 +326,7 @@ class Idefics3MultiModalProcessor(
326
prompt: str,
327
mm_data: Mapping[str, object],
328
mm_kwargs: Mapping[str, object],
329
+ tok_kwargs: Mapping[str, object],
330
) -> BatchFeature:
331
# Text-only input not supported in composite processor
332
if not (images := mm_data.get("images", [])):
@@ -337,6 +338,7 @@ class Idefics3MultiModalProcessor(
338
prompt,
339
mm_data,
340
mm_kwargs,
341
+ tok_kwargs,
342
)
343
344
parsed_images = (self._get_data_parser().parse_mm_data({
vllm/model_executor/models/internvl.py
+4
-1
@@ -758,11 +758,13 @@ class BaseInternVLMultiModalProcessor(BaseMultiModalProcessor[_I]):
758
prompt: str,
759
mm_data: Mapping[str, object],
760
mm_kwargs: Mapping[str, object],
761
+ tok_kwargs: Mapping[str, object],
762
) -> Mapping[str, NestedTensors]:
763
processed_outputs = super()._call_hf_processor(
764
prompt=prompt,
765
mm_data=mm_data,
766
mm_kwargs=mm_kwargs,
767
+ tok_kwargs=tok_kwargs,
768
)
769
770
hf_processor = self.info.get_hf_processor(**mm_kwargs)
@@ -941,9 +943,10 @@ class InternVLMultiModalProcessor(
943
prompt: str,
944
mm_data: Mapping[str, object],
945
mm_kwargs: Mapping[str, object],
946
+ tok_kwargs: Mapping[str, object],
947
) -> Mapping[str, NestedTensors]:
948
processed_outputs = super()._call_hf_processor(prompt, mm_data,
946
- mm_kwargs)
949
+ mm_kwargs, tok_kwargs)
950
951
hf_processor = self.info.get_hf_processor(**mm_kwargs)
952
if self.info.supports_video and (
vllm/model_executor/models/llava.py
+4
-1
@@ -296,11 +296,13 @@ class PixtralHFMultiModalProcessor(
296
prompt: str,
297
mm_data: Mapping[str, object],
298
mm_kwargs: Mapping[str, object],
299
+ tok_kwargs: Mapping[str, object],
300
) -> BatchFeature:
301
processed_outputs = super()._call_hf_processor(
302
prompt=prompt,
303
mm_data=mm_data,
304
mm_kwargs=mm_kwargs,
305
+ tok_kwargs=tok_kwargs,
306
)
307
308
pixel_values = processed_outputs.get("pixel_values")
@@ -797,6 +799,7 @@ class MantisMultiModalProcessor(LlavaMultiModalProcessor):
799
prompt: Union[str, list[int]],
800
mm_data: MultiModalDataDict,
801
hf_processor_mm_kwargs: Mapping[str, object],
802
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
803
return_mm_hashes: bool = False,
804
) -> MultiModalInputs:
805
hf_config = self.info.get_hf_config()
@@ -809,7 +812,7 @@ class MantisMultiModalProcessor(LlavaMultiModalProcessor):
812
)
813
814
result = super().apply(prompt, mm_data, hf_processor_mm_kwargs,
812
- return_mm_hashes)
815
+ tokenization_kwargs, return_mm_hashes)
816
817
mm_items = self._to_mm_items(mm_data)
818
mm_item_counts = mm_items.get_all_counts()
vllm/model_executor/models/llava_onevision.py
+7
@@ -286,6 +286,7 @@ class LlavaOnevisionMultiModalProcessor(
286
prompt: str,
287
mm_data: Mapping[str, object],
288
mm_kwargs: Mapping[str, object],
289
+ tok_kwargs: Mapping[str, object],
290
) -> BatchFeature:
291
mm_data = dict(mm_data)
292
videos = mm_data.pop("videos", [])
@@ -296,6 +297,7 @@ class LlavaOnevisionMultiModalProcessor(
297
prompt=prompt,
298
mm_data=mm_data,
299
mm_kwargs=mm_kwargs,
300
+ tok_kwargs=tok_kwargs,
301
)
302
303
# LLaVA-OneVision processor doesn't support multiple videos
@@ -310,6 +312,7 @@ class LlavaOnevisionMultiModalProcessor(
312
prompt=prompt,
313
mm_data={},
314
mm_kwargs=mm_kwargs,
315
+ tok_kwargs=tok_kwargs,
316
)
317
318
images = mm_data.pop("images", [])
@@ -319,6 +322,7 @@ class LlavaOnevisionMultiModalProcessor(
322
prompt=image_token * len(images),
323
mm_data={"images": images},
324
mm_kwargs=mm_kwargs,
325
+ tok_kwargs=tok_kwargs,
326
)
327
image_outputs = {
328
k: v
@@ -334,6 +338,7 @@ class LlavaOnevisionMultiModalProcessor(
338
prompt=video_token,
339
mm_data={"videos": video},
340
mm_kwargs=mm_kwargs,
341
+ tok_kwargs=tok_kwargs,
342
)
343
344
pixel_values_videos.append(item_outputs["pixel_values_videos"][0])
@@ -352,11 +357,13 @@ class LlavaOnevisionMultiModalProcessor(
357
prompt_text: str,
358
mm_items: MultiModalDataItems,
359
hf_processor_mm_kwargs: Mapping[str, object],
360
+ tokenization_kwargs: Mapping[str, object],
361
) -> bool:
362
base_result = super()._hf_processor_applies_updates(
363
prompt_text=prompt_text,
364
mm_items=mm_items,
365
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
366
+ tokenization_kwargs=tokenization_kwargs,
367
)
368
369
return base_result and mm_items.get_count("video", strict=False) == 0
vllm/model_executor/models/minicpmo.py
+6
-4
@@ -260,6 +260,7 @@ class MiniCPMOMultiModalProcessor(
260
self,
261
mm_data: Mapping[str, object],
262
mm_kwargs: Mapping[str, object],
263
+ tok_kwargs: Mapping[str, object],
264
) -> Mapping[str, NestedTensors]:
265
if (audios := mm_data.get("audios")) is None:
266
return {}
@@ -276,9 +277,9 @@ class MiniCPMOMultiModalProcessor(
277
prompts=[self.info.audio_pattern] * len(parsed_audios),
278
mm_data={"audios": [[audio] for audio in parsed_audios]},
279
mm_kwargs={
279
- **mm_kwargs,
280
- "chunk_input": True,
280
+ **mm_kwargs, "chunk_input": True
281
},
282
+ tok_kwargs=tok_kwargs,
283
out_keys={"audio_features", "audio_feature_lens"},
284
)
285
@@ -302,10 +303,11 @@ class MiniCPMOMultiModalProcessor(
303
self,
304
mm_data: Mapping[str, object],
305
mm_kwargs: Mapping[str, object],
306
+ tok_kwargs: Mapping[str, object],
307
) -> Mapping[str, NestedTensors]:
308
return {
307
- **super().process_mm_inputs(mm_data, mm_kwargs),
308
- **self.process_audios(mm_data, mm_kwargs),
309
+ **super().process_mm_inputs(mm_data, mm_kwargs, tok_kwargs),
310
+ **self.process_audios(mm_data, mm_kwargs, tok_kwargs),
311
}
312
313
def _get_prompt_updates(
vllm/model_executor/models/minicpmv.py
+14
-4
@@ -534,6 +534,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
534
self,
535
mm_data: Mapping[str, object],
536
mm_kwargs: Mapping[str, object],
537
+ tok_kwargs: Mapping[str, object],
538
) -> Mapping[str, NestedTensors]:
539
if (images := mm_data.get("images")) is None:
540
return {}
@@ -550,6 +551,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
551
prompts=[self.info.image_pattern] * len(parsed_images),
552
mm_data={"images": [[image] for image in parsed_images]},
553
mm_kwargs=mm_kwargs,
554
+ tok_kwargs=tok_kwargs,
555
out_keys={"pixel_values", "image_sizes", "tgt_sizes"},
556
)
557
@@ -563,6 +565,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
565
self,
566
mm_data: Mapping[str, object],
567
mm_kwargs: Mapping[str, object],
568
+ tok_kwargs: Mapping[str, object],
569
) -> Mapping[str, NestedTensors]:
570
if (videos := mm_data.get("videos")) is None:
571
return {}
@@ -586,6 +589,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
589
"max_slice_nums":
590
self.info.get_video_max_slice_num(),
591
},
592
+ tok_kwargs=tok_kwargs,
593
out_keys={"pixel_values", "image_sizes", "tgt_sizes"},
594
)
595
@@ -601,10 +605,11 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
605
self,
606
mm_data: Mapping[str, object],
607
mm_kwargs: Mapping[str, object],
608
+ tok_kwargs: Mapping[str, object],
609
) -> Mapping[str, NestedTensors]:
610
return {
606
- **self.process_images(mm_data, mm_kwargs),
607
- **self.process_videos(mm_data, mm_kwargs),
611
+ **self.process_images(mm_data, mm_kwargs, tok_kwargs),
612
+ **self.process_videos(mm_data, mm_kwargs, tok_kwargs),
613
}
614
615
def _base_call_hf_processor(
@@ -612,6 +617,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
617
prompts: list[str],
618
mm_data: Mapping[str, Sequence[object]],
619
mm_kwargs: Mapping[str, object],
620
+ tok_kwargs: Mapping[str, object],
621
*,
622
out_keys: set[str],
623
) -> dict[str, NestedTensors]:
@@ -621,6 +627,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
627
prompt=prompts, # type: ignore
628
mm_data=mm_data,
629
mm_kwargs=mm_kwargs,
630
+ tok_kwargs=tok_kwargs,
631
)
632
else:
633
inputs = defaultdict[str, list[torch.Tensor]](list)
@@ -633,6 +640,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
640
for k, v in mm_data.items()
641
},
642
mm_kwargs=mm_kwargs,
643
+ tok_kwargs=tok_kwargs,
644
)
645
646
for k, v in inputs_one.items():
@@ -646,11 +654,12 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
654
prompt: str,
655
mm_data: Mapping[str, object],
656
mm_kwargs: Mapping[str, object],
657
+ tok_kwargs: Mapping[str, object],
658
) -> BatchFeature:
659
tokenizer = self.info.get_tokenizer()
660
652
- input_ids = torch.tensor([tokenizer.encode(prompt)])
653
- mm_inputs = self.process_mm_inputs(mm_data, mm_kwargs)
661
+ input_ids = torch.tensor([tokenizer.encode(prompt, **tok_kwargs)])
662
+ mm_inputs = self.process_mm_inputs(mm_data, mm_kwargs, tok_kwargs)
663
664
return BatchFeature({
665
"input_ids": input_ids,
@@ -662,6 +671,7 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
671
prompt_text: str,
672
mm_items: MultiModalDataItems,
673
hf_processor_mm_kwargs: Mapping[str, object],
674
+ tokenization_kwargs: Mapping[str, object],
675
) -> bool:
676
return False
677
vllm/model_executor/models/minimax_vl_01.py
+2
@@ -113,11 +113,13 @@ class MiniMaxVL01MultiModalProcessor(
113
prompt: str,
114
mm_data: Mapping[str, object],
115
mm_kwargs: Mapping[str, object],
116
+ tok_kwargs: Mapping[str, object],
117
) -> BatchFeature:
118
processed_outputs = super()._call_hf_processor(
119
prompt=prompt,
120
mm_data=mm_data,
121
mm_kwargs=mm_kwargs,
122
+ tok_kwargs=tok_kwargs,
123
)
124
125
pixel_values = processed_outputs.get("pixel_values")
vllm/model_executor/models/mistral3.py
+2
@@ -228,11 +228,13 @@ class Mistral3MultiModalProcessor(
228
prompt: str,
229
mm_data: Mapping[str, object],
230
mm_kwargs: Mapping[str, object],
231
+ tok_kwargs: Mapping[str, object],
232
) -> BatchFeature:
233
processed_outputs = super()._call_hf_processor(
234
prompt=prompt,
235
mm_data=mm_data,
236
mm_kwargs=mm_kwargs,
237
+ tok_kwargs=tok_kwargs,
238
)
239
240
pixel_values = processed_outputs.get("pixel_values")
vllm/model_executor/models/mllama.py
+4
-2
@@ -166,10 +166,11 @@ class MllamaMultiModalProcessor(EncDecMultiModalProcessor[MllamaProcessingInfo]
166
prompt: Union[str, list[int]],
167
mm_data: MultiModalDataDict,
168
hf_processor_mm_kwargs: Mapping[str, object],
169
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
170
return_mm_hashes: bool = False,
171
) -> MultiModalEncDecInputs:
172
mm_inputs = super().apply(prompt, mm_data, hf_processor_mm_kwargs,
172
- return_mm_hashes)
173
+ tokenization_kwargs, return_mm_hashes)
174
175
image_token_id = self.info.get_hf_config().image_token_index
176
# Check that the number of image tokens in the decoder prompt matches
@@ -239,6 +240,7 @@ class MllamaMultiModalProcessor(EncDecMultiModalProcessor[MllamaProcessingInfo]
240
prompt: str,
241
mm_data: Mapping[str, object],
242
mm_kwargs: Mapping[str, object],
243
+ tok_kwargs: Mapping[str, object],
244
) -> BatchFeature:
245
tokenizer = self.info.get_tokenizer()
246
if mm_data:
@@ -247,7 +249,7 @@ class MllamaMultiModalProcessor(EncDecMultiModalProcessor[MllamaProcessingInfo]
249
for img in mm_data["images"]
250
]
251
processed_outputs = super()._call_hf_processor(
250
- prompt, mm_data, mm_kwargs)
252
+ prompt, mm_data, mm_kwargs, tok_kwargs)
253
processed_outputs["num_tiles"] = torch.tensor(num_tiles)
254
for k in ('pixel_values', 'aspect_ratio_ids', "aspect_ratio_mask"):
255
processed_outputs[k] = processed_outputs[k].squeeze(0)
vllm/model_executor/models/mllama4.py
+2
@@ -574,6 +574,7 @@ class Mllama4MultiModalProcessor(BaseMultiModalProcessor[Mllama4ProcessingInfo]
574
prompt: str,
575
mm_data: Mapping[str, object],
576
mm_kwargs: Mapping[str, object],
577
+ tok_kwargs: Mapping[str, object],
578
) -> BatchFeature:
579
tokenizer = self.info.get_tokenizer()
580
@@ -583,6 +584,7 @@ class Mllama4MultiModalProcessor(BaseMultiModalProcessor[Mllama4ProcessingInfo]
584
prompt=prompt,
585
mm_data=mm_data,
586
mm_kwargs=mm_kwargs,
587
+ tok_kwargs=tok_kwargs,
588
)
589
590
processor = self.info.get_hf_processor(**mm_kwargs)
vllm/model_executor/models/ovis.py
+2
@@ -335,6 +335,7 @@ class OvisMultiModalProcessor(BaseMultiModalProcessor[OvisProcessingInfo]):
335
prompt: str,
336
mm_data: Mapping[str, object],
337
mm_kwargs: Mapping[str, object],
338
+ tok_kwargs: Mapping[str, object],
339
) -> BatchFeature:
340
if not mm_data:
341
# Avoid warning from HF logger for text-only input
@@ -346,6 +347,7 @@ class OvisMultiModalProcessor(BaseMultiModalProcessor[OvisProcessingInfo]):
347
prompt=prompt,
348
mm_data=mm_data,
349
mm_kwargs=mm_kwargs,
350
+ tok_kwargs=tok_kwargs,
351
)
352
353
hf_processor = self.info.get_hf_processor()
vllm/model_executor/models/paligemma.py
+4
-1
@@ -121,6 +121,7 @@ class PaliGemmaMultiModalProcessor(
121
prompt: str,
122
mm_data: Mapping[str, object],
123
mm_kwargs: Mapping[str, object],
124
+ tok_kwargs: Mapping[str, object],
125
) -> BatchFeature:
126
tokenizer = self.info.get_tokenizer()
127
if not mm_data:
@@ -131,6 +132,7 @@ class PaliGemmaMultiModalProcessor(
132
prompt=prompt,
133
mm_data=mm_data,
134
mm_kwargs=mm_kwargs,
135
+ tok_kwargs=tok_kwargs,
136
)
137
138
def _get_mm_fields_config(
@@ -191,10 +193,11 @@ class PaliGemmaMultiModalProcessor(
193
prompt: Union[str, list[int]],
194
mm_data: MultiModalDataDict,
195
hf_processor_mm_kwargs: Mapping[str, object],
196
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
197
return_mm_hashes: bool = False,
198
) -> MultiModalInputs:
199
mm_inputs = super().apply(prompt, mm_data, hf_processor_mm_kwargs,
197
- return_mm_hashes)
200
+ tokenization_kwargs, return_mm_hashes)
201
prompt_token_ids = mm_inputs["prompt_token_ids"]
202
203
tokenizer = self.info.get_tokenizer()
vllm/model_executor/models/phi3v.py
+2
@@ -376,11 +376,13 @@ class Phi3VMultiModalProcessor(BaseMultiModalProcessor[Phi3VProcessingInfo]):
376
prompt: str,
377
mm_data: Mapping[str, object],
378
mm_kwargs: Mapping[str, object],
379
+ tok_kwargs: Mapping[str, object],
380
) -> BatchFeature:
381
processed_outputs = super()._call_hf_processor(
382
prompt=prompt,
383
mm_data=mm_data,
384
mm_kwargs=mm_kwargs,
385
+ tok_kwargs=tok_kwargs,
386
)
387
388
input_ids = processed_outputs["input_ids"]
vllm/model_executor/models/phi4mm.py
+2
-1
@@ -762,6 +762,7 @@ class Phi4MMMultiModalProcessor(BaseMultiModalProcessor[Phi4MMProcessingInfo]):
762
prompt: str,
763
mm_data: Mapping[str, object],
764
mm_kwargs: Mapping[str, object],
765
+ tok_kwargs: Mapping[str, object],
766
) -> BatchFeature:
767
if not mm_data:
768
prompt_ids = self.info.get_tokenizer().encode(prompt)
@@ -773,7 +774,7 @@ class Phi4MMMultiModalProcessor(BaseMultiModalProcessor[Phi4MMProcessingInfo]):
774
mm_data['audios'] = [(data, sr) for data in audio_data]
775
776
processed_outputs = super()._call_hf_processor(prompt, mm_data,
776
- mm_kwargs)
777
+ mm_kwargs, tok_kwargs)
778
779
num_img_tokens = [
780
self.info.get_num_image_tokens(image_width=img_size[0],
vllm/model_executor/models/pixtral.py
+6
-1
@@ -237,6 +237,7 @@ class PixtralDummyInputsBuilder(BaseDummyInputsBuilder[PixtralProcessingInfo]):
237
dummy_text = self.get_dummy_text(mm_counts)
238
dummy_mm_data = self.get_dummy_mm_data(seq_len, mm_counts)
239
dummy_images = dummy_mm_data.get("image", [])
240
+ tokenization_kwargs = {"truncation": False}
241
242
request = ChatCompletionRequest(messages=[
243
UserMessage(content=[
@@ -247,7 +248,9 @@ class PixtralDummyInputsBuilder(BaseDummyInputsBuilder[PixtralProcessingInfo]):
248
res = tokenizer.mistral.encode_chat_completion(request)
249
dummy_tokens = res.tokens
250
250
- return ProcessorInputs(prompt=dummy_tokens, mm_data=dummy_mm_data)
251
+ return ProcessorInputs(prompt=dummy_tokens,
252
+ mm_data=dummy_mm_data,
253
+ tokenization_kwargs=tokenization_kwargs)
254
255
256
class PixtralMultiModalProcessor(BaseMultiModalProcessor[PixtralProcessingInfo]
@@ -297,6 +300,7 @@ class PixtralMultiModalProcessor(BaseMultiModalProcessor[PixtralProcessingInfo]
300
prompt: Union[str, list[int]],
301
mm_data_items: MultiModalDataItems,
302
hf_processor_mm_kwargs: Mapping[str, object],
303
+ tokenization_kwargs: Mapping[str, object],
304
*,
305
return_mm_hashes: bool,
306
) -> tuple[list[int], MultiModalKwargs, Optional[MultiModalHashes], bool]:
@@ -309,6 +313,7 @@ class PixtralMultiModalProcessor(BaseMultiModalProcessor[PixtralProcessingInfo]
313
prompt=prompt,
314
mm_data_items=mm_data_items,
315
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
316
+ tokenization_kwargs=tokenization_kwargs,
317
return_mm_hashes=return_mm_hashes,
318
)
319
vllm/model_executor/models/prithvi_geospatial_mae.py
+1
@@ -92,6 +92,7 @@ class PrithviGeoSpatialMAEMultiModalProcessor(BaseMultiModalProcessor):
92
prompt: Union[str, list[int]],
93
mm_data: MultiModalDataDict,
94
hf_processor_mm_kwargs: Mapping[str, object],
95
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
96
return_mm_hashes: bool = False,
97
) -> MultiModalInputs:
98
mm_kwargs = {}
vllm/model_executor/models/qwen2_5_omni_thinker.py
+7
@@ -244,6 +244,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
244
prompt: str,
245
mm_data: Mapping[str, object],
246
mm_kwargs: Mapping[str, object],
247
+ tok_kwargs: Mapping[str, object],
248
) -> BatchFeature:
249
mm_data = dict(mm_data)
250
audios = mm_data.pop("audios", [])
@@ -258,6 +259,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
259
prompt=prompt,
260
mm_data=mm_data,
261
mm_kwargs=mm_kwargs,
262
+ tok_kwargs=tok_kwargs,
263
)
264
265
input_features = hf_inputs.pop('input_features', None)
@@ -453,6 +455,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
455
prompt: Union[str, list[int]],
456
mm_items: MultiModalDataItems,
457
hf_processor_mm_kwargs: Mapping[str, object],
458
+ tokenization_kwargs: Mapping[str, object],
459
*,
460
enable_hf_prompt_update: bool,
461
) -> tuple[list[int], MultiModalKwargs, bool]:
@@ -465,6 +468,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
468
prompt_text=prompt,
469
mm_items=mm_items,
470
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
471
+ tokenization_kwargs=tokenization_kwargs,
472
)
473
tokenizer = self.info.get_tokenizer()
474
prompt_ids = encode_tokens(tokenizer, prompt)
@@ -474,6 +478,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
478
mm_kwargs = self._apply_hf_processor_mm_only(
479
mm_items=mm_items,
480
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
481
+ tokenization_kwargs=tokenization_kwargs,
482
)
483
484
return prompt_ids, mm_kwargs, False
@@ -482,6 +487,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
487
self,
488
mm_items: MultiModalDataItems,
489
hf_processor_mm_kwargs: Mapping[str, object],
490
+ tokenization_kwargs: Mapping[str, object],
491
) -> MultiModalKwargs:
492
"""
493
Qwen2.5-Omni reimplements this function to handle `use_audio_in_video`.
@@ -498,6 +504,7 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
504
prompt_text=self.dummy_inputs.get_dummy_text(mm_counts),
505
mm_items=mm_items,
506
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
507
+ tokenization_kwargs=tokenization_kwargs,
508
)
509
510
return mm_kwargs
vllm/model_executor/models/qwen2_audio.py
+2
@@ -150,6 +150,7 @@ class Qwen2AudioMultiModalProcessor(
150
prompt: str,
151
mm_data: Mapping[str, object],
152
mm_kwargs: Mapping[str, Any],
153
+ tok_kwargs: Mapping[str, object],
154
) -> BatchFeature:
155
# NOTE - we rename audios -> audio in mm data because transformers has
156
# deprecated audios for the qwen2audio processor and will remove
@@ -174,6 +175,7 @@ class Qwen2AudioMultiModalProcessor(
175
prompt=prompt,
176
mm_data=mm_data,
177
mm_kwargs=mm_kwargs,
178
+ tok_kwargs=tok_kwargs,
179
)
180
181
def _get_mm_fields_config(
vllm/model_executor/models/qwen2_vl.py
+3
-1
@@ -1027,11 +1027,13 @@ class Qwen2VLMultiModalProcessor(BaseMultiModalProcessor[Qwen2VLProcessingInfo]
1027
prompt: str,
1028
mm_data: Mapping[str, object],
1029
mm_kwargs: Mapping[str, object],
1030
+ tok_kwargs: Mapping[str, object],
1031
) -> BatchFeature:
1032
+ mm_kwargs = self.info._get_image_processor_kwargs(**mm_kwargs)
1033
return self.info.ctx.call_hf_processor(
1034
self.info.get_hf_processor(**mm_kwargs),
1035
dict(text=prompt, **mm_data),
1034
- self.info._get_image_processor_kwargs(**mm_kwargs),
1036
+ dict(**mm_kwargs, **tok_kwargs),
1037
)
1038
1039
def _get_prompt_updates(
vllm/model_executor/models/qwen_vl.py
+3
@@ -580,6 +580,7 @@ class QwenVLMultiModalProcessor(BaseMultiModalProcessor[QwenVLProcessingInfo]):
580
prompt: str,
581
mm_data: Mapping[str, object],
582
mm_kwargs: Mapping[str, object],
583
+ tok_kwargs: Mapping[str, object],
584
) -> BatchFeature:
585
# Drops anything between <img>/</img> tags; encoding with the tokenizer
586
# will automatically add the image pads for the context.
@@ -600,6 +601,7 @@ class QwenVLMultiModalProcessor(BaseMultiModalProcessor[QwenVLProcessingInfo]):
601
prompt=prompt,
602
mm_data=mm_data,
603
mm_kwargs=mm_kwargs,
604
+ tok_kwargs=tok_kwargs,
605
)
606
607
def _hf_processor_applies_updates(
@@ -607,6 +609,7 @@ class QwenVLMultiModalProcessor(BaseMultiModalProcessor[QwenVLProcessingInfo]):
609
prompt_text: str,
610
mm_items: MultiModalDataItems,
611
hf_processor_mm_kwargs: Mapping[str, object],
612
+ tokenization_kwargs: Mapping[str, object],
613
) -> bool:
614
return False
615
vllm/model_executor/models/skyworkr1v.py
+2
@@ -534,11 +534,13 @@ class SkyworkR1VMultiModalProcessor(BaseMultiModalProcessor[_I]):
534
prompt: str,
535
mm_data: Mapping[str, object],
536
mm_kwargs: Mapping[str, object],
537
+ tok_kwargs: Mapping[str, object],
538
) -> Mapping[str, NestedTensors]:
539
processed_outputs = super()._call_hf_processor(
540
prompt=prompt,
541
mm_data=mm_data,
542
mm_kwargs=mm_kwargs,
543
+ tok_kwargs=tok_kwargs,
544
)
545
546
hf_processor = self.info.get_hf_processor(**mm_kwargs)
vllm/model_executor/models/ultravox.py
+6
@@ -144,6 +144,7 @@ class UltravoxMultiModalProcessor(
144
prompt: str,
145
mm_data: Mapping[str, object],
146
mm_kwargs: Mapping[str, object],
147
+ tok_kwargs: Mapping[str, object],
148
) -> BatchFeature:
149
# Text-only input not supported in composite processor
150
if not mm_data.get("audios", []):
@@ -165,10 +166,15 @@ class UltravoxMultiModalProcessor(
166
167
item_processor_data = dict(**mm_data, audios=audios)
168
169
+ # some tokenizer kwargs are incompatible with UltravoxProcessor
170
+ tok_kwargs.pop("padding", None)
171
+ tok_kwargs.pop("truncation", None)
172
+
173
output = super()._call_hf_processor(
174
prompt=prompt,
175
mm_data=item_processor_data,
176
mm_kwargs=mm_kwargs,
177
+ tok_kwargs=tok_kwargs,
178
)
179
output['audio_features'] = output.pop('audio_values')
180
vllm/model_executor/models/whisper.py
+3
-1
@@ -700,9 +700,10 @@ class WhisperMultiModalProcessor(
700
prompt: str,
701
mm_data: Mapping[str, object],
702
mm_kwargs: Mapping[str, object],
703
+ tok_kwargs: Mapping[str, object],
704
) -> BatchFeature:
705
if mm_data:
705
- feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
706
+ feature_extractor = self.info.get_feature_extractor()
707
mm_data = dict(audio=mm_data.pop("audios"))
708
mm_kwargs = dict(
709
**mm_kwargs,
@@ -712,6 +713,7 @@ class WhisperMultiModalProcessor(
713
prompt=prompt,
714
mm_data=mm_data,
715
mm_kwargs=mm_kwargs,
716
+ tok_kwargs=tok_kwargs,
717
)
718
if "labels" in processed_outputs:
719
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/multimodal/processing.py
+43
-11
@@ -1267,6 +1267,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1267
# This refers to the data to be passed to HF processor.
1268
mm_data: Mapping[str, object],
1269
mm_kwargs: Mapping[str, object],
1270
+ tok_kwargs: Mapping[str, object],
1271
) -> "BatchFeature":
1272
"""
1273
Call the HF processor on the prompt text and
@@ -1275,7 +1276,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1276
return self.info.ctx.call_hf_processor(
1277
self.info.get_hf_processor(**mm_kwargs),
1278
dict(text=prompt, **mm_data),
1278
- mm_kwargs,
1279
+ dict(**mm_kwargs, **tok_kwargs),
1280
)
1281
1282
def _hf_processor_applies_updates(
@@ -1283,6 +1284,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1284
prompt_text: str,
1285
mm_items: MultiModalDataItems,
1286
hf_processor_mm_kwargs: Mapping[str, object],
1287
+ tokenization_kwargs: Mapping[str, object],
1288
) -> bool:
1289
"""
1290
Return whether the HF processor applies prompt updates.
@@ -1300,6 +1302,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1302
prompt_text: str,
1303
mm_items: MultiModalDataItems,
1304
hf_processor_mm_kwargs: Mapping[str, object],
1305
+ tokenization_kwargs: Mapping[str, object],
1306
) -> tuple[list[int], MultiModalKwargs, bool]:
1307
"""
1308
Apply the HF processor on the prompt text and multi-modal data
@@ -1313,6 +1316,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1316
prompt=prompt_text,
1317
mm_data=processor_data,
1318
mm_kwargs=hf_processor_mm_kwargs,
1319
+ tok_kwargs=tokenization_kwargs,
1320
)
1321
processed_data.update(passthrough_data)
1322
@@ -1327,11 +1331,14 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1331
prompt_text=prompt_text,
1332
mm_items=mm_items,
1333
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1334
+ tokenization_kwargs=tokenization_kwargs,
1335
)
1336
1337
return prompt_ids, mm_kwargs, is_update_applied
1338
1334
- def _apply_hf_processor_text_only(self, prompt_text: str) -> list[int]:
1339
+ def _apply_hf_processor_text_only(
1340
+ self, prompt_text: str,
1341
+ tokenization_kwargs: Mapping[str, object]) -> list[int]:
1342
"""
1343
Apply the HF processor on the prompt text only.
1344
@@ -1343,6 +1350,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1350
prompt_text=prompt_text,
1351
mm_items=MultiModalDataItems({}),
1352
hf_processor_mm_kwargs={},
1353
+ tokenization_kwargs=tokenization_kwargs,
1354
)
1355
1356
return prompt_ids
@@ -1368,6 +1376,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1376
self,
1377
mm_items: MultiModalDataItems,
1378
hf_processor_mm_kwargs: Mapping[str, object],
1379
+ tokenization_kwargs: Mapping[str, object],
1380
) -> MultiModalKwargs:
1381
"""
1382
Apply the HF processor on the multi-modal data only.
@@ -1383,6 +1392,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1392
prompt_text=self.dummy_inputs.get_dummy_text(mm_counts),
1393
mm_items=mm_items,
1394
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1395
+ tokenization_kwargs=tokenization_kwargs,
1396
)
1397
1398
return mm_kwargs
@@ -1392,6 +1402,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1402
prompt: Union[str, list[int]],
1403
mm_items: MultiModalDataItems,
1404
hf_processor_mm_kwargs: Mapping[str, object],
1405
+ tokenization_kwargs: Mapping[str, object],
1406
*,
1407
enable_hf_prompt_update: bool,
1408
) -> tuple[list[int], MultiModalKwargs, bool]:
@@ -1412,15 +1423,18 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1423
prompt_text=prompt,
1424
mm_items=mm_items,
1425
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1426
+ tokenization_kwargs=tokenization_kwargs,
1427
)
1428
1417
- prompt_ids = self._apply_hf_processor_text_only(prompt)
1429
+ prompt_ids = self._apply_hf_processor_text_only(
1430
+ prompt, tokenization_kwargs)
1431
else:
1432
prompt_ids = self._apply_hf_processor_tokens_only(prompt)
1433
1434
mm_kwargs = self._apply_hf_processor_mm_only(
1435
mm_items=mm_items,
1436
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1437
+ tokenization_kwargs=tokenization_kwargs,
1438
)
1439
1440
return prompt_ids, mm_kwargs, False
@@ -1430,14 +1444,17 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1444
cache: ProcessingCache,
1445
mm_data_items: MultiModalDataItems,
1446
hf_processor_mm_kwargs: Mapping[str, object],
1447
+ tokenization_kwargs: Mapping[str, object],
1448
) -> tuple[dict[str, list[ProcessingCacheOptionalItem]], dict[
1449
str, list[object]]]:
1450
model_id = self.info.model_id
1451
1452
mm_cache_items = {
1453
modality: [
1439
- cache.get_item(model_id, modality, item,
1440
- hf_processor_mm_kwargs) for item in items
1454
+ cache.get_item(
1455
+ model_id, modality, item,
1456
+ dict(**hf_processor_mm_kwargs, **tokenization_kwargs))
1457
+ for item in items
1458
]
1459
for modality, items in mm_data_items.items()
1460
}
@@ -1457,10 +1474,9 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1474
return mm_cache_items, mm_missing_data
1475
1476
def _hash_mm_items(
1460
- self,
1461
- mm_items: MultiModalDataItems,
1462
- hf_processor_mm_kwargs: Mapping[str, object],
1463
- ) -> MultiModalHashes:
1477
+ self, mm_items: MultiModalDataItems,
1478
+ hf_processor_mm_kwargs: Mapping[str, object],
1479
+ tokenization_kwargs: Mapping[str, object]) -> MultiModalHashes:
1480
"""Create MM hashes to be returned (only used in V1)."""
1481
model_id = self.info.model_id
1482
@@ -1468,7 +1484,8 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1484
modality: [
1485
MultiModalHasher.hash_kwargs(model_id=model_id,
1486
**{modality: item},
1471
- **hf_processor_mm_kwargs)
1487
+ **hf_processor_mm_kwargs,
1488
+ **tokenization_kwargs)
1489
for item in items
1490
]
1491
for modality, items in mm_items.items()
@@ -1513,6 +1530,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1530
prompt: Union[str, list[int]],
1531
mm_data_items: MultiModalDataItems,
1532
hf_processor_mm_kwargs: Mapping[str, object],
1533
+ tokenization_kwargs: Mapping[str, object],
1534
*,
1535
return_mm_hashes: bool,
1536
) -> tuple[list[int], MultiModalKwargs, Optional[MultiModalHashes], bool]:
@@ -1524,10 +1542,12 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1542
prompt=prompt,
1543
mm_items=mm_data_items,
1544
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1545
+ tokenization_kwargs=tokenization_kwargs,
1546
enable_hf_prompt_update=True,
1547
)
1548
1530
- mm_hashes = (self._hash_mm_items(mm_data_items, hf_processor_mm_kwargs)
1549
+ mm_hashes = (self._hash_mm_items(mm_data_items, hf_processor_mm_kwargs,
1550
+ tokenization_kwargs)
1551
if return_mm_hashes else None)
1552
1553
return prompt_ids, mm_kwargs, mm_hashes, is_update_applied
@@ -1537,6 +1557,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1557
prompt: Union[str, list[int]],
1558
mm_data_items: MultiModalDataItems,
1559
hf_processor_mm_kwargs: Mapping[str, object],
1560
+ tokenization_kwargs: Mapping[str, object],
1561
*,
1562
return_mm_hashes: bool,
1563
) -> tuple[list[int], MultiModalKwargs, Optional[MultiModalHashes], bool]:
@@ -1552,6 +1573,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1573
prompt=prompt,
1574
mm_data_items=mm_data_items,
1575
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1576
+ tokenization_kwargs=tokenization_kwargs,
1577
return_mm_hashes=return_mm_hashes,
1578
)
1579
@@ -1562,6 +1584,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1584
cache=cache,
1585
mm_data_items=mm_data_items,
1586
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1587
+ tokenization_kwargs=tokenization_kwargs,
1588
)
1589
1590
# NOTE: `prompt` does not correspond to `mm_missing_data_items`,
@@ -1575,6 +1598,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1598
prompt=prompt,
1599
mm_items=self._to_mm_items(mm_missing_data),
1600
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1601
+ tokenization_kwargs=tokenization_kwargs,
1602
enable_hf_prompt_update=False,
1603
)
1604
@@ -1783,6 +1807,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1807
prompt: Union[str, list[int]],
1808
mm_data: MultiModalDataDict,
1809
hf_processor_mm_kwargs: Mapping[str, object],
1810
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
1811
return_mm_hashes: bool = False,
1812
) -> MultiModalInputs:
1813
"""
@@ -1800,6 +1825,9 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1825
"""
1826
mm_items = self._to_mm_items(mm_data)
1827
1828
+ if tokenization_kwargs is None:
1829
+ tokenization_kwargs = {}
1830
+
1831
(
1832
prompt_ids,
1833
mm_kwargs,
@@ -1809,9 +1837,11 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1837
prompt,
1838
mm_items,
1839
hf_processor_mm_kwargs,
1840
+ tokenization_kwargs=tokenization_kwargs,
1841
return_mm_hashes=return_mm_hashes,
1842
)
1843
1844
+ # NOTE: tokenization_kwargs are not required to init processor
1845
prompt_ids, prompt, mm_placeholders = self._maybe_apply_prompt_updates(
1846
mm_items=mm_items,
1847
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
@@ -1892,6 +1922,7 @@ class EncDecMultiModalProcessor(BaseMultiModalProcessor[_I]):
1922
prompt: Union[str, list[int]],
1923
mm_data: MultiModalDataDict,
1924
hf_processor_mm_kwargs: Mapping[str, object],
1925
+ tokenization_kwargs: Optional[Mapping[str, object]] = None,
1926
return_mm_hashes: bool = False,
1927
) -> MultiModalEncDecInputs:
1928
"""
@@ -1906,6 +1937,7 @@ class EncDecMultiModalProcessor(BaseMultiModalProcessor[_I]):
1937
encoder_prompt,
1938
mm_data,
1939
hf_processor_mm_kwargs,
1940
+ tokenization_kwargs,
1941
return_mm_hashes,
1942
)
1943
vllm/multimodal/profiling.py
+6
-1
@@ -30,6 +30,7 @@ class ProcessorInputs:
30
prompt: Union[str, list[int]]
31
mm_data: MultiModalDataDict
32
hf_processor_mm_kwargs: Mapping[str, object] = field(default_factory=dict)
33
+ tokenization_kwargs: Mapping[str, object] = field(default_factory=dict)
34
35
36
class DummyEncoderData(NamedTuple):
@@ -90,8 +91,11 @@ class BaseDummyInputsBuilder(ABC, Generic[_I]):
91
"""
92
dummy_text = self.get_dummy_text(mm_counts)
93
dummy_mm_data = self.get_dummy_mm_data(seq_len, mm_counts)
94
+ tokenization_kwargs = {"truncation": False}
95
94
- return ProcessorInputs(prompt=dummy_text, mm_data=dummy_mm_data)
96
+ return ProcessorInputs(prompt=dummy_text,
97
+ mm_data=dummy_mm_data,
98
+ tokenization_kwargs=tokenization_kwargs)
99
100
def _get_dummy_audios(
101
self,
@@ -170,6 +174,7 @@ class MultiModalProfiler(Generic[_I]):
174
prompt=processor_inputs.prompt,
175
mm_data=processor_inputs.mm_data,
176
hf_processor_mm_kwargs=processor_inputs.hf_processor_mm_kwargs,
177
+ tokenization_kwargs=processor_inputs.tokenization_kwargs,
178
)
179
180
def _get_mm_num_tokens(
vllm/utils.py
+2
@@ -1729,6 +1729,7 @@ def supports_kw(
1729
last_param = params[next(reversed(params))] # type: ignore
1730
return (last_param.kind == inspect.Parameter.VAR_KEYWORD
1731
and last_param.name != kw_name)
1732
+
1733
return False
1734
1735
@@ -1771,6 +1772,7 @@ def resolve_mm_processor_kwargs(
1772
# Merge the final processor kwargs, prioritizing inference
1773
# time values over the initialization time values.
1774
mm_processor_kwargs = {**init_mm_kwargs, **runtime_mm_kwargs}
1775
+
1776
return mm_processor_kwargs
1777
1778