function calling 这个词一听还以为是 GPT 帮我去调用函数,实际上并不是这样。
使用场景
我们在和 GPT 聊天的过程中,可能会涉及一些特定的问题,比如在聊天时,我突然问 GPT :北京今天天气怎么样?
很显然 GPT 是不知道实时的天气的,那怎么办呢,用 function calling 可以实现,我们可以提前定义好一个函数,这个函数有一个城市参数,函数内部会去调用 API 查询这个城市当前的天气情况。
请注意:这个调用天气的接口是我们自己提前写好的,当用户问天气相关问题时才会触发调用,并不是 GPT 帮我调用。
实际示例
请看下面示例:
- 我定义了 2 个函数tools,一个是查询指定城市的天气,一个是查询指定用户的地址。
- 函数调用分两步:1、GPT 帮我提取出问题中的参数,比如城市。2、把提取出的参数传递个 GPT,生成最终的回答。
- 如果没有触发定义的tools ,则正常回答问题即可。
from openai import OpenAI
import json
gpt_model = "gpt-3.5-turbo"
client = OpenAI(api_key='sk-xxx')
def get_current_weather(city):
# 实际上需要调用 API 接口 查询 city 的天气,然后再返回查到的温度。
return "25"
def get_user_address(username):
# 实际上需要调用 API 接口 查询 username 的地址,然后再返回查到的地址。
return "北京"
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get the current weather",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name",
}
},
"required": ["city"],
},
}
},
{
"type": "function",
"function": {
"name": "get_user_address",
"description": "Get the user address",
"parameters": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "The username",
}
},
"required": ["username"],
},
}
}
]
messages = [
{
"role": "system",
"content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
},
{
"role": "user",
"content": "北京天气怎么样,张阳的住址在哪儿呢?",
}
]
gpt_response = client.chat.completions.create(
model=gpt_model,
messages=messages,
tools=tools,
tool_choice="auto",
)
first_message = gpt_response.choices[0].message
# 检查是否提取到了参数,如果提取到了,直接执行
tool_calls = first_message.tool_calls
if tool_calls:
messages.append(first_message)
for tool_call in tool_calls:
function_name = tool_call.function.name
# 这里需要捕获错误,json.loads有可能会报错
function_args = json.loads(tool_call.function.arguments)
function_response = ""
if function_name == "get_current_weather":
function_response = get_current_weather(city=function_args.get("city"))
elif function_name == "get_user_address":
function_response = get_user_address(username=function_args.get("username"))
if function_response is not None:
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response,
})
gpt_response = client.chat.completions.create(
model=gpt_model,
messages=messages,
)
print(gpt_response.choices[0].message.content)
返回结果:
$ python x.py
北京的天气是晴天。张阳的住址是北京。
如果换成下面的问题,则不会触发 tools 的调用:
messages = [
{
"role": "system",
"content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."
},
{
"role": "user",
"content": "Python是什么?",
}
]
返回结果:
$ python x.py
请问您想了解Python的什么信息? 是一种编程语言还是其他方面的信息? 请提供更多细节,以便我可以为您提供准确的答案。
总结
实际上可以把 函数调用立即成一些列的触发器,我们提前定义好这些触发器 tools,一旦用户问的问题触发了这些问题,并且 GPT 帮我们提取出了指定的参数,就一个自动调用函数。让人感觉 GPT 帮你调用了函数以后。