From aa1df36c5316aa1f15187ead2f1ad65898f83bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=87=91=E6=97=AD?= <105263726+wjinxu@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:20:45 +0800 Subject: [PATCH] Fix/minicpmv46 missing version (#44980) Signed-off-by: wjinxu <1299461899@qq.com> Co-authored-by: Cursor --- vllm/model_executor/models/minicpmv4_6.py | 20 +++++++++++++++++++ .../transformers_utils/processors/minicpmo.py | 7 ++++++- .../transformers_utils/processors/minicpmv.py | 7 ++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/vllm/model_executor/models/minicpmv4_6.py b/vllm/model_executor/models/minicpmv4_6.py index c49af90476..605b7bd7a3 100644 --- a/vllm/model_executor/models/minicpmv4_6.py +++ b/vllm/model_executor/models/minicpmv4_6.py @@ -424,6 +424,26 @@ class MiniCPMV4_6ProcessingInfo(MiniCPMVProcessingInfo): def get_hf_config(self): return self.ctx.get_hf_config() + def get_hf_processor(self, **kwargs: object): + # MiniCPM-V 4.6 keeps the native transformers MiniCPMV4_6Processor: + # this model has its own image/video handling and prompt-update logic + # below, so it does not need (and is incompatible with) the vendored + # MiniCPMVProcessor used by 2.x/4.0/4.5, whose __init__ assumes a + # legacy `image_processor.version` attribute that 4.6 no longer has. + hf_processor = self.ctx.get_hf_processor(**kwargs) + + # NumPy arrays are considered as Iterable but not Sequence in + # https://github.com/huggingface/transformers/blob/main/src/transformers/image_transforms.py#L428 + image_processor = getattr(hf_processor, "image_processor", None) + if image_processor is not None: + # transformers v5+ renamed `mean`/`std` -> `image_mean`/`image_std` + for attr in ("mean", "std", "image_mean", "image_std"): + val = getattr(image_processor, attr, None) + if isinstance(val, np.ndarray): + setattr(image_processor, attr, val.tolist()) + + return hf_processor + def _get_expected_hidden_size(self) -> int: config = self.get_hf_config() if hasattr(config, "text_config") and config.text_config is not None: diff --git a/vllm/transformers_utils/processors/minicpmo.py b/vllm/transformers_utils/processors/minicpmo.py index 3059b8bac9..d5e5750ca5 100644 --- a/vllm/transformers_utils/processors/minicpmo.py +++ b/vllm/transformers_utils/processors/minicpmo.py @@ -64,7 +64,12 @@ class MiniCPMOProcessor(ProcessorMixin): pool_step=2, ): super().__init__(image_processor, feature_extractor, tokenizer) - self.version = image_processor.version + # Mirror the MiniCPMVProcessor guard: newer (transformers v5.7+) + # MiniCPM image processors may drop the legacy `version` attribute, + # so fall back to None instead of hard-crashing. `version` only + # special-cases the 2.5 tokenization path; other values take the + # default branch. + self.version = getattr(image_processor, "version", None) self.pool_step = pool_step def _safe_get_token_id(self, attr_name, default_token_str): diff --git a/vllm/transformers_utils/processors/minicpmv.py b/vllm/transformers_utils/processors/minicpmv.py index 03649234ea..91c3a8e479 100644 --- a/vllm/transformers_utils/processors/minicpmv.py +++ b/vllm/transformers_utils/processors/minicpmv.py @@ -58,7 +58,12 @@ class MiniCPMVProcessor(ProcessorMixin): def __init__(self, image_processor=None, tokenizer=None): super().__init__(image_processor, tokenizer) - self.version = image_processor.version + # Newer (transformers v5.7+) MiniCPM-V image processors, e.g. + # MiniCPMV4_6ImageProcessor, no longer carry a `version` attribute. + # Fall back to None instead of hard-crashing: `version` is only used + # to special-case the 2.5 tokenization path in `_convert`, and any + # value other than 2.5 takes the default branch anyway. + self.version = getattr(image_processor, "version", None) def __call__( self,