mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-25 05:54:53 +00:00
fix: download and base64-encode remote image URLs for ollama_chat
Ollama does not accept image URLs, so extract_images_from_message must send pure base64. Remote http(s) image_url values were forwarded verbatim, making Ollama fail with "illegal base64 data at input byte 5" (the ":" in "https:"). Download and base64-encode them, mirroring the data:-URL handling fixed in #18465.
This commit is contained in:
parent
ec9353cb69
commit
dcf5a2433f
2 changed files with 43 additions and 11 deletions
|
|
@ -1555,13 +1555,29 @@ def _extract_base64_data(image_url: str) -> str:
|
|||
return image_url
|
||||
|
||||
|
||||
def _extract_ollama_image_data(image_url: str) -> str:
|
||||
"""
|
||||
Return pure base64 image data for providers like Ollama that do not accept URLs.
|
||||
|
||||
Remote http(s) URLs are downloaded and base64-encoded; data URLs have their base64
|
||||
payload extracted; anything else is returned unchanged.
|
||||
"""
|
||||
if image_url.startswith(("http://", "https://")):
|
||||
from litellm.litellm_core_utils.prompt_templates.image_handling import (
|
||||
convert_url_to_base64,
|
||||
)
|
||||
|
||||
image_url = convert_url_to_base64(image_url)
|
||||
return _extract_base64_data(image_url)
|
||||
|
||||
|
||||
def extract_images_from_message(message: AllMessageValues) -> List[str]:
|
||||
"""
|
||||
Extract images from a message.
|
||||
|
||||
For data URLs (e.g., "data:image/png;base64,iVBOR..."), only the base64
|
||||
data portion is extracted. This is required for providers like Ollama
|
||||
that expect pure base64 data rather than full data URLs.
|
||||
For data URLs (e.g., "data:image/png;base64,iVBOR..."), only the base64 data portion is
|
||||
extracted, and remote http(s) URLs are downloaded and base64-encoded. This is required for
|
||||
providers like Ollama that expect pure base64 data rather than URLs or full data URLs.
|
||||
"""
|
||||
images = []
|
||||
message_content = message.get("content")
|
||||
|
|
@ -1570,9 +1586,9 @@ def extract_images_from_message(message: AllMessageValues) -> List[str]:
|
|||
image_url = m.get("image_url")
|
||||
if image_url:
|
||||
if isinstance(image_url, str):
|
||||
images.append(_extract_base64_data(image_url))
|
||||
images.append(_extract_ollama_image_data(image_url))
|
||||
elif isinstance(image_url, dict) and "url" in image_url:
|
||||
images.append(_extract_base64_data(image_url["url"]))
|
||||
images.append(_extract_ollama_image_data(image_url["url"]))
|
||||
return images
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ which fixes the Ollama error "illegal base64 data at input byte 4".
|
|||
Related issue: https://github.com/BerriAI/litellm/issues/18338
|
||||
"""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
|
|
@ -91,8 +93,12 @@ class TestExtractImagesFromMessage:
|
|||
result = extract_images_from_message(message)
|
||||
assert result == ["iVBORw0KGgo"]
|
||||
|
||||
def test_extract_from_message_with_regular_url(self):
|
||||
"""Test that regular URLs are preserved"""
|
||||
def test_extract_from_message_with_remote_url_downloads_and_encodes(self):
|
||||
"""Remote http(s) URLs must be downloaded and base64-encoded (issue #30313).
|
||||
|
||||
Ollama does not accept URLs, so forwarding one verbatim made it fail with
|
||||
"illegal base64 data at input byte 5".
|
||||
"""
|
||||
message = {
|
||||
"role": "user",
|
||||
"content": [
|
||||
|
|
@ -102,8 +108,14 @@ class TestExtractImagesFromMessage:
|
|||
}
|
||||
],
|
||||
}
|
||||
result = extract_images_from_message(message)
|
||||
assert result == ["https://example.com/image.png"]
|
||||
with patch(
|
||||
"litellm.litellm_core_utils.prompt_templates.image_handling.convert_url_to_base64",
|
||||
return_value="data:image/png;base64,ZmV0Y2hlZA==",
|
||||
) as mock_convert:
|
||||
result = extract_images_from_message(message)
|
||||
|
||||
mock_convert.assert_called_once_with("https://example.com/image.png")
|
||||
assert result == ["ZmV0Y2hlZA=="]
|
||||
|
||||
def test_extract_multiple_images(self):
|
||||
"""Test extracting multiple images from a single message"""
|
||||
|
|
@ -124,11 +136,15 @@ class TestExtractImagesFromMessage:
|
|||
},
|
||||
],
|
||||
}
|
||||
result = extract_images_from_message(message)
|
||||
with patch(
|
||||
"litellm.litellm_core_utils.prompt_templates.image_handling.convert_url_to_base64",
|
||||
return_value="data:image/png;base64,image3base64",
|
||||
):
|
||||
result = extract_images_from_message(message)
|
||||
assert result == [
|
||||
"image1base64",
|
||||
"image2base64",
|
||||
"https://example.com/image3.png",
|
||||
"image3base64",
|
||||
]
|
||||
|
||||
def test_empty_content(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue