From e734cc2d05cf8296ca75e24d1b91c6bdf3577d17 Mon Sep 17 00:00:00 2001 From: Genmin Date: Fri, 1 May 2026 07:44:04 -0700 Subject: [PATCH] fix: avoid standalone system separator blocks --- litellm/llms/base_llm/base_utils.py | 28 ++++++++++++++++++- .../test_base_llm_base_utils.py | 25 +++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/litellm/llms/base_llm/base_utils.py b/litellm/llms/base_llm/base_utils.py index d365c942dec..13c18b9ce5f 100644 --- a/litellm/llms/base_llm/base_utils.py +++ b/litellm/llms/base_llm/base_utils.py @@ -272,7 +272,33 @@ def _merge_system_message_contents(contents: List[Any]) -> Union[str, List[Any]] continue if merged_blocks: - merged_blocks.append({"type": "text", "text": "\n\n"}) + last_block = merged_blocks[-1] + first_block = content_blocks[0] + if ( + isinstance(last_block, dict) + and last_block.get("type") == "text" + and isinstance(last_block.get("text"), str) + and isinstance(first_block, dict) + and first_block.get("type") == "text" + and isinstance(first_block.get("text"), str) + ): + last_block["text"] += "\n\n" + first_block["text"] + merged_blocks.extend(content_blocks[1:]) + continue + if ( + isinstance(last_block, dict) + and last_block.get("type") == "text" + and isinstance(last_block.get("text"), str) + ): + last_block["text"] += "\n\n" + elif ( + isinstance(first_block, dict) + and first_block.get("type") == "text" + and isinstance(first_block.get("text"), str) + ): + first_block = dict(first_block) + first_block["text"] = "\n\n" + first_block["text"] + content_blocks = [first_block, *content_blocks[1:]] merged_blocks.extend(content_blocks) return merged_blocks diff --git a/tests/test_litellm/litellm_core_utils/test_base_llm_base_utils.py b/tests/test_litellm/litellm_core_utils/test_base_llm_base_utils.py index 7ed50edc1af..6794443d0a3 100644 --- a/tests/test_litellm/litellm_core_utils/test_base_llm_base_utils.py +++ b/tests/test_litellm/litellm_core_utils/test_base_llm_base_utils.py @@ -51,9 +51,28 @@ def test_map_developer_role_preserves_structured_leading_system_content(): { "role": "system", "content": [ - {"type": "text", "text": "System rules."}, - {"type": "text", "text": "\n\n"}, - {"type": "text", "text": "Developer rules."}, + {"type": "text", "text": "System rules.\n\nDeveloper rules."}, + ], + }, + {"role": "user", "content": "Hello!"}, + ] + + +def test_map_developer_role_avoids_standalone_separator_blocks(): + messages = [ + {"role": "system", "content": [{"type": "image", "url": "policy.png"}]}, + {"role": "developer", "content": "Developer rules."}, + {"role": "user", "content": "Hello!"}, + ] + + result = map_developer_role_to_system_role(messages=messages) + + assert result == [ + { + "role": "system", + "content": [ + {"type": "image", "url": "policy.png"}, + {"type": "text", "text": "\n\nDeveloper rules."}, ], }, {"role": "user", "content": "Hello!"},