From bbf9021189017b70a837cdebce1f3836916ea732 Mon Sep 17 00:00:00 2001 From: Vineeth Sai Date: Thu, 5 Nov 2026 16:32:35 -0800 Subject: [PATCH] fix(cloudflare): keep image parts when flattening message content Flattening content parts to a string keeps only the text, so a message with an image_url would lose its image on vision models like llama-3.2-11b-vision-instruct. Skip the flatten when any message carries an image or audio part, using the existing audio_or_image_in_message_content helper. --- litellm/llms/cloudflare/chat/transformation.py | 5 ++++- .../test_cloudflare_transformation.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/litellm/llms/cloudflare/chat/transformation.py b/litellm/llms/cloudflare/chat/transformation.py index b32215320c9..acc7609a36c 100644 --- a/litellm/llms/cloudflare/chat/transformation.py +++ b/litellm/llms/cloudflare/chat/transformation.py @@ -5,6 +5,7 @@ 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 @@ -113,7 +114,9 @@ class CloudflareChatConfig(OpenAIGPTConfig): model: str, is_async: bool = False, ) -> list[AllMessageValues] | Coroutine[object, object, list[AllMessageValues]]: # mutable-ok: base signature - flattened: Final = handle_messages_with_content_list_to_str_conversion(messages) + # 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) diff --git a/tests/unit/llms/cloudflare/test_cloudflare_transformation.py b/tests/unit/llms/cloudflare/test_cloudflare_transformation.py index 1b52e6a717d..256a3fcde95 100644 --- a/tests/unit/llms/cloudflare/test_cloudflare_transformation.py +++ b/tests/unit/llms/cloudflare/test_cloudflare_transformation.py @@ -246,6 +246,24 @@ def test_transform_request_leaves_string_content_untouched(): 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 = [