大模型应用开发教程09 | Function Calling 原理与实践(工具调用)
2026/8/13 8:25:31 网站建设 项目流程

理论部分

前面我们做的事情,本质上都是:给模型一段输入,让模型生成一段输出
但当我们希望模型“帮我们做事”时,仅靠生成文本往往不够:

  • 我们想要实时数据(天气、股价、数据库查询结果),模型本身拿不到
  • 我们想要模型触发动作(发请求、查文件、执行计算),文本并不能直接执行

Function Calling(工具调用)就是把“模型输出”升级为“可执行的结构化意图”:

  1. 我们把可用工具(函数)及参数规则告诉模型
  2. 模型根据用户问题,决定要不要调用工具、调用哪个工具、传什么参数
  3. 我们在代码里执行真实函数,把函数结果回传给模型
  4. 模型基于工具结果生成最终回答

从工程视角看,这里最关键的是:模型只负责决定“调用什么 + 参数是什么”,真正执行仍然由我们的程序掌控。这使得工具调用更可控、更可验证,也更容易接入业务系统。

一个完整的工具调用链路里,会出现三类关键信息:

  • Tool Definition(工具描述):函数名、用途描述、参数 schema(类型、枚举、必填字段)
  • Tool Call(工具调用请求):模型生成的结构化调用意图(函数名 + arguments)
  • Tool Result(工具执行结果):我们执行函数后的返回值(通常是 JSON 字符串或可解析文本)

实践部分

本案例做什么

我们实现一个“智能天气助手”,让模型在需要时自动调用get_current_weather工具:

  1. 用户提问(比如“北京天气怎么样?”)
  2. 模型决定调用工具,并给出参数(location、unit)
  3. 我们执行函数(这里用模拟数据代替真实天气 API)
  4. 把工具返回结果喂回模型,生成最终答复

主要代码

本篇使用项目脚本:src/4.1_weather_agent.py

importosimportjsonfromdotenvimportload_dotenvfromopenaiimportOpenAI# 加载环境变量load_dotenv()client=OpenAI(api_key=os.getenv("ZHIPUAI_API_KEY"),base_url=os.getenv("ZHIPUAI_BASE_URL"))# === 1. 定义实际的工具函数 ===# 这里我们用模拟数据,实际项目中可以调用真实的天气 APIdefget_current_weather(location,unit="celsius"):"""获取指定城市的当前天气"""print(f"DEBUG: 正在查询{location}的天气...")if"北京"inlocation:returnjson.dumps({"location":"北京","temperature":"22","unit":unit,"description":"晴朗"})elif"上海"inlocation:returnjson.dumps({"location":"上海","temperature":"25","unit":unit,"description":"多云"})elif"广州"inlocation:returnjson.dumps({"location":"广州","temperature":"30","unit":unit,"description":"雷阵雨"})else:returnjson.dumps({"location":location,"temperature":"unknown"})# === 2. 定义工具描述 (Tool Definitions) ===# 告诉 LLM 有哪些工具可用,以及参数格式tools=[{"type":"function","function":{"name":"get_current_weather","description":"获取指定城市的当前天气","parameters":{"type":"object","properties":{"location":{"type":"string","description":"城市名称,如:北京、上海",},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"温度单位,默认为摄氏度"},},"required":["location"],},},}]# === 3. 对话主循环 ===defrun_conversation():print("=== 🌦️ 智能天气助手 (Function Calling Demo) ===")print("试着问我:'北京天气怎么样?' 或 '上海和广州哪里更热?' (输入 q 退出)")messages=[]# 维护上下文whileTrue:user_input=input("\n👤 你: ")ifuser_input.lower()in['q','quit']:break# 将用户消息加入历史messages.append({"role":"user","content":user_input})# 第一次调用模型:查看是否需要调用工具response=client.chat.completions.create(model="glm-4-flash",# 确保模型支持 Function Callingmessages=messages,tools=tools,tool_choice="auto",# 让模型自动决定是否调用工具)response_message=response.choices[0].message tool_calls=response_message.tool_calls# 如果模型决定调用工具iftool_calls:# 必须先把模型的这条回复(包含工具调用请求)加入历史messages.append(response_message)print(f"🤖 AI 决定调用工具:{len(tool_calls)}个请求")# 建立函数名到实际函数的映射available_functions={"get_current_weather":get_current_weather,}# 遍历所有工具调用请求fortool_callintool_calls:function_name=tool_call.function.name function_to_call=available_functions[function_name]function_args=json.loads(tool_call.function.arguments)# 执行真正的函数function_response=function_to_call(location=function_args.get("location"),unit=function_args.get("unit"),)print(f" --> 调用{function_name}({function_args})")print(f" <-- 返回{function_response}")# 将工具执行结果作为 tool 类型的消息加入历史messages.append({"tool_call_id":tool_call.id,"role":"tool","name":function_name,"content":function_response,})# 第二次调用模型:让模型根据工具结果生成最终回答print("🤖 AI 正在根据工具结果生成回答...")final_response=client.chat.completions.create(model="glm-4-flash",messages=messages,)ai_reply=final_response.choices[0].message.contentprint(f"🤖 AI:{ai_reply}")# 把最终回答也加入历史messages.append({"role":"assistant","content":ai_reply})else:# 不需要调用工具,直接回复ai_reply=response_message.contentprint(f"🤖 AI:{ai_reply}")messages.append({"role":"assistant","content":ai_reply})if__name__=="__main__":run_conversation()

运行方式

在项目根目录执行:

python3 src/4.1_weather_agent.py

运行结果示例

我们可以输入一个需要实时信息的问题,例如:

  • “北京天气怎么样?”
  • “上海和广州哪里更热?”

运行时会看到类似输出(模型的措辞可能不同,但工具调用链路一致):

=== 🌦️ 智能天气助手 (Function Calling Demo) === 试着问我:'北京天气怎么样?' 或 '上海和广州哪里更热?' (输入 q 退出) 👤 你: 上海和广州哪里更热? 🤖 AI 决定调用工具: 2 个请求 DEBUG: 正在查询 上海 的天气... --> 调用 get_current_weather({'location': '上海', 'unit': 'celsius'}) <-- 返回 {"location": "上海", "temperature": "25", "unit": "celsius", "description": "多云"} DEBUG: 正在查询 广州 的天气... --> 调用 get_current_weather({'location': '广州', 'unit': 'celsius'}) <-- 返回 {"location": "广州", "temperature": "30", "unit": "celsius", "description": "雷阵雨"} 🤖 AI 正在根据工具结果生成回答... 🤖 AI: ...

总结

这一篇我们跑通了 Function Calling 的完整闭环:模型先决定是否调用工具以及工具参数,我们负责执行真实函数并把结果回传,最后再由模型整合工具结果生成最终回答。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询