| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | """Regression test: ``/tokenize`` must expand image placeholders for VLM models. |
| 4 | |
| 5 | Fixed by PR #34560 ("Move InputPreprocessor into Renderer (2/2)"). |
| 6 | Before that change, ``/tokenize`` returned ~26 tokens for a message with an |
| 7 | image instead of the expected 1451. Confirmed broken on 0.15.1 and 0.16.0. |
| 8 | """ |
| 9 | |
| 10 | import json |
| 11 | |
| 12 | import pytest |
| 13 | import requests |
| 14 | |
| 15 | from tests.utils import RemoteOpenAIServer |
| 16 | |
| 17 | MODEL_NAME = "Qwen/Qwen2.5-VL-3B-Instruct" |
| 18 | |
| 19 | |
| 20 | @pytest.fixture(scope="module") |
| 21 | def server(): |
| 22 | args = [ |
| 23 | "--dtype", |
| 24 | "bfloat16", |
| 25 | "--max-model-len", |
| 26 | "4096", |
| 27 | "--max-num-seqs", |
| 28 | "5", |
| 29 | "--enforce-eager", |
| 30 | "--limit-mm-per-prompt", |
| 31 | json.dumps({"image": 1}), |
| 32 | ] |
| 33 | with RemoteOpenAIServer(MODEL_NAME, args) as remote_server: |
| 34 | yield remote_server |
| 35 | |
| 36 | |
| 37 | def test_tokenize_chat_expands_image_placeholders( |
| 38 | server: RemoteOpenAIServer, |
| 39 | local_asset_server, |
| 40 | ): |
| 41 | image_url = local_asset_server.url_for("stop_sign.jpg") |
| 42 | messages = [ |
| 43 | { |
| 44 | "role": "user", |
| 45 | "content": [ |
| 46 | {"type": "image_url", "image_url": {"url": image_url}}, |
| 47 | {"type": "text", "text": "Describe this image."}, |
| 48 | ], |
| 49 | } |
| 50 | ] |
| 51 | |
| 52 | response = requests.post( |
| 53 | server.url_for("tokenize"), |
| 54 | json={"model": MODEL_NAME, "messages": messages}, |
| 55 | ) |
| 56 | response.raise_for_status() |
| 57 | |
| 58 | # stop_sign.jpg (1300x876) produces 1451 tokens after expansion. |
| 59 | # Without expansion the count would be ~26 (text + one placeholder). |
| 60 | assert response.json()["count"] == 1451 |