AI Evolution

7.2 函数调用(Function Calling)

Function Calling 技术为语言模型插上了“手脚”,解决了其无法与外部世界直接交互的“能力边界”问题。通过预先定义函数(工具)的描述和参数结构(JSON Schema),模型能够理解用户意图,自主选择并生成调用外部 API 或本地函数的请求。这使得 AI 不再局限于文本生成,而是能真正执行查询天气、发送邮件、预订机票等实际操作,成为连接数字与物理世界的桥梁。

如果说 RAG 解决了 AI 的“知识更新”问题,那么 函数调用(Function Calling) 则是试图解决AI的“能力边界”问题。再强大的语言模型,也只是一个文本预测生成器,它无法直接操作文件、访问网络、执行计算或与外部系统交互。而函数调用技术,就是为 AI 插上了“手脚”,让它能够真正地“做事情”而不仅仅是“说话”。

7.2.1 什么是 Function Calling?

早期人类和大模型的交互就是你发送一个问题,大模型给你一个回答,假如我们问大模型“查询北京明天的天气,基于明天的天气帮我规划一个日程安排”,完成这个任务的前提是大模型要知道明天的天气,显然大模型是不知道的,因为大模型的知识仅限于预训练时的语料(如图 7-3)。通常这时我们会先去手动查一下天气,然后粘贴进去天气提示词变成“北京明天雨夹雪伴随大风蓝色预警,帮我规划一下日程安排”,这个时候模型会根据天气做出回答。

图 7-3 用户与大模型交互流程图 7-3 用户与大模型交互流程

所以早期我们想要让大模型和外部数据信息交互,只能通过手动复制粘贴的方法,把外部数据粘贴给大模型。为了让大模型可以和外部数据信息交互,2023 年 6 月,OpenAI 推出了 Function Calling

我们可以把 Function Calling 理解成一种让模型与外部世界连接起来的桥梁。

大语言模型通过理解你的指令,判断当前任务需要用到哪个“工具函数”,再根据语义自动构造这个函数的调用指令(通常是一个结构化的 JSON 请求),然后由外部系统来实际执行这段函数逻辑,并将结果再交给语言模型继续处理。

7.2.2 Function Calling 工作原理

Function Calling 通常采用 JSON Schema 来描述可用的函数,函数开发者需要先定义可调用的函数,并为大模型提供以下元信息:

  • 函数名称(name): 唯一标识符(如get_weather)。
  • 功能描述(description): 用自然语言说明函数的作用,用来帮助模型判断什么时候调用。
  • 参数结构(parameters): 参数名称、类型、约束条件。

以 OpenAI 的 Function Calling 规范为例,我们写一个天气调用的函数(OpenAI 将其称之为工具 Tool,等价于函数 Function):

{
  "name": "get_weather",
  "description": "获取指定城市的当前天气信息",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {
        "type": "string",
        "description": "要查询天气的城市名称,例如:'北京' 或 'San Francisco'"
      },
      "date": {
        "type": "string",
        "format": "date",
        "description": "查询天气的具体日期,格式为 'YYYY-MM-DD'。例如:'2025-06-22'。留空表示今天。"
      }
    },
    "required": ["location", "date"]
  }
}

用户发送一个问题到服务器,服务器在调用大模型 API 接口的同时,需要通过大模型 API 的 functions 参数将 Tools(可多个)的元信息一起传递给大模型。

大模型收到一个问题后,会进行意图识别,判断用户的请求是否需要调用外部函数。

如果需要则进行函数选择,从传递进来的 Tools 列表中根据每个 Tool 的描述信息选择一个最合适的 Tool。

最后是参数生成,大模型需要读取选中 Tool 的整个元信息,理解这个 Tool 需要什么参数,然后根据用户的问题内容来生成与之匹配的参数。

经过这三步操作之后,大模型会生成一个标准 JSON Schema 的函数调用请求给到服务器。如下:

{
  "function_call": {
    "name": "get_weather",
    "arguments": "{ \\"location\\": \\"北京\\", \\"date\\": \\"2025-06-22\\" }"
  }
}

服务器在接收到模型函数调用的标准 JSON Schema 格式输出后,就会去解析这个调用函数的 JSON,然后去调用具体的函数并传入参数。

当服务器调用大模型想要调用的函数并拿到结果之后,就会将函数调用结果和之前的用户问题再次发送给大模型,大模型收到后根据这些信息生成内容返回给服务器输出结果,服务器再拿着结果给到用户。

上文中这个需要调用天气查询函数的示例,其整体流程如图 7-4 所示。

图 7-4 用户与支持Function Calling的大模型交互流程图 7-4 用户与支持Function Calling的大模型交互流程

7.2.3 Function Calling 优缺点

传统语言模型只能“说”,Function Calling 让模型可以“做”。它使模型能真正意义上主动调用外部函数,实现与真实世界的数据、服务、工具的集成,具备更高的实用性。比如,模型可以网络查询数据、发一个邮件、订票等等。

虽然 Function Calling 原生每轮只能调用一个函数,如果用户同时提出多个操作意图,模型无法并行调用多个函数,但是也可以配合外部控制逻辑(如循环机制等)去实现多个函数按流程串联调用,以此构建复杂应用。比如“查天气 → 判断晴雨 → 决定订机票或高铁”的任务流程。

随着 Function Calling 的问世,各个模型厂商陆续都支持了 Function Calling,但是不同的大模型厂商实现的接口定义、调用格式、参数结构存在明显差异,比如:

  • OpenAI 的函数调用使用 functions 参数注册 schema,并由模型生成 JSON 结构的 function_call
  • Anthropic Claude 使用 tool_use/tool_choice 机制,与 OpenAI 类似但细节语义不同
  • Google Gemini、阿里通义、百度文心等模型也都各自定义了不同的函数接口格式和插件系统

这导致开发者在集成多个模型时,无法“一套函数 schema 走天下”,需要针对每家厂商分别适配接入层逻辑、构建中间抽象层,增加了维护成本、系统复杂性,也让模型迁移、平台切换变得困难。

就比如你已经为 OpenAI 的 GPT 写好了一个函数 schema,结果换用 Claude 时你要重写接口适配逻辑,如果你要同时接入多个模型,还得为每个模型“单独定制调用方式”。

没有一套统一的协议规定各个大模型的 Function Calling 接口格式,这是 Function Calling 最大的问题所在。

Edit on GitHub

Last updated on