Skip to content

Commit

Permalink
fix: OpenAIChatGenerator - do not pass tools to the OpenAI client w…
Browse files Browse the repository at this point in the history
…hen none are provided (#8702)

* do not pass tools to OpenAI client if None

* release note

* fix release note
  • Loading branch information
anakin87 authored Jan 10, 2025
1 parent 08cf09f commit 741ce5d
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
7 changes: 4 additions & 3 deletions haystack/components/generators/chat/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,13 @@ def _prepare_api_call( # noqa: PLR0913
tools_strict = tools_strict if tools_strict is not None else self.tools_strict
_check_duplicate_tool_names(tools)

openai_tools = None
openai_tools = {}
if tools:
openai_tools = [
tool_definitions = [
{"type": "function", "function": {**t.tool_spec, **({"strict": tools_strict} if tools_strict else {})}}
for t in tools
]
openai_tools = {"tools": tool_definitions}

is_streaming = streaming_callback is not None
num_responses = generation_kwargs.pop("n", 1)
Expand All @@ -302,8 +303,8 @@ def _prepare_api_call( # noqa: PLR0913
"model": self.model,
"messages": openai_formatted_messages, # type: ignore[arg-type] # openai expects list of specific message types
"stream": streaming_callback is not None,
"tools": openai_tools, # type: ignore[arg-type]
"n": num_responses,
**openai_tools,
**generation_kwargs,
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
OpenAIChatGenerator no longer passes tools to the OpenAI client if none are provided.
Previously, a null value was passed.
This change improves compatibility with OpenAI-compatible APIs that do not support tools.
10 changes: 9 additions & 1 deletion test/components/generators/chat/test_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ def test_run_with_params(self, chat_messages, openai_mock_chat_completion):
assert kwargs["max_tokens"] == 10
assert kwargs["temperature"] == 0.5

# check that the tools are not passed to the OpenAI API (the generator is initialized without tools)
assert "tools" not in kwargs

# check that the component returns the correct response
assert isinstance(response, dict)
assert "replies" in response
Expand Down Expand Up @@ -400,9 +403,14 @@ def test_run_with_tools(self, tools):

mock_chat_completion_create.return_value = completion

component = OpenAIChatGenerator(api_key=Secret.from_token("test-api-key"), tools=tools)
component = OpenAIChatGenerator(api_key=Secret.from_token("test-api-key"), tools=tools, tools_strict=True)
response = component.run([ChatMessage.from_user("What's the weather like in Paris?")])

# ensure that the tools are passed to the OpenAI API
assert mock_chat_completion_create.call_args[1]["tools"] == [
{"type": "function", "function": {**tools[0].tool_spec, "strict": True}}
]

assert len(response["replies"]) == 1
message = response["replies"][0]

Expand Down

0 comments on commit 741ce5d

Please sign in to comment.