"vllm/vscode:/vscode.git/clone" did not exist on "9bebc9512f9340e94579b9bd69cfdc452c4d5bb0"
Unverified Commit 9bd9294f authored by HWH's avatar HWH Committed by GitHub
Browse files

[Bugfix] Fix MiniCPMV Image input inference failed (#22813)


Signed-off-by: default avatarHWH <67449739+jio-H@users.noreply.github.com>
Signed-off-by: default avatarDarkLight1337 <tlleungac@connect.ust.hk>
Signed-off-by: default avatarCyrus Leung <cyrus.tl.leung@gmail.com>
Co-authored-by: default avatarDarkLight1337 <tlleungac@connect.ust.hk>
Co-authored-by: default avatarCyrus Leung <cyrus.tl.leung@gmail.com>
parent da270519
...@@ -85,6 +85,23 @@ class MiniCPMVImagePixelInputs(TensorSchema): ...@@ -85,6 +85,23 @@ class MiniCPMVImagePixelInputs(TensorSchema):
- w: Width - w: Width
""" """
def _validate_nested_tensors(
self,
value: Union[list[torch.Tensor], tuple[torch.Tensor, ...]],
field_name: str,
expected_shape: tuple[Union[int, str], ...],
dynamic_dims: set[str],
) -> tuple[int, ...]:
# value[0] is the scaled image,
# and value[1:] is a collection of image slices.
# It is ensured that all slices in the collection
# have the same shape.
if field_name == "pixel_values":
value = value[1:] if len(value) > 1 else value
return super()._validate_nested_tensors(value, field_name,
expected_shape, dynamic_dims)
type: Literal["pixel_values"] = "pixel_values" type: Literal["pixel_values"] = "pixel_values"
# Note that the image size may vary, so we pass it as a list instead of a # Note that the image size may vary, so we pass it as a list instead of a
......
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from typing import Annotated, Any, Union, get_args, get_origin, get_type_hints from typing import (Annotated, Any, Optional, Union, get_args, get_origin,
get_type_hints)
import torch import torch
...@@ -11,9 +12,13 @@ logger = init_logger(__name__) ...@@ -11,9 +12,13 @@ logger = init_logger(__name__)
class TensorShape: class TensorShape:
def __init__(self, def __init__(
self,
*dims: Union[int, str], *dims: Union[int, str],
dynamic_dims: set[str, ...] = None) -> None: dynamic_dims: Optional[set[str]] = None,
) -> None:
super().__init__()
self.dims = dims self.dims = dims
self.dynamic_dims = dynamic_dims if dynamic_dims else set() self.dynamic_dims = dynamic_dims if dynamic_dims else set()
...@@ -44,11 +49,15 @@ class TensorShape: ...@@ -44,11 +49,15 @@ class TensorShape:
class TensorSchema: class TensorSchema:
def __init__(self, def __init__(
self,
*, *,
validate: bool = True, validate: bool = True,
resolve_bindings: dict[str, int] = None, resolve_bindings: Optional[dict[str, int]] = None,
**kwargs: Any) -> None: **kwargs: Any,
) -> None:
super().__init__()
self._resolve_bindings = resolve_bindings if resolve_bindings else {} self._resolve_bindings = resolve_bindings if resolve_bindings else {}
for key, value in kwargs.items(): for key, value in kwargs.items():
...@@ -57,16 +66,19 @@ class TensorSchema: ...@@ -57,16 +66,19 @@ class TensorSchema:
if validate: if validate:
self.validate() self.validate()
def __getitem__(self, item) -> Any: def __getitem__(self, key: str) -> Any:
return getattr(self, item) return getattr(self, key)
def get(self, item, default=None) -> Any: def get(self, key: str, default: Any = None) -> Any:
return getattr(self, item, default) return getattr(self, key, default)
def _match_shape_with_dynamic(self, actual: tuple[int, ...], def _match_shape_with_dynamic(
self,
actual: tuple[int, ...],
reference: tuple[int, ...], reference: tuple[int, ...],
expected_shape: tuple[Union[int, str], ...], expected_shape: tuple[Union[int, str], ...],
dynamic_dims: set[str, ...]) -> bool: dynamic_dims: set[str],
) -> bool:
if len(actual) != len(reference) or len(actual) > len(expected_shape): if len(actual) != len(reference) or len(actual) > len(expected_shape):
return False return False
...@@ -84,10 +96,12 @@ class TensorSchema: ...@@ -84,10 +96,12 @@ class TensorSchema:
return True return True
def _validate_nested_tensors( def _validate_nested_tensors(
self, value: Union[list[torch.Tensor, ...], self,
tuple[torch.Tensor, ...]], field_name: str, value: Union[list[torch.Tensor], tuple[torch.Tensor, ...]],
field_name: str,
expected_shape: tuple[Union[int, str], ...], expected_shape: tuple[Union[int, str], ...],
dynamic_dims: set[str, ...]) -> tuple[int, ...]: dynamic_dims: set[str],
) -> tuple[int, ...]:
"""Validate a list/tuple of tensors and return the actual shape.""" """Validate a list/tuple of tensors and return the actual shape."""
# Ensure all tensors in the list have the same # Ensure all tensors in the list have the same
# shape, besides dynamic dimensions # shape, besides dynamic dimensions
...@@ -110,12 +124,14 @@ class TensorSchema: ...@@ -110,12 +124,14 @@ class TensorSchema:
# shape = (len(list), *tensor.shape) # shape = (len(list), *tensor.shape)
return (len(value), ) + first.shape return (len(value), ) + first.shape
def _validate_tensor_shape_expected(self, actual_shape: tuple[int, ...], def _validate_tensor_shape_expected(
expected_shape: tuple[Union[int, str], self,
...], actual_shape: tuple[int, ...],
field_name: str, shape_env: dict[str, expected_shape: tuple[Union[int, str], ...],
int], field_name: str,
dynamic_dims: set[str, ...]) -> None: shape_env: dict[str, int],
dynamic_dims: set[str],
) -> None:
"""Validate that the actual tensor shape matches the expected shape.""" """Validate that the actual tensor shape matches the expected shape."""
if len(actual_shape) != len(expected_shape): if len(actual_shape) != len(expected_shape):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment