Skip to content

Commit afbb292

Browse files
committed
fix: preserve non-strict sync stream tools
1 parent a0a133b commit afbb292

2 files changed

Lines changed: 20 additions & 8 deletions

File tree

src/openai/resources/chat/completions/completions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
ResponseFormatT,
3838
validate_input_tools as _validate_input_tools,
3939
parse_chat_completion as _parse_chat_completion,
40+
materialize_input_tools as _materialize_input_tools,
4041
type_to_response_format_param as _type_to_response_format,
4142
)
4243
from ....lib.streaming.chat import ChatCompletionStreamManager, AsyncChatCompletionStreamManager
@@ -1612,7 +1613,7 @@ def stream(
16121613
When the context manager exits, the response will be closed, however the `stream` instance is still available outside
16131614
the context manager.
16141615
"""
1615-
chat_completion_tools = _validate_input_tools(tools)
1616+
chat_completion_tools = _materialize_input_tools(tools)
16161617

16171618
extra_headers = {
16181619
"X-Stainless-Helper-Method": "chat.completions.stream",

tests/lib/chat/test_single_pass_tools.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,24 @@ def test_stream_preserves_single_pass_tools(client: OpenAI, respx2_mock: MockRou
138138
assert_request_and_parsed_tool(respx2_mock, tool_calls[0].function.parsed_arguments)
139139

140140

141-
def test_stream_rejects_non_strict_tools(client: OpenAI) -> None:
142-
with pytest.raises(ValueError, match="Only `strict` function tools can be auto-parsed"):
143-
client.chat.completions.stream(
144-
model="gpt-test",
145-
messages=[{"role": "user", "content": "weather"}],
146-
tools=non_strict_tools(),
147-
)
141+
@pytest.mark.respx2(base_url=base_url)
142+
def test_stream_preserves_non_strict_single_pass_tools(client: OpenAI, respx2_mock: MockRouter) -> None:
143+
respx2_mock.post("/chat/completions").mock(
144+
return_value=httpx2.Response(200, text=STREAM_RESPONSE, headers={"content-type": "text/event-stream"})
145+
)
146+
147+
with client.chat.completions.stream(
148+
model="gpt-test",
149+
messages=[{"role": "user", "content": "weather"}],
150+
tools=non_strict_tools(),
151+
) as stream:
152+
completion = stream.get_final_completion()
153+
154+
tool_calls = completion.choices[0].message.tool_calls
155+
assert tool_calls is not None
156+
body = json.loads(cast("list[MockRequestCall]", respx2_mock.calls)[0].request.content)
157+
assert body["tools"] == list(non_strict_tools())
158+
assert tool_calls[0].function.parsed_arguments is None
148159

149160

150161
@pytest.mark.respx2(base_url=base_url)

0 commit comments

Comments
 (0)