乐于分享
好东西不私藏

给 AI Agent 装上「手」:Function Calling 实战

给 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(namestrargsdict->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"]
            }
        }
    }
]

用户说「我周末想去杭州,帮我规划一下」,模型会自动:

  1. 先调 get_weather("杭州"),看看天气

  2. 再调 search_attractions("杭州", weather="晴天"),推荐景点

  3. 最后综合两个结果,给出具体的周末计划

这就是 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。