| 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 |