结构化输出与推理模型
两个补丁主题,都是「模型行为控制」这一层: 结构化输出让模型的话能被程序读懂;推理模型让模型在难题上多想一会儿。
一、结构化输出:三种实现路径
| 方式 | 原理 | 可靠性 | 成本 |
|---|---|---|---|
| Prompt 要求 + 后处理 | 提示里写「只输出 JSON」 | 低(会带废话、少字段) | 低 |
| JSON Mode | 厂商保证输出是合法 JSON | 中(合法但不一定合你的 schema) | 低 |
| Schema 约束(结构化输出) | 按 JSON Schema 约束解码 | 高 | 低(新版基本无损耗) |
结论:能用 schema 约束就用,别靠提示词祈祷。
js
// 伪代码:带 schema 的调用
const res = await client.responses.create({
model: "gpt-4.1",
response_format: {
type: "json_schema",
json_schema: {
name: "order_result",
strict: true,
schema: {
type: "object",
properties: {
status: { type: "string", enum: ["ok", "rejected"] },
reason: { type: "string" },
items: { type: "array", items: { type: "string" } },
},
required: ["status", "reason"],
additionalProperties: false,
},
},
},
input: "把这段对话抽成订单结果",
})// 伪代码:带 schema 的调用
const res = await client.responses.create({
model: "gpt-4.1",
response_format: {
type: "json_schema",
json_schema: {
name: "order_result",
strict: true,
schema: {
type: "object",
properties: {
status: { type: "string", enum: ["ok", "rejected"] },
reason: { type: "string" },
items: { type: "array", items: { type: "string" } },
},
required: ["status", "reason"],
additionalProperties: false,
},
},
},
input: "把这段对话抽成订单结果",
})为什么「约束解码」能做到高可靠
模型每一步只允许采样符合 schema 的 token(例如枚举字段只能出枚举值)。所以不是「生成完再修」,而是从头就不会生成非法结构。
结构化的四个实践要点
- 给字段限制取值(enum / 数值区间 / 字符串长度),比
type: string更有约束力; additionalProperties: false,防止模型自己加字段;- 必填字段不要太多,字段越少越稳;嵌套别超过 3 层;
- 仍要校验:拿到后跑一次 schema 验证(如 zod/ajv),失败时走重试并附上错误信息,而不是直接崩。
js
// 校验 + 一次修复重试
let parsed = schema.safeParse(raw)
if (!parsed.success) {
const retry = await call({
input: `你的输出不符合 schema,错误:${parsed.error.message}\n请重新输出。`,
})
parsed = schema.safeParse(retry)
}// 校验 + 一次修复重试
let parsed = schema.safeParse(raw)
if (!parsed.success) {
const retry = await call({
input: `你的输出不符合 schema,错误:${parsed.error.message}\n请重新输出。`,
})
parsed = schema.safeParse(retry)
}和函数调用(工具)的关系
| 结构化输出 | 函数调用 | |
|---|---|---|
| 目标 | 拿数据 | 触发动作 |
| 谁执行 | 你的程序 | 你的程序(模型只提议) |
| 失败后果 | 解析失败 | 可能产生副作用 |
两者参数都用 schema 描述,但函数调用要额外做「参数校验 + 权限 + 二次确认」(见 02 AI 应用安全与合规)。
二、推理模型(o1 / R1 这一类)
它和普通模型的区别
普通模型「一次生成即输出」;推理模型在输出前会生成一段内部思考(test-time compute)—— 相当于「多想几步再答」。
| 普通模型 | 推理模型 | |
|---|---|---|
| 延迟 | 快 | 慢(思考要时间) |
| 成本 | 低 | 高(思考 token 也计费) |
| 擅长 | 写作、抽取、格式转换、常识问答 | 数学、逻辑、代码调试、多约束规划 |
| 不擅长 | 复杂多步推理 | 简单任务(浪费) |
什么时候该用
| 场景 | 用推理模型吗 |
|---|---|
| 数学/算法题、复杂 SQL | ✅ |
| 多约束的排班、规则组合 | ✅ |
| 代码 bug 定位(需要多步假设) | ✅ |
| 文本改写、摘要、抽取 | ❌ 普通模型更快更便宜 |
| 高频简单问答 | ❌ |
工程注意点
- 别把推理模型放进「流式打字」体验:思考阶段没有可见输出,用户会以为卡住 → 要有「正在思考」的显式状态;
- 思考内容不要直接暴露给用户(可能包含中间错误假设),需要的话只展示摘要;
- temperature 通常不建议调高(推理模型对采样更敏感);
- 成本按「思考 + 输出」双份算,评估时按最坏情况估预算;
- 同一任务先试普通模型,跑不通再升级推理模型 —— 否则成本翻几倍。
三、两者的结合:让推理模型输出结构化
推理模型思考 → 输出 JSON(schema 约束)推理模型思考 → 输出 JSON(schema 约束)注意:部分推理模型对「强制 JSON」支持较弱,容易在思考后带上解释性文字。稳妥做法:
- 用支持的
response_format; - 或让它输出「纯 JSON 代码块」,再抽取代码块内容;
- 仍要 schema 校验 + 重试兜底。
四、速查
| 问题 | 答案 |
|---|---|
| 结构化输出最可靠的方式 | JSON Schema 约束解码(不是提示词) |
| JSON Mode 和 schema 约束的区别 | 前者只保证合法 JSON,后者保证符合你的结构 |
| 拿到 JSON 后还要做什么 | schema 校验,失败带错误信息重试一次 |
| additionalProperties 为什么要 false | 防止模型自己加字段 |
| 推理模型贵在哪 | 思考 token 也计费,且延迟高 |
| 什么任务该用推理模型 | 数学、逻辑、多约束规划、复杂调试 |
| 什么任务不该用 | 摘要、改写、抽取、高频简单问答 |
| 推理模型怎么配 UI | 显式「思考中」状态,别让它像卡住 |
Cao Note