diff --git a/src/openai/lib/_parsing/_responses.py b/src/openai/lib/_parsing/_responses.py index 8853a0749f..a7f7550fe4 100644 --- a/src/openai/lib/_parsing/_responses.py +++ b/src/openai/lib/_parsing/_responses.py @@ -71,7 +71,11 @@ def parse_response( type_=ParsedResponseOutputText[TextFormatT], value={ **item.to_dict(), - "parsed": parse_text(item.text, text_format=text_format), + "parsed": ( + None + if output.status == "incomplete" + else parse_text(item.text, text_format=text_format) + ), }, ) ) diff --git a/tests/lib/responses/test_responses.py b/tests/lib/responses/test_responses.py index 8e5f16df95..f1737ad67b 100644 --- a/tests/lib/responses/test_responses.py +++ b/tests/lib/responses/test_responses.py @@ -4,10 +4,13 @@ import pytest from respx import MockRouter +from pydantic import BaseModel from inline_snapshot import snapshot from openai import OpenAI, AsyncOpenAI from openai._utils import assert_signatures_in_sync +from openai.types.responses import Response +from openai.lib._parsing._responses import parse_response from ...conftest import base_url from ..snapshots import make_snapshot_request @@ -41,6 +44,45 @@ def test_output_text(client: OpenAI, respx_mock: MockRouter) -> None: ) +def test_parse_incomplete_message_skips_text_parsing() -> None: + class Location(BaseModel): + city: str + + response = Response.model_validate( + { + "id": "resp_123", + "object": "response", + "created_at": 0, + "model": "gpt-4o-mini", + "output": [ + { + "id": "msg_123", + "type": "message", + "status": "incomplete", + "role": "assistant", + "content": [ + { + "type": "output_text", + "annotations": [], + "text": '{"city": "San Francisco",', + } + ], + } + ], + "parallel_tool_calls": True, + "tool_choice": "auto", + "tools": [], + } + ) + + parsed = parse_response(text_format=Location, input_tools=[], response=response) + + assert parsed.output[0].type == "message" + assert parsed.output[0].status == "incomplete" + assert parsed.output[0].content[0].type == "output_text" + assert parsed.output[0].content[0].parsed is None + + @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) def test_stream_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: checking_client: OpenAI | AsyncOpenAI = client if sync else async_client