给 AI Agent 装上「手」:Function Calling 实战
给 AI Agent 装上「手」:Function Calling 实战
你有没有想过,为什么有些 AI 能帮你查天气、订机票、操作数据库,而有些只会聊天?
差距就在这一个东西:Function Calling(工具调用)。
一、AI 的先天残缺
大模型本质上是个「封闭的大脑」。
它的知识来自训练数据,截止到某个时间点;它不能访问网络,不知道今天股价多少;它不会直接执行代码,无法帮你操作文件;它更不能发邮件、存数据、调 API。
简单说:大脑有了,但没有手。
Function Calling,就是给 AI 大脑配上手的那项技术。
二、Function Calling 是什么?
一句话:你告诉模型「有哪些工具可以用」,模型自己决定什么时候用、用哪个、传什么参数。
注意一个关键点——模型本身不直接执行任何操作。
整个过程是三方配合:
| 角色 | 做什么 |
|---|---|
| 你(开发者) | 定义工具,写好「说明书」(工具名、功能描述、参数格式) |
| 模型 | 读取说明书,判断该不该调用,生成调用指令 |
| 你的代码 | 真正去执行(查数据库、调接口、运行代码),把结果回传 |
模型只是个「大脑」,它告诉你:「去帮我查一下北京天气,参数 city=北京」。真正去查的是你的代码。
三、完整工作流程
来看一个具体的例子:用户问「北京今天天气怎么样?」
① 用户提问
"北京今天天气怎么样?"
↓
② 发送请求给模型(携带工具列表)
tools: [{ name: "get_weather", description: "查询城市天气", ... }]
↓
③ 模型返回:我要调用工具
finish_reason: "tool_calls"
tool_call: get_weather(city="北京")
↓
④ 你的代码执行 get_weather("北京")
→ 返回:{"temp": 22, "condition": "晴天"}
↓
⑤ 把结果回传给模型
↓
⑥ 模型生成最终回答
"北京今天天气晴朗,气温 22°C,适合出行。"
这个「提问 → 决策 → 执行 → 回传 → 回答」的循环,就叫做 Agentic Loop(智能体循环)。一个复杂任务可能循环多次,直到模型说「我搞定了」。
四、代码实战:从零搭一个天气查询 Agent
下面用 DeepSeek API(兼容 OpenAI 格式,国内免费额度充足)来演示。
第一步:定义工具
tools= [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的当前天气,包括温度和天气状况",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名,例如:北京、上海"
}
},
"required": ["city"]
}
}
}
]
这份 JSON 就是「工具说明书」。模型读完它,才知道:哦,有个叫 get_weather 的工具,需要传 city 参数。
第二步:模拟工具执行
importjson
defexecute_tool(name: str, args: dict) ->str:
"""真实项目里,这里对接真实的天气 API"""
ifname=="get_weather":
# 模拟返回(真实场景换成 requests.get 调天气接口)
returnjson.dumps({
"city": args["city"],
"temp": 22,
"condition": "晴天"
}, ensure_ascii=False)
returnjson.dumps({"error": f"未知工具: {name}"})
第三步:完整的 Agentic Loop
fromopenaiimportOpenAI
client=OpenAI(
api_key="你的 DeepSeek API Key",
base_url="https://api.deepseek.com/v1"
)
messages= [{"role": "user", "content": "北京和上海今天天气怎么样?"}]
whileTrue:
# 发请求给模型
response=client.chat.completions.create(
model="deepseek-chat",
tools=tools,
tool_choice="auto", # 让模型自己决定要不要调用工具
messages=messages
)
choice=response.choices[0]
# 把模型回复加入对话历史
messages.append({
"role": "assistant",
"content": choice.message.content,
"tool_calls": choice.message.tool_calls
})
# 如果模型不需要调工具了,直接输出结果
ifchoice.finish_reason!="tool_calls":
print("最终回答:", choice.message.content)
break
# 模型要调工具:逐个执行,把结果回传
fortool_callinchoice.message.tool_calls:
result=execute_tool(
tool_call.function.name,
json.loads(tool_call.function.arguments)
)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
注意这里:用户问的是「北京和上海」,模型会并行调用两次 get_weather,同时查两个城市,这就是 Parallel Function Calling(并行工具调用)。
五、三个常见坑,新手必踩
坑 1:工具描述写得太简单
模型靠描述决定要不要调这个工具。描述越清晰,调用越准确。
# ❌ 烂描述:模型经常搞错
"description": "获取天气"
# ✅ 好描述:明确场景和返回内容
"description": "获取指定城市的实时天气信息,返回温度(摄氏度)和天气状况(晴/多云/雨等)"
坑 2:忘记把工具结果加回对话历史
# ❌ 执行完工具,直接再问模型
response2=client.chat.completions.create(...) # 模型完全不知道工具返回了什么
# ✅ 必须把 tool result 追加到 messages
messages.append({
"role": "tool",
"tool_call_id": tool_call.id, # 必须对应!
"content": result
})
tool_call_id 是关键,模型用这个 ID 对应「哪个工具调用的结果」。漏了就会报错。
坑 3:没有设置循环退出条件
# ❌ 复杂任务可能死循环
whileTrue:
response=...
# ✅ 加一个最大迭代次数保险
max_iterations=10
for_inrange(max_iterations):
response=...
ifchoice.finish_reason!="tool_calls":
break
六、进阶:给 Agent 注册多个工具
一个真正实用的 Agent,往往需要多个工具配合。来看一个「查天气 + 做计划」的例子:
tools= [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "search_attractions",
"description": "搜索指定城市的热门景点和推荐活动",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"},
"weather": {"type": "string", "description": "当前天气状况,影响推荐结果"}
},
"required": ["city"]
}
}
}
]
用户说「我周末想去杭州,帮我规划一下」,模型会自动:
-
先调
get_weather("杭州"),看看天气 -
再调
search_attractions("杭州", weather="晴天"),推荐景点 -
最后综合两个结果,给出具体的周末计划
这就是 Agent 的魅力:任务拆解、工具编排、结果整合,全部自动完成。
七、不需要写代码也能用?
如果你不想写代码,Coze 和 Dify 这类无代码平台也支持工具调用:
-
Coze:在工作流里拖拽添加「插件」,本质上就是 Function Calling 的可视化封装
-
Dify:工具节点直接配置 API,自动生成工具描述给模型
适合快速验证想法;想要真正定制化,还是要回到代码层。
总结
| 概念 | 一句话记忆 |
|---|---|
| Function Calling | 给 AI 大脑配上「手」的技术 |
| 工具定义 | 写一份 JSON「说明书」,告诉模型有哪些工具可用 |
| Agentic Loop | 循环:模型决策 → 代码执行 → 结果回传,直到任务完成 |
| Parallel Calling | 模型可以同时调多个工具,不用傻等 |
| 工具描述 | 越清晰越准,直接影响模型的调用准确率 |
下次你见到某个 AI 助手能帮你做事而不只是聊天,十有八九用的就是这个原理。
学会 Function Calling,你就掌握了 AI Agent 最核心的能力之一。
下期预告:用 Function Calling + 真实 API,搭一个能自动查股票、发摘要的 Agent,感兴趣的在评论区扣 1。
夜雨聆风