[MM] Remove text components from ProcessorInputs (#53093)
Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>
Cyrus Leung committed
Aug 21, 2026 at 11:42 UTC
b00f475f09b7d54e811efc006cab2562d3b23893
92 files changed
+220
-806
docs/contributing/model/multimodal.md
-7
@@ -456,13 +456,11 @@ return a schema of the tensors outputted by the HF processor that are related to
456
prompt: str,
457
mm_data: Mapping[str, object],
458
mm_kwargs: Mapping[str, object],
459
- tok_kwargs: Mapping[str, object],
459
) -> BatchFeature:
460
processed_outputs = super()._call_hf_processor(
461
prompt=prompt,
462
mm_data=mm_data,
463
mm_kwargs=mm_kwargs,
465
- tok_kwargs=tok_kwargs,
464
)
465
466
pixel_values = processed_outputs.get("pixel_values")
@@ -479,11 +477,6 @@ return a schema of the tensors outputted by the HF processor that are related to
477
return processed_outputs
478
```
479
482
- !!! note
483
- The `_call_hf_processor` method specifies both `mm_kwargs` and `tok_kwargs` for
484
- processing. `mm_kwargs` is used to both initialize and call the huggingface
485
- processor, whereas `tok_kwargs` is only used to call the huggingface processor.
486
-
480
Since `pixel_values` is now a list with one tensor per image, we can override
481
[_get_mm_fields_config][vllm.multimodal.processing.BaseMultiModalProcessor._get_mm_fields_config] as follows:
482
tests/models/multimodal/processing/test_audioflamingo3.py
+1
-1
@@ -107,7 +107,7 @@ def test_audio_chunk_counting(mock_ctx):
107
mm_data = {"audio": [audio_1, audio_2]}
108
prompt = "<|user|>Listen.<|end|>"
109
110
- processed = processor._call_hf_processor(prompt, mm_data, {}, {})
110
+ processed = processor._call_hf_processor(prompt, mm_data, {})
111
112
chunk_counts = processed["chunk_counts"]
113
tests/models/multimodal/processing/test_common.py
+6
-62
@@ -145,10 +145,10 @@ def get_transformers_backend_model_ids_to_test():
145
)
146
147
148
-def get_text_token_prompts(
148
+def get_token_prompt(
149
processor: BaseMultiModalProcessor,
150
mm_data: MultiModalDataDict,
151
-):
151
+) -> list[int]:
152
dummy_inputs = processor.dummy_inputs
153
tokenizer: TokenizerLike = processor.info.get_tokenizer()
154
model_config = processor.info.ctx.model_config
@@ -178,21 +178,10 @@ def get_text_token_prompts(
178
mm_options={},
179
)
180
181
- text_prompt: str | None
182
- token_prompt: list[int]
183
- if isinstance(inputs.prompt, list):
184
- text_prompt = None
185
- token_prompt = inputs.prompt
186
- elif isinstance(inputs.prompt, str):
187
- text_prompt = inputs.prompt
188
- token_prompt = tokenizer.encode(
189
- text_prompt,
190
- **processor.info.get_default_tok_params().get_encode_kwargs(),
191
- )
192
- else:
181
+ if not isinstance(inputs.prompt, list):
182
raise TypeError(type(inputs.prompt))
183
195
- return text_prompt, token_prompt
184
+ return inputs.prompt
185
186
187
def random_vision_chunk(
@@ -358,7 +347,7 @@ def _test_processing_correctness_one(
347
):
348
model_type = model_config.hf_config.model_type
349
361
- text_prompt, token_prompt = get_text_token_prompts(baseline_processor, mm_data)
350
+ token_prompt = get_token_prompt(baseline_processor, mm_data)
351
mm_items = baseline_processor.info.parse_mm_data(mm_data)
352
ignore_mm_keys = _IGNORE_MM_KEYS.get(model_type, set[str]())
353
@@ -381,55 +370,10 @@ def _test_processing_correctness_one(
370
msg=(
371
f"Failed ({batch_idx=}, {hit_rate=}, "
372
f"{num_batches=}, {simplify_rate=}, "
384
- f"{text_prompt=}, {token_prompt=}, {mm_data=})"
373
+ f"{token_prompt=}, {mm_data=})"
374
),
375
)
376
388
- if text_prompt is not None:
389
- baseline_text_result = baseline_processor(
390
- text_prompt,
391
- mm_items=mm_items,
392
- hf_processor_mm_kwargs={},
393
- )
394
- cached_text_result = cached_processor(
395
- text_prompt,
396
- mm_items=mm_items,
397
- hf_processor_mm_kwargs={},
398
- )
399
-
400
- _assert_inputs_equal(
401
- baseline_text_result,
402
- cached_text_result,
403
- ignore_mm_keys=ignore_mm_keys,
404
- msg=(
405
- f"Failed ({batch_idx=}, {hit_rate=}, "
406
- f"{num_batches=}, {simplify_rate=}, "
407
- f"{text_prompt=}, {token_prompt=}, {mm_data=})"
408
- ),
409
- )
410
-
411
- _assert_inputs_equal(
412
- baseline_text_result,
413
- baseline_tokenized_result,
414
- ignore_mm_keys=ignore_mm_keys,
415
- msg=(
416
- f"Failed ({batch_idx=}, {hit_rate=}, "
417
- f"{num_batches=}, {simplify_rate=}, "
418
- f"{text_prompt=}, {token_prompt=}, {mm_data=})"
419
- ),
420
- )
421
-
422
- _assert_inputs_equal(
423
- cached_text_result,
424
- cached_tokenized_result,
425
- ignore_mm_keys=ignore_mm_keys,
426
- msg=(
427
- f"Failed ({batch_idx=}, {hit_rate=}, "
428
- f"{num_batches=}, {simplify_rate=}, "
429
- f"{text_prompt=}, {token_prompt=}, {mm_data=})"
430
- ),
431
- )
432
-
377
378
@pytest.mark.parametrize("model_id", get_model_ids_to_test())
379
@pytest.mark.parametrize("hit_rate", [0.3, 0.5, 1.0])
tests/models/multimodal/processing/test_llava_next.py
+17
-2
@@ -11,6 +11,7 @@ from pqdm.threads import pqdm
11
from vllm.multimodal import MULTIMODAL_REGISTRY
12
from vllm.multimodal.parse import ImageSize
13
from vllm.multimodal.processing import BaseMultiModalProcessor
14
+from vllm.tokenizers.hf import maybe_make_thread_pool
15
16
from ...utils import build_model_context
17
@@ -144,7 +145,14 @@ def test_processor_prompt_replacements_regression(model_id, num_imgs):
145
mm_processor_kwargs=None,
146
limit_mm_per_prompt={"image": num_imgs},
147
)
147
- processor = MULTIMODAL_REGISTRY.create_processor(ctx.model_config)
148
+
149
+ # Avoid tokenizer already borrowed error
150
+ maybe_make_thread_pool(ctx.tokenizer)
151
+
152
+ processor = MULTIMODAL_REGISTRY.create_processor(
153
+ ctx.model_config,
154
+ tokenizer=ctx.tokenizer,
155
+ )
156
157
image_ratios = [
158
(171, 152),
@@ -177,7 +185,14 @@ def test_processor_prompt_replacements_all(model_id, num_imgs):
185
mm_processor_kwargs=None,
186
limit_mm_per_prompt={"image": num_imgs},
187
)
180
- processor = MULTIMODAL_REGISTRY.create_processor(ctx.model_config)
188
+
189
+ # Avoid tokenizer already borrowed error
190
+ maybe_make_thread_pool(ctx.tokenizer)
191
+
192
+ processor = MULTIMODAL_REGISTRY.create_processor(
193
+ ctx.model_config,
194
+ tokenizer=ctx.tokenizer,
195
+ )
196
197
seen_aspect_ratios = set[float]()
198
image_sizes = list[ImageSize]()
tests/models/multimodal/processing/test_llava_onevision.py
+18
-2
@@ -11,6 +11,7 @@ from pqdm.threads import pqdm
11
from vllm.multimodal import MULTIMODAL_REGISTRY
12
from vllm.multimodal.parse import ImageSize
13
from vllm.multimodal.processing import BaseMultiModalProcessor
14
+from vllm.tokenizers.hf import maybe_make_thread_pool
15
16
from ...utils import build_model_context
17
@@ -42,7 +43,15 @@ def test_processor_max_tokens(model_id):
43
mm_processor_kwargs=None,
44
limit_mm_per_prompt={"image": 1},
45
)
45
- processor = MULTIMODAL_REGISTRY.create_processor(ctx.model_config)
46
+
47
+ # Avoid tokenizer already borrowed error
48
+ maybe_make_thread_pool(ctx.tokenizer)
49
+
50
+ processor = MULTIMODAL_REGISTRY.create_processor(
51
+ ctx.model_config,
52
+ tokenizer=ctx.tokenizer,
53
+ )
54
+
55
info = processor.info
56
57
seen_aspect_ratios = set[float]()
@@ -142,7 +151,14 @@ def test_processor_prompt_replacements_regression(model_id, num_imgs):
151
mm_processor_kwargs=None,
152
limit_mm_per_prompt={"image": num_imgs},
153
)
145
- processor = MULTIMODAL_REGISTRY.create_processor(ctx.model_config)
154
+
155
+ # Avoid tokenizer already borrowed error
156
+ maybe_make_thread_pool(ctx.tokenizer)
157
+
158
+ processor = MULTIMODAL_REGISTRY.create_processor(
159
+ ctx.model_config,
160
+ tokenizer=ctx.tokenizer,
161
+ )
162
163
image_ratios = [
164
(171, 152),
tests/models/multimodal/processing/test_moss_audio.py
+1
-3
@@ -35,12 +35,10 @@ from vllm.sequence import IntermediateTensors
35
36
37
class _Tokenizer:
38
- def encode(self, text, add_special_tokens=False):
39
- del add_special_tokens
38
+ def encode(self, text, **kwargs):
39
return [ord(char) for char in text]
40
41
def decode(self, token_ids, **kwargs):
43
- del kwargs
42
return "".join(chr(token_id) for token_id in token_ids)
43
44
def batch_decode(self, batch_token_ids, **kwargs):
tests/models/multimodal/processing/test_openvla.py
-5
@@ -185,11 +185,6 @@ def test_openvla_prompt_update_inserts_image_tokens_after_bos() -> None:
185
image = Image.new("RGB", (640, 480), color=(255, 255, 255))
186
mm_items = MultiModalDataItems({"image": ImageProcessorItems([image])})
187
188
- assert (
189
- processor._hf_processor_applies_updates("In: test\nOut:", mm_items, {}, {})
190
- is False
191
- )
192
-
188
prompt_update = processor._get_prompt_updates(mm_items, {}, {})[0]
189
resolved = prompt_update.resolve(0)
190
content = resolved.content
tests/models/multimodal/processing/test_tensor_schema.py
+3
-3
@@ -37,7 +37,7 @@ from vllm.utils.torch_utils import set_default_torch_dtype
37
from ....utils import create_new_process_for_each_test
38
from ...registry import HF_EXAMPLE_MODELS
39
from ...utils import dummy_hf_overrides
40
-from .test_common import get_model_ids_to_test, get_text_token_prompts
40
+from .test_common import get_model_ids_to_test, get_token_prompt
41
42
ImageInput = list[Image.Image]
43
VideoInput: TypeAlias = (
@@ -107,10 +107,10 @@ def create_batched_mm_kwargs(
107
}
108
109
# video metadata will be added back to the resized video data here.
110
- text_prompt, token_prompt = get_text_token_prompts(processor, resized_mm_data)
110
+ token_prompt = get_token_prompt(processor, resized_mm_data)
111
112
mm_kwargs = processor(
113
- prompt=token_prompt if text_prompt is None else text_prompt,
113
+ prompt=token_prompt,
114
mm_items=processor.info.parse_mm_data(resized_mm_data),
115
hf_processor_mm_kwargs=processor_inputs.hf_processor_mm_kwargs,
116
)["mm_kwargs"].require_data()
vllm/model_executor/models/audioflamingo3.py
-2
@@ -382,7 +382,6 @@ class AudioFlamingo3MultiModalProcessor(
382
prompt: str,
383
mm_data: Mapping[str, object],
384
mm_kwargs: Mapping[str, Any],
385
- tok_kwargs: Mapping[str, object],
385
) -> BatchFeature:
386
processor_mm_data = dict(mm_data)
387
audios = processor_mm_data.pop("audios", None)
@@ -393,7 +392,6 @@ class AudioFlamingo3MultiModalProcessor(
392
prompt=prompt,
393
mm_data=processor_mm_data,
394
mm_kwargs=mm_kwargs,
396
- tok_kwargs=tok_kwargs,
395
)
396
397
if "input_features_mask" in outputs:
vllm/model_executor/models/bagel.py
-9
@@ -273,15 +273,6 @@ class BagelDummyInputsBuilder(BaseDummyInputsBuilder[BagelProcessingInfo]):
273
class BagelMultiModalProcessor(BaseMultiModalProcessor[BagelProcessingInfo]):
274
"""Multimodal processor for BAGEL model."""
275
276
- def _hf_processor_applies_updates(
277
- self,
278
- prompt_text: str,
279
- mm_items: MultiModalDataItems,
280
- hf_processor_mm_kwargs: Mapping[str, object],
281
- tokenization_kwargs: Mapping[str, object],
282
- ) -> bool:
283
- return False
284
-
276
def _get_prompt_updates(
277
self,
278
mm_items: MultiModalDataItems,
vllm/model_executor/models/blip2.py
-2
@@ -472,7 +472,6 @@ class Blip2MultiModalProcessor(BaseMultiModalProcessor[Blip2ProcessingInfo]):
472
prompt: str,
473
mm_data: Mapping[str, object],
474
mm_kwargs: Mapping[str, object],
475
- tok_kwargs: Mapping[str, object],
475
) -> BatchFeature:
476
if not mm_data:
477
# HF processor always adds placeholders even when there's no image
@@ -484,7 +483,6 @@ class Blip2MultiModalProcessor(BaseMultiModalProcessor[Blip2ProcessingInfo]):
483
prompt=prompt,
484
mm_data=mm_data,
485
mm_kwargs=mm_kwargs,
487
- tok_kwargs=tok_kwargs,
486
)
487
488
def _get_mm_fields_config(
vllm/model_executor/models/chameleon.py
-2
@@ -140,7 +140,6 @@ class ChameleonMultiModalProcessor(BaseMultiModalProcessor[ChameleonProcessingIn
140
prompt: str,
141
mm_data: Mapping[str, object],
142
mm_kwargs: Mapping[str, object],
143
- tok_kwargs: Mapping[str, object],
143
) -> BatchFeature:
144
if not mm_data:
145
prompt_ids = self.info.get_tokenizer().encode(prompt)
@@ -151,7 +150,6 @@ class ChameleonMultiModalProcessor(BaseMultiModalProcessor[ChameleonProcessingIn
150
prompt=prompt,
151
mm_data=mm_data,
152
mm_kwargs=mm_kwargs,
154
- tok_kwargs=tok_kwargs,
153
)
154
155
def _apply_hf_processor_tokens_only(
vllm/model_executor/models/cheers.py
+1
-11
@@ -497,18 +497,8 @@ class CheersMultiModalProcessor(BaseMultiModalProcessor[CheersProcessingInfo]):
497
prompt: str,
498
mm_data: Mapping[str, object],
499
mm_kwargs: Mapping[str, object],
500
- tok_kwargs: Mapping[str, object],
500
) -> BatchFeature:
502
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
503
-
504
- def _hf_processor_applies_updates(
505
- self,
506
- prompt_text: str,
507
- mm_items: MultiModalDataItems,
508
- hf_processor_mm_kwargs: Mapping[str, object],
509
- tokenization_kwargs: Mapping[str, object],
510
- ) -> bool:
511
- return False
501
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
502
503
def _get_prompt_updates(
504
self,
vllm/model_executor/models/clip.py
+7
-30
@@ -208,40 +208,17 @@ class CLIPMultiModalProcessor(BaseMultiModalProcessor[CLIPProcessingInfo]):
208
timing_ctx: TimingContext,
209
) -> MultiModalInput:
210
if inputs.mm_data_items:
211
- if isinstance(inputs.prompt, str):
212
- if len(inputs.prompt) > 0:
213
- raise ValueError(
214
- "CLIP accepts text-only or image-only inputs, not both! "
215
- "You must pass an image with an empty text prompt."
216
- )
211
+ special_tokens = self.info.get_tokenizer().all_special_ids
212
+ if all(tok in special_tokens for tok in inputs.prompt):
213
+ inputs.prompt = []
214
else:
218
- special_tokens = self.info.get_tokenizer().all_special_ids
219
- if all(tok in special_tokens for tok in inputs.prompt):
220
- inputs.prompt = []
221
- else:
222
- raise ValueError(
223
- "CLIP accepts text-only or image-only inputs, not both! "
224
- "You must pass an image with an empty token prompt."
225
- )
226
-
227
- # For multi-modal data, the prompt after processing should
228
- # only contain the dummy image tokens
229
- inputs.tokenization_kwargs = {
230
- **inputs.tokenization_kwargs,
231
- "add_special_tokens": False,
232
- }
215
+ raise ValueError(
216
+ "CLIP accepts text-only or image-only inputs, not both! "
217
+ "You must pass an image with an empty token prompt."
218
+ )
219
220
return super().apply(inputs, timing_ctx)
221
236
- def _hf_processor_applies_updates(
237
- self,
238
- prompt_text: str,
239
- mm_items: MultiModalDataItems,
240
- hf_processor_mm_kwargs: Mapping[str, object],
241
- tokenization_kwargs: Mapping[str, object],
242
- ) -> bool:
243
- return False
244
-
222
def _get_mm_fields_config(
223
self,
224
hf_inputs: BatchFeature,
vllm/model_executor/models/cohere2_vision.py
-2
@@ -227,13 +227,11 @@ class Cohere2VisionMultiModalProcessor(
227
prompt: str,
228
mm_data: Mapping[str, object],
229
mm_kwargs: Mapping[str, object],
230
- tok_kwargs: Mapping[str, object],
230
) -> BatchFeature:
231
processed_outputs = super()._call_hf_processor(
232
prompt,
233
mm_data,
234
mm_kwargs,
236
- tok_kwargs,
235
)
236
237
# Ensure num_patches is available for proper tensor splitting
vllm/model_executor/models/cohere_asr.py
+2
-4
@@ -1936,9 +1936,9 @@ class CohereASRMultiModalProcessor(EncDecMultiModalProcessor[CohereASRProcessing
1936
1937
def create_encoder_prompt(
1938
self,
1939
- prompt: str | list[int],
1939
+ prompt: list[int],
1940
mm_items: MultiModalDataItems,
1941
- ) -> str | list[int]:
1941
+ ) -> list[int]:
1942
return [0]
1943
1944
def _call_hf_processor(
@@ -1946,7 +1946,6 @@ class CohereASRMultiModalProcessor(EncDecMultiModalProcessor[CohereASRProcessing
1946
prompt: str,
1947
mm_data: Mapping[str, object],
1948
mm_kwargs: Mapping[str, object],
1949
- tok_kwargs: Mapping[str, object],
1949
):
1950
if mm_data:
1951
feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
@@ -1959,7 +1958,6 @@ class CohereASRMultiModalProcessor(EncDecMultiModalProcessor[CohereASRProcessing
1958
prompt=prompt,
1959
mm_data=mm_data,
1960
mm_kwargs=mm_kwargs,
1962
- tok_kwargs=tok_kwargs,
1961
)
1962
if "labels" in processed_outputs:
1963
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/model_executor/models/colmodernvbert.py
-11
@@ -159,14 +159,12 @@ class ColModernVBertMultiModalProcessor(
159
prompt: str,
160
mm_data: Mapping[str, object],
161
mm_kwargs: Mapping[str, object],
162
- tok_kwargs: Mapping[str, object],
162
) -> BatchFeature:
163
tokenizer = self.info.get_tokenizer()
164
assert isinstance(tokenizer, HfTokenizer)
165
text_encoding = tokenizer(
166
prompt,
167
return_tensors="pt",
169
- **tok_kwargs,
168
)
169
result = BatchFeature(data=dict(text_encoding))
170
@@ -187,15 +185,6 @@ class ColModernVBertMultiModalProcessor(
185
186
return result
187
190
- def _hf_processor_applies_updates(
191
- self,
192
- prompt_text: str,
193
- mm_items: MultiModalDataItems,
194
- hf_processor_mm_kwargs: Mapping[str, object],
195
- tokenization_kwargs: Mapping[str, object],
196
- ) -> bool:
197
- return False
198
-
188
def _get_mm_fields_config(
189
self,
190
hf_inputs: BatchFeature,
vllm/model_executor/models/colpali.py
+6
-8
@@ -64,7 +64,6 @@ class ColPaliMultiModalProcessor(PaliGemmaMultiModalProcessor):
64
prompt: str,
65
mm_data: Mapping[str, object],
66
mm_kwargs: Mapping[str, object],
67
- tok_kwargs: Mapping[str, object],
67
) -> BatchFeature:
68
if mm_data:
69
# The ColPali tokenizer_config.json ships with a small default
@@ -72,13 +71,12 @@ class ColPaliMultiModalProcessor(PaliGemmaMultiModalProcessor):
71
# by PaliGemmaProcessor, causing a token-count mismatch.
72
# vLLM enforces its own max_model_len, so we disable HF
73
# truncation to keep all image + text tokens intact.
75
- tok_kwargs = dict(tok_kwargs, truncation=False)
76
- return super()._call_hf_processor(
77
- prompt=prompt,
78
- mm_data=mm_data,
79
- mm_kwargs=mm_kwargs,
80
- tok_kwargs=tok_kwargs,
81
- )
74
+ return self.info.ctx.call_hf_processor(
75
+ self.info.get_hf_processor(**mm_kwargs),
76
+ dict(text=prompt, **mm_data),
77
+ dict(**mm_kwargs, truncation=False),
78
+ )
79
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
80
81
82
@default_pooling_type(seq_pooling_type="CLS", tok_pooling_type="ALL")
vllm/model_executor/models/deepseek_ocr.py
-1
@@ -292,7 +292,6 @@ class DeepseekOCRMultiModalProcessor(
292
prompt: str,
293
mm_data: Mapping[str, object],
294
mm_kwargs: Mapping[str, object],
295
- tok_kwargs: Mapping[str, object],
295
) -> BatchFeature:
296
if mm_data:
297
processed_outputs = self.info.ctx.call_hf_processor(
vllm/model_executor/models/deepseek_ocr2.py
-1
@@ -163,7 +163,6 @@ class DeepseekOCR2MultiModalProcessor(
163
prompt: str,
164
mm_data: Mapping[str, object],
165
mm_kwargs: Mapping[str, object],
166
- tok_kwargs: Mapping[str, object],
166
) -> BatchFeature:
167
if mm_data:
168
processed_outputs = self.info.ctx.call_hf_processor(
vllm/model_executor/models/deepseek_vl2.py
-2
@@ -241,7 +241,6 @@ class DeepseekVL2MultiModalProcessor(
241
prompt: str,
242
mm_data: Mapping[str, object],
243
mm_kwargs: Mapping[str, object],
244
- tok_kwargs: Mapping[str, object],
244
) -> BatchFeature:
245
if not mm_data:
246
tokenizer = self.info.get_tokenizer()
@@ -252,7 +251,6 @@ class DeepseekVL2MultiModalProcessor(
251
prompt=prompt,
252
mm_data=mm_data,
253
mm_kwargs=mm_kwargs,
255
- tok_kwargs=tok_kwargs,
254
)
255
256
processed_outputs["num_patches"] = (
vllm/model_executor/models/ernie45_vl.py
+1
-2
@@ -1115,7 +1115,6 @@ class Ernie4_5VLMultiModalProcessor(BaseMultiModalProcessor[Ernie4_5_VLProcessin
1115
prompt: str,
1116
mm_data: Mapping[str, object],
1117
mm_kwargs: Mapping[str, object],
1118
- tok_kwargs: Mapping[str, object],
1118
) -> BatchFeature:
1119
# when the prompt is not empty but the multimodal data is empty,
1120
# directly invoke the tokenizer.
@@ -1151,7 +1150,7 @@ class Ernie4_5VLMultiModalProcessor(BaseMultiModalProcessor[Ernie4_5_VLProcessin
1150
processor_output = self.info.ctx.call_hf_processor(
1151
hf_processor,
1152
dict(text=[prompt], images=mm_data["images"], videos=mm_data["videos"]),
1154
- dict(**mm_kwargs, **tok_kwargs),
1153
+ mm_kwargs,
1154
)
1155
1156
# Divide the processor_output into two modalities: image and video.
vllm/model_executor/models/fireredasr2.py
-2
@@ -233,7 +233,6 @@ class FireRedASR2MultiModalProcessor(
233
prompt: str,
234
mm_data: Mapping[str, object],
235
mm_kwargs: Mapping[str, object],
236
- tok_kwargs: Mapping[str, object],
236
) -> BatchFeature:
237
if mm_data:
238
feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
@@ -246,7 +245,6 @@ class FireRedASR2MultiModalProcessor(
245
prompt=prompt,
246
mm_data=mm_data,
247
mm_kwargs=mm_kwargs,
249
- tok_kwargs=tok_kwargs,
248
)
249
if "labels" in processed_outputs:
250
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/model_executor/models/fireredlid.py
+2
-4
@@ -445,9 +445,9 @@ class FireRedLIDMultiModalProcessor(
445
):
446
def create_encoder_prompt(
447
self,
448
- prompt: str | list[int],
448
+ prompt: list[int],
449
mm_items: MultiModalDataItems,
450
- ) -> str | list[int]:
450
+ ) -> list[int]:
451
# Dummy encoder prompt for profiling (encoder only processes audio).
452
return [0]
453
@@ -456,7 +456,6 @@ class FireRedLIDMultiModalProcessor(
456
prompt: str,
457
mm_data: Mapping[str, object],
458
mm_kwargs: Mapping[str, object],
459
- tok_kwargs: Mapping[str, object],
459
) -> BatchFeature:
460
if mm_data:
461
feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
@@ -469,7 +468,6 @@ class FireRedLIDMultiModalProcessor(
468
prompt=prompt,
469
mm_data=mm_data,
470
mm_kwargs=mm_kwargs,
472
- tok_kwargs=tok_kwargs,
471
)
472
if "labels" in processed_outputs:
473
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/model_executor/models/funasr.py
-2
@@ -752,7 +752,6 @@ class FunASRMultiModalProcessor(BaseMultiModalProcessor[FunASRProcessingInfo]):
752
prompt: str,
753
mm_data: Mapping[str, object],
754
mm_kwargs: Mapping[str, object],
755
- tok_kwargs: Mapping[str, object],
755
) -> BatchFeature:
756
if mm_data:
757
feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
@@ -765,7 +764,6 @@ class FunASRMultiModalProcessor(BaseMultiModalProcessor[FunASRProcessingInfo]):
764
prompt=prompt,
765
mm_data=mm_data,
766
mm_kwargs=mm_kwargs,
768
- tok_kwargs=tok_kwargs,
767
)
768
if "labels" in processed_outputs:
769
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/model_executor/models/funaudiochat.py
+1
-11
@@ -617,10 +617,9 @@ class FunAudioChatMultiModalProcessor(
617
prompt: str,
618
mm_data: Mapping[str, object],
619
mm_kwargs: Mapping[str, object],
620
- tok_kwargs: Mapping[str, object],
620
) -> BatchFeature:
621
tokenizer = self.info.get_tokenizer()
623
- input_ids = torch.tensor([tokenizer.encode(prompt, **tok_kwargs)])
622
+ input_ids = torch.tensor([tokenizer.encode(prompt)])
623
624
audios = mm_data.get("audios", [])
625
if not audios:
@@ -679,15 +678,6 @@ class FunAudioChatMultiModalProcessor(
678
679
return BatchFeature({"input_ids": input_ids, **mm_inputs})
680
682
- def _hf_processor_applies_updates(
683
- self,
684
- prompt_text: str,
685
- mm_items: MultiModalDataItems,
686
- hf_processor_mm_kwargs: Mapping[str, object],
687
- tokenization_kwargs: Mapping[str, object],
688
- ) -> bool:
689
- return False
690
-
681
def _get_mm_fields_config(
682
self,
683
hf_inputs: BatchFeature,
vllm/model_executor/models/gemma3_mm.py
-2
@@ -266,13 +266,11 @@ class Gemma3MultiModalProcessor(BaseMultiModalProcessor[Gemma3ProcessingInfo]):
266
prompt: str,
267
mm_data: Mapping[str, object],
268
mm_kwargs: Mapping[str, object],
269
- tok_kwargs: Mapping[str, object],
269
) -> BatchFeature:
270
processed_outputs = super()._call_hf_processor(
271
prompt,
272
mm_data,
273
mm_kwargs,
275
- tok_kwargs,
274
)
275
276
# HF processor pops the `num_crops` kwarg, which is needed by vLLM
vllm/model_executor/models/gemma3n_mm.py
-2
@@ -262,7 +262,6 @@ class Gemma3nMultiModalProcessor(BaseMultiModalProcessor[Gemma3nProcessingInfo])
262
prompt: str,
263
mm_data: Mapping[str, object],
264
mm_kwargs: Mapping[str, object],
265
- tok_kwargs: Mapping[str, object],
265
) -> BatchFeature:
266
# HF Transformers audio processor no longer accepts `audios` key.
267
# We pop `audios` and replace it with `audio` key to suppress
@@ -273,7 +272,6 @@ class Gemma3nMultiModalProcessor(BaseMultiModalProcessor[Gemma3nProcessingInfo])
272
prompt,
273
mm_data,
274
mm_kwargs,
276
- tok_kwargs,
275
)
276
277
if "input_features" in processed_outputs:
vllm/model_executor/models/gemma4_mm.py
-22
@@ -560,31 +560,11 @@ class Gemma4DummyInputsBuilder(BaseDummyInputsBuilder[Gemma4ProcessingInfo]):
560
561
562
class Gemma4MultiModalProcessor(BaseMultiModalProcessor[Gemma4ProcessingInfo]):
563
- def _apply_hf_processor_text_only(
564
- self,
565
- prompt_text: str,
566
- tokenization_kwargs: Mapping[str, object],
567
- ) -> list[int]:
568
- # Bypass the HF processor and tokenize directly. The HF
569
- # processor expands multimodal placeholders (<|video|>, etc.)
570
- # via get_text_with_replacements, which raises StopIteration
571
- # when the prompt contains placeholders without matching data.
572
- # The text-only path only needs token IDs, so the tokenizer
573
- # alone is sufficient.
574
- processor = self.info.get_hf_processor()
575
- text_inputs = processor.tokenizer([prompt_text], **tokenization_kwargs)
576
- input_ids = text_inputs["input_ids"]
577
- if not isinstance(input_ids, list):
578
- input_ids = input_ids.tolist()
579
- (prompt_ids,) = input_ids
580
- return prompt_ids
581
-
563
def _call_hf_processor(
564
self,
565
prompt: str,
566
mm_data: Mapping[str, object],
567
mm_kwargs: Mapping[str, object],
587
- tok_kwargs: Mapping[str, object],
568
) -> BatchFeature:
569
merged_kwargs = self.info.ctx.get_merged_mm_kwargs(mm_kwargs)
570
val, is_top_level_max_soft_tokens = _get_max_soft_tokens(merged_kwargs)
@@ -640,7 +620,6 @@ class Gemma4MultiModalProcessor(BaseMultiModalProcessor[Gemma4ProcessingInfo]):
620
prompt=dummy_prompt,
621
mm_data={"images": frames},
622
mm_kwargs=video_mm_kwargs,
643
- tok_kwargs=tok_kwargs,
623
)
624
625
# Remap HF key name
@@ -741,7 +720,6 @@ class Gemma4MultiModalProcessor(BaseMultiModalProcessor[Gemma4ProcessingInfo]):
720
prompt,
721
mm_data,
722
patched_mm_kwargs,
744
- tok_kwargs,
723
)
724
725
# HF uses 'image_position_ids'; vLLM uses 'pixel_position_ids'.
vllm/model_executor/models/glm4_1v.py
-4
@@ -1581,7 +1581,6 @@ class Glm4vMultiModalProcessor(BaseMultiModalProcessor[Glm4vProcessingInfo]):
1581
prompt: str,
1582
mm_data: Mapping[str, object],
1583
mm_kwargs: Mapping[str, object],
1584
- tok_kwargs: Mapping[str, object],
1584
) -> BatchFeature:
1585
mm_data = dict(mm_data)
1586
if not mm_data:
@@ -1602,7 +1601,6 @@ class Glm4vMultiModalProcessor(BaseMultiModalProcessor[Glm4vProcessingInfo]):
1601
prompt=prompt,
1602
mm_data=prepared_data,
1603
mm_kwargs=prepared_kwargs,
1605
- tok_kwargs=tok_kwargs,
1604
)
1605
1606
if (
@@ -1631,7 +1629,6 @@ class Glm4vMultiModalProcessor(BaseMultiModalProcessor[Glm4vProcessingInfo]):
1629
prompt="<|begin_of_video|><|video|><|end_of_video|>",
1630
mm_data=video_mm_data,
1631
mm_kwargs=video_mm_kwargs,
1634
- tok_kwargs=tok_kwargs,
1632
)
1633
input_ids = video_outputs.pop("input_ids")
1634
if swap_video_frame_tokens:
@@ -1659,7 +1656,6 @@ class Glm4vMultiModalProcessor(BaseMultiModalProcessor[Glm4vProcessingInfo]):
1656
prompt=prompt,
1657
mm_data=mm_data,
1658
mm_kwargs=mm_kwargs,
1662
- tok_kwargs=tok_kwargs,
1659
)
1660
if swap_video_frame_tokens:
1661
input_ids = processed_outputs["input_ids"]
vllm/model_executor/models/glm4v.py
-9
@@ -466,15 +466,6 @@ class GLM4VDummyInputsBuilder(BaseDummyInputsBuilder[GLM4VProcessingInfo]):
466
467
468
class GLM4VMultiModalProcessor(BaseMultiModalProcessor[GLM4VProcessingInfo]):
469
- def _hf_processor_applies_updates(
470
- self,
471
- prompt_text: str,
472
- mm_items: MultiModalDataItems,
473
- hf_processor_mm_kwargs: Mapping[str, object],
474
- tokenization_kwargs: Mapping[str, object],
475
- ) -> bool:
476
- return False
477
-
469
def _get_mm_fields_config(
470
self,
471
hf_inputs: BatchFeature,
vllm/model_executor/models/glmasr.py
-2
@@ -755,7 +755,6 @@ class GlmAsrMultiModalProcessor(BaseMultiModalProcessor["GlmAsrProcessingInfo"])
755
prompt: str,
756
mm_data: dict[str, object],
757
mm_kwargs: Mapping[str, Any],
758
- tok_kwargs: Mapping[str, object],
758
) -> BatchFeature:
759
# Normalize input: handle deprecated key and list conversion.
760
if "audios" in mm_data:
@@ -782,7 +781,6 @@ class GlmAsrMultiModalProcessor(BaseMultiModalProcessor["GlmAsrProcessingInfo"])
781
prompt=prompt,
782
mm_data=mm_data,
783
mm_kwargs=mm_kwargs,
785
- tok_kwargs=tok_kwargs,
784
)
785
786
# Postprocess: rename mask and add chunk counts
vllm/model_executor/models/granite_speech.py
-2
@@ -185,7 +185,6 @@ class GraniteSpeechMultiModalProcessor(
185
prompt: str,
186
mm_data: Mapping[str, object],
187
mm_kwargs: Mapping[str, object],
188
- tok_kwargs: Mapping[str, object],
188
) -> BatchFeature:
189
mm_data = dict(mm_data)
190
audios = mm_data.pop("audios", [])
@@ -198,7 +197,6 @@ class GraniteSpeechMultiModalProcessor(
197
prompt=prompt,
198
mm_data=mm_data,
199
mm_kwargs=mm_kwargs,
201
- tok_kwargs=tok_kwargs,
200
)
201
202
if "audio" in mm_data:
vllm/model_executor/models/hunyuan_vision.py
+1
-2
@@ -736,7 +736,6 @@ class HunYuanVLMultiModalProcessor(BaseMultiModalProcessor[HunYuanVLProcessingIn
736
prompt: str,
737
mm_data: Mapping[str, object],
738
mm_kwargs: Mapping[str, object],
739
- tok_kwargs: Mapping[str, object],
739
) -> BatchFeature:
740
hf_processor = self.info.get_hf_processor(**mm_kwargs)
741
# HunYuanVLProcessor requires image placeholders wrapped with start/end tokens.
@@ -751,7 +750,7 @@ class HunYuanVLMultiModalProcessor(BaseMultiModalProcessor[HunYuanVLProcessingIn
750
return self.info.ctx.call_hf_processor(
751
hf_processor,
752
dict(text=prompt, **mm_data),
754
- dict(**mm_kwargs, **tok_kwargs),
753
+ mm_kwargs,
754
)
755
756
def _get_prompt_updates(
vllm/model_executor/models/hyperclovax_vision.py
-10
@@ -195,7 +195,6 @@ class HCXVisionMultiModalProcessor(BaseMultiModalProcessor[HCXVisionProcessingIn
195
prompt: str,
196
mm_data: Mapping[str, object],
197
mm_kwargs: Mapping[str, object],
198
- tok_kwargs: Mapping[str, object],
198
) -> BatchFeature:
199
for video_idx, video_arr in enumerate(mm_data.get("videos", [])):
200
if video_arr.dtype != np.uint8:
@@ -263,15 +262,6 @@ class HCXVisionMultiModalProcessor(BaseMultiModalProcessor[HCXVisionProcessingIn
262
263
return processed_outputs
264
266
- def _hf_processor_applies_updates(
267
- self,
268
- prompt_text: str,
269
- mm_items: MultiModalDataItems,
270
- hf_processor_mm_kwargs: Mapping[str, object],
271
- tokenization_kwargs: Mapping[str, object],
272
- ) -> bool:
273
- return False
274
-
265
def _get_prompt_updates(
266
self,
267
mm_items: MultiModalDataItems,
vllm/model_executor/models/hyperclovax_vision_v2.py
+9
-23
@@ -209,11 +209,16 @@ class HCXVisionV2DummyInputsBuilder(BaseDummyInputsBuilder[HCXVisionV2Processing
209
)
210
dummy_mm_items = self.info.parse_mm_data(dummy_mm_data, validate=False)
211
212
+ tokenizer = self.info.get_tokenizer()
213
+ prompt = tokenizer.encode(
214
+ prompt_text,
215
+ **self.info.default_tok_params.get_encode_kwargs(),
216
+ )
217
+
218
return ProcessorInputs(
213
- prompt=prompt_text,
219
+ prompt=prompt,
220
mm_data_items=dummy_mm_items,
221
hf_processor_mm_kwargs=mm_processor_kwargs or {},
216
- tokenization_kwargs={"truncation": False},
222
)
223
224
def get_dummy_mm_data(
@@ -261,7 +266,6 @@ class HCXVisionV2MultiModalProcessor(
266
prompt: str,
267
mm_data: Mapping[str, object],
268
mm_kwargs: Mapping[str, object],
264
- tok_kwargs: Mapping[str, object],
269
) -> BatchFeature:
270
images = mm_data.get("images")
271
videos = mm_data.get("videos")
@@ -271,8 +275,7 @@ class HCXVisionV2MultiModalProcessor(
275
276
# Build data dict for HF processor (images/videos only)
277
# NOTE: We pass the prompt as-is without token normalization.
274
- # Token expansion is handled by vLLM via _get_prompt_updates since
275
- # _hf_processor_applies_updates returns False.
278
+ # Token expansion is handled by vLLM via _get_prompt_updates.
279
data: dict[str, object] = dict(
280
text=prompt,
281
images=images,
@@ -282,28 +285,11 @@ class HCXVisionV2MultiModalProcessor(
285
processed_outputs = self.info.ctx.call_hf_processor(
286
hf_processor=hf_processor,
287
data=data,
285
- kwargs=dict(**mm_kwargs, **tok_kwargs),
288
+ kwargs=mm_kwargs,
289
)
290
291
return processed_outputs
292
290
- def _hf_processor_applies_updates(
291
- self,
292
- prompt_text: str,
293
- mm_items: MultiModalDataItems,
294
- hf_processor_mm_kwargs: Mapping[str, object],
295
- tokenization_kwargs: Mapping[str, object],
296
- ) -> bool:
297
- # Match BaseMultiModalProcessor behavior:
298
- # - raw multimodal inputs: HF processor applies updates
299
- # - embedding inputs: vLLM applies updates
300
- return super()._hf_processor_applies_updates(
301
- prompt_text,
302
- mm_items,
303
- hf_processor_mm_kwargs,
304
- tokenization_kwargs,
305
- )
306
-
293
def _get_prompt_updates(
294
self,
295
mm_items: MultiModalDataItems,
vllm/model_executor/models/idefics3.py
-2
@@ -244,7 +244,6 @@ class Idefics3MultiModalProcessor(BaseMultiModalProcessor[Idefics3ProcessingInfo
244
prompt: str,
245
mm_data: Mapping[str, object],
246
mm_kwargs: Mapping[str, object],
247
- tok_kwargs: Mapping[str, object],
247
) -> BatchFeature:
248
# Text-only input not supported in composite processor
249
if not (images := mm_data.get("images", [])):
@@ -260,7 +259,6 @@ class Idefics3MultiModalProcessor(BaseMultiModalProcessor[Idefics3ProcessingInfo
259
prompt,
260
mm_data,
261
mm_kwargs,
263
- tok_kwargs,
262
)
263
264
mm_items = self.info.parse_mm_data({"image": images}, validate=False)
vllm/model_executor/models/interns1.py
+1
-4
@@ -337,7 +337,6 @@ class InternS1MultiModalProcessor(BaseMultiModalProcessor[InternS1ProcessingInfo
337
prompt: str,
338
mm_data: Mapping[str, object],
339
mm_kwargs: Mapping[str, object],
340
- tok_kwargs: Mapping[str, object],
340
) -> BatchFeature:
341
mm_data = dict(mm_data)
342
videos = mm_data.pop("videos", [])
@@ -364,7 +363,6 @@ class InternS1MultiModalProcessor(BaseMultiModalProcessor[InternS1ProcessingInfo
363
prompt=hf_processor.image_token,
364
mm_data={"images": image},
365
mm_kwargs=mm_kwargs,
367
- tok_kwargs=tok_kwargs,
366
)
367
image_pixel_values.append(processed_outputs.pop("pixel_values"))
368
@@ -387,7 +385,6 @@ class InternS1MultiModalProcessor(BaseMultiModalProcessor[InternS1ProcessingInfo
385
prompt=hf_processor.video_token,
386
mm_data={"videos": video},
387
mm_kwargs=mm_kwargs,
390
- tok_kwargs=tok_kwargs,
388
)
389
video_pixel_values.append(processed_outputs.pop("pixel_values"))
390
@@ -406,7 +403,7 @@ class InternS1MultiModalProcessor(BaseMultiModalProcessor[InternS1ProcessingInfo
403
404
prompt = re.sub("<image_placeholder>", hf_processor.image_token, prompt)
405
prompt = re.sub("<video_placeholder>", hf_processor.video_token, prompt)
409
- text_outputs = tokenizer(prompt, **tok_kwargs, return_tensors="pt")
406
+ text_outputs = tokenizer(prompt, return_tensors="pt")
407
408
return BatchFeature({**text_outputs, **image_outputs, **video_outputs})
409
vllm/model_executor/models/internvl.py
+1
-6
@@ -225,13 +225,11 @@ class BaseInternVLMultiModalProcessor(BaseMultiModalProcessor[_I]):
225
prompt: str,
226
mm_data: Mapping[str, object],
227
mm_kwargs: Mapping[str, object],
228
- tok_kwargs: Mapping[str, object],
228
) -> BatchFeature:
229
processed_outputs = super()._call_hf_processor(
230
prompt=prompt,
231
mm_data=mm_data,
232
mm_kwargs=mm_kwargs,
234
- tok_kwargs=tok_kwargs,
233
)
234
235
hf_processor = self.info.get_hf_processor(**mm_kwargs)
@@ -462,11 +460,8 @@ class InternVLMultiModalProcessor(
460
prompt: str,
461
mm_data: Mapping[str, object],
462
mm_kwargs: Mapping[str, object],
465
- tok_kwargs: Mapping[str, object],
463
) -> BatchFeature:
467
- processed_outputs = super()._call_hf_processor(
468
- prompt, mm_data, mm_kwargs, tok_kwargs
469
- )
464
+ processed_outputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs)
465
466
hf_processor = self.info.get_hf_processor(**mm_kwargs)
467
if (video_token_id := hf_processor.ctx_video_token_id) is not None:
vllm/model_executor/models/jina_vl.py
+1
-2
@@ -59,7 +59,6 @@ class JinaVLMultiModalProcessor(Qwen2VLMultiModalProcessor):
59
prompt: str,
60
mm_data: Mapping[str, object],
61
mm_kwargs: Mapping[str, object],
62
- tok_kwargs: Mapping[str, object],
62
) -> BatchFeature:
63
# NOTE: We should reverse the order of the mm_data because the
64
# query prompt is placed after the document prompt in the score
@@ -67,7 +66,7 @@ class JinaVLMultiModalProcessor(Qwen2VLMultiModalProcessor):
66
# stored in the opposite order (query first, then document).
67
for _, value in mm_data.items():
68
value.reverse()
70
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
69
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
70
71
72
@MULTIMODAL_REGISTRY.register_processor(
vllm/model_executor/models/kanana_v.py
-1
@@ -466,7 +466,6 @@ class KananaVMultiModalProcessor(BaseMultiModalProcessor[KananaVProcessingInfo])
466
prompt: str,
467
mm_data: Mapping[str, object],
468
mm_kwargs: Mapping[str, object],
469
- tok_kwargs: Mapping[str, object],
469
) -> BatchFeature:
470
"""Run the underlying HF processor on text and image data."""
471
# Text-only input is handled as a special case here.
vllm/model_executor/models/keye.py
+1
-2
@@ -1167,11 +1167,10 @@ class KeyeMultiModalProcessor(BaseMultiModalProcessor[KeyeProcessingInfo]):
1167
prompt: str,
1168
mm_data: Mapping[str, object],
1169
mm_kwargs: Mapping[str, object],
1170
- tok_kwargs: Mapping[str, object],
1170
) -> BatchFeature:
1171
# Override to use the text path instead of token path to use the
1172
# video-specific logic in processing_keye.py
1174
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
1173
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
1174
1175
def _get_prompt_updates(
1176
self,
vllm/model_executor/models/keye_vl1_5.py
+1
-2
@@ -383,11 +383,10 @@ class KeyeVL1_5MultiModalProcessor(BaseMultiModalProcessor[KeyeVL1_5ProcessingIn
383
prompt: str,
384
mm_data: Mapping[str, object],
385
mm_kwargs: Mapping[str, object],
386
- tok_kwargs: Mapping[str, object],
386
) -> BatchFeature:
387
# Override to use the text path instead of token path to use the
388
# video-specific logic in processing_keye.py
390
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
389
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
390
391
def _get_prompt_updates(
392
self,
vllm/model_executor/models/kimi_audio.py
+1
-2
@@ -231,7 +231,6 @@ class KimiAudioMultiModalProcessor(BaseMultiModalProcessor[KimiAudioProcessingIn
231
prompt: str,
232
mm_data: Mapping[str, object],
233
mm_kwargs: Mapping[str, object],
234
- tok_kwargs: Mapping[str, object],
234
) -> BatchFeature:
235
"""Call the HuggingFace processor."""
236
# Convert mm_data format: {'audios': [...]} -> {'audio': ...}
@@ -256,7 +255,7 @@ class KimiAudioMultiModalProcessor(BaseMultiModalProcessor[KimiAudioProcessingIn
255
return self.info.ctx.call_hf_processor(
256
self.info.get_hf_processor(**mm_kwargs),
257
dict(text=prompt, **mm_data),
259
- dict(**mm_kwargs, **tok_kwargs),
258
+ mm_kwargs,
259
)
260
261
def _get_mm_fields_config(
vllm/model_executor/models/kimi_k25.py
+1
-2
@@ -263,11 +263,10 @@ class KimiK25MultiModalProcessor(BaseMultiModalProcessor[KimiK25ProcessingInfo])
263
prompt: str,
264
mm_data: Mapping[str, object],
265
mm_kwargs: Mapping[str, object],
266
- tok_kwargs: Mapping[str, object],
266
) -> BatchFeature:
267
# Override to use the text path instead of token path because vision chunk
268
# is not considered
270
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
269
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
270
271
def _get_prompt_updates(
272
self,
vllm/model_executor/models/lfm2_vl.py
-2
@@ -398,7 +398,6 @@ class Lfm2VLMultiModalProcessor(BaseMultiModalProcessor[Lfm2VLProcessingInfo]):
398
prompt: str,
399
mm_data: Mapping[str, object],
400
mm_kwargs: Mapping[str, object],
401
- tok_kwargs: Mapping[str, object],
401
) -> BatchFeature:
402
# Text-only input not supported in composite processor
403
if not (images := mm_data.get("images", [])):
@@ -412,7 +411,6 @@ class Lfm2VLMultiModalProcessor(BaseMultiModalProcessor[Lfm2VLProcessingInfo]):
411
prompt,
412
mm_data,
413
mm_kwargs,
415
- tok_kwargs,
414
)
415
416
mm_items = self.info.parse_mm_data({"image": images}, validate=False)
vllm/model_executor/models/lightonocr.py
-2
@@ -44,13 +44,11 @@ class LightOnOCRMultiModalProcessor(BaseMultiModalProcessor[Mistral3ProcessingIn
44
prompt: str,
45
mm_data: Mapping[str, object],
46
mm_kwargs: Mapping[str, object],
47
- tok_kwargs: Mapping[str, object],
47
) -> BatchFeature:
48
processed_outputs = super()._call_hf_processor(
49
prompt=prompt,
50
mm_data=mm_data,
51
mm_kwargs=mm_kwargs,
53
- tok_kwargs=tok_kwargs,
52
)
53
54
# NOTE: LightOnOCR does not use break/end tokens, so we remove them here.
vllm/model_executor/models/llava.py
-2
@@ -326,13 +326,11 @@ class PixtralHFMultiModalProcessor(BaseMultiModalProcessor[PixtralHFProcessingIn
326
prompt: str,
327
mm_data: Mapping[str, object],
328
mm_kwargs: Mapping[str, object],
329
- tok_kwargs: Mapping[str, object],
329
) -> BatchFeature:
330
processed_outputs = super()._call_hf_processor(
331
prompt=prompt,
332
mm_data=mm_data,
333
mm_kwargs=mm_kwargs,
335
- tok_kwargs=tok_kwargs,
334
)
335
336
pixel_values = processed_outputs.get("pixel_values")
vllm/model_executor/models/llava_onevision.py
-21
@@ -326,7 +326,6 @@ class LlavaOnevisionMultiModalProcessor(
326
prompt: str,
327
mm_data: Mapping[str, object],
328
mm_kwargs: Mapping[str, object],
329
- tok_kwargs: Mapping[str, object],
329
) -> BatchFeature:
330
mm_data = dict(mm_data)
331
videos = mm_data.pop("videos", [])
@@ -337,7 +336,6 @@ class LlavaOnevisionMultiModalProcessor(
336
prompt=prompt,
337
mm_data=mm_data,
338
mm_kwargs=mm_kwargs,
340
- tok_kwargs=tok_kwargs,
339
)
340
341
# LLaVA-OneVision processor doesn't support multiple videos
@@ -352,7 +350,6 @@ class LlavaOnevisionMultiModalProcessor(
350
prompt=prompt,
351
mm_data={},
352
mm_kwargs=mm_kwargs,
355
- tok_kwargs=tok_kwargs,
353
)
354
355
images = mm_data.pop("images", [])
@@ -362,7 +359,6 @@ class LlavaOnevisionMultiModalProcessor(
359
prompt=image_token * len(images),
360
mm_data={"images": images},
361
mm_kwargs=mm_kwargs,
365
- tok_kwargs=tok_kwargs,
362
)
363
image_outputs = {
364
k: v
@@ -378,7 +374,6 @@ class LlavaOnevisionMultiModalProcessor(
374
prompt=video_token,
375
mm_data={"videos": video},
376
mm_kwargs=mm_kwargs,
381
- tok_kwargs=tok_kwargs,
377
)
378
379
pixel_values_videos.append(item_outputs["pixel_values_videos"][0])
@@ -392,22 +387,6 @@ class LlavaOnevisionMultiModalProcessor(
387
)
388
return BatchFeature(combined_outputs)
389
395
- def _hf_processor_applies_updates(
396
- self,
397
- prompt_text: str,
398
- mm_items: MultiModalDataItems,
399
- hf_processor_mm_kwargs: Mapping[str, object],
400
- tokenization_kwargs: Mapping[str, object],
401
- ) -> bool:
402
- base_result = super()._hf_processor_applies_updates(
403
- prompt_text=prompt_text,
404
- mm_items=mm_items,
405
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
406
- tokenization_kwargs=tokenization_kwargs,
407
- )
408
-
409
- return base_result and mm_items.get_count("video", strict=False) == 0
410
-
390
def _get_prompt_updates(
391
self,
392
mm_items: MultiModalDataItems,
vllm/model_executor/models/llava_onevision2.py
+1
-7
@@ -1552,16 +1552,13 @@ class LlavaOnevision2MultiModalProcessor(
1552
prompt: str,
1553
mm_data: Mapping[str, object],
1554
mm_kwargs: Mapping[str, object],
1555
- tok_kwargs: Mapping[str, object],
1555
) -> BatchFeature:
1556
# The wrapped OV2 processor is a bare custom class without the standard
1557
# ProcessorMixin ``_merge_kwargs`` machinery, so vLLM's default path
1558
# fails; overriding this method routes the base class to call us
1559
# directly.
1560
hf_processor = self.info.get_hf_processor(**mm_kwargs)
1562
- merged_kwargs = self.info.ctx.get_merged_mm_kwargs(
1563
- dict(**mm_kwargs, **tok_kwargs)
1564
- )
1561
+ merged_kwargs = self.info.ctx.get_merged_mm_kwargs(mm_kwargs)
1562
merged_kwargs.setdefault("return_tensors", "pt")
1563
call_kwargs = {
1564
k: v
@@ -1638,7 +1635,6 @@ class LlavaOnevision2MultiModalProcessor(
1635
prompt=prompt,
1636
mm_data=mm_data,
1637
mm_kwargs={**mm_kwargs, "video_backend": "codec"},
1641
- tok_kwargs=tok_kwargs,
1638
)
1639
data = dict(output)
1640
return BatchFeature(
@@ -1736,7 +1732,6 @@ class LlavaOnevision2MultiModalProcessor(
1732
prompt=new_prompt,
1733
mm_data=merged_mm_data,
1734
mm_kwargs=mm_kwargs,
1739
- tok_kwargs=tok_kwargs,
1735
)
1736
data = dict(output)
1737
@@ -1803,7 +1798,6 @@ class LlavaOnevision2MultiModalProcessor(
1798
prompt=prompt,
1799
mm_data=mm_data,
1800
mm_kwargs=mm_kwargs,
1806
- tok_kwargs=tok_kwargs,
1801
)
1802
1803
def _rename_codec_outputs_to_video(
vllm/model_executor/models/midashenglm.py
-2
@@ -588,7 +588,6 @@ class MiDashengLMMultiModalProcessor(
588
prompt: str,
589
mm_data: Mapping[str, object],
590
mm_kwargs: Mapping[str, Any],
591
- tok_kwargs: Mapping[str, object],
591
) -> BatchFeature:
592
audios = mm_data.pop("audios", [])
593
@@ -622,7 +621,6 @@ class MiDashengLMMultiModalProcessor(
621
prompt=prompt,
622
mm_data=mm_data,
623
mm_kwargs=mm_kwargs,
625
- tok_kwargs=tok_kwargs,
624
)
625
626
def _get_mm_fields_config(
vllm/model_executor/models/mimo_v2_omni.py
+1
-2
@@ -917,7 +917,6 @@ class MiMoV2OmniMultiModalProcessor(BaseMultiModalProcessor[MiMoV2OmniProcessing
917
prompt: str,
918
mm_data: Mapping[str, object],
919
mm_kwargs: Mapping[str, object],
920
- tok_kwargs: Mapping[str, object],
920
) -> BatchFeature:
921
"""Convert numpy video arrays to (TCHW, timestamps) tuples for MiMo.
922
Also remap 'audios' → 'audio' since MiMoOmniProcessor.__call__ uses
@@ -1000,7 +999,7 @@ class MiMoV2OmniMultiModalProcessor(BaseMultiModalProcessor[MiMoV2OmniProcessing
999
1000
mm_data = {**mm_data, "videos": converted}
1001
1003
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
1002
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
1003
1004
def _get_prompt_updates(
1005
self,
vllm/model_executor/models/minicpmo.py
+2
-5
@@ -436,7 +436,6 @@ class MiniCPMOMultiModalProcessor(MiniCPMVMultiModalProcessor[MiniCPMOProcessing
436
self,
437
mm_data: Mapping[str, object],
438
mm_kwargs: Mapping[str, object],
439
- tok_kwargs: Mapping[str, object],
439
) -> Mapping[str, NestedTensors]:
440
if (audios := mm_data.get("audios")) is None:
441
return {}
@@ -453,7 +452,6 @@ class MiniCPMOMultiModalProcessor(MiniCPMVMultiModalProcessor[MiniCPMOProcessing
452
prompts=[self.info.audio_pattern] * len(parsed_audios),
453
mm_data={"audios": [[audio] for audio in parsed_audios]},
454
mm_kwargs={**mm_kwargs, "chunk_input": True},
456
- tok_kwargs=tok_kwargs,
455
out_keys={"audio_features", "audio_feature_lens"},
456
)
457
@@ -486,11 +484,10 @@ class MiniCPMOMultiModalProcessor(MiniCPMVMultiModalProcessor[MiniCPMOProcessing
484
self,
485
mm_data: Mapping[str, object],
486
mm_kwargs: Mapping[str, object],
489
- tok_kwargs: Mapping[str, object],
487
) -> Mapping[str, NestedTensors]:
488
return {
492
- **super().process_mm_inputs(mm_data, mm_kwargs, tok_kwargs),
493
- **self.process_audios(mm_data, mm_kwargs, tok_kwargs),
489
+ **super().process_mm_inputs(mm_data, mm_kwargs),
490
+ **self.process_audios(mm_data, mm_kwargs),
491
}
492
493
def _get_prompt_updates(
vllm/model_executor/models/minicpmv.py
+4
-22
@@ -869,7 +869,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
869
self,
870
mm_data: Mapping[str, object],
871
mm_kwargs: Mapping[str, object],
872
- tok_kwargs: Mapping[str, object],
872
) -> Mapping[str, NestedTensors]:
873
if (images := mm_data.get("images")) is None:
874
return {}
@@ -886,7 +885,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
885
prompts=[self.info.image_pattern] * len(parsed_images),
886
mm_data={"images": [[image] for image in parsed_images]},
887
mm_kwargs=mm_kwargs,
889
- tok_kwargs=tok_kwargs,
888
out_keys={"pixel_values", "image_sizes", "tgt_sizes"},
889
)
890
@@ -896,7 +894,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
894
self,
895
mm_data: Mapping[str, object],
896
mm_kwargs: Mapping[str, object],
899
- tok_kwargs: Mapping[str, object],
897
) -> Mapping[str, NestedTensors]:
898
if (videos := mm_data.get("videos")) is None:
899
return {}
@@ -918,7 +915,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
915
**mm_kwargs,
916
"max_slice_nums": self.info.get_video_max_slice_num(),
917
},
921
- tok_kwargs=tok_kwargs,
918
out_keys={"pixel_values", "image_sizes", "tgt_sizes"},
919
)
920
@@ -930,11 +926,10 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
926
self,
927
mm_data: Mapping[str, object],
928
mm_kwargs: Mapping[str, object],
933
- tok_kwargs: Mapping[str, object],
929
) -> Mapping[str, NestedTensors]:
930
return {
936
- **self.process_images(mm_data, mm_kwargs, tok_kwargs),
937
- **self.process_videos(mm_data, mm_kwargs, tok_kwargs),
931
+ **self.process_images(mm_data, mm_kwargs),
932
+ **self.process_videos(mm_data, mm_kwargs),
933
}
934
935
def _apply_prompt_updates(
@@ -993,7 +988,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
988
prompts: list[str],
989
mm_data: Mapping[str, Sequence[object]],
990
mm_kwargs: Mapping[str, object],
996
- tok_kwargs: Mapping[str, object],
991
*,
992
out_keys: set[str],
993
) -> dict[str, NestedTensors]:
@@ -1003,7 +997,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
997
prompt=prompts, # type: ignore
998
mm_data=mm_data,
999
mm_kwargs=mm_kwargs,
1006
- tok_kwargs=tok_kwargs,
1000
)
1001
else:
1002
inputs = defaultdict[str, list[torch.Tensor]](list)
@@ -1013,7 +1006,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
1006
prompt=prompt,
1007
mm_data={k: v[i] for k, v in mm_data.items()},
1008
mm_kwargs=mm_kwargs,
1016
- tok_kwargs=tok_kwargs,
1009
)
1010
1011
for k, v in inputs_one.items():
@@ -1027,12 +1019,11 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
1019
prompt: str,
1020
mm_data: Mapping[str, object],
1021
mm_kwargs: Mapping[str, object],
1030
- tok_kwargs: Mapping[str, object],
1022
) -> BatchFeature:
1023
tokenizer = self.info.get_tokenizer()
1024
1034
- input_ids = torch.tensor([tokenizer.encode(prompt, **tok_kwargs)])
1035
- mm_inputs = self.process_mm_inputs(mm_data, mm_kwargs, tok_kwargs)
1025
+ input_ids = torch.tensor([tokenizer.encode(prompt)])
1026
+ mm_inputs = self.process_mm_inputs(mm_data, mm_kwargs)
1027
1028
return BatchFeature(
1029
{
@@ -1041,15 +1032,6 @@ class MiniCPMVMultiModalProcessor(BaseMultiModalProcessor[_I]):
1032
}
1033
)
1034
1044
- def _hf_processor_applies_updates(
1045
- self,
1046
- prompt_text: str,
1047
- mm_items: MultiModalDataItems,
1048
- hf_processor_mm_kwargs: Mapping[str, object],
1049
- tokenization_kwargs: Mapping[str, object],
1050
- ) -> bool:
1051
- return False
1052
-
1035
def _get_prompt_updates(
1036
self,
1037
mm_items: MultiModalDataItems,
vllm/model_executor/models/minicpmv4_6.py
-2
@@ -154,7 +154,6 @@ class MiniCPMV4_6MultiModalProcessor(MiniCPMVMultiModalProcessor):
154
self,
155
mm_data: Mapping[str, object],
156
mm_kwargs: Mapping[str, object],
157
- tok_kwargs: Mapping[str, object],
157
) -> Mapping[str, NestedTensors]:
158
if (images := mm_data.get("images")) is None:
159
return {}
@@ -221,7 +220,6 @@ class MiniCPMV4_6MultiModalProcessor(MiniCPMVMultiModalProcessor):
220
self,
221
mm_data: Mapping[str, object],
222
mm_kwargs: Mapping[str, object],
224
- tok_kwargs: Mapping[str, object],
223
) -> Mapping[str, NestedTensors]:
224
if (videos := mm_data.get("videos")) is None:
225
return {}
vllm/model_executor/models/mistral3.py
-2
@@ -238,13 +238,11 @@ class Mistral3MultiModalProcessor(BaseMultiModalProcessor[Mistral3ProcessingInfo
238
prompt: str,
239
mm_data: Mapping[str, object],
240
mm_kwargs: Mapping[str, object],
241
- tok_kwargs: Mapping[str, object],
241
) -> BatchFeature:
242
processed_outputs = super()._call_hf_processor(
243
prompt=prompt,
244
mm_data=mm_data,
245
mm_kwargs=mm_kwargs,
247
- tok_kwargs=tok_kwargs,
246
)
247
248
pixel_values = processed_outputs.get("pixel_values")
vllm/model_executor/models/mllama4.py
-2
@@ -594,13 +594,11 @@ class Mllama4MultiModalProcessor(BaseMultiModalProcessor[Mllama4ProcessingInfo])
594
prompt: str,
595
mm_data: Mapping[str, object],
596
mm_kwargs: Mapping[str, object],
597
- tok_kwargs: Mapping[str, object],
597
) -> BatchFeature:
598
processed_outputs = super()._call_hf_processor(
599
prompt=prompt,
600
mm_data=mm_data,
601
mm_kwargs=mm_kwargs,
603
- tok_kwargs=tok_kwargs,
602
)
603
604
processor = self.info.get_hf_processor(**mm_kwargs)
vllm/model_executor/models/molmo.py
+1
-2
@@ -1128,13 +1128,12 @@ class MolmoMultiModalProcessor(BaseMultiModalProcessor[MolmoProcessingInfo]):
1128
prompt: str,
1129
mm_data: Mapping[str, object],
1130
mm_kwargs: Mapping[str, object],
1131
- tok_kwargs: Mapping[str, object],
1131
) -> BatchFeature:
1132
hf_processor = self.info.get_hf_processor(**mm_kwargs)
1133
processed_outputs = self.info.ctx.call_hf_processor(
1134
hf_processor.process,
1135
dict(text=prompt, **mm_data),
1137
- dict(**mm_kwargs, **tok_kwargs),
1136
+ mm_kwargs,
1137
)
1138
1139
tokenizer = hf_processor.tokenizer
vllm/model_executor/models/molmo2.py
+2
-3
@@ -1948,7 +1948,6 @@ class Molmo2MultiModalProcessor(BaseMultiModalProcessor[Molmo2ProcessingInfo]):
1948
prompt: str,
1949
mm_data: Mapping[str, object],
1950
mm_kwargs: Mapping[str, object],
1951
- tok_kwargs: Mapping[str, object],
1951
) -> BatchFeature:
1952
mm_data = dict(mm_data)
1953
@@ -2008,7 +2007,7 @@ class Molmo2MultiModalProcessor(BaseMultiModalProcessor[Molmo2ProcessingInfo]):
2007
video_outputs = self.info.ctx.call_hf_processor(
2008
patched_call,
2009
dict(text=VIDEO_PROMPT, **video_mm_data),
2011
- dict(**video_mm_kwargs, **tok_kwargs),
2010
+ video_mm_kwargs,
2011
)
2012
2013
input_ids = video_outputs.pop("input_ids")
@@ -2058,7 +2057,7 @@ class Molmo2MultiModalProcessor(BaseMultiModalProcessor[Molmo2ProcessingInfo]):
2057
processed_outputs = self.info.ctx.call_hf_processor(
2058
patched_call,
2059
dict(text=prompt, **mm_data),
2061
- dict(**mm_kwargs, **tok_kwargs),
2060
+ mm_kwargs,
2061
)
2062
2063
if (images := mm_data.get("images")) is not None:
vllm/model_executor/models/moondream3.py
+1
-14
@@ -947,11 +947,10 @@ class Moondream3MultiModalProcessor(BaseMultiModalProcessor[Moondream3Processing
947
prompt: str,
948
mm_data: Mapping[str, object],
949
mm_kwargs: Mapping[str, object],
950
- tok_kwargs: Mapping[str, object],
950
) -> BatchFeature:
951
# Moondream3's processor handles images directly rather than exposing a
952
# separate `image_processor`, so keep the cache path on text+MM calls.
954
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
953
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
954
955
@cached_property
956
def bos_image_placeholder_tokens(self) -> list[int]:
@@ -977,18 +976,6 @@ class Moondream3MultiModalProcessor(BaseMultiModalProcessor[Moondream3Processing
976
"tilings": MultiModalFieldConfig.batched("image", keep_on_cpu=True),
977
}
978
980
- def _hf_processor_applies_updates(
981
- self,
982
- prompt_text: str,
983
- mm_items: MultiModalDataItems,
984
- hf_processor_mm_kwargs: Mapping[str, object],
985
- tokenization_kwargs: Mapping[str, object],
986
- ) -> bool:
987
- # Moondream3 HF processor does NOT expand placeholder tokens.
988
- # vLLM expands BOS + <image> so the whole HF image prefix is marked
989
- # bidirectional by the multimodal prefix-LM mask.
990
- return False
991
-
979
def _get_prompt_updates(
980
self,
981
mm_items: MultiModalDataItems,
vllm/model_executor/models/moss_audio.py
+35
-7
@@ -49,6 +49,7 @@ from vllm.multimodal.processing import (
49
BaseDummyInputsBuilder,
50
BaseMultiModalProcessor,
51
BaseProcessingInfo,
52
+ InputProcessingContext,
53
PromptReplacement,
54
PromptUpdate,
55
PromptUpdateDetails,
@@ -102,6 +103,34 @@ MOSS_AUDIO_PROCESSOR_CONFIG_KEYS = {
103
"enable_time_marker",
104
"mel_config",
105
}
106
+MOSS_AUDIO_PLACEHOLDER_TOKENS = (
107
+ MOSS_AUDIO_BOS_TOKEN,
108
+ MOSS_AUDIO_TOKEN,
109
+ MOSS_AUDIO_EOS_TOKEN,
110
+)
111
+
112
+
113
+def _ensure_moss_audio_placeholder_tokens(tokenizer: object) -> None:
114
+ """Register the audio placeholder tokens if the tokenizer lacks them.
115
+
116
+ The MOSS-Audio hub tokenizer does not define the audio placeholder
117
+ tokens (the reference HF processor patches them in at runtime). Left
118
+ as plain text, they merge with adjacent tokens under BPE, so prompts
119
+ no longer contain a stable token sequence for prompt updates to match.
120
+ """
121
+ convert_tokens_to_ids = getattr(tokenizer, "convert_tokens_to_ids", None)
122
+ add_tokens = getattr(tokenizer, "add_tokens", None)
123
+ if convert_tokens_to_ids is None or add_tokens is None:
124
+ return
125
+
126
+ unk_token_id = getattr(tokenizer, "unk_token_id", None)
127
+ missing_tokens = [
128
+ token
129
+ for token in MOSS_AUDIO_PLACEHOLDER_TOKENS
130
+ if convert_tokens_to_ids(token) in (None, unk_token_id)
131
+ ]
132
+ if missing_tokens:
133
+ add_tokens(missing_tokens, special_tokens=True)
134
135
136
class MossAudioAudioInputs(TensorSchema):
@@ -1157,6 +1186,11 @@ class MossAudioProcessor:
1186
1187
1188
class MossAudioProcessingInfo(BaseProcessingInfo):
1189
+ def __init__(self, ctx: InputProcessingContext) -> None:
1190
+ super().__init__(ctx)
1191
+ if ctx.tokenizer is not None:
1192
+ _ensure_moss_audio_placeholder_tokens(ctx.tokenizer)
1193
+
1194
def get_hf_config(self) -> MossAudioConfig:
1195
config = self.ctx.get_hf_config()
1196
if isinstance(config, MossAudioConfig):
@@ -1306,7 +1340,6 @@ class MossAudioMultiModalProcessor(BaseMultiModalProcessor[MossAudioProcessingIn
1340
prompt: str,
1341
mm_data: Mapping[str, object],
1342
mm_kwargs: Mapping[str, object],
1309
- tok_kwargs: Mapping[str, object],
1343
) -> BatchFeature:
1344
mm_data = dict(mm_data)
1345
audios = mm_data.pop("audios", [])
@@ -1314,15 +1347,10 @@ class MossAudioMultiModalProcessor(BaseMultiModalProcessor[MossAudioProcessingIn
1347
mm_data["audio"] = audios
1348
mm_kwargs = dict(mm_kwargs)
1349
processor_kwargs = _filter_moss_audio_processor_config(mm_kwargs)
1317
- tok_kwargs = {
1318
- key: value
1319
- for key, value in tok_kwargs.items()
1320
- if key not in MOSS_AUDIO_PROCESSOR_CONFIG_KEYS
1321
- }
1350
return self.info.ctx.call_hf_processor(
1351
self.info.get_hf_processor(**processor_kwargs),
1352
dict(text=prompt, **mm_data),
1325
- dict(**tok_kwargs),
1353
+ {},
1354
)
1355
1356
def _get_mm_fields_config(
vllm/model_executor/models/moss_transcribe_diarize.py
+2
-15
@@ -466,33 +466,20 @@ class MossTranscribeDiarizeMultiModalProcessor(
466
prompt: str,
467
mm_data: Mapping[str, object],
468
mm_kwargs: Mapping[str, object],
469
- tok_kwargs: Mapping[str, object],
469
) -> BatchFeature:
470
tokenizer = self.info.get_tokenizer()
471
audios = _get_audios_from_mm_data(mm_data)
472
if not audios:
474
- input_ids = tokenizer.encode(
475
- prompt,
476
- add_special_tokens=tok_kwargs.get("add_special_tokens", False),
477
- )
473
+ input_ids = tokenizer.encode(prompt, add_special_tokens=False)
474
return BatchFeature({"input_ids": [input_ids]}, tensor_type="pt")
475
476
processed = self.info.ctx.call_hf_processor(
477
self.info.get_hf_processor(**mm_kwargs),
478
dict(text=prompt, audio=audios),
483
- dict(**mm_kwargs, **tok_kwargs),
479
+ mm_kwargs,
480
)
481
return _add_vllm_audio_metadata(processed, len(audios))
482
487
- def _hf_processor_applies_updates(
488
- self,
489
- prompt_text: str,
490
- mm_items: MultiModalDataItems,
491
- hf_processor_mm_kwargs: Mapping[str, object],
492
- tokenization_kwargs: Mapping[str, object],
493
- ) -> bool:
494
- return mm_items.get_count("audio", strict=False) > 0
495
-
483
def _get_mm_fields_config(
484
self,
485
hf_inputs: BatchFeature,
vllm/model_executor/models/muse_glimmer.py
-13
@@ -262,23 +262,11 @@ class MuseGlimmerDummyInputsBuilder(BaseDummyInputsBuilder[MuseGlimmerProcessing
262
class MuseGlimmerMultiModalProcessor(
263
BaseMultiModalProcessor[MuseGlimmerProcessingInfo]
264
):
265
- def _apply_hf_processor_text_only(
266
- self,
267
- prompt_text: str,
268
- tokenization_kwargs: Mapping[str, object],
269
- ) -> list[int]:
270
- tokenizer = self.info.get_tokenizer()
271
- return tokenizer.encode(
272
- prompt_text,
273
- **{"add_special_tokens": False, **tokenization_kwargs},
274
- )
275
-
265
def _call_hf_processor(
266
self,
267
prompt: str,
268
mm_data: Mapping[str, object],
269
mm_kwargs: Mapping[str, object],
281
- tok_kwargs: Mapping[str, object],
270
) -> BatchFeature:
271
processor = self.info.get_hf_processor(**mm_kwargs)
272
tokenizer = processor.tokenizer
@@ -366,7 +354,6 @@ class MuseGlimmerMultiModalProcessor(
354
video_pixel_values=video_pixels,
355
video_feature_sizes=torch.tensor(video_sizes),
356
)
369
- del tok_kwargs
357
return BatchFeature(data=data, tensor_type=None)
358
359
def _get_mm_fields_config(
vllm/model_executor/models/nano_nemotron_vl.py
+2
-8
@@ -366,14 +366,13 @@ class NanoNemotronVLMultiModalProcessor(
366
prompt: str,
367
mm_data: Mapping[str, object],
368
mm_kwargs: Mapping[str, object],
369
- tok_kwargs: Mapping[str, object],
369
) -> BatchFeature:
370
"""
371
Bypass `call_hf_processor_mm_only` by no-op overriding`_call_hf_processor`,
372
so it chooses this path:
373
`type(self)._call_hf_processor != BaseMultiModalProcessor._call_hf_processor`
374
"""
376
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
375
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
376
377
def _get_image_fields_config(self, hf_inputs: BatchFeature):
378
if self.info.is_dynamic_tiler:
@@ -714,10 +713,8 @@ class NanoNemotronVLMultiModalProcessor(
713
if not audio_items:
714
return super().apply(inputs, timing_ctx)
715
717
- prompt = inputs.prompt
716
tokenizer = self.info.get_tokenizer()
719
- if not isinstance(prompt, str):
720
- prompt = tokenizer.decode(prompt, skip_special_tokens=False)
717
+ prompt = tokenizer.decode(inputs.prompt, skip_special_tokens=False)
718
719
# Inject AUDIO_CONTEXT only after <video> tokens whose video
720
# actually contained an audio stream (preserving video-audio pairing).
@@ -733,9 +730,6 @@ class NanoNemotronVLMultiModalProcessor(
730
731
inputs.prompt = tokenizer.encode(prompt, add_special_tokens=False)
732
736
- if inputs.tokenization_kwargs is None:
737
- inputs.tokenization_kwargs = {}
738
-
733
# Bypass the cached path: the HF processor must receive the
734
# prompt (with injected <so_embedding>) and the audio data
735
# together so it can perform audio-token replacement natively.
vllm/model_executor/models/nemotron_parse.py
+3
-6
@@ -406,9 +406,9 @@ class NemotronParseMultiModalProcessor(
406
):
407
def create_encoder_prompt(
408
self,
409
- prompt: str | list[int],
409
+ prompt: list[int],
410
mm_items: MultiModalDataItems,
411
- ) -> str | list[int]:
411
+ ) -> list[int]:
412
return [0]
413
414
def _call_hf_processor(
@@ -416,12 +416,9 @@ class NemotronParseMultiModalProcessor(
416
prompt: str,
417
mm_data: Mapping[str, object],
418
mm_kwargs: Mapping[str, object],
419
- tok_kwargs: Mapping[str, object],
419
) -> BatchFeature:
420
if mm_data:
422
- processed_outputs = super()._call_hf_processor(
423
- prompt, mm_data, mm_kwargs, tok_kwargs
424
- )
421
+ processed_outputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs)
422
else:
423
hf_processor = self.info.get_hf_processor()
424
tokenizer = hf_processor.tokenizer
vllm/model_executor/models/opencua.py
-10
@@ -141,16 +141,6 @@ class OpenCUAMultiModalProcessor(BaseMultiModalProcessor[OpenCUAProcessingInfo])
141
self.info.get_hf_config().vision_config.spatial_merge_size
142
)(hf_inputs)
143
144
- def _hf_processor_applies_updates(
145
- self,
146
- prompt_text: str,
147
- mm_items: MultiModalDataItems,
148
- hf_processor_mm_kwargs: Mapping[str, object],
149
- tokenization_kwargs: Mapping[str, object],
150
- ) -> bool:
151
- """vLLM이 prompt 업데이트를 처리하도록 False 반환."""
152
- return False
153
-
144
def _get_prompt_updates(
145
self,
146
mm_items: MultiModalDataItems,
vllm/model_executor/models/openvla.py
-9
@@ -327,15 +327,6 @@ class OpenVLAMultiModalProcessor(BaseMultiModalProcessor[OpenVLAProcessingInfo])
327
) -> Mapping[str, MultiModalFieldConfig]:
328
return dict(pixel_values=MultiModalFieldConfig.batched("image"))
329
330
- def _hf_processor_applies_updates(
331
- self,
332
- prompt_text: str,
333
- mm_items: MultiModalDataItems,
334
- hf_processor_mm_kwargs: Mapping[str, object],
335
- tokenization_kwargs: Mapping[str, object],
336
- ) -> bool:
337
- return False
338
-
330
def _get_prompt_updates(
331
self,
332
mm_items: MultiModalDataItems,
vllm/model_executor/models/ovis.py
-2
@@ -346,7 +346,6 @@ class OvisMultiModalProcessor(BaseMultiModalProcessor[OvisProcessingInfo]):
346
prompt: str,
347
mm_data: Mapping[str, object],
348
mm_kwargs: Mapping[str, object],
349
- tok_kwargs: Mapping[str, object],
349
) -> BatchFeature:
350
if not mm_data:
351
# Avoid warning from HF logger for text-only input
@@ -358,7 +357,6 @@ class OvisMultiModalProcessor(BaseMultiModalProcessor[OvisProcessingInfo]):
357
prompt=prompt,
358
mm_data=mm_data,
359
mm_kwargs=mm_kwargs,
361
- tok_kwargs=tok_kwargs,
360
)
361
362
hf_processor = self.info.get_hf_processor()
vllm/model_executor/models/ovis2_5.py
-2
@@ -337,7 +337,6 @@ class Ovis2_5MultiModalProcessor(BaseMultiModalProcessor[Ovis2_5ProcessingInfo])
337
prompt: str,
338
mm_data: Mapping[str, object],
339
mm_kwargs: Mapping[str, object],
340
- tok_kwargs: Mapping[str, object],
340
) -> BatchFeature:
341
if not mm_data:
342
# Avoid warning from HF logger for text-only input
@@ -349,7 +348,6 @@ class Ovis2_5MultiModalProcessor(BaseMultiModalProcessor[Ovis2_5ProcessingInfo])
348
prompt=prompt,
349
mm_data=mm_data,
350
mm_kwargs=mm_kwargs,
352
- tok_kwargs=tok_kwargs,
351
)
352
hf_processor = self.info.get_hf_processor()
353
vllm/model_executor/models/paddleocr_vl.py
+1
-2
@@ -249,7 +249,6 @@ class PaddleOCRVLMultiModalProcessor(
249
prompt: str,
250
mm_data: Mapping[str, object],
251
mm_kwargs: Mapping[str, object],
252
- tok_kwargs: Mapping[str, object],
252
) -> BatchFeature:
253
if mm_data:
254
final_mm_kwargs = dict(mm_kwargs or {})
@@ -259,7 +258,7 @@ class PaddleOCRVLMultiModalProcessor(
258
processed_outputs = self.info.ctx.call_hf_processor(
259
self.info.get_hf_processor(**final_mm_kwargs),
260
dict(text=prompt, **mm_data),
262
- dict(**mm_kwargs, **tok_kwargs),
261
+ mm_kwargs,
262
)
263
num_patches_per_image = processed_outputs["image_grid_thw"].prod(-1)
264
processed_outputs["pixel_values"] = processed_outputs["pixel_values"].split(
vllm/model_executor/models/paligemma.py
-2
@@ -157,7 +157,6 @@ class PaliGemmaMultiModalProcessor(BaseMultiModalProcessor[PaliGemmaProcessingIn
157
prompt: str,
158
mm_data: Mapping[str, object],
159
mm_kwargs: Mapping[str, object],
160
- tok_kwargs: Mapping[str, object],
160
) -> BatchFeature:
161
tokenizer = self.info.get_tokenizer()
162
if not mm_data:
@@ -168,7 +167,6 @@ class PaliGemmaMultiModalProcessor(BaseMultiModalProcessor[PaliGemmaProcessingIn
167
prompt=prompt,
168
mm_data=mm_data,
169
mm_kwargs=mm_kwargs,
171
- tok_kwargs=tok_kwargs,
170
)
171
172
def _get_mm_fields_config(
vllm/model_executor/models/phi3v.py
+2
-8
@@ -401,13 +401,11 @@ class Phi3VMultiModalProcessor(BaseMultiModalProcessor[Phi3VProcessingInfo]):
401
prompt: str,
402
mm_data: Mapping[str, object],
403
mm_kwargs: Mapping[str, object],
404
- tok_kwargs: Mapping[str, object],
404
) -> BatchFeature:
405
processed_outputs = super()._call_hf_processor(
406
prompt=prompt,
407
mm_data=mm_data,
408
mm_kwargs=mm_kwargs,
410
- tok_kwargs=tok_kwargs,
409
)
410
411
input_ids = processed_outputs["input_ids"]
@@ -497,12 +495,8 @@ class Phi3VMultiModalProcessor(BaseMultiModalProcessor[Phi3VProcessingInfo]):
495
if len(token_ids) and token_ids[0] == tokenizer.bos_token_id:
496
token_ids = token_ids[1:]
497
text = tokenizer.decode(token_ids)
500
- for special_tokens in tokenizer.special_tokens_map.values():
501
- if isinstance(special_tokens, str):
502
- text = text.replace(f"{special_tokens} ", special_tokens)
503
- elif isinstance(special_tokens, list):
504
- for special_token in special_tokens:
505
- text = text.replace(f"{special_token} ", special_token)
498
+ for special_token in tokenizer.all_special_tokens:
499
+ text = text.replace(f"{special_token} ", special_token)
500
# perform hf behavior
501
# https://huggingface.co/microsoft/Phi-3.5-vision-instruct/blob/64f88b6/processing_phi3_v.py#L407
502
pattern = r"<\|image_\d+\|>"
vllm/model_executor/models/phi4mm.py
+1
-4
@@ -873,7 +873,6 @@ class Phi4MMMultiModalProcessor(BaseMultiModalProcessor[Phi4MMProcessingInfo]):
873
prompt: str,
874
mm_data: Mapping[str, object],
875
mm_kwargs: Mapping[str, object],
876
- tok_kwargs: Mapping[str, object],
876
) -> BatchFeature:
877
if not mm_data:
878
prompt_ids = self.info.get_tokenizer().encode(prompt)
@@ -884,9 +883,7 @@ class Phi4MMMultiModalProcessor(BaseMultiModalProcessor[Phi4MMProcessingInfo]):
883
if audio_data := mm_data.get("audios", []):
884
mm_data["audios"] = [(data, sr) for data in audio_data]
885
887
- processed_outputs = super()._call_hf_processor(
888
- prompt, mm_data, mm_kwargs, tok_kwargs
889
- )
886
+ processed_outputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs)
887
888
hf_processor = self.info.get_hf_processor(**mm_kwargs)
889
num_img_tokens = [
vllm/model_executor/models/phi4siglip.py
-16
@@ -147,13 +147,11 @@ class Phi4SiglipMultiModalProcessor(
147
prompt: str,
148
mm_data: Mapping[str, object],
149
mm_kwargs: Mapping[str, object],
150
- tok_kwargs: Mapping[str, object],
150
) -> BatchFeature:
151
processed = super()._call_hf_processor(
152
prompt=prompt,
153
mm_data=mm_data,
154
mm_kwargs=mm_kwargs,
156
- tok_kwargs=tok_kwargs,
155
)
156
157
# The HF processor's tokenizer_image_token() replaces the "<image>"
@@ -170,20 +168,6 @@ class Phi4SiglipMultiModalProcessor(
168
169
return processed
170
173
- def _hf_processor_applies_updates(
174
- self,
175
- prompt_text: str,
176
- mm_items: MultiModalDataItems,
177
- hf_processor_mm_kwargs: Mapping[str, object],
178
- tokenization_kwargs: Mapping[str, object],
179
- ) -> bool:
180
- # The HF processor replaces "<image>" with a single -200 placeholder
181
- # but does NOT expand it into N vision-encoder tokens. Since we also
182
- # re-tokenize the prompt (see _call_hf_processor), prompt updates are
183
- # never applied by the HF processor — vLLM handles the expansion via
184
- # _apply_prompt_updates.
185
- return False
186
-
171
def _get_mm_fields_config(
172
self,
173
hf_inputs: BatchFeature,
vllm/model_executor/models/pixtral.py
+4
-6
@@ -225,14 +225,12 @@ class PixtralMultiModalProcessor(BaseMultiModalProcessor[PixtralProcessingInfo])
225
prompt: str,
226
mm_data: Mapping[str, object],
227
mm_kwargs: Mapping[str, object],
228
- tok_kwargs: Mapping[str, object],
228
) -> BatchFeature:
230
- outputs = super()._call_hf_processor(
231
- prompt=prompt,
232
- mm_data=mm_data,
233
- mm_kwargs=mm_kwargs,
229
+ outputs = self.info.ctx.call_hf_processor(
230
+ self.info.get_hf_processor(**mm_kwargs),
231
+ dict(text=prompt, **mm_data),
232
# Avoid padding issue
235
- tok_kwargs={**tok_kwargs, "return_tensors": None},
233
+ dict(**mm_kwargs, return_tensors=None),
234
)
235
236
# Missing batch dimension
vllm/model_executor/models/qwen2_5_omni_thinker.py
+1
-38
@@ -504,7 +504,6 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
504
prompt: str,
505
mm_data: Mapping[str, object],
506
mm_kwargs: Mapping[str, object],
507
- tok_kwargs: Mapping[str, object],
507
) -> BatchFeature:
508
mm_data = dict(mm_data)
509
audios = mm_data.pop("audios", [])
@@ -552,7 +551,6 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
551
prompt=prompt,
552
mm_data=mm_data,
553
mm_kwargs=mm_kwargs,
555
- tok_kwargs=tok_kwargs,
554
)
555
556
input_features = hf_inputs.pop("input_features", None)
@@ -887,44 +885,10 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
885
),
886
]
887
890
- def _apply_hf_processor_main(
891
- self,
892
- prompt: str | list[int],
893
- mm_items: MultiModalDataItems,
894
- hf_processor_mm_kwargs: Mapping[str, object],
895
- tokenization_kwargs: Mapping[str, object],
896
- *,
897
- enable_hf_prompt_update: bool,
898
- ) -> tuple[list[int], BatchFeature, bool]:
899
- """
900
- Qwen2.5-Omni reimplements this function to handle text only.
901
- """
902
- if isinstance(prompt, str):
903
- if enable_hf_prompt_update:
904
- return self._apply_hf_processor_text_mm(
905
- prompt_text=prompt,
906
- mm_items=mm_items,
907
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
908
- tokenization_kwargs=tokenization_kwargs,
909
- )
910
- tokenizer = self.info.get_tokenizer()
911
- prompt_ids = tokenizer.encode(prompt)
912
- else:
913
- prompt_ids = self._apply_hf_processor_tokens_only(prompt)
914
-
915
- mm_processed_data = self._apply_hf_processor_mm_only(
916
- mm_items=mm_items,
917
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
918
- tokenization_kwargs=tokenization_kwargs,
919
- )
920
-
921
- return prompt_ids, mm_processed_data, False
922
-
888
def _apply_hf_processor_mm_only(
889
self,
890
mm_items: MultiModalDataItems,
891
hf_processor_mm_kwargs: Mapping[str, object],
927
- tokenization_kwargs: Mapping[str, object],
892
) -> BatchFeature:
893
"""
894
Qwen2.5-Omni reimplements this function to handle `use_audio_in_video`.
@@ -939,11 +903,10 @@ class Qwen2_5OmniThinkerMultiModalProcessor(
903
)
904
mm_counts["audio"] -= mm_counts["video"]
905
942
- _, mm_processed_data, _ = self._apply_hf_processor_text_mm(
906
+ _, mm_processed_data = self._apply_hf_processor_text_mm(
907
prompt_text=self.dummy_inputs.get_dummy_text(mm_counts),
908
mm_items=mm_items,
909
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
946
- tokenization_kwargs=tokenization_kwargs,
910
)
911
912
return mm_processed_data
vllm/model_executor/models/qwen2_5_vl.py
+1
-2
@@ -1159,11 +1159,10 @@ class Qwen2_5_VLMultiModalProcessor(Qwen2VLMultiModalProcessor):
1159
prompt: str,
1160
mm_data: Mapping[str, object],
1161
mm_kwargs: Mapping[str, object],
1162
- tok_kwargs: Mapping[str, object],
1162
) -> BatchFeature:
1163
# Override to use the text path instead of token path to use the
1164
# video-specific logic in processing_qwen2_5_vl.py
1166
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
1165
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
1166
1167
def _get_prompt_updates(
1168
self,
vllm/model_executor/models/qwen2_audio.py
-2
@@ -240,7 +240,6 @@ class Qwen2AudioMultiModalProcessor(BaseMultiModalProcessor[Qwen2AudioProcessing
240
prompt: str,
241
mm_data: Mapping[str, object],
242
mm_kwargs: Mapping[str, Any],
243
- tok_kwargs: Mapping[str, object],
243
) -> BatchFeature:
244
# NOTE - we rename audios -> audio in mm data because transformers has
245
# deprecated audios for the qwen2audio processor and will remove
@@ -265,7 +264,6 @@ class Qwen2AudioMultiModalProcessor(BaseMultiModalProcessor[Qwen2AudioProcessing
264
prompt=prompt,
265
mm_data=mm_data,
266
mm_kwargs=mm_kwargs,
268
- tok_kwargs=tok_kwargs,
267
)
268
269
def _get_mm_fields_config(
vllm/model_executor/models/qwen3_omni_moe_thinker.py
+1
-4
@@ -1200,7 +1200,6 @@ class Qwen3OmniMoeThinkerMultiModalProcessor(
1200
prompt: str,
1201
mm_data: Mapping[str, object],
1202
mm_kwargs: Mapping[str, object],
1203
- tok_kwargs: Mapping[str, object],
1203
) -> BatchFeature:
1204
mm_data = dict(mm_data)
1205
audios = mm_data.pop("audios", [])
@@ -1230,7 +1229,6 @@ class Qwen3OmniMoeThinkerMultiModalProcessor(
1229
# released and Transformers version update:
1230
# https://github.com/huggingface/transformers/pull/41473
1231
mm_kwargs = dict(mm_kwargs)
1233
- tok_kwargs = dict(tok_kwargs)
1232
mm_kwargs["audio_kwargs"] = dict(mm_kwargs.get("audio_kwargs") or {})
1233
mm_kwargs["text_kwargs"] = dict(mm_kwargs.get("text_kwargs") or {})
1234
elif mm_kwargs.get("use_audio_in_video") and mm_data.get("videos"):
@@ -1245,7 +1243,6 @@ class Qwen3OmniMoeThinkerMultiModalProcessor(
1243
prompt=prompt,
1244
mm_data=mm_data,
1245
mm_kwargs=mm_kwargs,
1248
- tok_kwargs=tok_kwargs,
1246
)
1247
1248
if (
@@ -1279,7 +1276,7 @@ class Qwen3OmniMoeThinkerMultiModalProcessor(
1276
mm_kwargs: MultiModalKwargsItems,
1277
mm_prompt_updates: MultiModalPromptUpdates,
1278
is_update_applied: bool,
1282
- ) -> tuple[list[int], str, Mapping[str, list[PlaceholderFeaturesInfo]]]:
1279
+ ) -> tuple[list[int], Mapping[str, list[PlaceholderFeaturesInfo]]]:
1280
"""
1281
Qwen3-Omni reimplements this function to handle `use_audio_in_video`.
1282
"""
vllm/model_executor/models/qwen3_vl.py
-3
@@ -1285,7 +1285,6 @@ class Qwen3VLMultiModalProcessor(BaseMultiModalProcessor[Qwen3VLProcessingInfo])
1285
prompt: str,
1286
mm_data: Mapping[str, object],
1287
mm_kwargs: Mapping[str, object],
1288
- tok_kwargs: Mapping[str, object],
1288
) -> BatchFeature:
1289
mm_data = dict(mm_data)
1290
@@ -1370,7 +1369,6 @@ class Qwen3VLMultiModalProcessor(BaseMultiModalProcessor[Qwen3VLProcessingInfo])
1369
prompt="<|vision_start|><|video_pad|><|vision_end|>",
1370
mm_data=video_mm_data,
1371
mm_kwargs=video_mm_kwargs,
1373
- tok_kwargs=tok_kwargs,
1372
)
1373
1374
# Discard HF output input_ids — we use get_video_repl below
@@ -1432,7 +1430,6 @@ class Qwen3VLMultiModalProcessor(BaseMultiModalProcessor[Qwen3VLProcessingInfo])
1430
prompt=prompt,
1431
mm_data=mm_data,
1432
mm_kwargs=non_video_mm_kwargs,
1435
- tok_kwargs=tok_kwargs,
1433
)
1434
1435
# Replace each placeholder with pre-computed video tokens.
vllm/model_executor/models/siglip.py
+7
-30
@@ -191,40 +191,17 @@ class SiglipMultiModalProcessor(BaseMultiModalProcessor[SiglipProcessingInfo]):
191
timing_ctx: TimingContext,
192
) -> MultiModalInput:
193
if inputs.mm_data_items:
194
- if isinstance(inputs.prompt, str):
195
- if len(inputs.prompt) > 0:
196
- raise ValueError(
197
- "SigLIP accepts text-only or image-only inputs, not both! "
198
- "You must pass an image with an empty text prompt."
199
- )
194
+ special_tokens = self.info.get_tokenizer().all_special_ids
195
+ if all(tok in special_tokens for tok in inputs.prompt):
196
+ inputs.prompt = []
197
else:
201
- special_tokens = self.info.get_tokenizer().all_special_ids
202
- if all(tok in special_tokens for tok in inputs.prompt):
203
- inputs.prompt = []
204
- else:
205
- raise ValueError(
206
- "SigLIP accepts text-only or image-only inputs, not both! "
207
- "You must pass an image with an empty token prompt."
208
- )
209
-
210
- # For multi-modal data, the prompt after processing should
211
- # only contain the dummy image tokens
212
- inputs.tokenization_kwargs = {
213
- **inputs.tokenization_kwargs,
214
- "add_special_tokens": False,
215
- }
198
+ raise ValueError(
199
+ "SigLIP accepts text-only or image-only inputs, not both! "
200
+ "You must pass an image with an empty token prompt."
201
+ )
202
203
return super().apply(inputs, timing_ctx)
204
219
- def _hf_processor_applies_updates(
220
- self,
221
- prompt_text: str,
222
- mm_items: MultiModalDataItems,
223
- hf_processor_mm_kwargs: Mapping[str, object],
224
- tokenization_kwargs: Mapping[str, object],
225
- ) -> bool:
226
- return False
227
-
205
def _get_mm_fields_config(
206
self,
207
hf_inputs: BatchFeature,
vllm/model_executor/models/transformers/multimodal.py
+16
-63
@@ -350,24 +350,21 @@ class _MultiModalProcessorBase(BaseMultiModalProcessor[MultiModalProcessingInfo]
350
prompt: str,
351
mm_data: Mapping[str, object],
352
mm_kwargs: Mapping[str, object],
353
- tok_kwargs: Mapping[str, object],
353
) -> "BatchFeature":
354
"""Run the HF processor and unpad inputs."""
355
try:
357
- hf_inputs = super()._call_hf_processor(
358
- prompt, mm_data, mm_kwargs, tok_kwargs
359
- )
356
+ hf_inputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs)
357
except ValueError:
358
if any(mm_data.values()):
359
raise
360
# Some processors reject a prompt holding placeholders with
361
# no data to go with them, so tokenize it without them
365
- prompt_ids = self.info.get_tokenizer().encode(prompt, **tok_kwargs)
362
+ prompt_ids = self.info.get_tokenizer().encode(prompt)
363
hf_inputs = transformers.BatchFeature(
364
dict(input_ids=[prompt_ids]), tensor_type="pt"
365
)
366
self._unpad_images(hf_inputs)
370
- self._unpad_audios(hf_inputs, mm_data, mm_kwargs, tok_kwargs)
367
+ self._unpad_audios(hf_inputs, mm_data, mm_kwargs)
368
return hf_inputs
369
370
def _unpad_audios(
@@ -375,7 +372,6 @@ class _MultiModalProcessorBase(BaseMultiModalProcessor[MultiModalProcessingInfo]
372
hf_inputs: "BatchFeature",
373
mm_data: Mapping[str, object],
374
mm_kwargs: Mapping[str, object],
378
- tok_kwargs: Mapping[str, object],
375
) -> None:
376
"""Replace the audio fields with each audio processed on its own.
377
@@ -395,7 +391,7 @@ class _MultiModalProcessorBase(BaseMultiModalProcessor[MultiModalProcessingInfo]
391
dict(
392
text=self.dummy_inputs.get_dummy_text({"audio": 1}), audio=[audio]
393
),
398
- dict(**mm_kwargs, **tok_kwargs),
394
+ mm_kwargs,
395
)
396
for audio in audios
397
]
@@ -459,13 +455,13 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
455
prompt: str,
456
mm_data: Mapping[str, object],
457
mm_kwargs: Mapping[str, object],
462
- tok_kwargs: Mapping[str, object],
458
) -> "BatchFeature":
459
"""Ask which modality owns each token of the expanded prompt, which is the
460
only marking of the tokens an expansion adds around an item."""
461
if any(mm_data.values()):
462
mm_data = {**mm_data, "return_mm_token_type_ids": True}
468
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
463
+
464
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
465
466
def _get_mm_token_ids(self, modality: str) -> list[int]:
467
"""Token ids marking where `modality` sits in the prompt, which for some
@@ -613,29 +609,26 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
609
prompt = inputs.prompt
610
mm_items = inputs.mm_data_items
611
hf_processor_mm_kwargs = inputs.hf_processor_mm_kwargs
616
- tokenization_kwargs = inputs.tokenization_kwargs
612
613
with timing_ctx.record("apply_hf_processor"):
614
hf_processor = self.info.get_hf_processor(**hf_processor_mm_kwargs)
620
- if not isinstance(prompt, str):
621
- # HF processors only accept text, and the decoded string already
622
- # contains any special tokens, so don't let them be added again
623
- prompt = hf_processor.decode(prompt)
624
- tokenization_kwargs = {
625
- **tokenization_kwargs,
626
- "add_special_tokens": False,
627
- }
615
+ prompt = hf_processor.decode(prompt)
616
617
# Bypass cached processor and always apply to the full set of mm inputs
618
# NOTE: we can't just set caching=False because base class method
619
# transforms outputs to `MultiModalKwargs` which is not going to
620
# work for Transformers. The vision path has logic tied to
621
# `mm_tokens_per_modality` in _apply_vision()
634
- prompt_ids, processed_data, _ = self._apply_hf_processor_text_mm(
622
+ prompt_ids, processed_data = self._apply_hf_processor_text_mm(
623
prompt_text=prompt,
624
mm_items=mm_items,
637
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
638
- tokenization_kwargs=tokenization_kwargs,
625
+ hf_processor_mm_kwargs={
626
+ **hf_processor_mm_kwargs,
627
+ # HF processors only accept text, and the decoded string already
628
+ # contains any special tokens, so don't let them be added again
629
+ # (`_call_hf_processor` disables `add_special_tokens`).
630
+ "add_special_tokens": False,
631
+ },
632
)
633
634
# Use overrides if provided; fallback to data-dependent hashing.
@@ -731,45 +724,6 @@ class OffsetsMultiModalProcessor(_MultiModalProcessorBase):
724
)
725
return updates
726
734
- def _apply_hf_processor_main(
735
- self,
736
- prompt: str | list[int],
737
- mm_items: MultiModalDataItems,
738
- hf_processor_mm_kwargs: Mapping[str, object],
739
- tokenization_kwargs: Mapping[str, object],
740
- *,
741
- enable_hf_prompt_update: bool,
742
- ) -> tuple[list[int], "BatchFeature", bool]:
743
- """Tokenize the prompt unexpanded, leaving the expansion for vLLM to splice
744
- in, whatever `enable_hf_prompt_update` asks for.
745
-
746
- This differs from `super()` only for a text prompt with
747
- `enable_hf_prompt_update`, where `super()` would keep the expanded token
748
- ids the HF processor returns. Both routes give the same ids, so forcing
749
- this one costs an extra processor call and buys the guarantee that a
750
- request bypassing the cache is identical to a cached one.
751
-
752
- A text prompt only arrives with `enable_hf_prompt_update` when there is
753
- no multi-modal processor cache. Requests carrying pre-computed
754
- embeddings bypass the cache too, but `--enable-mm-embeds` is unsupported
755
- here, so they fail validation shortly afterwards.
756
- """
757
- if isinstance(prompt, str) and enable_hf_prompt_update:
758
- logger.warning_once(
759
- "Disabling the multi-modal processor cache is extra slow with the "
760
- "Transformers modeling backend: the prompt is still tokenized "
761
- "unexpanded and the expansion spliced in, to keep the token ids "
762
- "identical to what the cache produces, which costs an extra HF "
763
- "processor call per request."
764
- )
765
- return super()._apply_hf_processor_main(
766
- prompt,
767
- mm_items,
768
- hf_processor_mm_kwargs,
769
- tokenization_kwargs,
770
- enable_hf_prompt_update=False,
771
- )
772
-
727
def _get_num_image_patches(
728
self,
729
hf_inputs: "BatchFeature",
@@ -824,13 +778,12 @@ class OffsetsMultiModalProcessor(_MultiModalProcessorBase):
778
prompt: str,
779
mm_data: Mapping[str, object],
780
mm_kwargs: Mapping[str, object],
827
- tok_kwargs: Mapping[str, object],
781
) -> "BatchFeature":
782
"""Ask for the replacement each placeholder expands to, and record it as
783
per-item fields: its token ids, and the tokens or patches behind them."""
784
if has_mm_data := any(mm_data.values()):
785
mm_data = {**mm_data, "return_text_replacement_offsets": True}
833
- hf_inputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
786
+ hf_inputs = super()._call_hf_processor(prompt, mm_data, mm_kwargs)
787
# Drop the inputs the model would reject
788
hf_inputs.pop("mm_token_type_ids", None)
789
hf_inputs.pop("token_type_ids", None)
vllm/model_executor/models/ultravox.py
-7
@@ -195,7 +195,6 @@ class UltravoxMultiModalProcessor(BaseMultiModalProcessor[UltravoxProcessingInfo
195
prompt: str,
196
mm_data: Mapping[str, object],
197
mm_kwargs: Mapping[str, object],
198
- tok_kwargs: Mapping[str, object],
198
) -> BatchFeature:
199
# Text-only input not supported in composite processor
200
if not mm_data.get("audios", []):
@@ -218,16 +217,10 @@ class UltravoxMultiModalProcessor(BaseMultiModalProcessor[UltravoxProcessingInfo
217
218
item_processor_data = dict(**mm_data, audios=audios)
219
221
- # some tokenizer kwargs are incompatible with UltravoxProcessor
222
- tok_kwargs.pop("add_special_tokens", None)
223
- tok_kwargs.pop("padding", None)
224
- tok_kwargs.pop("truncation", None)
225
-
220
output = super()._call_hf_processor(
221
prompt=prompt,
222
mm_data=item_processor_data,
223
mm_kwargs=mm_kwargs,
230
- tok_kwargs=tok_kwargs,
224
)
225
output["audio_features"] = output.pop("audio_values")
226
vllm/model_executor/models/voxtral.py
+4
-6
@@ -225,7 +225,6 @@ class VoxtralMultiModalProcessor(BaseMultiModalProcessor[VoxtralProcessingInfo])
225
prompt: str,
226
mm_data: Mapping[str, object],
227
mm_kwargs: Mapping[str, object],
228
- tok_kwargs: Mapping[str, object],
228
) -> BatchFeature:
229
mm_data = dict(mm_data)
230
audios = mm_data.pop("audios", [])
@@ -234,12 +233,11 @@ class VoxtralMultiModalProcessor(BaseMultiModalProcessor[VoxtralProcessingInfo])
233
# MistralCommonVoxtralProcessor accepts "audio"
234
mm_data["audio"] = audios
235
237
- outputs = super()._call_hf_processor(
238
- prompt=prompt,
239
- mm_data=mm_data,
240
- mm_kwargs=mm_kwargs,
236
+ outputs = self.info.ctx.call_hf_processor(
237
+ self.info.get_hf_processor(**mm_kwargs),
238
+ dict(text=prompt, **mm_data),
239
# Avoid padding issue
242
- tok_kwargs={**tok_kwargs, "return_tensors": None},
240
+ dict(**mm_kwargs, return_tensors=None),
241
)
242
243
# Missing batch dimension
vllm/model_executor/models/whisper.py
+2
-12
@@ -747,9 +747,9 @@ class WhisperDummyInputsBuilder(BaseDummyInputsBuilder[WhisperProcessingInfo]):
747
class WhisperMultiModalProcessor(EncDecMultiModalProcessor[WhisperProcessingInfo]):
748
def create_encoder_prompt(
749
self,
750
- prompt: str | list[int],
750
+ prompt: list[int],
751
mm_items: MultiModalDataItems,
752
- ) -> str | list[int]:
752
+ ) -> list[int]:
753
# Strictly speaking, whisper encoder only accept audio features.
754
# We create a dummy encoder prompt here which will be padded to
755
# num_audio_tokens. So that we can create dummy data from this
@@ -761,7 +761,6 @@ class WhisperMultiModalProcessor(EncDecMultiModalProcessor[WhisperProcessingInfo
761
prompt: str,
762
mm_data: Mapping[str, object],
763
mm_kwargs: Mapping[str, object],
764
- tok_kwargs: Mapping[str, object],
764
) -> BatchFeature:
765
if mm_data:
766
feature_extractor = self.info.get_feature_extractor(**mm_kwargs)
@@ -770,19 +769,10 @@ class WhisperMultiModalProcessor(EncDecMultiModalProcessor[WhisperProcessingInfo
769
**mm_kwargs,
770
sampling_rate=feature_extractor.sampling_rate,
771
)
773
- # The HF WhisperProcessor passes **kwargs to both the tokenizer
774
- # and the feature extractor. Text-tokenizer kwargs like
775
- # `truncation` and `max_length` must be removed when audio data
776
- # is present, otherwise the feature extractor interprets
777
- # `max_length` as raw audio samples and truncates the audio.
778
- tok_kwargs = {
779
- k: v for k, v in tok_kwargs.items() if k not in ("truncation", "max_length")
780
- }
772
processed_outputs = super()._call_hf_processor(
773
prompt=prompt,
774
mm_data=mm_data,
775
mm_kwargs=mm_kwargs,
785
- tok_kwargs=tok_kwargs,
776
)
777
if "labels" in processed_outputs:
778
processed_outputs["input_ids"] = processed_outputs.pop("labels")
vllm/models/dots3_note/common/processor.py
+1
-11
@@ -654,18 +654,8 @@ class Dots3NoteMultiModalProcessor(BaseMultiModalProcessor[Dots3NoteProcessingIn
654
prompt: str,
655
mm_data: Mapping[str, object],
656
mm_kwargs: Mapping[str, object],
657
- tok_kwargs: Mapping[str, object],
657
) -> BatchFeature:
659
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
660
-
661
- def _hf_processor_applies_updates(
662
- self,
663
- prompt_text: str,
664
- mm_items: MultiModalDataItems,
665
- hf_processor_mm_kwargs: Mapping[str, object],
666
- tokenization_kwargs: Mapping[str, object],
667
- ) -> bool:
668
- return False
658
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
659
660
def _get_mm_fields_config(
661
self,
vllm/models/inkling/common/mm_preprocess.py
+3
-15
@@ -22,7 +22,7 @@ from vllm.multimodal.inputs import (
22
MultiModalFieldConfig,
23
MultiModalKwargsItems,
24
)
25
-from vllm.multimodal.parse import MultiModalDataItems, MultiModalDataParser
25
+from vllm.multimodal.parse import MultiModalDataParser
26
from vllm.multimodal.processing import (
27
BaseDummyInputsBuilder,
28
BaseMultiModalProcessor,
@@ -179,21 +179,11 @@ class InklingDummyInputsBuilder(BaseDummyInputsBuilder[InklingProcessingInfo]):
179
180
181
class InklingMultiModalProcessor(BaseMultiModalProcessor[InklingProcessingInfo]):
182
- def _hf_processor_applies_updates(
183
- self,
184
- prompt_text: str,
185
- mm_items: MultiModalDataItems,
186
- hf_processor_mm_kwargs: Mapping[str, object],
187
- tokenization_kwargs: Mapping[str, object],
188
- ) -> bool:
189
- return False
190
-
182
def _call_hf_processor(
183
self,
184
prompt: str,
185
mm_data: Mapping[str, object],
186
mm_kwargs: Mapping[str, object],
196
- tok_kwargs: Mapping[str, object],
187
) -> BatchFeature:
188
# Inkling is not a standard HF processor (no fused text+mm call), so we run
189
# the vendored extractors ourselves and tokenize the text separately.
@@ -275,10 +265,8 @@ class InklingMultiModalProcessor(BaseMultiModalProcessor[InklingProcessingInfo])
265
ids.extend(tokenizer.encode(chunk, add_special_tokens=False))
266
267
# Reconcile against the declared media counts only when media is
278
- # present. With no media items -- e.g. the base text-only tokenization
279
- # probe (``_apply_hf_processor_text_only``), which calls this via
280
- # ``_call_hf_processor`` with empty ``mm_data`` -- emit the markers
281
- # verbatim; the marker<->item correspondence is enforced later by
268
+ # present. With no media items, emit the markers verbatim; the
269
+ # marker<->item correspondence is enforced later by
270
# ``_get_prompt_updates`` once the media features are available.
271
if num_images or num_audios:
272
# Fail clearly on a placeholder/media-count mismatch instead of
vllm/models/kimi_k3/common/mm_preprocess.py
+1
-11
@@ -236,23 +236,13 @@ class KimiK3MultiModalProcessor(BaseMultiModalProcessor[KimiK3ProcessingInfo]):
236
prompt: str,
237
mm_data: Mapping[str, object],
238
mm_kwargs: Mapping[str, object],
239
- tok_kwargs: Mapping[str, object],
239
) -> BatchFeature:
240
# Override so the base always routes through the text+mm path
241
# (`KimiK3Processor.__call__`). Otherwise the mm-only fast path calls
242
# the checkpoint image processor directly with bare PIL images, but it
243
# requires `{"type": "image", "image": PIL}` media dicts that only our
244
# wrapper builds.
246
- return super()._call_hf_processor(prompt, mm_data, mm_kwargs, tok_kwargs)
247
-
248
- def _hf_processor_applies_updates(
249
- self,
250
- prompt_text: str,
251
- mm_items: MultiModalDataItems,
252
- hf_processor_mm_kwargs: Mapping[str, object],
253
- tokenization_kwargs: Mapping[str, object],
254
- ) -> bool:
255
- return False
245
+ return super()._call_hf_processor(prompt, mm_data, mm_kwargs)
246
247
def _get_mm_fields_config(
248
self,
vllm/models/minimax_m3/common/mm_preprocess.py
+1
-2
@@ -311,7 +311,6 @@ class MiniMaxM3VLMultiModalProcessor(
311
prompt: str,
312
mm_data: Mapping[str, object],
313
mm_kwargs: Mapping[str, object],
314
- tok_kwargs: Mapping[str, object],
314
) -> BatchFeature:
315
mm_data = dict(mm_data)
316
# With ``video_needs_metadata=True`` each video arrives as a
@@ -341,7 +340,7 @@ class MiniMaxM3VLMultiModalProcessor(
340
341
# Override the video processor's default do_resize=False (set for a
342
# pre-resized pipeline) to True for vLLM's raw-frame inputs.
344
- merged = dict(do_resize=True, **mm_kwargs, **tok_kwargs)
343
+ merged = dict(do_resize=True, **mm_kwargs)
344
data = dict(text=prompt, **mm_data)
345
if video_metadata is not None:
346
data["video_metadata"] = video_metadata
vllm/multimodal/processing/dummy_inputs.py
+13
-3
@@ -83,12 +83,22 @@ class BaseDummyInputsBuilder(ABC, Generic[_I]):
83
dummy_mm_data = self.get_dummy_mm_data(seq_len, mm_counts, mm_options)
84
dummy_mm_items = self.info.parse_mm_data(dummy_mm_data, validate=False)
85
86
- tokenization_kwargs = {"truncation": False}
86
+ tokenizer = self.info.ctx.tokenizer
87
+ dummy_prompt: list[int]
88
+ if tokenizer is None:
89
+ # Tokenizer-less models (e.g. `skip_tokenizer_init=True`) only
90
+ # accept embeddings and have an empty dummy text, so there are no
91
+ # prompt tokens.
92
+ dummy_prompt = []
93
+ else:
94
+ dummy_prompt = tokenizer.encode(
95
+ dummy_text,
96
+ **self.info.default_tok_params.get_encode_kwargs(),
97
+ )
98
99
return ProcessorInputs(
89
- prompt=dummy_text,
100
+ prompt=dummy_prompt,
101
mm_data_items=dummy_mm_items,
91
- tokenization_kwargs=tokenization_kwargs,
102
)
103
104
def _get_dummy_audios(
vllm/multimodal/processing/inputs.py
+1
-2
@@ -17,11 +17,10 @@ class ProcessorInputs:
17
[`vllm.multimodal.processing.BaseMultiModalProcessor.apply`][].
18
"""
19
20
- prompt: str | list[int]
20
+ prompt: list[int]
21
mm_data_items: MultiModalDataItems
22
mm_uuid_items: MultiModalUUIDItems | None = None
23
hf_processor_mm_kwargs: Mapping[str, object] = field(default_factory=dict)
24
- tokenization_kwargs: Mapping[str, object] = field(default_factory=dict)
24
25
def get_mm_hashes(
26
self,
vllm/multimodal/processing/processor.py
+23
-103
@@ -38,12 +38,7 @@ from ..inputs import (
38
MultiModalKwargsOptionalItems,
39
PlaceholderRange,
40
)
41
-from ..parse import (
42
- DictEmbeddingItems,
43
- EmbeddingItems,
44
- MultiModalDataItems,
45
- MultiModalUUIDItems,
46
-)
41
+from ..parse import MultiModalDataItems, MultiModalUUIDItems
42
from .context import BaseProcessingInfo, TimingContext
43
from .dummy_inputs import BaseDummyInputsBuilder
44
from .inputs import ProcessorInputs
@@ -1199,11 +1194,18 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1194
1195
def __call__(
1196
self,
1202
- prompt: str,
1197
+ prompt: str | list[int],
1198
mm_items: MultiModalDataItems,
1199
mm_uuid_items: MultiModalUUIDItems | None = None,
1200
hf_processor_mm_kwargs: Mapping[str, object] | None = None,
1201
) -> MultiModalInput:
1202
+ if isinstance(prompt, str):
1203
+ tokenizer = self.info.get_tokenizer()
1204
+ prompt = tokenizer.encode(
1205
+ prompt,
1206
+ **self.info.default_tok_params.get_encode_kwargs(),
1207
+ )
1208
+
1209
processor_inputs = ProcessorInputs(
1210
prompt,
1211
mm_items,
@@ -1307,7 +1309,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1309
# This refers to the data to be passed to HF processor.
1310
mm_data: Mapping[str, object],
1311
mm_kwargs: Mapping[str, object],
1310
- tok_kwargs: Mapping[str, object],
1312
) -> BatchFeature:
1313
"""
1314
Call the HF processor on the prompt text and
@@ -1316,26 +1317,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1317
return self.info.ctx.call_hf_processor(
1318
self.info.get_hf_processor(**mm_kwargs),
1319
dict(text=prompt, **mm_data),
1319
- dict(**mm_kwargs, **tok_kwargs),
1320
- )
1321
-
1322
- def _hf_processor_applies_updates(
1323
- self,
1324
- prompt_text: str,
1325
- mm_items: MultiModalDataItems,
1326
- hf_processor_mm_kwargs: Mapping[str, object],
1327
- tokenization_kwargs: Mapping[str, object],
1328
- ) -> bool:
1329
- """
1330
- Return whether the HF processor applies prompt updates.
1331
-
1332
- For most HF processors, this should be `True` when multi-modal
1333
- data items are passed, but `False` when multi-modal embeddings
1334
- are passed.
1335
- """
1336
- return not any(
1337
- isinstance(items, (EmbeddingItems, DictEmbeddingItems))
1338
- for items in mm_items.values()
1320
+ mm_kwargs,
1321
)
1322
1323
def _apply_hf_processor_text_mm(
@@ -1343,13 +1325,10 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1325
prompt_text: str,
1326
mm_items: MultiModalDataItems,
1327
hf_processor_mm_kwargs: Mapping[str, object],
1346
- tokenization_kwargs: Mapping[str, object],
1347
- ) -> tuple[list[int], BatchFeature, bool]:
1328
+ ) -> tuple[list[int], BatchFeature]:
1329
"""
1330
Apply the HF processor on the prompt text and multi-modal data
1331
together.
1351
-
1352
- In addition, return whether prompt updates have been applied.
1332
"""
1333
valid_mm_items = mm_items.select(
1334
{k for k, c in mm_items.get_all_counts().items() if c > 0}
@@ -1360,7 +1339,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1339
prompt=prompt_text,
1340
mm_data=processor_data,
1341
mm_kwargs=hf_processor_mm_kwargs,
1363
- tok_kwargs=tokenization_kwargs,
1342
)
1343
processed_data.update(passthrough_data)
1344
@@ -1370,35 +1348,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1348
1349
(prompt_ids,) = input_ids
1350
1373
- is_update_applied = self._hf_processor_applies_updates(
1374
- prompt_text=prompt_text,
1375
- mm_items=mm_items,
1376
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1377
- tokenization_kwargs=tokenization_kwargs,
1378
- )
1379
-
1380
- return prompt_ids, processed_data, is_update_applied
1381
-
1382
- def _apply_hf_processor_text_only(
1383
- self,
1384
- prompt_text: str,
1385
- tokenization_kwargs: Mapping[str, object],
1386
- ) -> list[int]:
1387
- """
1388
- Apply the HF processor on the prompt text only.
1389
-
1390
- Since HF processor requires that text and multi-modal items
1391
- correspond to each other, we create dummy multi-modal items
1392
- to go along with the text.
1393
- """
1394
- prompt_ids, _, _ = self._apply_hf_processor_text_mm(
1395
- prompt_text=prompt_text,
1396
- mm_items=MultiModalDataItems({}),
1397
- hf_processor_mm_kwargs={},
1398
- tokenization_kwargs=tokenization_kwargs,
1399
- )
1400
-
1401
- return prompt_ids
1351
+ return prompt_ids, processed_data
1352
1353
def _apply_hf_processor_tokens_only(
1354
self,
@@ -1410,10 +1360,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1360
Most HF processors accept prompt text but not prompt tokens.
1361
If the HF processor adds or removes tokens that are not related to
1362
multi-modal data, you should override this method so it is consistent
1413
- with the output of
1414
- [`_apply_hf_processor_text_only`][vllm.multimodal.processing.BaseMultiModalProcessor._apply_hf_processor_text_only]
1415
- on the
1416
- corresponding text.
1363
+ with the tokenization of the corresponding text.
1364
"""
1365
return prompt_tokens
1366
@@ -1421,7 +1368,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1368
self,
1369
mm_items: MultiModalDataItems,
1370
hf_processor_mm_kwargs: Mapping[str, object],
1424
- tokenization_kwargs: Mapping[str, object],
1371
) -> BatchFeature:
1372
"""
1373
Apply the HF processor on the multi-modal data only.
@@ -1435,11 +1381,10 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1381
if type(self)._call_hf_processor != BaseMultiModalProcessor._call_hf_processor:
1382
mm_counts = mm_items.get_all_counts()
1383
1438
- _, mm_processed_data, _ = self._apply_hf_processor_text_mm(
1384
+ _, mm_processed_data = self._apply_hf_processor_text_mm(
1385
prompt_text=self.dummy_inputs.get_dummy_text(mm_counts),
1386
mm_items=mm_items,
1387
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1442
- tokenization_kwargs=tokenization_kwargs,
1388
)
1389
1390
return mm_processed_data
@@ -1455,7 +1400,7 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1400
self.info.get_hf_processor(**hf_processor_mm_kwargs),
1401
),
1402
processor_data,
1458
- dict(**hf_processor_mm_kwargs, **tokenization_kwargs),
1403
+ hf_processor_mm_kwargs,
1404
)
1405
processed_data.update(passthrough_data)
1406
@@ -1463,41 +1408,22 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1408
1409
def _apply_hf_processor_main(
1410
self,
1466
- prompt: str | list[int],
1411
+ prompt: list[int],
1412
mm_items: MultiModalDataItems,
1413
hf_processor_mm_kwargs: Mapping[str, object],
1469
- tokenization_kwargs: Mapping[str, object],
1470
- *,
1471
- enable_hf_prompt_update: bool,
1414
) -> tuple[list[int], BatchFeature, bool]:
1415
"""
1474
- Apply the HF processor on the prompt text and multi-modal data.
1416
+ Apply the HF processor on the prompt tokens and multi-modal data.
1417
1418
In addition, return whether prompt updates have been applied
1477
- (for most HF processors, this should be `True`).
1478
-
1479
- Note:
1480
- If `enable_hf_prompt_update=False`, we use HF processor
1481
- to perform prompt updates if available; HF processor requires
1482
- that the prompt corresponds to multi-modal items.
1419
+ (`False` here, since for token prompts the updates are normally
1420
+ applied separately via `_maybe_apply_prompt_updates`).
1421
"""
1484
- if isinstance(prompt, str):
1485
- if enable_hf_prompt_update:
1486
- return self._apply_hf_processor_text_mm(
1487
- prompt_text=prompt,
1488
- mm_items=mm_items,
1489
- hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1490
- tokenization_kwargs=tokenization_kwargs,
1491
- )
1492
-
1493
- prompt_ids = self._apply_hf_processor_text_only(prompt, tokenization_kwargs)
1494
- else:
1495
- prompt_ids = self._apply_hf_processor_tokens_only(prompt)
1422
+ prompt_ids = self._apply_hf_processor_tokens_only(prompt)
1423
1424
mm_processed_data = self._apply_hf_processor_mm_only(
1425
mm_items=mm_items,
1426
hf_processor_mm_kwargs=hf_processor_mm_kwargs,
1500
- tokenization_kwargs=tokenization_kwargs,
1427
)
1428
1429
return prompt_ids, mm_processed_data, False
@@ -1615,8 +1541,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1541
prompt=inputs.prompt,
1542
mm_items=inputs.mm_data_items,
1543
hf_processor_mm_kwargs=inputs.hf_processor_mm_kwargs,
1618
- tokenization_kwargs=inputs.tokenization_kwargs,
1619
- enable_hf_prompt_update=True,
1544
)
1545
1546
mm_kwargs = MultiModalKwargsItems.from_hf_inputs(
@@ -1687,8 +1611,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1611
prompt=inputs.prompt,
1612
mm_items=mm_missing_data_items,
1613
hf_processor_mm_kwargs=inputs.hf_processor_mm_kwargs,
1690
- tokenization_kwargs=inputs.tokenization_kwargs,
1691
- enable_hf_prompt_update=False,
1614
)
1615
1616
mm_missing_kwargs = MultiModalKwargsItems.from_hf_inputs(
@@ -1938,7 +1860,6 @@ class BaseMultiModalProcessor(ABC, Generic[_I]):
1860
is_update_applied,
1861
) = self._cached_apply_hf_processor(inputs, timing_ctx)
1862
1941
- # NOTE: tokenization_kwargs are not required to init processor
1863
with timing_ctx.record("apply_prompt_updates"):
1864
prompt_ids, mm_placeholders = self._maybe_apply_prompt_updates(
1865
mm_items=inputs.mm_data_items,
@@ -1967,9 +1888,9 @@ class EncDecMultiModalProcessor(BaseMultiModalProcessor[_I]):
1888
@abstractmethod
1889
def create_encoder_prompt(
1890
self,
1970
- prompt: str | list[int],
1891
+ prompt: list[int],
1892
mm_items: MultiModalDataItems,
1972
- ) -> str | list[int]:
1893
+ ) -> list[int]:
1894
"""
1895
Create input prompt for the encoder. HF processor will be applied on
1896
this prompt during profiling and generation.
@@ -1986,7 +1907,7 @@ class EncDecMultiModalProcessor(BaseMultiModalProcessor[_I]):
1907
1908
def _get_enc_dec_inputs(
1909
self,
1989
- prompt: str | list[int],
1910
+ prompt: list[int],
1911
mm_items: MultiModalDataItems,
1912
encoder_inputs: MultiModalInput,
1913
):
@@ -2028,7 +1949,6 @@ class EncDecMultiModalProcessor(BaseMultiModalProcessor[_I]):
1949
inputs.mm_data_items,
1950
inputs.mm_uuid_items,
1951
hf_processor_mm_kwargs=inputs.hf_processor_mm_kwargs,
2031
- tokenization_kwargs=inputs.tokenization_kwargs,
1952
)
1953
1954
encoder_inputs = super().apply(encoder_processor_inputs, timing_ctx)