Upgrade openAI sdk version (#730)

---
[//]: # (BEGIN SAPLING FOOTER)
* #732
* #731
* __->__ #730
This commit is contained in:
Rohan Mehta 2025-05-21 15:17:58 -04:00 committed by GitHub
parent 466b44df18
commit ce2e2a4571
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 43 additions and 18 deletions

View file

@ -7,7 +7,7 @@ requires-python = ">=3.9"
license = "MIT"
authors = [{ name = "OpenAI", email = "support@openai.com" }]
dependencies = [
"openai>=1.76.0",
"openai>=1.81.0",
"pydantic>=2.10, <3",
"griffe>=1.5.6, <2",
"typing-extensions>=4.12.2, <5",

View file

@ -38,6 +38,16 @@ class StreamingState:
function_calls: dict[int, ResponseFunctionToolCall] = field(default_factory=dict)
class SequenceNumber:
def __init__(self):
self._sequence_number = 0
def get_and_increment(self) -> int:
num = self._sequence_number
self._sequence_number += 1
return num
class ChatCmplStreamHandler:
@classmethod
async def handle_stream(
@ -47,13 +57,14 @@ class ChatCmplStreamHandler:
) -> AsyncIterator[TResponseStreamEvent]:
usage: CompletionUsage | None = None
state = StreamingState()
sequence_number = SequenceNumber()
async for chunk in stream:
if not state.started:
state.started = True
yield ResponseCreatedEvent(
response=response,
type="response.created",
sequence_number=sequence_number.get_and_increment(),
)
# This is always set by the OpenAI API, but not by others e.g. LiteLLM
@ -89,6 +100,7 @@ class ChatCmplStreamHandler:
item=assistant_item,
output_index=0,
type="response.output_item.added",
sequence_number=sequence_number.get_and_increment(),
)
yield ResponseContentPartAddedEvent(
content_index=state.text_content_index_and_output[0],
@ -100,6 +112,7 @@ class ChatCmplStreamHandler:
annotations=[],
),
type="response.content_part.added",
sequence_number=sequence_number.get_and_increment(),
)
# Emit the delta for this segment of content
yield ResponseTextDeltaEvent(
@ -108,6 +121,7 @@ class ChatCmplStreamHandler:
item_id=FAKE_RESPONSES_ID,
output_index=0,
type="response.output_text.delta",
sequence_number=sequence_number.get_and_increment(),
)
# Accumulate the text into the response part
state.text_content_index_and_output[1].text += delta.content
@ -134,6 +148,7 @@ class ChatCmplStreamHandler:
item=assistant_item,
output_index=0,
type="response.output_item.added",
sequence_number=sequence_number.get_and_increment(),
)
yield ResponseContentPartAddedEvent(
content_index=state.refusal_content_index_and_output[0],
@ -145,6 +160,7 @@ class ChatCmplStreamHandler:
annotations=[],
),
type="response.content_part.added",
sequence_number=sequence_number.get_and_increment(),
)
# Emit the delta for this segment of refusal
yield ResponseRefusalDeltaEvent(
@ -153,6 +169,7 @@ class ChatCmplStreamHandler:
item_id=FAKE_RESPONSES_ID,
output_index=0,
type="response.refusal.delta",
sequence_number=sequence_number.get_and_increment(),
)
# Accumulate the refusal string in the output part
state.refusal_content_index_and_output[1].refusal += delta.refusal
@ -190,6 +207,7 @@ class ChatCmplStreamHandler:
output_index=0,
part=state.text_content_index_and_output[1],
type="response.content_part.done",
sequence_number=sequence_number.get_and_increment(),
)
if state.refusal_content_index_and_output:
@ -201,6 +219,7 @@ class ChatCmplStreamHandler:
output_index=0,
part=state.refusal_content_index_and_output[1],
type="response.content_part.done",
sequence_number=sequence_number.get_and_increment(),
)
# Actually send events for the function calls
@ -216,6 +235,7 @@ class ChatCmplStreamHandler:
),
output_index=function_call_starting_index,
type="response.output_item.added",
sequence_number=sequence_number.get_and_increment(),
)
# Then, yield the args
yield ResponseFunctionCallArgumentsDeltaEvent(
@ -223,6 +243,7 @@ class ChatCmplStreamHandler:
item_id=FAKE_RESPONSES_ID,
output_index=function_call_starting_index,
type="response.function_call_arguments.delta",
sequence_number=sequence_number.get_and_increment(),
)
# Finally, the ResponseOutputItemDone
yield ResponseOutputItemDoneEvent(
@ -235,6 +256,7 @@ class ChatCmplStreamHandler:
),
output_index=function_call_starting_index,
type="response.output_item.done",
sequence_number=sequence_number.get_and_increment(),
)
# Finally, send the Response completed event
@ -258,6 +280,7 @@ class ChatCmplStreamHandler:
item=assistant_msg,
output_index=0,
type="response.output_item.done",
sequence_number=sequence_number.get_and_increment(),
)
for function_call in state.function_calls.values():
@ -289,4 +312,5 @@ class ChatCmplStreamHandler:
yield ResponseCompletedEvent(
response=final_response,
type="response.completed",
sequence_number=sequence_number.get_and_increment(),
)

View file

@ -10,6 +10,7 @@ from openai.types import ChatModel
from openai.types.responses import (
Response,
ResponseCompletedEvent,
ResponseIncludable,
ResponseStreamEvent,
ResponseTextConfigParam,
ToolParam,
@ -36,13 +37,6 @@ if TYPE_CHECKING:
_USER_AGENT = f"Agents/Python {__version__}"
_HEADERS = {"User-Agent": _USER_AGENT}
# From the Responses API
IncludeLiteral = Literal[
"file_search_call.results",
"message.input_image.image_url",
"computer_call_output.output.image_url",
]
class OpenAIResponsesModel(Model):
"""
@ -273,7 +267,7 @@ class OpenAIResponsesModel(Model):
@dataclass
class ConvertedTools:
tools: list[ToolParam]
includes: list[IncludeLiteral]
includes: list[ResponseIncludable]
class Converter:
@ -330,7 +324,7 @@ class Converter:
handoffs: list[Handoff[Any]],
) -> ConvertedTools:
converted_tools: list[ToolParam] = []
includes: list[IncludeLiteral] = []
includes: list[ResponseIncludable] = []
computer_tools = [tool for tool in tools if isinstance(tool, ComputerTool)]
if len(computer_tools) > 1:
@ -348,7 +342,7 @@ class Converter:
return ConvertedTools(tools=converted_tools, includes=includes)
@classmethod
def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, IncludeLiteral | None]:
def _convert_tool(cls, tool: Tool) -> tuple[ToolParam, ResponseIncludable | None]:
"""Returns converted tool and includes"""
if isinstance(tool, FunctionTool):
@ -359,7 +353,7 @@ class Converter:
"type": "function",
"description": tool.description,
}
includes: IncludeLiteral | None = None
includes: ResponseIncludable | None = None
elif isinstance(tool, WebSearchTool):
ws: WebSearchToolParam = {
"type": "web_search_preview",

View file

@ -129,6 +129,7 @@ class FakeModel(Model):
yield ResponseCompletedEvent(
type="response.completed",
response=get_response_obj(output, usage=self.hardcoded_usage),
sequence_number=0,
)

View file

@ -50,6 +50,7 @@ class DummyResponse:
yield ResponseCompletedEvent(
type="response.completed",
response=fake_model.get_response_obj(self.output),
sequence_number=0,
)
@ -201,6 +202,7 @@ async def test_stream_response_creates_trace(monkeypatch):
yield ResponseCompletedEvent(
type="response.completed",
response=fake_model.get_response_obj([], "dummy-id-123"),
sequence_number=0,
)
return DummyStream()
@ -253,6 +255,7 @@ async def test_stream_non_data_tracing_doesnt_set_response_id(monkeypatch):
yield ResponseCompletedEvent(
type="response.completed",
response=fake_model.get_response_obj([], "dummy-id-123"),
sequence_number=0,
)
return DummyStream()
@ -304,6 +307,7 @@ async def test_stream_disabled_tracing_doesnt_create_span(monkeypatch):
yield ResponseCompletedEvent(
type="response.completed",
response=fake_model.get_response_obj([], "dummy-id-123"),
sequence_number=0,
)
return DummyStream()

View file

@ -81,11 +81,13 @@ class FakeStreamingModel(Model):
type="response.output_text.delta",
output_index=0,
item_id=item.id,
sequence_number=0,
)
yield ResponseCompletedEvent(
type="response.completed",
response=get_response_obj(output),
sequence_number=1,
)

10
uv.lock
View file

@ -1461,7 +1461,7 @@ wheels = [
[[package]]
name = "openai"
version = "1.76.0"
version = "1.81.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@ -1473,14 +1473,14 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/84/51/817969ec969b73d8ddad085670ecd8a45ef1af1811d8c3b8a177ca4d1309/openai-1.76.0.tar.gz", hash = "sha256:fd2bfaf4608f48102d6b74f9e11c5ecaa058b60dad9c36e409c12477dfd91fb2", size = 434660 }
sdist = { url = "https://files.pythonhosted.org/packages/1c/89/a1e4f3fa7ca4f7fec90dbf47d93b7cd5ff65924926733af15044e302a192/openai-1.81.0.tar.gz", hash = "sha256:349567a8607e0bcffd28e02f96b5c2397d0d25d06732d90ab3ecbf97abf030f9", size = 456861 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/59/aa/84e02ab500ca871eb8f62784426963a1c7c17a72fea3c7f268af4bbaafa5/openai-1.76.0-py3-none-any.whl", hash = "sha256:a712b50e78cf78e6d7b2a8f69c4978243517c2c36999756673e07a14ce37dc0a", size = 661201 },
{ url = "https://files.pythonhosted.org/packages/02/66/bcc7f9bf48e8610a33e3b5c96a5a644dad032d92404ea2a5e8b43ba067e8/openai-1.81.0-py3-none-any.whl", hash = "sha256:1c71572e22b43876c5d7d65ade0b7b516bb527c3d44ae94111267a09125f7bae", size = 717529 },
]
[[package]]
name = "openai-agents"
version = "0.0.14"
version = "0.0.15"
source = { editable = "." }
dependencies = [
{ name = "griffe" },
@ -1536,7 +1536,7 @@ requires-dist = [
{ name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.67.4.post1,<2" },
{ name = "mcp", marker = "python_full_version >= '3.10'", specifier = ">=1.8.0,<2" },
{ name = "numpy", marker = "python_full_version >= '3.10' and extra == 'voice'", specifier = ">=2.2.0,<3" },
{ name = "openai", specifier = ">=1.76.0" },
{ name = "openai", specifier = ">=1.81.0" },
{ name = "pydantic", specifier = ">=2.10,<3" },
{ name = "requests", specifier = ">=2.0,<3" },
{ name = "types-requests", specifier = ">=2.0,<3" },