-
Notifications
You must be signed in to change notification settings - Fork 0
/
02_amap_multiple_function_calling.py
148 lines (130 loc) · 5.26 KB
/
02_amap_multiple_function_calling.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
import json
import requests
from dotenv import load_dotenv, find_dotenv
from openai import OpenAI
# 加载 OpenAI key 到环境变量
_ = load_dotenv(find_dotenv())
client = OpenAI()
# 多function calling的例子, 调用高德地图获取酒店等信息。
def get_completion(messages):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=0,
seed=1024, # 随机种子保持不变,temperature 和 prompt 不变的情况下,输出就会不变
tool_choice="auto", # 默认值,由 GPT 自主决定返回 function call 还是返回文字回复。也可以强制要求必须调用指定的函数
tools=[{
"type": "function",
"function": {
# 定义函数名称
"name": "search_pois",
"description": "搜索坐标附近的POI",
"parameters": {
"type": "object",
"properties": {
"longitude": {
"type": "string",
"description": "经度"
},
"latitude": {
"type": "string",
"description": "维度"
},
"keyword": {
"type": "string",
"description": "目标POI的关键字"
}
}
}
# ,"required": ["longitude", "latitude", "keyword"] 这个写不写貌似都可
}}, {
"type": "function",
"function": {
# 定义函数名称
"name": "get_location",
"description": "根据POI名称,获取POI的经纬度坐标",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "POI的名称,必须是中文"
},
"city": {
"type": "string",
"description": "POI所在城市,必须是中文"
}
},
"required": ["location", "city"]
}
}}
]
)
if response and response.choices and response.choices[0].message:
return response.choices[0].message
return None
# 高德地图APP KEY
amap_key = os.environ.get("AMAP_KEY")
# 调用高德地图的API接口,获取地址的经纬度坐标
def get_location(location, city):
url = f"https://restapi.amap.com/v5/place/text?key={amap_key}&keywords={location}®ion={city}"
print(url)
try:
r = requests.get(url, timeout=5) # 设置超时时间为5秒
r.raise_for_status() # 检查是否有错误的响应码
result = r.json()
if result is not None and 'pois' in result:
return result['pois'][0] # 返回第一个结果
else:
print(f"UnknownResponse: {result}")
except requests.exceptions.RequestException as e:
print(f"Error by get_location: {e}")
return None
# 调用高德地图的API接口,搜索坐标附近的POI
def search_pois(longitude, latitude, keyword):
url = f"https://restapi.amap.com/v5/place/around?key={amap_key}&keywords={keyword}&location={longitude},{latitude}"
print(url)
try:
return requests.get(url, timeout=5)
except requests.exceptions.RequestException as e:
print(f"Error by search_pois: {e}")
return None
def handel_func_calling(tool_call):
result = None
# 获取参数
args_json = json.loads(tool_call.function.arguments)
# calling 函数名称
func_name = tool_call.function.name
if func_name == 'get_location':
result = get_location(**args_json) # 调用函数,并传入参数
elif func_name == 'search_pois':
result = search_pois(**args_json) # 调用函数,并传入参数
return result
# 定义一个prompt
prompt = "推荐几个北京大望路附近的咖啡店"
print('Prompt==>', prompt)
messages = [
{"role": "system", "content": '你是一个地理专家,所有地址你都知道'},
{"role": "user", "content": prompt}
]
response = get_completion(messages)
print('GPT回复==>', response)
# 把大模型生成的答案追加到prompt中
messages.append(response)
max_iter = 3
while response.tool_calls is not None and max_iter > 0:
max_iter -= 1 # 防止死循环,设置一个最大调用次数
for tool_call in response.tool_calls:
result = handel_func_calling(tool_call)
# 追加到prompt中,这样GPT就能知道这个结果了
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": tool_call.function.name,
"content": str(result) # 必须转成字符串
})
response = get_completion(messages)
messages.append(response) # 把大模型的回复追加到prompt中
# for循环结束,说明没有tool_calls了,说明已经调用完所有的函数了
print('最终GPT回复==>\n', response.content)