diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index ab9e7db343a..99be6d02e2c 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -86,8 +86,10 @@ DEFAULT_ASSISTANT_CONTINUE_MESSAGE = ChatCompletionAssistantMessage( ) # similar to autogen. Only used if `litellm.modify_params=True`. -def _get_content_as_str(content: Union[str, list]) -> str: - """Extract text from content that may be a string or a list of content blocks.""" +def _get_content_as_str(content: Union[str, list, None]) -> str: + """Extract text from content that may be a string, a list of content blocks, or None.""" + if content is None: + return "" if isinstance(content, str): return content if isinstance(content, list): diff --git a/tests/llm_translation/test_optional_params.py b/tests/llm_translation/test_optional_params.py index 565a6e644e7..16b4e5e2b82 100644 --- a/tests/llm_translation/test_optional_params.py +++ b/tests/llm_translation/test_optional_params.py @@ -110,6 +110,24 @@ def test_supports_system_message_list_content_last_message(): assert new_messages[0]["content"] == "Only system" +def test_supports_system_message_none_content(): + """ + Test map_system_message_pt when next message has content=None (e.g. assistant + tool-call messages). Should not produce the literal string 'None'. + """ + messages = [ + {"role": "system", "content": "Be helpful."}, + {"role": "assistant", "content": None, "tool_calls": [{"id": "1", "type": "function", "function": {"name": "f", "arguments": "{}"}}]}, + ] + + new_messages = map_system_message_pt(messages=messages) + + assert len(new_messages) == 1 + # content should start with system text, not contain literal "None" + assert "None" not in new_messages[0]["content"] + assert "Be helpful." in new_messages[0]["content"] + + @pytest.mark.parametrize( "stop_sequence, expected_count", [("\n", 0), (["\n"], 0), (["finish_reason"], 1)] )