diff --git a/litellm/utils.py b/litellm/utils.py index fc3acd3065d..e7dfd0fc934 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -7514,7 +7514,7 @@ class TextCompletionStreamWrapper: if isinstance(chunk, Choices): # chunk should always be of type StreamingChoices raise Exception delta: Final = chunk["choices"][0]["delta"] - text_choices["text"] = delta["content"] + text_choices["text"] = delta["content"] or "" text_choices["reasoning_content"] = delta.get("reasoning_content") text_choices["index"] = chunk["choices"][0]["index"] text_choices["finish_reason"] = chunk["choices"][0]["finish_reason"] diff --git a/tests/integration/providers/test_ollama_prompt_tools_wire.py b/tests/integration/providers/test_ollama_prompt_tools_wire.py index 59a2ee58a44..527a6c8301a 100644 --- a/tests/integration/providers/test_ollama_prompt_tools_wire.py +++ b/tests/integration/providers/test_ollama_prompt_tools_wire.py @@ -846,7 +846,7 @@ def _thinking_reply(thinking: str) -> Reply: def _completion_texts(chunks: Sequence[Completion]) -> Iterator[str]: for chunk in chunks: - yield from (choice.text or "" for choice in chunk.choices) + yield from (choice.text for choice in chunk.choices) def _raw_stream_frames(gateway: Gateway, path: str, body: dict[str, JsonValue]) -> tuple[str, ...]: diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 87f9d58e247..edc9f38e2aa 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -2535,6 +2535,23 @@ def test_reasoning_content_preserved_in_text_completion_wrapper(): assert choice["reasoning_content"] == "Here's my chain of thought..." +def test_text_completion_wrapper_sends_empty_text_on_finish_chunk(): + finish_chunk: Final = ModelResponseStream( + id="test-id", + created=1234567890, + model="test-model", + object="chat.completion.chunk", + choices=[StreamingChoices(finish_reason="stop", index=0, delta=Delta(content=None, role=None))], + ) + wrapper: Final = TextCompletionStreamWrapper(completion_stream=None, model="test-model", stream_options=None) + + choice: Final = wrapper.convert_to_text_completion_object(finish_chunk)["choices"][0] + + assert choice["text"] == "" + assert choice["finish_reason"] == "stop" + assert choice["index"] == 0 + + def test_anthropic_claude_4_invoke_chat_provider_config(): """Test that the Anthropic Claude 4 Invoke chat provider config is correct.""" from litellm.llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation import (