AI-Agent 中 Function-Calling 机制技术报告
主题: 外部工具如何被大模型理解,以及大模型如何学习 Function-Calling 能力
日期: 2026-06-30
适用对象: AI-Agent 初学者、应用开发者、技术方案撰写者

1. 摘要
在 AI-Agent 中,Function-Calling 的核心作用是:把外部工具能力转换成大模型可以理解、可以选择、可以填参的结构化接口说明。大模型本身并不会直接运行外部 API、数据库或业务系统,它只是根据工具描述和用户意图,生成一段结构化的调用请求;真正执行工具的是 Agent 框架或后端程序。
大模型学习 Function-Calling 能力,也不是学习某个外部函数内部的业务代码,而是学习一种映射能力:
用户自然语言请求 + 工具说明 + 参数 Schema + 当前上下文
→ 是否调用工具 + 调用哪个工具 + 参数如何填写 + 如何整合工具返回结果
因此,Function-Calling 可以被理解为 AI-Agent 的“动作接口层”:它让语言模型从“只会说话”扩展到“能够调用外部系统完成任务”。
2. 问题一:Function-Call 如何把外部工具变成大模型可以理解的方式?
2.1 核心观点
Function-Call 并不是把外部工具的代码直接塞进大模型,也不是让模型真正获得外部系统的执行权限。它做的是一件“翻译”工作:
外部工具 / API / 数据库 / 业务系统
→ 工具名称 + 自然语言描述 + 参数结构 + 参数约束
→ 大模型可读的工具说明
模型理解的是工具的“能力说明”和“参数格式”,不是工具内部实现。
2.2 工具注册:把外部工具写成模型可读的 Schema
例如,真实业务中可能有一个天气查询函数:
def get_weather(city: str, unit: str = "celsius"):
...
大模型不能直接理解这个函数的运行环境、鉴权方式、网络请求方式或数据库连接方式。因此,在 Agent 中通常需要把它包装成结构化工具说明:
{
"type": "function",
"name": "get_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "要查询天气的城市名称"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位"
}
},
"required": ["city"]
}
}
这份说明告诉模型四件事:
| 字段 | 对模型的作用 |
|---|---|
name |
工具叫什么,便于模型生成调用目标 |
description |
工具能做什么,便于模型判断是否需要调用 |
parameters |
调用工具需要哪些参数 |
type / enum / required |
参数类型、可选范围和必填约束 |
2.3 运行链路:模型生成调用意图,后端负责执行
当用户输入:
今天上海天气怎么样?
模型不会真的去查天气,而是可能输出一个结构化工具调用请求:
{
"name": "get_weather",
"arguments": {
"city": "上海",
"unit": "celsius"
}
}
接下来,Agent 框架或后端程序读取这段调用请求,并执行真实函数:
result = get_weather(city="上海", unit="celsius")
如果工具返回:
{
"city": "上海",
"temperature": 29,
"weather": "多云",
"humidity": "72%"
}
模型再根据工具结果组织最终回答:
上海今天多云,气温约 29°C,湿度 72%,体感会有些闷热。
2.4 Function-Calling 的六步机制
其中,大模型主要负责:
- 理解用户意图;
- 判断是否需要工具;
- 选择合适的工具;
- 从用户输入中抽取参数;
- 按 Schema 输出合法结构;
- 将工具结果转化为自然语言回答。
后端主要负责:
- 校验模型输出的函数名和参数;
- 执行真实外部工具;
- 处理权限、鉴权、网络请求和异常;
- 把工具返回结果重新传给模型。
3. 问题二:大模型如何学习到 Function-Calling 能力?
3.1 核心观点
大模型学习 Function-Calling 能力,本质上是学习一种“自然语言任务到结构化动作”的转换能力。它学到的不是某个工具内部如何运行,而是:
什么情况下需要调用工具?
应该调用哪个工具?
参数应该从哪里来?
输出格式应该是什么?
工具结果回来后应该如何继续回答?
3.2 预训练:获得结构化文本和代码理解基础
在预训练阶段,大模型会接触大量自然语言、代码、JSON、API 文档、配置文件、函数声明等内容。因此,它天然具备一定的结构化文本理解能力。
例如,模型在预训练中可能见过大量类似内容:
{
"city": "Shanghai",
"date": "today"
}
也见过大量类似函数说明:
def search_product(keyword, price_min=None, price_max=None):
...
这让模型具备了 Function-Calling 的底层语言基础:能理解函数名、参数名、JSON 结构和自然语言描述之间的关系。
但是,预训练只能提供基础能力,不能保证模型稳定地按照某个平台的工具调用协议输出。
3.3 监督微调 SFT:学习标准工具调用样本
监督微调会向模型展示大量“用户请求 → 正确工具调用”的样本。例如:
用户:帮我查一下订单 12345 的物流状态。
可用工具:get_order_status(order_id)
正确输出:
{
"name": "get_order_status",
"arguments": {
"order_id": "12345"
}
}
经过大量类似样本训练后,模型会逐渐学会:
| 训练目标 | 具体能力 |
|---|---|
| 意图识别 | 判断用户是否需要外部工具 |
| 工具选择 | 从多个工具中选择最合适的一个 |
| 参数抽取 | 从自然语言中抽取订单号、城市、时间等参数 |
| 格式遵循 | 按照 JSON Schema 输出合法结构 |
| 结果整合 | 根据工具返回结果生成自然语言回答 |
3.4 强化学习与偏好优化:学习“该不该调工具”
只会生成 JSON 还不够,模型还必须学会“什么时候不要调用工具”。
例如:
用户:你是谁?
这个问题通常不需要工具。
而:
用户:查一下我这个订单到哪了。
这个问题通常需要调用订单查询工具。
训练系统可以对模型行为进行反馈:
| 模型行为 | 反馈方向 |
|---|---|
| 该调用工具却直接编答案 | 负反馈 |
| 不该调用工具却乱调用 | 负反馈 |
| 工具选择错误 | 负反馈 |
| 参数填写错误 | 负反馈 |
| 工具结果回来后回答准确 | 正反馈 |
通过这类训练,模型不仅学会“会不会写调用格式”,还会学会“何时行动、何时直接回答”。
3.5 工具使用轨迹数据:学习多步 Agent 行为
Agent 任务往往不是一次工具调用就能完成,而是多步流程。例如:
用户:帮我安排明天下午去上海的行程,并提醒我出发。
模型可能需要:
1. 查询日历是否有空;
2. 查询交通时间;
3. 创建提醒;
4. 汇总安排。
这类训练数据通常表现为“轨迹”:
用户问题
→ 判断需要工具
→ 调用工具 A
→ 读取结果
→ 调用工具 B
→ 读取结果
→ 生成最终回答
这种轨迹数据让模型学会把推理和行动交替进行,也就是 Agent 常见的“Reasoning + Acting”模式。
3.6 自监督和合成数据:扩展工具使用能力
除了人工标注,还可以通过模型自动生成候选工具调用,再用规则、执行结果或评价器筛选高质量样本。
基本流程是:
普通文本
→ 模型尝试插入 API 调用
→ 执行 API
→ 判断工具结果是否让后续预测更好
→ 保留有效样本
→ 继续训练模型
这种方法可以降低人工标注成本,让模型在更多工具场景下学习调用能力。
3.7 推理阶段:模型读取当前工具说明,而不是更新权重
当开发者在 Agent 中注册一个新工具时,例如:
{
"name": "search_product",
"description": "根据关键词搜索商品",
"parameters": {
"type": "object",
"properties": {
"keyword": { "type": "string" },
"price_min": { "type": "number" },
"price_max": { "type": "number" }
}
}
}
模型的参数权重并不会因此改变。它只是把这段工具说明作为上下文读取,然后临时判断:
这个工具是干什么的?
用户问题是否需要它?
需要填哪些参数?
用户是否已经提供了这些参数?
因此需要区分:
| 阶段 | 发生了什么 |
|---|---|
| 训练阶段 | 模型学会如何理解工具说明、如何生成工具调用 |
| 推理阶段 | 模型根据当前上下文中提供的工具说明进行临时调用决策 |
4. 综合架构图
5. 开发实践建议
5.1 工具描述要清晰
工具的 description 不要只写“查询信息”,而应写清楚适用场景。例如:
{
"name": "get_order_status",
"description": "根据订单号查询用户订单的物流状态、发货状态和预计送达时间"
}
这样模型更容易判断什么时候该调用该工具。
5.2 参数设计要稳定
建议使用明确、可验证的参数类型:
{
"order_id": { "type": "string" },
"date": { "type": "string", "description": "格式为 YYYY-MM-DD" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
}
避免参数名过于模糊,例如 value、info、data。
5.3 后端必须做校验和安全控制
模型输出的 function-call 不能被无条件信任。后端应当:
- 校验工具名是否在白名单中;
- 校验参数类型和必填字段;
- 控制权限和用户身份;
- 对高风险操作增加确认环节;
- 处理工具异常和超时;
- 避免把敏感信息直接暴露给模型或用户。
5.4 工具结果要适度压缩
工具返回的数据可能很长,例如数据库查询结果、搜索结果、日志结果等。直接把大量原始数据塞回模型可能导致上下文浪费和错误理解。
更好的做法是:
工具原始结果 → 后端过滤 / 排序 / 摘要 → 模型可读结果 → 最终回答
6. 结论
Function-Calling 是 AI-Agent 从“语言生成系统”走向“可执行任务系统”的关键机制。
它解决了两个核心问题:
- 工具如何被模型理解: 通过工具名称、自然语言描述、参数 Schema 和约束,把外部工具能力转化为模型可读的结构化接口。
- 模型如何学会调用工具: 通过预训练、监督微调、偏好优化、工具轨迹数据和合成数据,让模型学会从自然语言任务中判断工具需求、选择工具、生成参数并整合结果。
最终,Function-Calling 的本质可以概括为:
训练阶段:模型学会“如何把语言任务转成结构化动作”。
推理阶段:模型读取“当前有哪些工具”,并生成可执行的调用请求。
执行阶段:Agent 框架或后端真正运行工具,并把结果回填给模型。
换句话说,大模型是“前台调度员”,Function-Calling 是“派单系统”,外部工具才是真正执行任务的“业务部门”。
7. 参考阅读
- OpenAI Developers:Function Calling / Tool Calling 官方文档。
- Yao et al. (2022). ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629.
- Schick et al. (2023). Toolformer: Language Models Can Teach Themselves to Use Tools. arXiv:2302.04761.
- Patil et al. (2023). Gorilla: Large Language Model Connected with Massive APIs. arXiv:2305.15334.
更多推荐

所有评论(0)