This commit is contained in:
Vineeth Sai Varikuntla 2026-11-07 02:58:08 +00:00 • committed by GitHub
commit c950e524a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 119 additions and 1 deletions

View file

@ -1,8 +1,13 @@
from typing import Final
from collections.abc import Coroutine
from typing import Final, Literal, overload
import httpx
from litellm._logging import verbose_logger
from litellm.litellm_core_utils.prompt_templates.common_utils import (
audio_or_image_in_message_content,
handle_messages_with_content_list_to_str_conversion,
)
from litellm.litellm_core_utils.url_utils import join_api_base
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
@ -87,6 +92,35 @@ class CloudflareChatConfig(OpenAIGPTConfig):
api_base=api_base,
)
@overload
def _transform_messages(
self,
messages: list[AllMessageValues], # mutable-ok: base signature
model: str,
is_async: Literal[True],
) -> Coroutine[object, object, list[AllMessageValues]]: ... # mutable-ok: base signature
@overload
def _transform_messages(
self,
messages: list[AllMessageValues], # mutable-ok: base signature
model: str,
is_async: Literal[False] = False,
) -> list[AllMessageValues]: ... # mutable-ok: base signature
def _transform_messages(
self,
messages: list[AllMessageValues], # mutable-ok: base signature
model: str,
is_async: bool = False,
) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]: # mutable-ok: base signature
# Flattening keeps only the text, so skip it when any message carries an image or audio part
has_media: Final = any(audio_or_image_in_message_content(message) for message in messages)
flattened: Final = messages if has_media else handle_messages_with_content_list_to_str_conversion(messages)
if is_async:
return super()._transform_messages(messages=flattened, model=model, is_async=True)
return super()._transform_messages(messages=flattened, model=model, is_async=False)
def get_error_class(self, error_message: str, status_code: int, headers: dict | httpx.Headers) -> BaseLLMException:
return CloudflareError(
status_code=status_code,

View file

@ -205,6 +205,90 @@ def test_validate_environment_sets_bearer_and_content_type():
assert headers["Content-Type"] == "application/json"
def test_transform_request_flattens_content_part_arrays_to_string():
config = CloudflareChatConfig()
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Hello"},
{"type": "text", "text": "More text"},
],
}
]
body = config.transform_request(
model="@cf/meta/llama-2-7b-chat-int8",
messages=messages,
optional_params={},
litellm_params={},
headers={},
)
assert body["messages"][0]["content"] == "HelloMore text"
def test_transform_request_leaves_string_content_untouched():
config = CloudflareChatConfig()
messages = [
{"role": "system", "content": "you are terse"},
{"role": "user", "content": "weather in nyc?"},
]
body = config.transform_request(
model="@cf/meta/llama-2-7b-chat-int8",
messages=messages,
optional_params={},
litellm_params={},
headers={},
)
assert [m["content"] for m in body["messages"]] == ["you are terse", "weather in nyc?"]
def test_transform_request_does_not_flatten_when_a_part_is_not_text():
config = CloudflareChatConfig()
parts = [
{"type": "text", "text": "What is in this picture?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.png"}},
]
body = config.transform_request(
model="@cf/meta/llama-3.2-11b-vision-instruct",
messages=[{"role": "user", "content": parts}],
optional_params={},
litellm_params={},
headers={},
)
assert body["messages"][0]["content"] == parts
def test_async_transform_request_flattens_content_part_arrays_to_string():
config = CloudflareChatConfig()
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Hello"},
{"type": "text", "text": "More text"},
],
}
]
body = asyncio.run(
config.async_transform_request(
model="@cf/meta/llama-2-7b-chat-int8",
messages=messages,
optional_params={},
litellm_params={},
headers={},
)
)
assert body["messages"][0]["content"] == "HelloMore text"
def _chat_response() -> dict[str, object]:
return {
"id": "chatcmpl-cf",