Enhance chunk parsing for Ollama streaming responses

Updated the chunk_parser method to return a ModelResponseStream when handling 'thinking' field content, allowing UIs to render reasoning information. Adjusted tests to verify the new behavior, ensuring that reasoning content is correctly returned in the response.
This commit is contained in:
Cole McIntosh
2025-08-11 07:01:44 -06:00
parent 7a1c6efa0a
commit d5d7e00d34
2 changed files with 17 additions and 14 deletions
@@ -24,6 +24,8 @@ from litellm.types.utils import (
ModelResponse,
ModelResponseStream,
ProviderField,
StreamingChoices,
Delta,
)
from ..common_utils import OllamaError, _convert_image
@@ -423,7 +425,7 @@ class OllamaTextCompletionResponseIterator(BaseModelResponseIterator):
) -> Union[GenericStreamingChunk, ModelResponseStream]:
return self.chunk_parser(json.loads(str_line))
def chunk_parser(self, chunk: dict) -> GenericStreamingChunk:
def chunk_parser(self, chunk: dict) -> Union[GenericStreamingChunk, ModelResponseStream]:
try:
if "error" in chunk:
raise Exception(f"Ollama Error - {chunk}")
@@ -460,13 +462,15 @@ class OllamaTextCompletionResponseIterator(BaseModelResponseIterator):
usage=None,
)
elif "thinking" in chunk and not chunk["response"]:
# Handle GPT-OSS models that include 'thinking' field with empty response
# These are intermediate chunks that don't contain user-facing content
return GenericStreamingChunk(
text="",
is_finished=is_finished,
finish_reason="",
usage=None,
# Return reasoning content as ModelResponseStream so UIs can render it
thinking_content = chunk.get("thinking") or ""
return ModelResponseStream(
choices=[
StreamingChoices(
index=0,
delta=Delta(reasoning_content=thinking_content),
)
]
)
else:
raise Exception(f"Unable to parse ollama chunk - {chunk}")
@@ -14,7 +14,7 @@ from litellm.llms.ollama.completion.transformation import (
OllamaConfig,
OllamaTextCompletionResponseIterator,
)
from litellm.types.utils import Message, ModelResponse
from litellm.types.utils import Message, ModelResponse, ModelResponseStream
class TestOllamaConfig:
@@ -178,11 +178,10 @@ class TestOllamaTextCompletionResponseIterator:
result = iterator.chunk_parser(chunk_with_thinking)
# Should return empty text and not be finished
assert result["text"] == ""
assert result["is_finished"] is False
assert result["finish_reason"] == ""
assert result["usage"] is None
# Should return a ModelResponseStream with reasoning content
assert isinstance(result, ModelResponseStream)
assert result.choices and result.choices[0].delta is not None
assert getattr(result.choices[0].delta, "reasoning_content") == "User"
def test_chunk_parser_normal_response(self):
"""Test that normal response chunks still work."""