mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-16 23:41:43 +00:00
Merge 1f6b62f535 into c2c2a623c0
This commit is contained in:
commit
dde202ac16
2 changed files with 57 additions and 7 deletions
|
|
@ -8,12 +8,31 @@ from collections.abc import Coroutine
|
|||
from typing import Any, Final, Literal, overload
|
||||
|
||||
from litellm.litellm_core_utils.prompt_templates.common_utils import (
|
||||
handle_messages_with_content_list_to_str_conversion,
|
||||
convert_content_list_to_str,
|
||||
)
|
||||
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
|
||||
from litellm.types.llms.openai import AllMessageValues
|
||||
|
||||
|
||||
def _flatten_text_only_messages(
|
||||
messages: list[AllMessageValues],
|
||||
) -> list[AllMessageValues]:
|
||||
"""
|
||||
Flatten a message's content list to a plain string only when it contains
|
||||
text alone. A content list that carries any non-text part (e.g. image_url)
|
||||
is left as a list so that part still reaches the SambaNova API, which
|
||||
accepts content lists for vision-capable models. Flattening those would
|
||||
drop the image and silently return a text-only answer.
|
||||
"""
|
||||
for message in messages:
|
||||
content = message.get("content")
|
||||
if isinstance(content, list) and all(isinstance(part, dict) and part.get("type") == "text" for part in content):
|
||||
texts = convert_content_list_to_str(message=message)
|
||||
if texts:
|
||||
message["content"] = texts
|
||||
return messages
|
||||
|
||||
|
||||
class SambanovaConfig(OpenAIGPTConfig):
|
||||
"""
|
||||
Reference: https://docs.sambanova.ai/cloud/api-reference/
|
||||
|
|
@ -117,14 +136,15 @@ class SambanovaConfig(OpenAIGPTConfig):
|
|||
"""
|
||||
Transform messages to handle content list conversion.
|
||||
|
||||
SambaNova API doesn't support content as a list - only string content.
|
||||
This converts content lists like [{"type": "text", "text": "..."}] to strings.
|
||||
Text-only content lists like [{"type": "text", "text": "..."}] are
|
||||
flattened to a plain string. Content lists that carry non-text parts
|
||||
(e.g. image_url) are left intact so those parts still reach the
|
||||
SambaNova API, which accepts content lists for vision-capable models.
|
||||
"""
|
||||
|
||||
async def _async_transform():
|
||||
return handle_messages_with_content_list_to_str_conversion(messages)
|
||||
return _flatten_text_only_messages(messages)
|
||||
|
||||
if is_async:
|
||||
return _async_transform()
|
||||
messages = handle_messages_with_content_list_to_str_conversion(messages)
|
||||
return messages
|
||||
return _flatten_text_only_messages(messages)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
Unit tests for SambaNova chat message transformation
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from litellm.llms.sambanova.chat import SambanovaConfig
|
||||
|
||||
|
||||
|
|
@ -102,3 +101,34 @@ class TestSambanovaContentListHandling:
|
|||
assert transformed_messages[1]["content"] == "What is the weather?"
|
||||
assert transformed_messages[2]["content"] == "I need your location."
|
||||
assert transformed_messages[3]["content"] == "I'm in San Francisco"
|
||||
|
||||
def test_content_list_with_image_url_is_preserved(self):
|
||||
"""
|
||||
A content list carrying a non-text part (image_url) must stay a list so
|
||||
the image reaches the SambaNova API, instead of being flattened to a
|
||||
text-only string that silently drops the image.
|
||||
"""
|
||||
config = SambanovaConfig()
|
||||
|
||||
image_part = {
|
||||
"type": "image_url",
|
||||
"image_url": {"url": "data:image/png;base64,aGVsbG8="},
|
||||
}
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "What colors are in this image?"},
|
||||
image_part,
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
transformed_messages = config._transform_messages(
|
||||
messages=messages, model="sambanova/gpt-oss-120b", is_async=False
|
||||
)
|
||||
|
||||
content = transformed_messages[0]["content"]
|
||||
assert isinstance(content, list)
|
||||
assert image_part in content
|
||||
assert any(part.get("type") == "image_url" for part in content)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue