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 用户与大模型交互流程
所以早期我们想要让大模型和外部数据信息交互,只能通过手动复制粘贴的方法,把外部数据粘贴给大模型。为了让大模型可以和外部数据信息交互,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.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 最大的问题所在。
Last updated on
7.1 检索增强生成(RAG)
为解决大模型知识更新慢、成本高的问题,检索增强生成(RAG)架构应运而生。它通过外挂一个可随时更新的知识库,在生成答案前先进行“检索”,将相关信息注入提示词,从而让模型能够参考最新资料回答问题。该技术的核心在于利用Embedding模型进行语义向量化、对知识库内容分块(Chunking)以及通过向量数据库实现高效检索,有效缓解了模型幻觉,并提升了答案的时效性和准确性。
7.3 模型上下文协议(MCP)
为解决各家大模型 Function Calling 接口不统一的问题,MCP 应运而生。作为一个开放标准,MCP 规范了模型与外部工具、数据源之间的交互方式,使得开发者可以“一次开发,到处运行”工具服务(MCP Server)。这大大降低了多模型适配的复杂性,促进了一个可互操作的AI工具生态系统的形成,其定位类似于硬件领域的 USB 标准。