From 2470d251b751e92e8950bc9e3026965e9925ac1c Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:23:46 -0500 Subject: [PATCH 1/8] fix(client): add support for streaming binary responses (#866) --- examples/audio.py | 5 ++++- src/openai/_base_client.py | 8 ++++++-- src/openai/_models.py | 2 ++ src/openai/_types.py | 23 +++++++++++++++++++++-- src/openai/resources/audio/speech.py | 20 ++++++++++++++++++-- src/openai/resources/files.py | 20 ++++++++++++++++++-- 6 files changed, 69 insertions(+), 9 deletions(-) diff --git a/examples/audio.py b/examples/audio.py index a5f535dcd6..e86acbf828 100755 --- a/examples/audio.py +++ b/examples/audio.py @@ -13,7 +13,10 @@ def main() -> None: # Create text-to-speech audio file response = openai.audio.speech.create( - model="tts-1", voice="alloy", input="the quick brown fox jumped over the lazy dogs" + model="tts-1", + voice="alloy", + input="the quick brown fox jumped over the lazy dogs", + stream=True, ) response.stream_to_file(speech_file_path) diff --git a/src/openai/_base_client.py b/src/openai/_base_client.py index a168301f75..9a023ba961 100644 --- a/src/openai/_base_client.py +++ b/src/openai/_base_client.py @@ -863,7 +863,7 @@ def _request( self._prepare_request(request) try: - response = self._client.send(request, auth=self.custom_auth, stream=stream) + response = self._client.send(request, auth=self.custom_auth, stream=stream or options.stream or False) log.debug( 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase ) @@ -1304,7 +1304,7 @@ async def _request( await self._prepare_request(request) try: - response = await self._client.send(request, auth=self.custom_auth, stream=stream) + response = await self._client.send(request, auth=self.custom_auth, stream=stream or options.stream or False) log.debug( 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase ) @@ -1541,6 +1541,7 @@ def make_request_options( idempotency_key: str | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, post_parser: PostParser | NotGiven = NOT_GIVEN, + stream: bool | None = None, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} @@ -1562,6 +1563,9 @@ def make_request_options( if idempotency_key is not None: options["idempotency_key"] = idempotency_key + if stream is not None: + options["stream"] = stream + if is_given(post_parser): # internal options["post_parser"] = post_parser # type: ignore diff --git a/src/openai/_models.py b/src/openai/_models.py index 5b8c96010f..a0e596149c 100644 --- a/src/openai/_models.py +++ b/src/openai/_models.py @@ -403,6 +403,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): params: Query headers: Headers max_retries: int + stream: bool | None timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str @@ -420,6 +421,7 @@ class FinalRequestOptions(pydantic.BaseModel): timeout: Union[float, Timeout, None, NotGiven] = NotGiven() files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None + stream: Union[bool, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() # It should be noted that we cannot use `json` here as that would override diff --git a/src/openai/_types.py b/src/openai/_types.py index 9e962a1078..013b658f0e 100644 --- a/src/openai/_types.py +++ b/src/openai/_types.py @@ -130,7 +130,16 @@ def stream_to_file( chunk_size: int | None = None, ) -> None: """ - Stream the output to the given file. + Stream the output to the given file. NOTE, requires passing `stream=True` + to the request for expected behavior, e.g., + + response = openai.audio.speech.create( + model="tts-1", + voice="alloy", + input="the quick brown fox jumped over the lazy dogs", + stream=True, + ) + response.stream_to_file(speech_file_path) """ pass @@ -185,7 +194,16 @@ async def astream_to_file( chunk_size: int | None = None, ) -> None: """ - Stream the output to the given file. + Stream the output to the given file. NOTE, requires passing `stream=True` + to the request for expected behavior, e.g., + + response = await openai.audio.speech.create( + model="tts-1", + voice="alloy", + input="the quick brown fox jumped over the lazy dogs", + stream=True, + ) + response.stream_to_file(speech_file_path) """ pass @@ -257,6 +275,7 @@ async def aclose(self) -> None: class RequestOptions(TypedDict, total=False): headers: Headers max_retries: int + stream: bool timeout: float | Timeout | None params: Query extra_json: AnyMapping diff --git a/src/openai/resources/audio/speech.py b/src/openai/resources/audio/speech.py index 458843866f..66916d0d50 100644 --- a/src/openai/resources/audio/speech.py +++ b/src/openai/resources/audio/speech.py @@ -41,6 +41,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Generates audio from the input text. @@ -67,6 +68,9 @@ def create( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds + + stream: Whether or not the response content should be streamed (i.e. not read to + completion immediately), default False """ return self._post( "/audio/speech", @@ -81,7 +85,11 @@ def create( speech_create_params.SpeechCreateParams, ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + stream=stream, ), cast_to=HttpxBinaryResponseContent, ) @@ -108,6 +116,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Generates audio from the input text. @@ -134,6 +143,9 @@ async def create( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds + + stream: Whether or not the response content should be streamed (i.e. not read to + completion immediately), default False """ return await self._post( "/audio/speech", @@ -148,7 +160,11 @@ async def create( speech_create_params.SpeechCreateParams, ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + stream=stream, ), cast_to=HttpxBinaryResponseContent, ) diff --git a/src/openai/resources/files.py b/src/openai/resources/files.py index a6f75e5a4c..be6eff1e08 100644 --- a/src/openai/resources/files.py +++ b/src/openai/resources/files.py @@ -212,6 +212,7 @@ def content( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Returns the contents of the specified file. @@ -224,11 +225,18 @@ def content( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds + + stream: Whether or not the response content should be streamed (i.e. not read to + completion immediately), default False """ return self._get( f"/files/{file_id}/content", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + stream=stream, ), cast_to=HttpxBinaryResponseContent, ) @@ -475,6 +483,7 @@ async def content( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Returns the contents of the specified file. @@ -487,11 +496,18 @@ async def content( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds + + stream: Whether or not the response content should be streamed (i.e. not read to + completion immediately), default False """ return await self._get( f"/files/{file_id}/content", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + stream=stream, ), cast_to=HttpxBinaryResponseContent, ) From 0a06d6a078c5ee898dae75bab4988e1a1936bfbf Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Thu, 23 Nov 2023 17:34:15 -0500 Subject: [PATCH 2/8] chore: revert binary streaming change (#875) --- examples/audio.py | 5 +---- src/openai/_base_client.py | 8 ++------ src/openai/_models.py | 2 -- src/openai/_types.py | 23 ++--------------------- src/openai/resources/audio/speech.py | 20 ++------------------ src/openai/resources/files.py | 20 ++------------------ 6 files changed, 9 insertions(+), 69 deletions(-) diff --git a/examples/audio.py b/examples/audio.py index e86acbf828..a5f535dcd6 100755 --- a/examples/audio.py +++ b/examples/audio.py @@ -13,10 +13,7 @@ def main() -> None: # Create text-to-speech audio file response = openai.audio.speech.create( - model="tts-1", - voice="alloy", - input="the quick brown fox jumped over the lazy dogs", - stream=True, + model="tts-1", voice="alloy", input="the quick brown fox jumped over the lazy dogs" ) response.stream_to_file(speech_file_path) diff --git a/src/openai/_base_client.py b/src/openai/_base_client.py index 9a023ba961..a168301f75 100644 --- a/src/openai/_base_client.py +++ b/src/openai/_base_client.py @@ -863,7 +863,7 @@ def _request( self._prepare_request(request) try: - response = self._client.send(request, auth=self.custom_auth, stream=stream or options.stream or False) + response = self._client.send(request, auth=self.custom_auth, stream=stream) log.debug( 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase ) @@ -1304,7 +1304,7 @@ async def _request( await self._prepare_request(request) try: - response = await self._client.send(request, auth=self.custom_auth, stream=stream or options.stream or False) + response = await self._client.send(request, auth=self.custom_auth, stream=stream) log.debug( 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase ) @@ -1541,7 +1541,6 @@ def make_request_options( idempotency_key: str | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, post_parser: PostParser | NotGiven = NOT_GIVEN, - stream: bool | None = None, ) -> RequestOptions: """Create a dict of type RequestOptions without keys of NotGiven values.""" options: RequestOptions = {} @@ -1563,9 +1562,6 @@ def make_request_options( if idempotency_key is not None: options["idempotency_key"] = idempotency_key - if stream is not None: - options["stream"] = stream - if is_given(post_parser): # internal options["post_parser"] = post_parser # type: ignore diff --git a/src/openai/_models.py b/src/openai/_models.py index a0e596149c..5b8c96010f 100644 --- a/src/openai/_models.py +++ b/src/openai/_models.py @@ -403,7 +403,6 @@ class FinalRequestOptionsInput(TypedDict, total=False): params: Query headers: Headers max_retries: int - stream: bool | None timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str @@ -421,7 +420,6 @@ class FinalRequestOptions(pydantic.BaseModel): timeout: Union[float, Timeout, None, NotGiven] = NotGiven() files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None - stream: Union[bool, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() # It should be noted that we cannot use `json` here as that would override diff --git a/src/openai/_types.py b/src/openai/_types.py index 013b658f0e..9e962a1078 100644 --- a/src/openai/_types.py +++ b/src/openai/_types.py @@ -130,16 +130,7 @@ def stream_to_file( chunk_size: int | None = None, ) -> None: """ - Stream the output to the given file. NOTE, requires passing `stream=True` - to the request for expected behavior, e.g., - - response = openai.audio.speech.create( - model="tts-1", - voice="alloy", - input="the quick brown fox jumped over the lazy dogs", - stream=True, - ) - response.stream_to_file(speech_file_path) + Stream the output to the given file. """ pass @@ -194,16 +185,7 @@ async def astream_to_file( chunk_size: int | None = None, ) -> None: """ - Stream the output to the given file. NOTE, requires passing `stream=True` - to the request for expected behavior, e.g., - - response = await openai.audio.speech.create( - model="tts-1", - voice="alloy", - input="the quick brown fox jumped over the lazy dogs", - stream=True, - ) - response.stream_to_file(speech_file_path) + Stream the output to the given file. """ pass @@ -275,7 +257,6 @@ async def aclose(self) -> None: class RequestOptions(TypedDict, total=False): headers: Headers max_retries: int - stream: bool timeout: float | Timeout | None params: Query extra_json: AnyMapping diff --git a/src/openai/resources/audio/speech.py b/src/openai/resources/audio/speech.py index 66916d0d50..458843866f 100644 --- a/src/openai/resources/audio/speech.py +++ b/src/openai/resources/audio/speech.py @@ -41,7 +41,6 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Generates audio from the input text. @@ -68,9 +67,6 @@ def create( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds - - stream: Whether or not the response content should be streamed (i.e. not read to - completion immediately), default False """ return self._post( "/audio/speech", @@ -85,11 +81,7 @@ def create( speech_create_params.SpeechCreateParams, ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - stream=stream, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=HttpxBinaryResponseContent, ) @@ -116,7 +108,6 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Generates audio from the input text. @@ -143,9 +134,6 @@ async def create( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds - - stream: Whether or not the response content should be streamed (i.e. not read to - completion immediately), default False """ return await self._post( "/audio/speech", @@ -160,11 +148,7 @@ async def create( speech_create_params.SpeechCreateParams, ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - stream=stream, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=HttpxBinaryResponseContent, ) diff --git a/src/openai/resources/files.py b/src/openai/resources/files.py index be6eff1e08..a6f75e5a4c 100644 --- a/src/openai/resources/files.py +++ b/src/openai/resources/files.py @@ -212,7 +212,6 @@ def content( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Returns the contents of the specified file. @@ -225,18 +224,11 @@ def content( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds - - stream: Whether or not the response content should be streamed (i.e. not read to - completion immediately), default False """ return self._get( f"/files/{file_id}/content", options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - stream=stream, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=HttpxBinaryResponseContent, ) @@ -483,7 +475,6 @@ async def content( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - stream: bool | None = None, ) -> HttpxBinaryResponseContent: """ Returns the contents of the specified file. @@ -496,18 +487,11 @@ async def content( extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds - - stream: Whether or not the response content should be streamed (i.e. not read to - completion immediately), default False """ return await self._get( f"/files/{file_id}/content", options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - stream=stream, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=HttpxBinaryResponseContent, ) From 69e054947d587ff2548b101ece690d21d3c38f74 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:42:36 -0500 Subject: [PATCH 3/8] chore(internal): send more detailed x-stainless headers (#877) --- pyproject.toml | 1 + src/openai/_client.py | 4 +++- src/openai/_utils/__init__.py | 1 + src/openai/_utils/_utils.py | 9 +++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f17def16b6..d2d85a5018 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ "typing-extensions>=4.5, <5", "anyio>=3.5.0, <4", "distro>=1.7.0, <2", + "sniffio", "tqdm > 4" ] requires-python = ">= 3.7.1" diff --git a/src/openai/_client.py b/src/openai/_client.py index aa00073281..202162070b 100644 --- a/src/openai/_client.py +++ b/src/openai/_client.py @@ -20,7 +20,7 @@ ProxiesTypes, RequestOptions, ) -from ._utils import is_given, is_mapping +from ._utils import is_given, is_mapping, get_async_library from ._version import __version__ from ._streaming import Stream as Stream from ._streaming import AsyncStream as AsyncStream @@ -147,6 +147,7 @@ def auth_headers(self) -> dict[str, str]: def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, + "X-Stainless-Async": "false", "OpenAI-Organization": self.organization if self.organization is not None else Omit(), **self._custom_headers, } @@ -356,6 +357,7 @@ def auth_headers(self) -> dict[str, str]: def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, + "X-Stainless-Async": f"async:{get_async_library()}", "OpenAI-Organization": self.organization if self.organization is not None else Omit(), **self._custom_headers, } diff --git a/src/openai/_utils/__init__.py b/src/openai/_utils/__init__.py index d3397212de..400ca9b828 100644 --- a/src/openai/_utils/__init__.py +++ b/src/openai/_utils/__init__.py @@ -25,6 +25,7 @@ from ._utils import deepcopy_minimal as deepcopy_minimal from ._utils import extract_type_arg as extract_type_arg from ._utils import is_required_type as is_required_type +from ._utils import get_async_library as get_async_library from ._utils import is_annotated_type as is_annotated_type from ._utils import maybe_coerce_float as maybe_coerce_float from ._utils import get_required_header as get_required_header diff --git a/src/openai/_utils/_utils.py b/src/openai/_utils/_utils.py index 4b51dcb2e8..d2bfc91a70 100644 --- a/src/openai/_utils/_utils.py +++ b/src/openai/_utils/_utils.py @@ -18,6 +18,8 @@ from pathlib import Path from typing_extensions import Required, Annotated, TypeGuard, get_args, get_origin +import sniffio + from .._types import Headers, NotGiven, FileTypes, NotGivenOr, HeadersLike from .._compat import is_union as _is_union from .._compat import parse_date as parse_date @@ -406,3 +408,10 @@ def get_required_header(headers: HeadersLike, header: str) -> str: return value raise ValueError(f"Could not find {header} header") + + +def get_async_library() -> str: + try: + return sniffio.current_async_library() + except Exception: + return "false" From c522f21e2a685454185d57e462e74a28499460f9 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 28 Nov 2023 00:26:59 -0500 Subject: [PATCH 4/8] docs: update readme code snippet (#890) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33ec6add52..3861b7db2b 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,7 @@ completion = client.chat.completions.create( "content": "Can you generate an example json object describing a fruit?", } ], - model="gpt-3.5-turbo", + model="gpt-3.5-turbo-1106", response_format={"type": "json_object"}, ) ``` From 11fcb2a3cd4205b307c13c65ad47d9e315b0084d Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 28 Nov 2023 08:43:59 -0500 Subject: [PATCH 5/8] chore(deps): bump mypy to v1.7.1 (#891) --- pyproject.toml | 2 +- requirements-dev.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d2d85a5018..351c464313 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ openai = "openai.cli:main" managed = true dev-dependencies = [ "pyright==1.1.332", - "mypy==1.6.1", + "mypy==1.7.1", "black==23.3.0", "respx==0.19.2", "pytest==7.1.1", diff --git a/requirements-dev.lock b/requirements-dev.lock index 0747babdc5..683454d678 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -16,10 +16,10 @@ azure-identity==1.15.0 black==23.3.0 certifi==2023.7.22 cffi==1.16.0 -charset-normalizer==3.3.1 +charset-normalizer==3.3.2 click==8.1.7 colorlog==6.7.0 -cryptography==41.0.5 +cryptography==41.0.7 dirty-equals==0.6.0 distlib==0.3.7 distro==1.8.0 @@ -31,15 +31,15 @@ httpx==0.23.0 idna==3.4 iniconfig==2.0.0 isort==5.10.1 -msal==1.24.1 +msal==1.25.0 msal-extensions==1.0.0 -mypy==1.6.1 +mypy==1.7.1 mypy-extensions==1.0.0 nodeenv==1.8.0 nox==2023.4.22 -numpy==1.26.1 +numpy==1.26.2 packaging==23.2 -pandas==2.1.1 +pandas==2.1.3 pandas-stubs==2.1.1.230928 pathspec==0.11.2 platformdirs==3.11.0 @@ -68,7 +68,7 @@ types-pytz==2023.3.1.1 types-tqdm==4.66.0.2 typing-extensions==4.8.0 tzdata==2023.3 -urllib3==2.0.7 +urllib3==2.1.0 virtualenv==20.24.5 # The following packages are considered to be unsafe in a requirements file: setuptools==68.2.2 From 124da8720c44d40c083d29179f46a265761c1f4f Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 28 Nov 2023 17:01:57 -0500 Subject: [PATCH 6/8] docs(readme): update examples (#893) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3861b7db2b..96865aba78 100644 --- a/README.md +++ b/README.md @@ -94,9 +94,9 @@ stream = client.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], stream=True, ) -for chunk in stream: +for part in stream: if chunk.choices[0].delta.content is not None: - print(chunk.choices[0].delta.content, end="") + print(part.choices[0].delta.content) ``` The async client uses the exact same interface. @@ -111,9 +111,9 @@ stream = await client.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], stream=True, ) -async for chunk in stream: +async for part in stream: if chunk.choices[0].delta.content is not None: - print(chunk.choices[0].delta.content, end="") + print(part.choices[0].delta.content) ``` ## Module-level client From 54584572df4c2a086172d812c6acb84e3405328b Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 28 Nov 2023 17:18:32 -0500 Subject: [PATCH 7/8] docs(readme): minor updates (#894) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 96865aba78..83392e9585 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ stream = client.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], stream=True, ) -for part in stream: +for chunk in stream: if chunk.choices[0].delta.content is not None: print(part.choices[0].delta.content) ``` @@ -111,7 +111,7 @@ stream = await client.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], stream=True, ) -async for part in stream: +async for chunk in stream: if chunk.choices[0].delta.content is not None: print(part.choices[0].delta.content) ``` From c1f370824a806c1a1cadc4b7cf6ba98e8ef73478 Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Tue, 28 Nov 2023 17:19:13 -0500 Subject: [PATCH 8/8] release: 1.3.6 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ pyproject.toml | 2 +- src/openai/_version.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 13787787c4..907051ec7d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.3.5" + ".": "1.3.6" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0869b3888c..a4c324e4f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 1.3.6 (2023-11-28) + +Full Changelog: [v1.3.5...v1.3.6](https://github.com/openai/openai-python/compare/v1.3.5...v1.3.6) + +### Bug Fixes + +* **client:** add support for streaming binary responses ([#866](https://github.com/openai/openai-python/issues/866)) ([2470d25](https://github.com/openai/openai-python/commit/2470d251b751e92e8950bc9e3026965e9925ac1c)) + + +### Chores + +* **deps:** bump mypy to v1.7.1 ([#891](https://github.com/openai/openai-python/issues/891)) ([11fcb2a](https://github.com/openai/openai-python/commit/11fcb2a3cd4205b307c13c65ad47d9e315b0084d)) +* **internal:** send more detailed x-stainless headers ([#877](https://github.com/openai/openai-python/issues/877)) ([69e0549](https://github.com/openai/openai-python/commit/69e054947d587ff2548b101ece690d21d3c38f74)) +* revert binary streaming change ([#875](https://github.com/openai/openai-python/issues/875)) ([0a06d6a](https://github.com/openai/openai-python/commit/0a06d6a078c5ee898dae75bab4988e1a1936bfbf)) + + +### Documentation + +* **readme:** minor updates ([#894](https://github.com/openai/openai-python/issues/894)) ([5458457](https://github.com/openai/openai-python/commit/54584572df4c2a086172d812c6acb84e3405328b)) +* **readme:** update examples ([#893](https://github.com/openai/openai-python/issues/893)) ([124da87](https://github.com/openai/openai-python/commit/124da8720c44d40c083d29179f46a265761c1f4f)) +* update readme code snippet ([#890](https://github.com/openai/openai-python/issues/890)) ([c522f21](https://github.com/openai/openai-python/commit/c522f21e2a685454185d57e462e74a28499460f9)) + ## 1.3.5 (2023-11-21) Full Changelog: [v1.3.4...v1.3.5](https://github.com/openai/openai-python/compare/v1.3.4...v1.3.5) diff --git a/pyproject.toml b/pyproject.toml index 351c464313..daa765a7c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "1.3.5" +version = "1.3.6" description = "The official Python library for the openai API" readme = "README.md" license = "Apache-2.0" diff --git a/src/openai/_version.py b/src/openai/_version.py index 1ef6479491..bf8fdd1b4f 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "openai" -__version__ = "1.3.5" # x-release-please-version +__version__ = "1.3.6" # x-release-please-version