3. 函数调用
# 3.1 核心概念
Function Calling 是 OpenAI Assistants API 提供的一项功能(现在绝大多数模型都已经支持),允许开发者预先定义一组可供 AI 助手调用的函数。这些函数被描述为结构化的工具,包含名称、用途说明以及 JSON 格式的参数定义。其主要目的是使助手能够在对话过程中,当遇到需要执行特定操作(如查询外部数据、执行实际操作、调用系统接口等)的场景时,不再仅仅依靠纯文本生成回答,而是能够触发这些预定义函数,从而获得精确且结构化的输出。
# 3.2 加减乘除案例
# 3.2.1 自定义函数
def add(num1, num2):
return num1 + num2
def sub(num1, num2):
return num1 - num2
def mul(num1, num2):
return num1 * num2
def div(num1, num2):
return num1 / num2 if num2 != 0 else "除数不能为0"
function_map = {
"add": add,
"sub": sub,
"mul": mul,
"div": div
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3.2.2 创建助手
from openai import OpenAI
import time
import json
client = OpenAI()
assistant = client.beta.assistants.create(
name="计算器",
instructions="你是一个计算器,请根据用户的问题结合我定义的函数给出回答",
model="gpt-4o",
tools=[
{
"type": "function",
"function": {
"name": "add",
"description": "计算两个数的和",
"parameters": {
"type": "object",
"properties": {
"num1": {
"type": "number",
"description": "第一个数"
},
"num2": {
"type": "number",
"description": "第二个数"
}
},
"required": ["num1", "num2"]
}
}
},
{
"type": "function",
"function": {
"name": "sub",
"description": "计算两个数的差",
"parameters": {
"type": "object",
"properties": {
"num1": {
"type": "number",
"description": "第一个数"
},
"num2": {
"type": "number",
"description": "第二个数"
}
},
"required": ["num1", "num2"]
}
}
},
{
"type": "function",
"function": {
"name": "mul",
"description": "计算两个数的乘积",
"parameters": {
"type": "object",
"properties": {
"num1": {
"type": "number",
"description": "第一个数"
},
"num2": {
"type": "number",
"description": "第二个数"
}
},
"required": ["num1", "num2"]
}
}
},
{
"type": "function",
"function": {
"name": "div",
"description": "计算两个数的商",
"parameters": {
"type": "object",
"properties": {
"num1": {
"type": "number",
"description": "第一个数"
},
"num2": {
"type": "number",
"description": "第二个数"
}
},
"required": ["num1", "num2"]
}
}
}
]
)
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
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
# 3.2.3 创建会话并等待响应
thread = client.beta.threads.create()
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="请根据我的要求按照优先级规则逐步调用函数。3 + 5 * (8 - 2) / 2 等于多少?",
)
print(f"------------------prompt------------------")
print(message.content[0].text.value)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id,
)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3.2.4 循环处理function_call直至完成
i = 1
while True:
if run.status == 'requires_action':
tool_outputs = []
print(f"------------------第{i}次请求回调tools------------------")
i = i + 1
for tool in run.required_action.submit_tool_outputs.tool_calls:
function_call = function_map.get(tool.function.name)
if function_call:
args = json.loads(tool.function.arguments)
print(f"调用函数{tool.function.name},参数为{args}")
result = function_call(
num1=float(args["num1"]),
num2=float(args["num2"])
)
tool_outputs.append({
"tool_call_id": tool.id,
"output": str(result)
})
if tool_outputs:
try:
run = client.beta.threads.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
except Exception as e:
print("Failed to submit tool outputs:", e)
break
# 检查运行状态
run = client.beta.threads.runs.retrieve(
thread_id=thread.id,
run_id=run.id
)
if run.status == 'completed':
messages = client.beta.threads.messages.list(
thread_id=thread.id
)
print(f"------------------最终回答------------------")
print(messages.data[0].content[0].text.value)
break
elif run.status == 'failed':
print("Run failed")
break
time.sleep(1)
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
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
编辑 (opens new window)
上次更新: 2025/09/18, 08:16:15