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
例如,真实业务中可能有一个天气查询函数:
defget_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"}也见过大量类似函数说明:
defsearch_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.
