7.2 函数调用:大模型的工具使用格式

7.1 节介绍了工具调用的基本原理和工具定义方式。本节深入一层,讲解函数调用(Function Calling)的数据格式和交互协议。这是大模型调用外部工具的核心机制——模型不直接执行代码,而是通过结构化的数据格式,告诉应用程序该调用哪个函数、传入什么参数。

理解这套数据格式,是后续学习 MCP 协议、构建金融智能体工具链的基础。

7.2.1 Function Calling 的诞生

2023 年 6 月,OpenAI 在 GPT 模型的 API 中率先推出函数调用(Function Calling)功能。这是大模型工具使用领域的一个分水岭。

在此之前,开发者想让模型调用工具,只能靠提示词引导模型输出特定格式的文本,再用正则表达式解析。这种方式脆弱且不可靠——模型稍微改变措辞,解析就会失败。

Function Calling 改变了这一局面。模型不再输出自由文本让开发者猜测意图,而是直接返回结构化的 JSON 数据,明确指定要调用的函数名和参数值。格式固定、字段明确、机器可直接解析。

注记知识卡片

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由键值对组成。例如 {"name": "贵州茅台", "code": "600519"} 就是一条 JSON 数据。它是当前 Web 开发和 API 通信中最主流的数据格式。

各大模型厂商迅速跟进。Anthropic 为 Claude 推出了 Tool Use 功能,Google 为 Gemini 推出了 Function Calling 支持。虽然各家的数据格式略有差异,但核心思路一致:模型通过结构化输出声明工具调用意图,应用程序负责实际执行。

下表汇总了主流厂商的工具调用功能:

厂商 功能名称 推出时间 格式特点
OpenAI Function Calling 2023 年 6 月 tools + tool_calls 字段
Anthropic Tool Use 2024 年 4 月 content block 模型
Google Function Calling 2023 年 12 月 functionCall 字段
智谱 AI Function Call 2024 年 兼容 OpenAI 格式
MiniMax Function Call 2024 年 兼容 OpenAI 格式

国内厂商(智谱、MiniMax 等)大多兼容 OpenAI 格式,这降低了开发者的迁移成本。

7.2.2 工具定义的数据格式

函数调用的第一步,是告诉模型有哪些工具可用。工具定义遵循 JSON Schema 规范,由三个核心字段构成。

三个核心字段

字段 作用 重要程度
name 工具的唯一标识符,模型据此调用 ★★★
description 功能描述,模型依赖此信息判断何时调用 ★★★
parameters 参数定义,规定输入数据的结构 ★★★

其中 description 的质量至关重要。模型根据 description 判断当前问题是否需要调用该工具。描述越精确,模型的调用决策越准确。

重要核心概念

description 是工具定义中最关键的字段。一个好的描述应回答三个问题:这个工具做什么?什么时候该用它?返回什么结果?模型完全依赖这段文字来决定是否调用工具。

下面用一个查询 A 股行情的工具定义来说明完整格式。这是 OpenAI 风格的定义方式,也是目前最通用的格式:

{
  "type": "function",
  "function": {
    "name": "get_stock_price",
    "description": "查询 A 股股票的实时行情数据,包括最新价、涨跌幅、成交量。当用户询问某只股票的价格、涨跌情况时调用此工具。",
    "parameters": {
      "type": "object",
      "properties": {
        "symbol": {
          "type": "string",
          "description": "6 位 A 股股票代码,如 600519 表示贵州茅台"
        },
        "metrics": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["price", "change", "volume", "turnover", "pe_ratio"]
          },
          "description": "需要查询的指标列表,默认返回全部"
        },
        "include_history": {
          "type": "boolean",
          "description": "是否包含最近 5 个交易日的历史数据,默认为 false"
        }
      },
      "required": ["symbol"]
    }
  }
}

逐层解读这段定义:

  • 最外层的 "type": "function" 声明这是一个函数类型的工具。
  • name 是函数名,必须是合法标识符(字母、数字、下划线)。
  • description 详细说明功能和适用场景。
  • parameters 采用 JSON Schema 格式定义输入参数。

参数类型系统

JSON Schema 提供了六种常用参数类型,足以覆盖绝大多数金融场景:

类型 说明 金融应用示例
string 字符串 股票代码、公司名称
integer 整数 持股数量、交易天数
number 浮点数 价格、收益率、权重
boolean 布尔值 是否含历史数据、是否复权
array 数组 多个股票代码、指标列表
enum 枚举(限定取值范围) 市场类型、订单类型

必需参数与可选参数

required 数组列出的参数为必需参数,模型必须提供。未列入的参数为可选参数,模型可根据情况决定是否填写。

在上面的例子中,symbol 是必需参数——查股票必须指定代码;metricsinclude_history 是可选参数——不指定也能返回默认结果。

提示设计建议

设计工具参数时,尽量减少必需参数的数量。只把真正不可或缺的参数设为 required,其余用合理的默认值处理。这能降低模型的调用门槛,提高工具被正确使用的概率。

7.2.3 请求与响应的完整数据流

函数调用四阶段数据流

一次完整的函数调用涉及两次 API 请求,分为四个阶段:

阶段 方向 数据内容
① 第一次请求 应用 → 模型 API 用户消息 + 可用工具定义列表
② 模型返回调用指令 模型 API → 应用 tool_calls 数组:工具名、参数、调用 ID
③ 第二次请求 应用 → 模型 API 完整对话历史 + 工具执行结果(通过调用 ID 匹配)
④ 模型生成回复 模型 API → 应用 自然语言最终回复

以用户提问「帮我查一下贵州茅台的最新股价和市盈率」为例:阶段 ① 应用将问题和 get_stock_price 工具定义发送给模型;阶段 ② 模型返回调用指令,指定工具名 get_stock_price、参数 {"symbol": "600519", "metrics": ["price", "pe_ratio"]};阶段 ③ 应用执行实际 API 查询,将结果连同对话历史发回模型;阶段 ④ 模型将结构化数据组织成自然语言回复。

注记知识卡片

函数调用需要两次 API 请求才能完成一轮交互。第一次发送用户问题和工具定义,获取调用指令;第二次发送工具执行结果,获取最终回复。如果模型判断不需要工具,第一次请求就直接返回文本回复,无需第二次调用。

7.2.4 多工具调用与工具链

实际的金融分析场景往往需要多个工具协同工作。Function Calling 支持两种多工具使用模式。

并行调用:一次请求多个工具

当用户的问题涉及多个独立的数据查询时,模型可以在一次响应中同时调用多个工具。例如用户问「对比一下贵州茅台和五粮液的股价」,模型会返回:

{
  "tool_calls": [
    {
      "id": "call_001",
      "type": "function",
      "function": {
        "name": "get_stock_price",
        "arguments": "{\"symbol\": \"600519\"}"
      }
    },
    {
      "id": "call_002",
      "type": "function",
      "function": {
        "name": "get_stock_price",
        "arguments": "{\"symbol\": \"000858\"}"
      }
    }
  ]
}

tool_calls 数组中包含两个调用请求,应用程序可以并行执行,分别查询两只股票的数据,然后将两个结果都返回给模型。

顺序调用(工具链):一个工具的输出作为另一个的输入

有些任务需要按步骤完成。例如「分析贵州茅台的估值是否合理」,可能需要:

  1. 先调用 get_stock_price 获取当前股价和市盈率
  2. 再调用 get_financial_report 获取最近一期财报数据
  3. 最后调用 calculate_valuation 计算估值指标

这就是工具链(Tool Chaining)。模型在每一步拿到结果后,决定下一步调用什么工具。整个过程可能涉及多轮 API 交互,每轮都遵循上一小节描述的四阶段流程。

提示设计建议

设计工具集合时,每个工具应职责单一、边界清晰。一个工具只做一件事,通过工具链组合完成复杂任务。这与软件工程中的单一职责原则一致,也便于模型理解和选择工具。

7.2.5 从 Function Calling 到 MCP

各大模型厂商的 Function Calling 格式大同小异,但细节各有不同(如 OpenAI 用 parameters,Claude 用 input_schema;OpenAI 的工具结果用 role: "tool",Claude 用 role: "user"tool_result 块)。格式差异对最终用户影响不大,智能体框架会自动处理适配。

Function Calling 解决了单个模型调用工具的问题,但它仍然是 API 级别的机制——每个模型厂商有自己的格式,每个应用需要为每个工具单独编写对接代码。

当工具数量增长、模型种类增多时,开发者面临 M 个模型 × N 个工具的集成难题。这正是下一节 MCP 协议要解决的问题:在 Function Calling 之上建立一层标准化协议,让任何模型都能通过统一接口访问任何工具。

Function Calling 是工具调用的数据格式,MCP 是工具连接的通信协议。前者规定调用请求的格式,后者规定工具如何被发现、连接和管理。理解了 Function Calling 的数据流,学习 MCP 就有了坚实的基础。