-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Add support for Prithvi geospatial model in serving mode #20307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
198ff71
808cc3c
8e99b4c
8ce3cd7
06a51bd
7e2df9e
b53a07d
c7f80c0
c9dad63
29053cf
4ffb0fe
ea01dbd
f6d7aad
567500a
725e381
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project | ||
|
||
import pytest | ||
import torch | ||
|
||
from ....conftest import VllmRunner | ||
|
||
|
||
def generate_test_mm_data(): | ||
mm_data = { | ||
"pixel_values": torch.full((6, 512, 512), 1.0, dtype=torch.float16), | ||
"location_coords": torch.full((1, 2), 1.0, dtype=torch.float16), | ||
} | ||
return mm_data | ||
|
||
|
||
def _run_test( | ||
vllm_runner: type[VllmRunner], | ||
model: str, | ||
) -> None: | ||
|
||
mm_data = generate_test_mm_data() | ||
prompt = { | ||
# This model deals with no text input | ||
"prompt_token_ids": [1], | ||
"multi_modal_data": mm_data | ||
} | ||
with vllm_runner(model, | ||
task="embed", | ||
dtype=torch.float16, | ||
enforce_eager=True, | ||
skip_tokenizer_init=True) as vllm_model: | ||
vllm_model.encode(prompt) | ||
|
||
|
||
MODELS = ["christian-pinto/Prithvi-EO-2.0-300M-TL-VLLM"] | ||
|
||
|
||
@pytest.mark.parametrize("model", MODELS) | ||
def test_models_image( | ||
hf_runner, | ||
vllm_runner, | ||
image_assets, | ||
model: str, | ||
) -> None: | ||
_run_test( | ||
vllm_runner, | ||
model, | ||
) |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -75,6 +75,17 @@ class ChatCompletionContentPartImageEmbedsParam(TypedDict, total=False): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""The type of the content part.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class ChatCompletionContentPartTensorsParam(TypedDict, total=False): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensors: Required[Union[str, dict[str, str]]] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The tensors. It can be either: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- A single base64 string. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- A dictionary where each value is a base64 string. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type: Required[Literal["tensors"]] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""The type of the content part.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class VideoURL(TypedDict, total=False): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url: Required[str] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -129,6 +140,7 @@ class CustomChatCompletionContentSimpleVideoParam(TypedDict, total=False): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ChatCompletionContentPartVideoParam, ChatCompletionContentPartRefusalParam, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CustomChatCompletionContentSimpleImageParam, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ChatCompletionContentPartImageEmbedsParam, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ChatCompletionContentPartTensorsParam, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CustomChatCompletionContentSimpleAudioParam, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CustomChatCompletionContentSimpleVideoParam, str] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -468,7 +480,7 @@ def resolve_chat_template_content_format( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ModalityStr = Literal["image", "audio", "video", "image_embeds"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ModalityStr = Literal["image", "audio", "video", "image_embeds","tensors"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_T = TypeVar("_T") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -572,6 +584,8 @@ def _placeholder_str(self, modality: ModalityStr, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return self._cached_token_str(self._tokenizer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hf_config.video_token_index) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise TypeError(f"Unknown {modality} model type: {model_type}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
elif modality == "tensors": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise TypeError(f"Unknown modality: {modality}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -630,6 +644,13 @@ def all_mm_data(self) -> Optional[MultiModalDataDict]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError(\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Only one message can have {'type': 'image_embeds'}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["image"] = image_embeds_lst[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "tensors" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensors_lst = items_by_modality["tensors"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if len(tensors_lst) > 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError(\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Only one message can have {'type': 'tensors'}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["tensors"] = tensors_lst[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "image" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["image"] = items_by_modality["image"] # A list of images | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "audio" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -663,6 +684,12 @@ async def all_mm_data(self) -> Optional[MultiModalDataDict]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Only one message can have {'type': 'image_embeds'}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["image"] = image_embeds_lst[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "tensors" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensors_lst = items_by_modality["tensors"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if len(tensors_lst) > 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError(\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Only one message can have {'type': 'tensors'}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["tensors"] = tensors_lst[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "image" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_inputs["image"] = items_by_modality["image"] # A list of images | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "audio" in items_by_modality: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -695,8 +722,9 @@ def parse_image(self, image_url: str) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise NotImplementedError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@abstractmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_image_embeds(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
image_embeds: Union[str, dict[str, str]]) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_tensors(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensor_encodings: Union[str, dict[str, str]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
modality_str: ModalityStr) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise NotImplementedError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@abstractmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -729,18 +757,22 @@ def parse_image(self, image_url: str) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add("image", image) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._add_placeholder(placeholder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_image_embeds(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
image_embeds: Union[str, dict[str, str]]) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(image_embeds, dict): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
embeds = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
k: self._connector.fetch_image_embedding(v) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for k, v in image_embeds.items() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_tensors(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensor_encodings: Union[str, dict[str, str]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
modality_str: ModalityStr) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if modality_str not in ["image_embeds","tensors"]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise Exception("tensors are acceptable only as part " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"of 'image_embeds' or 'tensors' modalities.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(tensor_encodings, dict): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensors = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
k: self._connector.fetch_tensor_encoding(v) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for k, v in tensor_encodings.items() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add("image_embeds", embeds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add(modality_str, tensors) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(image_embeds, str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
embedding = self._connector.fetch_image_embedding(image_embeds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add("image_embeds", embedding) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(tensor_encodings, str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensor= self._connector.fetch_tensor_encoding(tensor_encodings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add(modality_str, tensor) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._add_placeholder(placeholder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -780,23 +812,27 @@ def parse_image(self, image_url: str) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add("image", image_coro) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._add_placeholder(placeholder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_image_embeds(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
image_embeds: Union[str, dict[str, str]]) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_tensors(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensor_encodings: Union[str, dict[str, str]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
modality_str: ModalityStr) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
future: asyncio.Future[Union[str, dict[str, str]]] = asyncio.Future() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(image_embeds, dict): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
embeds = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
k: self._connector.fetch_image_embedding(v) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for k, v in image_embeds.items() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if modality_str not in ["image_embeds","tensors"]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise Exception("tensors are acceptable only as part " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"of 'image_embeds' or 'tensors' modalities.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(tensor_encodings, dict): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensors= { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
k: self._connector.fetch_tensor_encoding(v) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for k, v in tensor_encodings.items() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
future.set_result(embeds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
future.set_result(tensors) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(image_embeds, str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
embedding = self._connector.\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fetch_image_embedding(image_embeds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
future.set_result(embedding) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(tensors, str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tensor= self._connector.\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fetch_tensor_encoding(tensor_encodings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
future.set_result(tensor) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
819
to
+833
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This asynchronous version of Additionally, similar to the synchronous version, using
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add("image_embeds", future) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
placeholder = self._tracker.add(modality_str, future) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._add_placeholder(placeholder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+815
to
836
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In To fix this, use if isinstance(tensor_encodings, dict):
tensors= {
k: self._connector.fetch_tensor_encoding(v)
for k, v in tensor_encodings.items()
}
future.set_result(tensors)
if isinstance(tensor_encodings, str):
tensor= self._connector.\
fetch_tensor_encoding(tensor_encodings)
future.set_result(tensor) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_audio(self, audio_url: str) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -819,6 +855,8 @@ def parse_video(self, video_url: str) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._add_placeholder(placeholder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def validate_chat_template(chat_template: Optional[Union[Path, str]]): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Raises if the provided chat template appears invalid.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if chat_template is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -915,6 +953,7 @@ def _get_full_multimodal_text_prompt(placeholder_counts: dict[str, int], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# No need to validate using Pydantic again | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_TextParser = partial(cast, ChatCompletionContentPartTextParam) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_ImageEmbedsParser = partial(cast, ChatCompletionContentPartImageEmbedsParam) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_TensorsParser = partial(cast, ChatCompletionContentPartTensorsParam) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_InputAudioParser = partial(cast, ChatCompletionContentPartInputAudioParam) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_RefusalParser = partial(cast, ChatCompletionContentPartRefusalParam) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Need to validate url objects | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -935,6 +974,8 @@ def _get_full_multimodal_text_prompt(placeholder_counts: dict[str, int], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lambda part: _ImageParser(part).get("image_url", {}).get("url", None), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"image_embeds": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lambda part: _ImageEmbedsParser(part).get("image_embeds", None), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"tensors": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lambda part: _TensorsParser(part).get("tensors", None), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"audio_url": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lambda part: _AudioParser(part).get("audio_url", {}).get("url", None), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"input_audio": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1004,7 +1045,7 @@ def _parse_chat_message_content_mm_part( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VALID_MESSAGE_CONTENT_MM_PART_TYPES = ("text", "refusal", "image_url", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"image_embeds", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"image_embeds", "tensors", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"audio_url", "input_audio", "video_url") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1081,8 +1122,12 @@ def _parse_chat_message_content_part( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {'type': 'image'} if wrap_dicts else None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if part_type == "image_embeds": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
content = cast(Union[str, dict[str, str]], content) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_parser.parse_image_embeds(content) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_parser.parse_tensors(content,"image_embeds") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {'type': 'image'} if wrap_dicts else None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if part_type == "tensors": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
content = cast(Union[str, dict[str, str]], content) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_parser.parse_tensors(content,"tensors") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return {'type': 'tensors'} if wrap_dicts else None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if part_type == "audio_url": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
str_content = cast(str, content) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mm_parser.parse_audio(str_content) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
from vllm.entrypoints.openai.serving_models import OpenAIServingModels | ||
from vllm.entrypoints.utils import _validate_truncation_size | ||
from vllm.logger import init_logger | ||
from vllm.multimodal.image import ImageEmbeddingMediaIO | ||
from vllm.outputs import PoolingOutput, PoolingRequestOutput | ||
from vllm.utils import merge_async_iterators | ||
|
||
|
@@ -33,7 +34,7 @@ | |
|
||
def _get_data( | ||
output: PoolingOutput, | ||
encoding_format: Literal["float", "base64"], | ||
encoding_format: Literal["float", "base64", "tensors"], | ||
) -> Union[list[float], str]: | ||
if encoding_format == "float": | ||
return output.data.tolist() | ||
|
@@ -43,6 +44,9 @@ def _get_data( | |
pt_float32 = output.data.to(dtype=torch.float32) | ||
pooling_bytes = np.array(pt_float32, dtype="float32").tobytes() | ||
return base64.b64encode(pooling_bytes).decode("utf-8") | ||
elif encoding_format == "tensor": | ||
tensor_encoding_io = ImageEmbeddingMediaIO() | ||
return tensor_encoding_io.encode_base64(output.data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand this. The pooler output is a torch.Tensor but ImageEmbeddingMediaIO.encode_base64 expects an image. How does this work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I highlighted this in the RFC as part of Additional features explored to enable tensors:. ImageMediaIO expects an image. ImageEmbeddingMediaIO expects Tensors. I thought about reusing If this makes it too confusing we can have a dedicated class like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: I run a couple of tests using Here an example from vllm.multimodal.image import ImageEmbeddingMediaIO
import torch
pixel_values = torch.full((6, 512, 512), 1.0,dtype=torch.float16)
image_embeds_media_io = ImageEmbeddingMediaIO()
encoded = image_embeds_media_io.encode_base64(pixel_values)
decoded = image_embeds_media_io.load_base64("",encoded) Here the error:
If we encoded via
Looks like a bug in the current implementation. Maybe the solution is updating There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also see Gemini is suggesting against using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opened a separate issue on this: #20427 |
||
|
||
assert_never(encoding_format) | ||
|
||
|
@@ -99,7 +103,11 @@ async def create_pooling( | |
prompt_adapter_request, | ||
) = self._maybe_get_adapters(request) | ||
|
||
tokenizer = await self.engine_client.get_tokenizer(lora_request) | ||
if not self.model_config.skip_tokenizer_init: | ||
tokenizer = await self.engine_client.get_tokenizer(lora_request | ||
) | ||
else: | ||
tokenizer = None | ||
|
||
if prompt_adapter_request is not None: | ||
raise NotImplementedError("Prompt adapter is not supported " | ||
|
@@ -205,7 +213,7 @@ def request_output_to_pooling_response( | |
request_id: str, | ||
created_time: int, | ||
model_name: str, | ||
encoding_format: Literal["float", "base64"], | ||
encoding_format: Literal["float", "base64", "tensors"], | ||
) -> PoolingResponse: | ||
items: list[PoolingResponseData] = [] | ||
num_prompt_tokens = 0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a potential
UnboundLocalError
inparse_tensors
. Iftensor_encodings
is neither adict
nor astr
,placeholder
will not be assigned before being used inself._add_placeholder(placeholder)
.To fix this, add an
else
clause that raises aTypeError
for unsupported types and ensureplaceholder
is always assigned.