From 0adb32ec323bb74cc3ad632e67c579bdbf5fcd58 Mon Sep 17 00:00:00 2001 From: anakin87 Date: Fri, 10 Jan 2025 13:02:05 +0100 Subject: [PATCH 1/3] do not pass tools to OpenAI client if None --- haystack/components/generators/chat/openai.py | 7 ++++--- test/components/generators/chat/test_openai.py | 10 +++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/haystack/components/generators/chat/openai.py b/haystack/components/generators/chat/openai.py index 251b0b741c..0b699e3bc1 100644 --- a/haystack/components/generators/chat/openai.py +++ b/haystack/components/generators/chat/openai.py @@ -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) @@ -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, } diff --git a/test/components/generators/chat/test_openai.py b/test/components/generators/chat/test_openai.py index 8333608ea6..eb50d92739 100644 --- a/test/components/generators/chat/test_openai.py +++ b/test/components/generators/chat/test_openai.py @@ -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 @@ -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] From a37394c8570c8d49e4a7045f17a6838d59e8aa77 Mon Sep 17 00:00:00 2001 From: anakin87 Date: Fri, 10 Jan 2025 13:08:06 +0100 Subject: [PATCH 2/3] release note --- ...o-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml diff --git a/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml b/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml new file mode 100644 index 0000000000..1c42489e19 --- /dev/null +++ b/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + OpenAIChatGenerator no longer passes tools to the OpenAI client none are provided. + Previously, an empty list was passed. + This change improves compatibility with OpenAI-compatible APIs that do not support tools. From 3e4d6bfca7813d8077cd6084fada6062c04ed0d5 Mon Sep 17 00:00:00 2001 From: anakin87 Date: Fri, 10 Jan 2025 13:11:49 +0100 Subject: [PATCH 3/3] fix release note --- .../do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml b/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml index 1c42489e19..aa309098fa 100644 --- a/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml +++ b/releasenotes/notes/do-not-pass-tools-to-openai-if-none-1fe09e924e7fad7a.yaml @@ -1,6 +1,6 @@ --- fixes: - | - OpenAIChatGenerator no longer passes tools to the OpenAI client none are provided. - Previously, an empty list was passed. + 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.