Skip to content

Commit a0a133b

Browse files
committed
fix: validate sync chat stream tools consistently
1 parent a82e012 commit a0a133b

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
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,
4140
type_to_response_format_param as _type_to_response_format,
4241
)
4342
from ....lib.streaming.chat import ChatCompletionStreamManager, AsyncChatCompletionStreamManager
@@ -1613,7 +1612,7 @@ def stream(
16131612
When the context manager exits, the response will be closed, however the `stream` instance is still available outside
16141613
the context manager.
16151614
"""
1616-
chat_completion_tools = _materialize_input_tools(tools)
1615+
chat_completion_tools = _validate_input_tools(tools)
16171616

16181617
extra_headers = {
16191618
"X-Stainless-Helper-Method": "chat.completions.stream",

tests/lib/chat/test_single_pass_tools.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ def single_pass_tools() -> Iterator[ChatCompletionToolUnionParam]:
3434
}
3535

3636

37+
def non_strict_tools() -> Iterator[ChatCompletionToolUnionParam]:
38+
yield {
39+
"type": "function",
40+
"function": {
41+
"name": "get_weather",
42+
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}},
43+
"strict": False,
44+
},
45+
}
46+
47+
3748
TOOL_CALL = {
3849
"id": "call-test",
3950
"type": "function",
@@ -127,6 +138,15 @@ def test_stream_preserves_single_pass_tools(client: OpenAI, respx2_mock: MockRou
127138
assert_request_and_parsed_tool(respx2_mock, tool_calls[0].function.parsed_arguments)
128139

129140

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+
)
148+
149+
130150
@pytest.mark.respx2(base_url=base_url)
131151
@pytest.mark.asyncio
132152
async def test_async_stream_preserves_single_pass_tools(async_client: AsyncOpenAI, respx2_mock: MockRouter) -> None:

0 commit comments

Comments
 (0)