Skip to content
 

Function Calling(函数调用)详解 ​

更新: 10/14/2026字数: 0 字 时长: 0 分钟

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

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

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

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

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

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

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

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

json
// 发送给大模型的请求载荷 (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 的响应:

json
{
  "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 类型的角色,再次发给大模型:
json
[
  {"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(天气工具的参数定义):

json
{
  "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 作为"瞄准镜和触发器",决定何时调用哪件武器。