Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 1.59.8 #2013

Merged
merged 11 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.59.7"
".": "1.59.8"
}
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Changelog

## 1.59.8 (2025-01-17)

Full Changelog: [v1.59.7...v1.59.8](https://github.com/openai/openai-python/compare/v1.59.7...v1.59.8)

### Bug Fixes

* streaming ([c16f58e](https://github.com/openai/openai-python/commit/c16f58ead0bc85055b164182689ba74b7e939dfa))
* **structured outputs:** avoid parsing empty empty content ([#2023](https://github.com/openai/openai-python/issues/2023)) ([6d3513c](https://github.com/openai/openai-python/commit/6d3513c86f6e5800f8f73a45e089b7a205327121))
* **structured outputs:** correct schema coercion for inline ref expansion ([#2025](https://github.com/openai/openai-python/issues/2025)) ([2f4f0b3](https://github.com/openai/openai-python/commit/2f4f0b374207f162060c328b71ec995049dc42e8))
* **types:** correct type for vector store chunking strategy ([#2017](https://github.com/openai/openai-python/issues/2017)) ([e389279](https://github.com/openai/openai-python/commit/e38927950a5cdad99065853fe7b72aad6bb322e9))


### Chores

* **examples:** update realtime model ([f26746c](https://github.com/openai/openai-python/commit/f26746cbcd893d66cf8a3fd68a7c3779dc8c833c)), closes [#2020](https://github.com/openai/openai-python/issues/2020)
* **internal:** bump pyright dependency ([#2021](https://github.com/openai/openai-python/issues/2021)) ([0a9a0f5](https://github.com/openai/openai-python/commit/0a9a0f5d8b9d5457643798287f893305006dd518))
* **internal:** streaming refactors ([#2012](https://github.com/openai/openai-python/issues/2012)) ([d76a748](https://github.com/openai/openai-python/commit/d76a748f606743407f94dfc26758095560e2082a))
* **internal:** update deps ([#2015](https://github.com/openai/openai-python/issues/2015)) ([514e0e4](https://github.com/openai/openai-python/commit/514e0e415f87ab4510262d29ed6125384e017b84))


### Documentation

* **examples/azure:** example script with realtime API ([#1967](https://github.com/openai/openai-python/issues/1967)) ([84f2f9c](https://github.com/openai/openai-python/commit/84f2f9c0439229a7db7136fe78419292d34d1f81))

## 1.59.7 (2025-01-13)

Full Changelog: [v1.59.6...v1.59.7](https://github.com/openai/openai-python/compare/v1.59.6...v1.59.7)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ from openai import AsyncOpenAI
async def main():
client = AsyncOpenAI()

async with client.beta.realtime.connect(model="gpt-4o-realtime-preview-2024-10-01") as connection:
async with client.beta.realtime.connect(model="gpt-4o-realtime-preview") as connection:
await connection.session.update(session={'modalities': ['text']})

await connection.conversation.item.create(
Expand Down Expand Up @@ -309,7 +309,7 @@ Whenever an error occurs, the Realtime API will send an [`error` event](https://
```py
client = AsyncOpenAI()

async with client.beta.realtime.connect(model="gpt-4o-realtime-preview-2024-10-01") as connection:
async with client.beta.realtime.connect(model="gpt-4o-realtime-preview") as connection:
...
async for event in connection:
if event.type == 'error':
Expand Down
2 changes: 1 addition & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ from openai.types.beta import (
OtherFileChunkingStrategyObject,
StaticFileChunkingStrategy,
StaticFileChunkingStrategyObject,
StaticFileChunkingStrategyParam,
StaticFileChunkingStrategyObjectParam,
VectorStore,
VectorStoreDeleted,
)
Expand Down
57 changes: 57 additions & 0 deletions examples/realtime/azure_realtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import asyncio

from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider

from openai import AsyncAzureOpenAI

# Azure OpenAI Realtime Docs

# How-to: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio
# Supported models and API versions: https://learn.microsoft.com/azure/ai-services/openai/how-to/realtime-audio#supported-models
# Entra ID auth: https://learn.microsoft.com/azure/ai-services/openai/how-to/managed-identity


async def main() -> None:
"""The following example demonstrates how to configure Azure OpenAI to use the Realtime API.
For an audio example, see push_to_talk_app.py and update the client and model parameter accordingly.

When prompted for user input, type a message and hit enter to send it to the model.
Enter "q" to quit the conversation.
"""

credential = DefaultAzureCredential()
client = AsyncAzureOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_ad_token_provider=get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default"),
api_version="2024-10-01-preview",
)
async with client.beta.realtime.connect(
model="gpt-4o-realtime-preview", # deployment name for your model
) as connection:
await connection.session.update(session={"modalities": ["text"]}) # type: ignore
while True:
user_input = input("Enter a message: ")
if user_input == "q":
break

await connection.conversation.item.create(
item={
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": user_input}],
}
)
await connection.response.create()
async for event in connection:
if event.type == "response.text.delta":
print(event.delta, flush=True, end="")
elif event.type == "response.text.done":
print()
elif event.type == "response.done":
break

await credential.close()


asyncio.run(main())
2 changes: 1 addition & 1 deletion examples/realtime/push_to_talk_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async def on_mount(self) -> None:
self.run_worker(self.send_mic_audio())

async def handle_realtime_connection(self) -> None:
async with self.client.beta.realtime.connect(model="gpt-4o-realtime-preview-2024-10-01") as conn:
async with self.client.beta.realtime.connect(model="gpt-4o-realtime-preview") as conn:
self.connection = conn
self.connected.set()

Expand Down
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ cache_fine_grained = True
# ```
# Changing this codegen to make mypy happy would increase complexity
# and would not be worth it.
disable_error_code = func-returns-value
disable_error_code = func-returns-value,overload-cannot-match

# https://github.com/python/mypy/issues/12162
[mypy.overrides]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "openai"
version = "1.59.7"
version = "1.59.8"
description = "The official Python library for the openai API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
4 changes: 2 additions & 2 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ msal==1.31.0
# via msal-extensions
msal-extensions==1.2.0
# via azure-identity
mypy==1.13.0
mypy==1.14.1
mypy-extensions==1.0.0
# via black
# via mypy
Expand Down Expand Up @@ -124,7 +124,7 @@ pygments==2.18.0
# via rich
pyjwt==2.8.0
# via msal
pyright==1.1.390
pyright==1.1.392.post0
pytest==8.3.3
# via pytest-asyncio
pytest-asyncio==0.24.0
Expand Down
12 changes: 10 additions & 2 deletions src/openai/_legacy_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
if origin == LegacyAPIResponse:
raise RuntimeError("Unexpected state - cast_to is `APIResponse`")

if inspect.isclass(origin) and issubclass(origin, httpx.Response):
if inspect.isclass(
origin # pyright: ignore[reportUnknownArgumentType]
) and issubclass(origin, httpx.Response):
# Because of the invariance of our ResponseT TypeVar, users can subclass httpx.Response
# and pass that class to our request functions. We cannot change the variance to be either
# covariant or contravariant as that makes our usage of ResponseT illegal. We could construct
Expand All @@ -279,7 +281,13 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`")
return cast(R, response)

if inspect.isclass(origin) and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel):
if (
inspect.isclass(
origin # pyright: ignore[reportUnknownArgumentType]
)
and not issubclass(origin, BaseModel)
and issubclass(origin, pydantic.BaseModel)
):
raise TypeError("Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`")

if (
Expand Down
8 changes: 7 additions & 1 deletion src/openai/_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,13 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
raise ValueError(f"Subclasses of httpx.Response cannot be passed to `cast_to`")
return cast(R, response)

if inspect.isclass(origin) and not issubclass(origin, BaseModel) and issubclass(origin, pydantic.BaseModel):
if (
inspect.isclass(
origin # pyright: ignore[reportUnknownArgumentType]
)
and not issubclass(origin, BaseModel)
and issubclass(origin, pydantic.BaseModel)
):
raise TypeError("Pydantic models must subclass our base model type, e.g. `from openai import BaseModel`")

if (
Expand Down
2 changes: 1 addition & 1 deletion src/openai/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "openai"
__version__ = "1.59.7" # x-release-please-version
__version__ = "1.59.8" # x-release-please-version
2 changes: 1 addition & 1 deletion src/openai/lib/_parsing/_completions.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def maybe_parse_content(
response_format: type[ResponseFormatT] | ResponseFormatParam | NotGiven,
message: ChatCompletionMessage | ParsedChatCompletionMessage[object],
) -> ResponseFormatT | None:
if has_rich_response_format(response_format) and message.content is not None and not message.refusal:
if has_rich_response_format(response_format) and message.content and not message.refusal:
return _parse_content(response_format, message.content)

return None
Expand Down
3 changes: 3 additions & 0 deletions src/openai/lib/_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ def _ensure_strict_json_schema(
# properties from the json schema take priority over the ones on the `$ref`
json_schema.update({**resolved, **json_schema})
json_schema.pop("$ref")
# Since the schema expanded from `$ref` might not have `additionalProperties: false` applied,
# we call `_ensure_strict_json_schema` again to fix the inlined schema and ensure it's valid.
return _ensure_strict_json_schema(json_schema, path=path, root=root)

return json_schema

Expand Down
3 changes: 3 additions & 0 deletions src/openai/types/beta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@
from .assistant_response_format_option_param import (
AssistantResponseFormatOptionParam as AssistantResponseFormatOptionParam,
)
from .static_file_chunking_strategy_object_param import (
StaticFileChunkingStrategyObjectParam as StaticFileChunkingStrategyObjectParam,
)
4 changes: 2 additions & 2 deletions src/openai/types/beta/file_chunking_strategy_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from typing_extensions import TypeAlias

from .auto_file_chunking_strategy_param import AutoFileChunkingStrategyParam
from .static_file_chunking_strategy_param import StaticFileChunkingStrategyParam
from .static_file_chunking_strategy_object_param import StaticFileChunkingStrategyObjectParam

__all__ = ["FileChunkingStrategyParam"]

FileChunkingStrategyParam: TypeAlias = Union[AutoFileChunkingStrategyParam, StaticFileChunkingStrategyParam]
FileChunkingStrategyParam: TypeAlias = Union[AutoFileChunkingStrategyParam, StaticFileChunkingStrategyObjectParam]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing_extensions import Literal, Required, TypedDict

from .static_file_chunking_strategy_param import StaticFileChunkingStrategyParam

__all__ = ["StaticFileChunkingStrategyObjectParam"]


class StaticFileChunkingStrategyObjectParam(TypedDict, total=False):
static: Required[StaticFileChunkingStrategyParam]

type: Required[Literal["static"]]
"""Always `static`."""
Loading
Loading