多function-calling 调用
接上一篇function-calling调用,本篇实现了一个多function-calling的调用。OpenAI会根据function的描述自己来判断应该调用哪个function。最终调用function的动作是由我们来决定的,当然你也可以不调对应的函数。
两个函数分别是:
- 根据POI名称查询经纬度坐标
- 搜索给定坐标附近的POI
下面上代码,代码中如有方法未找到,请翻看之前的文章:
python
import requests
## 这里的ampKey可以通过高德开发者平台免费注册一个,个人开发者可免费的少量调用
amap_key = "XXXX"
def get_location_coordinate(location, city):
url = f"https://restapi.amap.com/v5/place/text?key={amap_key}&keywords={location}®ion={city}"
print(url)
r = requests.get(url)
result = r.json()
if "pois" in result and result["pois"]:
return result["pois"][0]
return None
def search_nearby_pois(longitude, latitude, keyword):
url = f"https://restapi.amap.com/v5/place/around?key={amap_key}&keywords={keyword}&location={longitude},{latitude}"
print(url)
r = requests.get(url)
result = r.json()
ans = ""
if "pois" in result and result["pois"]:
for i in range(min(3, len(result["pois"]))):
name = result["pois"][i]["name"]
address = result["pois"][i]["address"]
distance = result["pois"][i]["distance"]
ans += f"{name}\n{address}\n距离:{distance}米\n\n"
return ans
# 定义tools和要调用的函数
def get_completion(messages, model="gpt-3.5-turbo"):
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=0, # 模型输出的随机性,0 表示随机性最小
seed=1024, # 随机种子保持不变,temperature 和 prompt 不变的情况下,输出就会不变
tool_choice="auto", # 默认值,由 GPT 自主决定返回 function call 还是返回文字回复。也可以强制要求必须调用指定的函数,详见官方文档
tools=[{
"type": "function",
"function": {
"name": "get_location_coordinate",
"description": "根据POI名称,获得POI的经纬度坐标",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "POI名称,必须是中文",
},
"city": {
"type": "string",
"description": "POI所在的城市名,必须是中文",
}
},
"required": ["location", "city"],
}
}
},
{
"type": "function",
"function": {
"name": "search_nearby_pois",
"description": "搜索给定坐标附近的poi",
"parameters": {
"type": "object",
"properties": {
"longitude": {
"type": "string",
"description": "中心点的经度",
},
"latitude": {
"type": "string",
"description": "中心点的纬度",
},
"keyword": {
"type": "string",
"description": "目标poi的关键字",
}
},
"required": ["longitude", "latitude", "keyword"],
}
}
}],
)
return response.choices[0].message
prompt = "我想在北京三里屯附近喝咖啡,给我推荐几个"
# prompt = "我到北京出差,给我推荐北京三里屯附近的酒店,和北京三里屯附近的咖啡"
messages = [
{"role": "system", "content": "你是一个地图通,你可以找到任何地址。"},
{"role": "user", "content": prompt}
]
response = get_completion(messages)
messages.append(response) # 把大模型的回复加入到对话中
print("=====GPT回复=====")
print_json(response)
while (response.tool_calls is not None):
# 新版模型支持一次返回多个函数调用请求,所以要考虑到这种情况
for tool_call in response.tool_calls:
args = json.loads(tool_call.function.arguments)
print("函数参数展开:")
print_json(args)
if (tool_call.function.name == "get_location_coordinate"):
print("Call: get_location_coordinate")
result = get_location_coordinate(**args)
elif (tool_call.function.name == "search_nearby_pois"):
print("Call: search_nearby_pois")
result = search_nearby_pois(**args)
print("=====函数返回=====")
print_json(result)
messages.append({
"tool_call_id": tool_call.id, # 用于标识函数调用的 ID
"role": "tool",
"name": tool_call.function.name,
"content": str(result) # 数值result 必须转成字符串
})
response = get_completion(messages)
print(response)
messages.append(response) # 把大模型的回复加入到对话中
print("=====最终回复=====")
print(response.content)
print("=====对话历史=====")
print(messages)
运行结果:
=====GPT回复=====
{
"content": null,
"role": "assistant",
"function_call": null,
"tool_calls": [
{
"id": "call_C4xbz7ABvNOde510rStBhK8K",
"function": {
"arguments": "{\"location\":\"三里屯\",\"city\":\"北京\"}",
"name": "get_location_coordinate"
},
"type": "function"
}
]
}
函数参数展开:
{
"location": "三里屯",
"city": "北京"
}
Call: get_location_coordinate
https://restapi.amap.com/v5/place/text?key=59b58777beb50f8f180ac36ebe2159d9&keywords=三里屯®ion=北京
=====函数返回=====
{
"parent": "",
"address": "朝阳区",
"distance": "",
"pcode": "110000",
"adcode": "110105",
"pname": "北京市",
"cityname": "北京市",
"type": "地名地址信息;热点地名;热点地名",
"typecode": "190700",
"adname": "朝阳区",
"citycode": "010",
"name": "三里屯",
"location": "116.455294,39.937492",
"id": "B0FFF5BER7"
}
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_TZc2RkF2uKmRag6PI1s67RKw', function=Function(arguments='{"longitude":"116.455294","latitude":"39.937492","keyword":"咖啡"}', name='search_nearby_pois'), type='function')])
函数参数展开:
{
"longitude": "116.455294",
"latitude": "39.937492",
"keyword": "咖啡"
}
Call: search_nearby_pois
https://restapi.amap.com/v5/place/around?key=59b58777beb50f8f180ac36ebe2159d9&keywords=咖啡&location=116.455294,39.937492
=====函数返回=====
星巴克(北京三里屯三点三大厦店)
三里屯路33号3.3大厦1层1010号
距离:52米
内山咖啡店(3·3大厦店)
三里屯路33号3·3大厦B1层
距离:82米
春丽咖啡(3·3大厦店)
三里屯路33号3.3大厦东门1层1099
距离:93米
ChatCompletionMessage(content='以下是在北京三里屯附近的几家咖啡店推荐:\n\n1. 星巴克(北京三里屯三点三大厦店)\n 地址:三里屯路33号3.3大厦1层1010号\n 距离:52米\n\n2. 内山咖啡店(3·3大厦店)\n 地址:三里屯路33号3·3大厦B1层\n 距离:82米\n\n3. 春丽咖啡(3·3大厦店)\n 地址:三里屯路33号3.3大厦东门1层1099\n 距离:93米\n\n您可以选择其中一家前往享受咖啡时光。祝您喝咖啡愉快!', role='assistant', function_call=None, tool_calls=None)
=====最终回复=====
以下是在北京三里屯附近的几家咖啡店推荐:
1. 星巴克(北京三里屯三点三大厦店)
地址:三里屯路33号3.3大厦1层1010号
距离:52米
2. 内山咖啡店(3·3大厦店)
地址:三里屯路33号3·3大厦B1层
距离:82米
3. 春丽咖啡(3·3大厦店)
地址:三里屯路33号3.3大厦东门1层1099
距离:93米
您可以选择其中一家前往享受咖啡时光。祝您喝咖啡愉快!
=====对话历史=====
[{'role': 'system', 'content': '你是一个地图通,你可以找到任何地址。'}, {'role': 'user', 'content': '我想在北京三里屯附近喝咖啡,给我推荐几个'}, ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_C4xbz7ABvNOde510rStBhK8K', function=Function(arguments='{"location":"三里屯","city":"北京"}', name='get_location_coordinate'), type='function')]), {'tool_call_id': 'call_C4xbz7ABvNOde510rStBhK8K', 'role': 'tool', 'name': 'get_location_coordinate', 'content': "{'parent': '', 'address': '朝阳区', 'distance': '', 'pcode': '110000', 'adcode': '110105', 'pname': '北京市', 'cityname': '北京市', 'type': '地名地址信息;热点地名;热点地名', 'typecode': '190700', 'adname': '朝阳区', 'citycode': '010', 'name': '三里屯', 'location': '116.455294,39.937492', 'id': 'B0FFF5BER7'}"}, ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_TZc2RkF2uKmRag6PI1s67RKw', function=Function(arguments='{"longitude":"116.455294","latitude":"39.937492","keyword":"咖啡"}', name='search_nearby_pois'), type='function')]), {'tool_call_id': 'call_TZc2RkF2uKmRag6PI1s67RKw', 'role': 'tool', 'name': 'search_nearby_pois', 'content': '星巴克(北京三里屯三点三大厦店)\n三里屯路33号3.3大厦1层1010号\n距离:52米\n\n内山咖啡店(3·3大厦店)\n三里屯路33号3·3大厦B1层\n距离:82米\n\n春丽咖啡(3·3大厦店)\n三里屯路33号3.3大厦东门1层1099\n距离:93米\n\n'}, ChatCompletionMessage(content='以下是在北京三里屯附近的几家咖啡店推荐:\n\n1. 星巴克(北京三里屯三点三大厦店)\n 地址:三里屯路33号3.3大厦1层1010号\n 距离:52米\n\n2. 内山咖啡店(3·3大厦店)\n 地址:三里屯路33号3·3大厦B1层\n 距离:82米\n\n3. 春丽咖啡(3·3大厦店)\n 地址:三里屯路33号3.3大厦东门1层1099\n 距离:93米\n\n您可以选择其中一家前往享受咖啡时光。祝您喝咖啡愉快!', role='assistant', function_call=None, tool_calls=None)]