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
This commit is contained in:
chris stucchio 2023-11-16 18:47:05 -06:00 committed by GitHub
parent 41a433fa33
commit d7f014cd89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 1 deletions

View File

@ -44,7 +44,12 @@ class OpenAIFunctionsAgentOutputParser(AgentOutputParser):
if function_call: if function_call:
function_name = function_call["name"] function_name = function_call["name"]
try: 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: except JSONDecodeError:
raise OutputParserException( raise OutputParserException(
f"Could not parse tool input: {function_call} because " f"Could not parse tool input: {function_call} because "

View File

@ -46,6 +46,22 @@ def test_func_call() -> None:
assert result.message_log == [msg] 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). # Test: Model response with a function call (old style tools).
def test_func_call_oldstyle() -> None: def test_func_call_oldstyle() -> None:
parser = OpenAIFunctionsAgentOutputParser() parser = OpenAIFunctionsAgentOutputParser()