大模型本身只会生成文字,既查不了实时天气,也算不准复杂数学。Function Calling(函数调用)让它能”请求”调用你写好的工具:模型判断该用哪个函数、给出参数,你的程序执行后把结果喂回去。这是所有 AI Agent 的地基,这篇教程用 OpenAI 兼容接口完整实现一次。

工作原理

模型并不真的执行代码,它只输出”我想调用哪个函数、传什么参数”,执行由你的程序完成:

前置准备

pip install openai

并设置好 OPENAI_API_KEY 环境变量(参考「如何调用大模型 API」那篇)。

步骤一:写好要暴露的工具函数

先实现真正的功能,这里用查天气做示例:

def get_weather(city: str) -> str:
# 实际项目里应调用真实天气 API
fake_data = {"北京": "晴,25℃", "上海": "多云,28℃"}
return fake_data.get(city, "暂无该城市数据")

步骤二:用 JSON Schema 描述工具

模型靠这段描述来决定何时、如何调用。描述越清楚,调用越准:

tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名,如 北京"}
},
"required": ["city"],
},
},
}
]

步骤三:发起请求,接收调用意图

把用户问题和工具清单一起发给模型:

import os, json
from openai import OpenAI

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
messages = [{"role": "user", "content": "北京今天天气怎么样?"}]

resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
)
msg = resp.choices[0].message

如果模型决定调用工具,msg.tool_calls 就不为空。

步骤四:执行函数并回填结果

解析出函数名和参数,执行真实函数,再把结果作为一条新消息发回:

if msg.tool_calls:
messages.append(msg) # 先存入模型的调用请求
for call in msg.tool_calls:
name = call.function.name
args = json.loads(call.function.arguments)
result = get_weather(**args) # 真正执行
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result,
})

步骤五:让模型生成最终回答

带着工具结果再请求一次,模型就会用自然语言总结:

final = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=tools)
print(final.choices[0].message.content)
# 输出:北京今天是晴天,气温 25℃。

步骤六:封装成通用循环

把上面串起来,支持模型连续调用多个工具:

AVAILABLE = {"get_weather": get_weather}

def run_agent(user_input):
messages = [{"role": "user", "content": user_input}]
while True:
resp = client.chat.completions.create(
model="gpt-4o-mini", messages=messages, tools=tools)
msg = resp.choices[0].message
if not msg.tool_calls:
return msg.content # 不再需要工具,返回答案
messages.append(msg)
for call in msg.tool_calls:
fn = AVAILABLE[call.function.name]
result = fn(**json.loads(call.function.arguments))
messages.append({"role": "tool", "tool_call_id": call.id,
"content": str(result)})

print(run_agent("北京和上海哪个更热?"))

它的循环判断逻辑:

注意事项

  • 工具描述是关键,写不清模型就不会用或用错
  • 参数要做校验,模型偶尔会给出不合法的值
  • 工具权限越大风险越高,涉及删除、支付等要加确认
  • 多轮调用会累积 token,注意成本和超时

小结

Function Calling 的精髓是一个循环:模型提出调用意图 → 程序执行 → 结果回填 → 模型继续,直到不需要工具为止。掌握它,你就理解了 AI Agent”能干活”的底层机制,后续接入搜索、数据库、代码执行都是同一套路子。