Appearance
Tool、Function Calling 与 Structured Output
只把模型接口接通,系统通常还只是“能生成”。
但只要一进业务,后面很快就会冒出来两个很现实的需求:
- 让模型去查外部数据、调外部能力
- 让模型别再乱飘,稳定按结构返回结果
这时最常遇到的就是这 3 个词:
ToolFunction CallingStructured Output
它们经常一起出现,但不是同一层概念。
1. 把这 3 个词分开
把最外层分开:
Tool:系统里准备好的一个动作Function Calling:模型表达“我想调用哪个动作,参数是什么”Structured Output:模型按约定结构返回结果
把它们压成最短的一层关系,就是:
Tool是能力本身Function Calling是调用意图Structured Output是输出约束
如果这三层不先分开,后面很容易把“能调用工具”和“按 JSON 返回”混成一回事。
2. Tool 到底是什么
Tool 可以理解成:
应用提供给模型使用的一个具体动作入口。
它最适合承载的是清晰、边界明确的动作,例如:
- 查订单
- 查天气
- 搜文档
- 读文件
- 调内部接口
2.1 Tool 在项目里主要解决什么问题
模型本身能理解、能生成,但它不能直接:
- 查数据库
- 调你公司的内部系统
- 访问你的文件系统
- 执行真实业务动作
Tool 的价值就在这里:
把“模型想做某个动作”变成“系统里真的有一个动作可以执行”。
2.2 一个典型 Tool 长什么样
一个极简示意可以看成这样:
json
{
"name": "get_order_summary",
"description": "根据订单号查询订单状态和关键时间点",
"parameters": {
"type": "object",
"properties": {
"orderNo": { "type": "string" }
},
"required": ["orderNo"]
}
}这里最关键的不是 JSON 长什么样,而是它在表达 3 件事:
- 这个动作叫什么
- 它是做什么的
- 调它时需要什么参数
2.3 Tool 最容易踩的坑
最常见的问题有:
- 把一个 Tool 设计成完整业务流程
- 把底层能力裸暴露给模型
- 以为 Tool 越多系统越强
🌟 Tool 更适合表达一个清晰动作,不适合直接承载一整条复杂流程。流程编排通常应该放到 Workflow 或 Agent 那一层。
3. Function Calling 到底在干什么
当模型判断“只靠文本回答不够,需要外部能力”时,它不会自己直接去调数据库,而是先输出一个结构化调用意图。
例如:
json
{
"name": "get_order_summary",
"arguments": {
"orderNo": "A001"
}
}这一步最关键的不是执行,而是表达:
我现在需要哪个 Tool,参数应该是什么。
3.1 Function Calling 主要解决什么问题
它解决的是:
模型如何把“我要查外部信息”这件事稳定表达出来。
没有这一层,模型就只能在自然语言里模糊地说:
- “你去帮我查一下订单”
- “也许应该调用某个接口”
但系统很难从这种自由文本里稳定解析出真正的调用动作。
有了 Function Calling 之后,模型就能把调用意图收成更稳定的结构。
3.2 一条典型链路怎么走
mermaid
sequenceDiagram
participant U as 用户
participant A as 应用
participant M as 模型
participant T as Tool
U->>A: 查订单 A001
A->>M: 用户问题 + tools 描述
M-->>A: 调用 getOrder(orderNo=A001)
A->>T: 执行 Tool
T-->>A: 返回订单数据
A->>M: 追加 tool 结果
M-->>A: 生成最终回答这条线里要先分清两件事:
- 模型负责表达要不要调工具
- 应用负责真正执行工具
也就是说,Function Calling 不是“模型自己动手了”,而是“模型把调用意图说清楚了”。
3.3 Function Calling 最容易被误解成什么
最常见的误解是:
- 以为它等于工具本身
- 以为模型拿到 Tool 就一定会调用
- 以为调用意图出来之后执行就天然安全
这些都不太准。
是否真的执行、能不能执行、该不该执行,最后都还是应用系统负责。
4. Structured Output 又在干什么
有些场景并不需要模型调工具,只是希望它稳定返回一个结构。
例如:
- 分类结果
- 表单抽取
- 审核结论
- 风险评分
- 报告字段提取
这时更适合用的是 Structured Output。
例如:
json
{
"category": "refund",
"confidence": 0.92,
"reason": "用户主要在询问退款流程"
}它解决的问题不是“去做动作”,而是:
让模型别只返回一段自由文本,而是按约定结构把结果交出来。
4.1 Structured Output 在项目里为什么这么重要
因为只要输出要继续进入系统后续环节,例如:
- 存库
- 分流
- 审批
- 前端表单回填
自然语言就会变得很不稳。
系统真正需要的往往不是“说得像不像人”,而是:
- 字段有没有
- 结构稳不稳
- 能不能继续被程序消费
4.2 Structured Output 和 Function Calling 的区别
这两个词最容易混。
可以用一句话分开:
Function Calling更偏“我要调谁”Structured Output更偏“我要按什么结构返回”
前者强调调用意图,后者强调输出约束。
5. 这 3 者放在一起怎么配合
把它们放在同一条线上看,会更容易理解:
mermaid
flowchart LR
A[用户问题] --> B{是否需要外部能力}
B -- 否 --> C[Structured Output / 普通文本输出]
B -- 是 --> D[Function Calling]
D --> E[调用 Tool]
E --> F[回传结果]
F --> G[模型生成最终结果]这条线里:
Tool是能力入口Function Calling是调用表达Structured Output是结果约束
它们会一起出现,但并不总是一起出现。
例如:
- 分类任务可能只需要
Structured Output - 查订单任务通常会涉及
Tool + Function Calling
6. 真实项目里最容易踩的几个边界
6.1 不是所有结构化输出都是 Tool Calling
模型只要按 JSON 返回,就已经是结构化输出。
但只有当它在表达:
- 要调哪个工具
- 参数是什么
这才更接近 Function Calling。
6.2 不是有 Tool 就一定要调用
很多系统会给模型挂很多 Tool,但模型不一定每次都需要调用。
是否调用,本质上取决于:
- 当前问题能不能直接回答
- 外部数据是不是必须
- 调用成本和值不值得
6.3 调用意图不等于执行安全
模型能把调用意图表达出来,不代表执行就一定安全。
应用层通常还要继续负责:
- 参数校验
- 权限控制
- 风险动作拦截
- 幂等和审计
7. 一段更稳的总结
如果把这 3 个词压成一句话,可以记成:
Tool 解决“系统里有什么动作可以调”,Function Calling 解决“模型如何把调用意图表达清楚”,Structured Output 解决“模型怎么稳定地按结构返回结果”。它们经常一起出现,但分别站在能力、调用和输出这 3 个不同层次。