diff --git a/src/openai/types/responses/response_text_delta_event.py b/src/openai/types/responses/response_text_delta_event.py index 4f802abfd2..ba54349950 100644 --- a/src/openai/types/responses/response_text_delta_event.py +++ b/src/openai/types/responses/response_text_delta_event.py @@ -1,4 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# NOTE: logprobs field manually changed to Optional to support non-OpenAI providers +# that may not include logprobs in streaming responses. See #2489. from typing import List, Optional from typing_extensions import Literal @@ -43,8 +45,6 @@ class ResponseTextDeltaEvent(BaseModel): """The text delta that was added.""" item_id: str - """The ID of the output item that the text delta was added to.""" - logprobs: List[Logprob] """The log probabilities of the tokens in the delta.""" diff --git a/src/openai/types/responses/response_text_done_event.py b/src/openai/types/responses/response_text_done_event.py index 75bd479870..9a85b1e623 100644 --- a/src/openai/types/responses/response_text_done_event.py +++ b/src/openai/types/responses/response_text_done_event.py @@ -1,4 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# NOTE: logprobs field manually changed to Optional to support non-OpenAI providers +# that may not include logprobs in streaming responses. See #2489. from typing import List, Optional from typing_extensions import Literal @@ -40,8 +42,6 @@ class ResponseTextDoneEvent(BaseModel): """The index of the content part that the text content is finalized.""" item_id: str - """The ID of the output item that the text content is finalized.""" - logprobs: List[Logprob] """The log probabilities of the tokens in the delta.""" diff --git a/tests/test_response_event_logprobs.py b/tests/test_response_event_logprobs.py new file mode 100644 index 0000000000..61e664559a --- /dev/null +++ b/tests/test_response_event_logprobs.py @@ -0,0 +1,64 @@ +"""Tests for optional logprobs in response event types. + +Regression tests for https://github.com/openai/openai-python/issues/2489 +Non-OpenAI providers may not include logprobs in streaming responses. +""" + +from openai.types.responses.response_text_done_event import ResponseTextDoneEvent +from openai.types.responses.response_text_delta_event import ResponseTextDeltaEvent + +_DELTA_BASE = { + "content_index": 0, + "delta": "Hello", + "item_id": "item_1", + "output_index": 0, + "sequence_number": 1, + "type": "response.output_text.delta", +} + +_DONE_BASE = { + "content_index": 0, + "item_id": "item_1", + "output_index": 0, + "sequence_number": 2, + "text": "Hello world", + "type": "response.output_text.done", +} + +_SAMPLE_LOGPROBS = [{"token": "Hello", "logprob": -0.1, "top_logprobs": None}] + + +class TestResponseTextDeltaEventLogprobs: + def test_without_logprobs(self) -> None: + event = ResponseTextDeltaEvent.model_validate(_DELTA_BASE) + assert event.logprobs is None + + def test_with_logprobs(self) -> None: + data = {**_DELTA_BASE, "logprobs": _SAMPLE_LOGPROBS} + event = ResponseTextDeltaEvent.model_validate(data) + assert event.logprobs is not None + assert len(event.logprobs) == 1 + assert event.logprobs[0].token == "Hello" + + def test_with_empty_logprobs(self) -> None: + data = {**_DELTA_BASE, "logprobs": []} + event = ResponseTextDeltaEvent.model_validate(data) + assert event.logprobs == [] + + +class TestResponseTextDoneEventLogprobs: + def test_without_logprobs(self) -> None: + event = ResponseTextDoneEvent.model_validate(_DONE_BASE) + assert event.logprobs is None + + def test_with_logprobs(self) -> None: + data = {**_DONE_BASE, "logprobs": _SAMPLE_LOGPROBS} + event = ResponseTextDoneEvent.model_validate(data) + assert event.logprobs is not None + assert len(event.logprobs) == 1 + assert event.logprobs[0].token == "Hello" + + def test_with_empty_logprobs(self) -> None: + data = {**_DONE_BASE, "logprobs": []} + event = ResponseTextDoneEvent.model_validate(data) + assert event.logprobs == []