@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 1c3a72b8b2
Fork 0

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

[Bugfix] Add fetch_images to MistralCommonImageProcessor (#45180)

Signed-off-by: juliendenize <julien.denize@mistral.ai>

Julien Denize committed Jun 11, 2026 at 10:13 UTC 1c3a72b8b2e33fe6aa6023ab800c46f066ac4614
2 files changed +81
tests/transformers_utils/processors/test_pixtral.py new
+65
@@ -0,0 +1,65 @@
1 +# SPDX-License-Identifier: Apache-2.0
2 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 +import pytest
4 +import transformers.image_utils
5 +from PIL import Image
6 +
7 +from vllm.transformers_utils.processors.pixtral import MistralCommonImageProcessor
8 +
9 +
10 +@pytest.fixture(scope="module")
11 +def image_processor() -> MistralCommonImageProcessor:
12 + return MistralCommonImageProcessor(mm_encoder=None)
13 +
14 +
15 +def test_fetch_images_passes_through_decoded_image(
16 + image_processor: MistralCommonImageProcessor,
17 +):
18 + image = Image.new("RGB", (4, 4))
19 + result = image_processor.fetch_images(image)
20 + assert result is image
21 +
22 +
23 +def test_fetch_images_recurses_over_list(
24 + image_processor: MistralCommonImageProcessor,
25 +):
26 + a = Image.new("RGB", (4, 4))
27 + b = Image.new("RGB", (8, 8))
28 + result = image_processor.fetch_images([a, b])
29 + assert isinstance(result, list)
30 + assert len(result) == 2
31 + assert result[0] is a
32 + assert result[1] is b
33 +
34 +
35 +def test_fetch_images_recurses_over_nested_list(
36 + image_processor: MistralCommonImageProcessor,
37 +):
38 + a = Image.new("RGB", (4, 4))
39 + b = Image.new("RGB", (8, 8))
40 + result = image_processor.fetch_images([[a], [b]])
41 + assert result == [[a], [b]]
42 +
43 +
44 +def test_fetch_images_str_delegates_to_load_image(
45 + monkeypatch, image_processor: MistralCommonImageProcessor
46 +):
47 + sentinel = Image.new("RGB", (2, 2))
48 + received: dict[str, object] = {}
49 +
50 + def fake_load_image(path):
51 + received["path"] = path
52 + return sentinel
53 +
54 + monkeypatch.setattr(transformers.image_utils, "load_image", fake_load_image)
55 +
56 + result = image_processor.fetch_images("/tmp/fake.png")
57 + assert result is sentinel
58 + assert received["path"] == "/tmp/fake.png"
59 +
60 +
61 +def test_fetch_images_rejects_unsupported_type(
62 + image_processor: MistralCommonImageProcessor,
63 +):
64 + with pytest.raises(TypeError, match="only a single or a list"):
65 + image_processor.fetch_images(42)
vllm/transformers_utils/processors/pixtral.py
+16
@@ -46,6 +46,22 @@ class MistralCommonImageProcessor:
46 ncols, nrows = self.mm_encoder._image_to_num_tokens(image)
47 return ncols * nrows, nrows, ncols
48
49 + # Copied from Transformers (Apache-2.0):
50 + # https://github.com/huggingface/transformers/blob/d20946079fd422335fbae3eeb98b7cd88334612f/src/transformers/image_processing_base.py#L473
51 + def fetch_images(self, image_url_or_urls):
52 + from transformers.image_utils import is_valid_image, load_image
53 +
54 + if isinstance(image_url_or_urls, (list, tuple)):
55 + return [self.fetch_images(x) for x in image_url_or_urls]
56 + if isinstance(image_url_or_urls, str):
57 + return load_image(image_url_or_urls)
58 + if is_valid_image(image_url_or_urls):
59 + return image_url_or_urls
60 + raise TypeError(
61 + "only a single or a list of entries is supported but got "
62 + f"type={type(image_url_or_urls)}"
63 + )
64 +
65
66 class MistralCommonPixtralProcessor(ProcessorMixin):
67 attributes = ["image_processor", "tokenizer"]