☰
Function Calling(函数调用)详解
2026/10/15 15:31:43 网站建设 项目流程

文章目录

    • 一、核心概念:大模型是如何"理解并调用"函数的?
    • 二、标准的代码交互流程(以 OpenAI / 兼容 API 为例)
      • 第 1 轮:开发者声明工具,用户提出需求
      • 第 2 轮:大模型识别意图,返回"工具调用指令"
      • 第 3 轮:你的后端执行代码,将结果传回,大模型生成最终回复
    • 三、三大核心技术细节
      • 1. JSON Schema 的重要性
      • 2. Tool Choice(工具选择策略)
      • 3. 并行函数调用(Parallel Function Calling)
    • 四、开发中的常见痛点与"坑"
    • 五、Function Calling 和 MCP 区别
      • 1. 核心定位对比
      • 2. 工作架构对比
      • 3. 维度对比表
      • 4. 总结

一、核心概念:大模型是如何"理解并调用"函数的?

很多人第一次听见Function Calling,以为是大模型真的去服务器里"运行"了一段代码。其实不是的。

大模型本质上是一个概率生成器(它只擅长根据上下文接龙文字)。它做不到在沙箱里跑 Python 或调系统的 API。Function Calling 的真相是:大模型只负责"做决策"和"翻译参数"。

  1. 大模型不执行函数:它只是在读了用户的话和你的函数定义后,觉得"此时应该调用函数 A,参数是 X 和 Y"。
  2. 大模型输出结构化文本:它把这个决定伪装成一段特定的 JSON 格式文本吐给你的程序。
  3. 真正的执行者是你的后端代码:你的程序拦截到这段 JSON,在本地服务器运行真正的函数,再把运行结果喂回给大模型。

二、标准的代码交互流程(以 OpenAI / 兼容 API 为例)

一个完整的Function Calling交互,通常需要前后 3 轮对话:

第 1 轮:开发者声明工具,用户提出需求

你向大模型发送请求时,除了常规的messages(对话历史),还要加上一个tools(或functions)字段,告诉大模型:“我这里有这几个工具你可以用。”

// 发送给大模型的请求载荷 (Payload){"model":"gpt-4o","messages":[{"role":"user","content":"北京明天穿什么衣服合适?"}],"tools":[{"type":"function","function":{"name":"get_weather","description":"获取指定城市和日期的天气信息","parameters":{"type":"object","properties":{"location":{"type":"string","description":"城市名称,例如:北京"},"date":{"type":"string","description":"日期,格式为 YYYY-MM-DD"}},"required":["location"]}}}]}

第 2 轮:大模型识别意图,返回"工具调用指令"

大模型分析后,发现用户的需求和get_weather完美匹配。它不会直接回答"北京明天多云",而是返回一个带有tool_calls的响应:

{"role":"assistant","content":null,"tool_calls":[{"id":"call_abc123xyz","type":"function","function":{"name":"get_weather","arguments":"{\"location\": \"北京\", \"date\": \"2026-10-14\"}"}}]}

第 3 轮:你的后端执行代码,将结果传回,大模型生成最终回复

  1. 你的代码截获到tool_calls,解析出location="北京"和date="2026-10-14"。
  2. 你的程序去调真实的天气 API,得到结果:{"temperature": "22°C", "condition": "晴"}。
  3. 你把这个结果包装成tool类型的角色,再次发给大模型:
[{"role":"user","content":"北京明天穿什么衣服合适?"},{"role":"assistant","tool_calls":[...]},// 上一步模型吐的指令{"role":"tool","tool_call_id":"call_abc123xyz","content":"{\"temperature\": \"22°C\", \"condition\": \"晴\"}"}]
  1. 大模型看到结果后,组织最终的自然语言答复给用户:“北京明天是晴天,气温约 22°C,建议穿轻薄的外套或长袖衬衫。”

三、三大核心技术细节

要用好Function Calling,有几个底层设计非常关键:

1. JSON Schema 的重要性

在定义工具的parameters时,大模型强制要求使用JSON Schema规范。它相当于 JSON 数据的"合同",规定了对象里有哪些字段、每个字段是什么类型、哪些必填,甚至对取值做严格限制。

以下就是一个标准的 JSON Schema(天气工具的参数定义):

{"type":"object","properties":{"location":{"type":"string","description":"城市名称,例如:北京"},"date":{"type":"string","description":"日期,格式为 YYYY-MM-DD"},"temperature_unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"温度单位:摄氏度或华氏度"}},"required":["location"]}

几个核心关键字:

  • type:字段的数据类型。常见的有string(字符串)、number/integer(数字)、boolean(布尔)、array(数组,用items定义元素类型)、object(嵌套对象)。
  • properties:定义对象里可以包含哪些字段。
  • enum:枚举,限定字段只能从给定值里选一个(如上例的temperature_unit只能传celsius或fahrenheit)。
  • required:必填项。缺少必填参数时,模型会向用户追问而不是瞎编。

description比类型更重要:大模型靠自然语言理解参数。只写{"type": "string", "name": "q"},它根本不知道q是啥;补上description(如"用户的全局搜索关键词,支持模糊搜索,严禁包含特殊符号"),它就能精准提取用户话里的核心词填进去。给每个字段写清晰、带示例的description,是保证工具调用成功率的核心秘诀。

2. Tool Choice(工具选择策略)

你可以通过参数控制大模型对待工具的态度:

  • auto(默认):模型自己决定是直接和用户聊天,还是去调用工具。
  • none:强制模型不使用任何工具,只进行普通对话。
  • 强制指定:你可以硬性规定模型这一轮必须调用某个特定的工具(常用于多步骤复杂 Agent 的强控制流)。

3. 并行函数调用(Parallel Function Calling)

现代先进的大模型支持在同一轮对话中返回多个工具调用。

  • 例如用户说:“帮我查一下北京和上海明天的天气。”
  • 模型可以一次性吐出两个tool_calls分别查北京和上海,后端并发去请求,然后再把两个结果一起喂给模型。这大大减少了多轮对话的延迟。

四、开发中的常见痛点与"坑"

  1. 大模型"幻觉参数":有时候用户没说全信息,大模型可能会自己"瞎编"一个合理的参数传给函数。因此,在后端代码接收到大模型传来的参数时,必须进行二次校验与防呆处理。
  2. 长提示词与 Token 消耗:如果你给大模型注册了几十个甚至上百个工具,每次请求光是tools里面的 JSON Schema 描述就会吃掉大量的 Prompt Token。因此,复杂的生产系统通常会做工具检索(Tool Retrieval)——根据用户当前的意图,先用向量检索或简单分类,动态挑选最相关的 3~5 个工具塞给模型,而不是一次性全量加载。
  3. 错误处理机制:如果你的 API 挂了,或者返回了404 Not Found,不要直接报错中断。你需要把这个错误信息(作为tool结果)传回给大模型,大模型具备一定的容错和解释能力,它会温柔地告诉用户:“不好意思,天气服务暂时开小差了,请稍后再试。”

Function Calling从根本上打通了"自然语言"与"结构化世界"的壁垒,把大模型从一个"只会夸夸其谈的聊天机器"变成了"能够驱动软件系统的数字员工"。

五、Function Calling 和 MCP 区别

两者常被一起讨论,但解决的是不同层级的问题:Function Calling 是"能力",MCP 是"协议"。

1. 核心定位对比

  • Function Calling(能力层):大模型的一项原生底层能力,解决了"无法产生结构化数据"的问题——能把自然语言精准提取为{"name": "func_name", "args": {...}}这样的 JSON。

    • 局限:只定义了格式、没定义连接方式。工具定义要硬编码进请求,新增工具要改所有代码,且各家接口规范不统一、难以复用。
  • MCP(协议层):一套开放的客户端-服务器通信协议(类似 HTTP/REST),解决工具生态的"碎片化"与"重复造轮子"。

    • 优势:工具只写一次、部署为MCP Server,任何支持 MCP 的客户端(Cursor、Claude Desktop 等)都能动态连接、即插即用,无需硬编码实现。

2. 工作架构对比

纯 Function Calling:逻辑全侵入在应用代码里。

用户输入 → 应用代码(硬编码工具定义) → 大模型(返回 JSON 指令) → 应用代码手动调 API → 结果喂回大模型 → 生成回答

结合 MCP:工具解耦为独立服务。

用户输入 → MCP 客户端 1. 向 MCP Server 动态获取工具列表 2. 把工具定义塞给大模型 3. 大模型用 Function Calling 吐出 JSON 调用 4. 客户端按 MCP 协议转发给 Server 执行并返回

3. 维度对比表

维度Function CallingMCP 协议
所属层级算法/模型层(参数提取与意图判断)系统/网络层(通信规范)
扮演角色决策者与翻译官基础设施与管道
代码耦合度高耦合,与应用代码绑定低耦合,工具独立运行
工具发现方式静态,调用前写死在代码里动态,连接后自动扫描
跨模型/应用复用差,换框架需适配极佳,一套规范多方复用

4. 总结

MCP 不是 Function Calling 的替代品,而是它的"升级载体"。MCP 负责管理连接"军火库"(工具与数据源),大模型则用 Function Calling 作为"瞄准镜和触发器",决定何时调用哪件武器。


🚀 感谢阅读!想了解更多?

📖 我的博客网站 | 记录思考,分享干货
🏡 我的个人主页 | 关于我、开源项目


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

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

立即咨询