DOCAI · 课程 · L3 · 35 分钟
给模型一个工具,让它自己用
定义一个函数、把它的结构告诉模型、执行模型返回的调用、再把结果发回去:亲手跑一遍工具调用的完整回合。
你将学会
- 能定义一个模型可调用的工具并跑通一次调用
- 能读懂模型返回的工具调用结构
- 能给循环设步数上限和人工确认点
先分清谁在执行
模型只输出「我要调 get_weather,参数是上海」。真正发请求的是你的代码。
这条边界想清楚,后面所有权限与安全问题都好谈。概念见什么是工具调用。
第一步:定义工具
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string", "description": "城市名"}},
"required": ["city"],
},
},
}]
description 写清楚「什么时候该用」,模型靠它选工具。
第二步:发出请求,看返回
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "上海现在多少度?"}],
tools=tools,
)
call = resp.choices[0].message.tool_calls[0]
print(call.function.name, call.function.arguments) # get_weather {"city":"上海"}
注意:arguments 是字符串,要自己 json.loads 并校验字段。
第三步:执行并回传
result = get_weather(**json.loads(call.function.arguments))
messages.append(resp.choices[0].message)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
tool_call_id 必须对上,否则服务端不知道这是哪次调用的结果。
加上循环与边界
- 步数上限:比如 6 步,到了就停并返回已有结果。
- 写操作要确认:发邮件、下单、删数据,先给人看一遍。
- 执行前校验参数:模型给的参数不一定合法。
- 记录每一步:调了什么、返回什么,出问题才有得查。
需要接现成工具时,看什么是 MCP;需要多步自主决策时,那才是Agent。
自测
- 模型会不会自己执行
get_weather?为什么这个区别很重要? - 忘记回传
tool_call_id会发生什么? - 为什么「步数上限」是 agent 的必需件而不是可选项?