main
py 53 lines 1.81 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """DeepSeek-V4 VL processing helpers."""
4
5 from PIL import Image
6
7 from vllm.models.deepseek_v4.common.mm_preprocess import (
8 DeepseekV4VLProcessingInfo,
9 DeepseekV4VLProcessor,
10 build_image_block_pad_free,
11 )
12 from vllm.transformers_utils.configs.deepseek_v4 import DeepseekV4Config
13
14
15 class _ConfigCtx:
16 def __init__(self, config: DeepseekV4Config) -> None:
17 self._config = config
18
19 def get_hf_config(self, *args, **kwargs):
20 return self._config
21
22
23 def _feature_counts(
24 processor: DeepseekV4VLProcessor, width: int, height: int
25 ) -> tuple[int, int]:
26 out = processor(images=[Image.new("RGB", (width, height))])
27 n_llm_h, n_llm_w = out["llm_grid"][0].tolist()
28 types, _ = build_image_block_pad_free(n_llm_h, n_llm_w)
29 return len(types), out["patches"].shape[0]
30
31
32 def test_get_image_size_with_most_features_beats_wide_real_image():
33 """Dummy size must maximize tokens/patches within the budget (#59271).
34
35 A square under-counts because each aligner row pays an IMAGE_NEW_LINE.
36 """
37 config = DeepseekV4Config(vision_n_layers=24)
38 info = DeepseekV4VLProcessingInfo(_ConfigCtx(config))
39 processor = DeepseekV4VLProcessor(config)
40
41 dummy = info.get_image_size_with_most_features()
42 dummy_features = _feature_counts(processor, dummy.width, dummy.height)
43 wide_features = _feature_counts(processor, 1932, 336)
44
45 assert dummy == (1932, 336)
46 assert wide_features <= dummy_features
47
48
49 def test_get_image_size_with_most_features_respects_max_wh_ratio():
50 config = DeepseekV4Config(vision_n_layers=24)
51 info = DeepseekV4VLProcessingInfo(_ConfigCtx(config))
52 dummy = info.get_image_size_with_most_features()
53 assert dummy.width / dummy.height <= config.vision_max_wh_ratio