Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions litellm/llms/vertex_ai/gemini/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,15 +351,28 @@ def _gemini_convert_messages_with_history( # noqa: PLR0915
img_element = element
format: Optional[str] = None
media_resolution_enum: Optional[Dict[str, str]] = None
if isinstance(img_element["image_url"], dict):
image_url = img_element["image_url"]["url"]
format = img_element["image_url"].get("format")
detail = img_element["image_url"].get("detail")
raw_image_url = img_element.get("image_url")
if raw_image_url is None:
raise litellm.BadRequestError(
message="Invalid message content: element type is 'image_url' but 'image_url' field is missing ",
model=model,
llm_provider="vertex_ai",
)
if isinstance(raw_image_url, dict):
image_url = raw_image_url.get("url")
if image_url is None:
raise litellm.BadRequestError(
message="Invalid message content: element type is 'image_url' but 'url' field is missing inside 'image_url' ",
model=model,
llm_provider="vertex_ai",
)
format = raw_image_url.get("format")
detail = raw_image_url.get("detail")
media_resolution_enum = (
_convert_detail_to_media_resolution_enum(detail)
)
else:
image_url = img_element["image_url"]
image_url = raw_image_url
_part = _process_gemini_media(
image_url=image_url,
format=format,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from typing import List, cast

import litellm
from litellm.llms.vertex_ai.gemini.transformation import (
_gemini_convert_messages_with_history,
)
from litellm.types.llms.openai import AllMessageValues


def test_missing_image_url_field_raises_bad_request_error():
"""When element type is 'image_url' but 'image_url' field is missing, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url"}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'image_url' field is missing" in str(exc_info.value)


def test_missing_url_inside_image_url_dict_raises_bad_request_error():
"""When image_url is a dict but 'url' key is absent, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": {"detail": "high"}}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'url' field is missing inside" in str(exc_info.value)


def test_explicit_null_image_url_raises_bad_request_error():
"""When image_url key is present but explicitly null, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": None}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'image_url' field is missing" in str(exc_info.value)


def test_empty_dict_image_url_raises_bad_request_error():
"""When image_url is an empty dict (no url), a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": {}}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'url' field is missing inside" in str(exc_info.value)
Loading