fix(chatgpt5.4): recover output text deltas when complete output is empty

This commit is contained in:
Harsh2KumarPrasad 2026-04-26 17:14:20 +05:30
parent 14f6dd5c8c
commit c5234f3db5
2 changed files with 68 additions and 0 deletions

View file

@ -133,7 +133,9 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
)
completed_response = None
completed_response_payload = None
error_message = None
output_text_parts = []
for chunk in body_text.splitlines():
stripped_chunk = CustomStreamWrapper._strip_sse_data_from_chunk(chunk)
if not stripped_chunk:
@ -150,10 +152,16 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
if not isinstance(parsed_chunk, dict):
continue
event_type = parsed_chunk.get("type")
if event_type == ResponsesAPIStreamEvents.OUTPUT_TEXT_DELTA:
content_part = parsed_chunk.get("delta", None)
if isinstance(content_part, str) and content_part:
output_text_parts.append(content_part)
continue
if event_type == ResponsesAPIStreamEvents.RESPONSE_COMPLETED:
response_payload = parsed_chunk.get("response")
if isinstance(response_payload, dict):
response_payload = dict(response_payload)
completed_response_payload = response_payload
if "created_at" in response_payload:
response_payload["created_at"] = _safe_convert_created_field(
response_payload["created_at"]
@ -178,6 +186,34 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
else:
error_message = str(error_obj)
if (
completed_response_payload is not None
and not completed_response_payload.get("output")
and len(output_text_parts) > 0
):
completed_response_payload["output"] = [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "".join(output_text_parts),
}
],
}
]
if "created_at" in completed_response_payload:
completed_response_payload["created_at"] = _safe_convert_created_field(
completed_response_payload["created_at"]
)
try:
completed_response = ResponsesAPIResponse(**completed_response_payload)
except Exception:
completed_response = ResponsesAPIResponse.model_construct(
**completed_response_payload
)
if completed_response is None:
raise OpenAIError(
message=error_message or raw_response.text,

View file

@ -201,3 +201,35 @@ class TestChatGPTResponsesAPITransformation:
)
assert parsed.output_text == "Hello!"
def test_chatgpt_non_stream_sse_response_parsing_empty_completed_output(self):
config = ChatGPTResponsesAPIConfig()
response_payload = {
"id": "resp_test",
"object": "response",
"created_at": 1700000000,
"status": "completed",
"model": "gpt-5.4",
"output": [],
}
sse_body = "\n".join(
[
f"data: {json.dumps({'type': 'response.output_text.delta', 'delta': 'Hel'})}",
f"data: {json.dumps({'type': 'response.output_text.delta', 'delta': 'lo!'})}",
f"data: {json.dumps({'type': 'response.completed', 'response': response_payload})}",
"data: [DONE]",
"",
]
)
raw_response = httpx.Response(
200, headers={"content-type": "text/event-stream"}, text=sse_body
)
logging_obj = MagicMock()
parsed = config.transform_response_api_response(
model="chatgpt/gpt-5.4",
raw_response=raw_response,
logging_obj=logging_obj,
)
assert parsed.output_text == "Hello!"