fix(ollama): preserve image_url blocks in ollama_chat multimodal requests

Fixes https://github.com/BerriAI/litellm/issues/24615

Four bugs fixed across two files:

1. ollama/chat/transformation.py: extract images BEFORE flattening content
   to prevent silent regression if text-processing path mutates content

2. ollama/chat/transformation.py: `if images is not None` -> `if images:`
   Empty list [] is falsy, so the key is now omitted for text-only messages

3. ollama/chat/transformation.py: `if content_str is not None` -> `if content_str:`
   Empty string "" is falsy, so the key is now omitted for image-only messages

4. ollama/completion/transformation.py: fix /api/show URL construction
   Strip /api/chat suffix before appending /api/show to prevent 404 errors

Updated 2 existing tests to expect correct behavior (empty keys not set)
This commit is contained in:
whoismonesh 2026-03-26 13:34:49 +05:30
parent 306621deb3
commit bd89cbf3ac
3 changed files with 10 additions and 8 deletions

View file

@ -283,17 +283,17 @@ class OllamaChatConfig(BaseConfig):
reasoning_content, parsed_content = _extract_reasoning_content(
cast(dict, m)
)
content_str = convert_content_list_to_str(cast(AllMessageValues, m))
images = extract_images_from_message(cast(AllMessageValues, m))
content_str = convert_content_list_to_str(cast(AllMessageValues, m))
ollama_message = OllamaChatCompletionMessage(
role=cast(str, m.get("role")),
)
if reasoning_content is not None:
ollama_message["thinking"] = reasoning_content
if content_str is not None:
if content_str:
ollama_message["content"] = content_str
if images is not None:
if images:
ollama_message["images"] = images
new_messages.append(ollama_message)

View file

@ -236,6 +236,9 @@ class OllamaConfig(BaseConfig):
api_base = (
api_base or get_secret_str("OLLAMA_API_BASE") or "http://localhost:11434"
)
# Strip /api/chat suffix if present (same logic as get_complete_url in chat/transformation.py)
if api_base.endswith("/api/chat"):
api_base = api_base[:-10]
api_key = self.get_api_key()
headers = {"Authorization": f"Bearer {api_key}"} if api_key else {}

View file

@ -173,9 +173,9 @@ class TestOllamaChatConfigResponseFormat:
headers={},
)
# Verify empty content becomes empty string
# Verify empty content is not set (empty string is falsy, so key is omitted)
assert len(result["messages"]) == 1
assert result["messages"][0]["content"] == ""
assert "content" not in result["messages"][0]
assert result["messages"][0]["role"] == "user"
def test_transform_request_image_extraction(self):
@ -321,9 +321,8 @@ class TestOllamaChatConfigResponseFormat:
# Verify no images key when no images present
assert result["messages"][0]["content"] == "Just text here"
# Since extract_images_from_message returns empty list [] when no images found,
# and the code checks "if images is not None", an empty list will still be set
assert "images" in result["messages"][0]
assert result["messages"][0]["images"] == []
# and the code now checks "if images:" (truthy), empty list is not set
assert "images" not in result["messages"][0]
class TestOllamaToolCalling: