[Bugfix][Processor] Replace bare asserts with ValueError in DeepseekVLV2/OCR processors (#53854)
Signed-off-by: adisivaprasad <adisivaprasad@users.noreply.github.com> Co-authored-by: adisivaprasad <adisivaprasad@users.noreply.github.com>
adisivaprasad committed
Aug 26, 2026 at 02:10 UTC
73bd7c83c4847cd38cb0054dbd9aa912e0eafd03
3 files changed
+42
-8
tests/models/multimodal/processing/test_deepseek_ocr.py
+24
@@ -132,3 +132,27 @@ class TestDeepseekOCREmptyImagesCrop:
132
"image_size": 1024, # Wrong! Tensor has 640
133
},
134
)
135
+
136
+
137
+class TestDeepseekOCRInputValidation:
138
+ """Bare ``assert`` used to validate user input here returned HTTP 500
139
+ (AssertionError) instead of HTTP 400 (ValueError) and disappeared under
140
+ ``python -O``, silently corrupting the tokenized sequence. See #53850.
141
+ """
142
+
143
+ def test_mismatched_image_count_raises_value_error(self, processor):
144
+ """Two ``<image>`` tokens with one image must raise ValueError, not
145
+ AssertionError (which would yield HTTP 500 and, under ``-O``, silently
146
+ drop the middle text segment)."""
147
+ image = Image.new("RGB", (100, 100), color="red")
148
+ with pytest.raises(ValueError, match="does not match number of images"):
149
+ processor(prompt="<image> and <image>", images=[image])
150
+
151
+ def test_missing_prompt_raises_value_error(self, processor):
152
+ image = Image.new("RGB", (100, 100), color="red")
153
+ with pytest.raises(ValueError, match="prompt and images"):
154
+ processor(prompt=None, images=[image])
155
+
156
+ def test_missing_images_raises_value_error(self, processor):
157
+ with pytest.raises(ValueError, match="prompt and images"):
158
+ processor(prompt="<image>\nDescribe this image.", images=None)
vllm/transformers_utils/processors/deepseek_ocr.py
+9
-4
@@ -250,9 +250,8 @@ class DeepseekOCRProcessor(ProcessorMixin):
250
- num_image_tokens (List[int]): the number of image tokens
251
"""
252
253
- assert prompt is not None and images is not None, (
254
- "prompt and images must be used at the same time."
255
- )
253
+ if prompt is None or images is None:
254
+ raise ValueError("prompt and images must be used at the same time.")
255
256
sft_format = prompt
257
@@ -311,7 +310,13 @@ class DeepseekOCRProcessor(ProcessorMixin):
310
):
311
"""Tokenize text with <image> tags."""
312
314
- assert conversation.count(self.image_token) == len(images)
313
+ num_image_tags = conversation.count(self.image_token)
314
+ if num_image_tags != len(images):
315
+ raise ValueError(
316
+ f"Number of {self.image_token!r} tokens in prompt "
317
+ f"({num_image_tags}) does not match number of images "
318
+ f"({len(images)})."
319
+ )
320
text_splits = conversation.split(self.image_token)
321
images_list, images_crop_list, images_seq_mask, images_spatial_crop = (
322
[],
vllm/transformers_utils/processors/deepseek_vl2.py
+9
-4
@@ -203,9 +203,8 @@ class DeepseekVLV2Processor(ProcessorMixin):
203
- num_image_tokens (list[int]): the number of image tokens
204
"""
205
206
- assert prompt is not None and images is not None, (
207
- "prompt and images must be used at the same time."
208
- )
206
+ if prompt is None or images is None:
207
+ raise ValueError("prompt and images must be used at the same time.")
208
209
sft_format = prompt
210
(
@@ -310,7 +309,13 @@ class DeepseekVLV2Processor(ProcessorMixin):
309
cropping: bool = True,
310
):
311
"""Tokenize text with <image> tags."""
313
- assert conversation.count(self.image_token) == len(images)
312
+ num_image_tags = conversation.count(self.image_token)
313
+ if num_image_tags != len(images):
314
+ raise ValueError(
315
+ f"Number of {self.image_token!r} tokens in prompt "
316
+ f"({num_image_tags}) does not match number of images "
317
+ f"({len(images)})."
318
+ )
319
text_splits = conversation.split(self.image_token)
320
images_list, images_seq_mask, images_spatial_crop = [], [], []
321
num_image_tokens = []