用大模型做「从非结构化文本里抽取结构化数据」是刚需:解析工单、抽取会议纪要、做分类标签……但模型输出 JSON 经常不守规矩——少字段、类型错、多嘴解释。OpenAI 的 Structured Outputs 就是为解决这个问题而生的:它让模型输出严格遵循你给的 JSON Schema,官方评测里 gpt-4o 的合规率达到 100%。
一、它和 JSON Mode 的区别
早前的 JSON Mode 只是「保证输出是合法 JSON」,并不保证符合你的字段结构。Structured Outputs 更进一步:用约束解码(constrained decoding)从工程层面强制模型只生成符合 schema 的 token,再配合对复杂 schema 的理解训练,做到确定性的结构合规。简单说——你定义结构,模型填内容,格式错误不再需要你兜底。
启用 Structured Outputs 时,schema 里的每个字段都必须写进 required,且根对象要设 additionalProperties: false。这是「严格模式(strict)」的硬要求,漏了会报错。
二、两种用法
Structured Outputs 提供两种入口:
- 函数调用(tools):在工具定义里设 strict: true,模型输出会匹配该工具的参数 schema;
- response_format:直接给 json_schema,适合「模型不是调工具、而是以结构化方式回答用户」的场景。
三、Python 实战示例
下面用 response_format 从一段会议记录里抽取行动项。注意三个字段都进了 required:
from openai import OpenAI
import json
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "从会议记录中提取行动项、截止日期和负责人。"},
{"role": "user", "content": "周一例会对齐了上线时间:张三负责登录页改版,9 月 30 日前完成;李四跟进压测,本周五交报告。"},
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "action_items",
"strict": True,
"schema": {
"type": "object",
"properties": {
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {"type": "string"},
"due_date": {"type": ["string", "null"]},
"owner": {"type": ["string", "null"]},
},
"required": ["description", "due_date", "owner"],
"additionalProperties": False,
},
}
},
"required": ["action_items"],
"additionalProperties": False,
},
},
},
)
data = json.loads(resp.choices[0].message.content)
print(data)
模型拒绝回答时怎么办
当请求触碰安全策略,模型不会硬凑 schema,而是返回一个 refusal 字段。你应当在代码里判断 message.refusal:为空且 finish_reason 正常,才认为输出可靠可用。这样能干净地区分「被拒答」和「正常结构化输出」。
四、什么时候该用它
只要你的下游要直接消费模型输出(写库、调接口、渲染 UI),就该上 Structured Outputs。它把「反复重试 + 手写容错」的脏活变成确定性保证。但要注意:strict 模式目前对 schema 有约束(如不支持某些组合类型),复杂嵌套结构建议先在小样本上验证。
阅读 OpenAI 官方 Structured Outputs 文档常见问题
Structured Outputs 支持哪些模型?
函数调用形式支持所有支持 tools 的模型;response_format 的 json_schema 形式主要面向 gpt-4o 及更新系列,老模型请查官方文档确认。
100% 合规是绝对的吗?
在 strict 模式下、且响应未被中途截断(finish_reason 正常、无 refusal)时成立;一旦模型拒答,返回的是 refusal 而非 schema 数据。
和函数调用怎么选?
让模型「决定调哪个工具」用函数调用;让模型「以固定结构回答」用 response_format。两者都能开 strict。









评论 (0)