From d7f014cd895712394464c2bd3238fb77f5a9cc2b Mon Sep 17 00:00:00 2001 From: chris stucchio <62957343+chrisaffirm@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:47:05 -0600 Subject: [PATCH] Bug: OpenAIFunctionsAgentOutputParser doesn't handle functions with no args (#13467) **Description/Issue:** When OpenAI calls a function with no args, the args are `""` rather than `"{}"`. Then `json.loads("")` blows up. This PR handles it correctly. **Dependencies:** None --- .../agents/output_parsers/openai_functions.py | 7 ++++++- .../output_parsers/test_openai_functions.py | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libs/langchain/langchain/agents/output_parsers/openai_functions.py b/libs/langchain/langchain/agents/output_parsers/openai_functions.py index 9e6aa315e8..c6b4aadb71 100644 --- a/libs/langchain/langchain/agents/output_parsers/openai_functions.py +++ b/libs/langchain/langchain/agents/output_parsers/openai_functions.py @@ -44,7 +44,12 @@ class OpenAIFunctionsAgentOutputParser(AgentOutputParser): if function_call: function_name = function_call["name"] try: - _tool_input = json.loads(function_call["arguments"]) + if len(function_call["arguments"].strip()) == 0: + # OpenAI returns an empty string for functions containing no args + _tool_input = {} + else: + # otherwise it returns a json object + _tool_input = json.loads(function_call["arguments"]) except JSONDecodeError: raise OutputParserException( f"Could not parse tool input: {function_call} because " diff --git a/libs/langchain/tests/unit_tests/agents/output_parsers/test_openai_functions.py b/libs/langchain/tests/unit_tests/agents/output_parsers/test_openai_functions.py index d07d4775a0..613a486a4b 100644 --- a/libs/langchain/tests/unit_tests/agents/output_parsers/test_openai_functions.py +++ b/libs/langchain/tests/unit_tests/agents/output_parsers/test_openai_functions.py @@ -46,6 +46,22 @@ def test_func_call() -> None: assert result.message_log == [msg] +# Test: Model response with a function call for a function taking no arguments +def test_func_call_no_args() -> None: + parser = OpenAIFunctionsAgentOutputParser() + msg = AIMessage( + content="LLM thoughts.", + additional_kwargs={"function_call": {"name": "foo", "arguments": ""}}, + ) + result = parser.invoke(msg) + + assert isinstance(result, AgentActionMessageLog) + assert result.tool == "foo" + assert result.tool_input == {} + assert result.log == ("\nInvoking: `foo` with `{}`\nresponded: LLM thoughts.\n\n") + assert result.message_log == [msg] + + # Test: Model response with a function call (old style tools). def test_func_call_oldstyle() -> None: parser = OpenAIFunctionsAgentOutputParser()