30秒快速回答: 结构化输出(Structured Outputs)是一类让大模型严格按预定义格式(通常是 JSON 对象)返回结果的技术,由模型厂商(OpenAI、Anthropic、Google 等)在 API 层面原生保证”输出 100% 符合你的 JSON Schema”。它解决的痛点是:普通 LLM 输出是自由文本,一旦用于程序对接,格式稍微偏差(多一个逗号、字段名变了)程序就崩溃。核心价值一句话:让 AI 的输出像数据库记录一样规范,程序拿来就能用,不解析、不报错。
一、为什么需要结构化输出?——AI 输出的”原生困境”
大模型的本质是”预测下一个 token”,天生输出的是自由文本。当你让它”返回 JSON”时,它可能:
// 模型经常返回的样子 → 程序直接崩溃
{"name": "张三", "age": "28", "courses": ["Python", "AI", "数据库",]}
// 多了一个逗号
| 常见问题 | 具体表现 | 后果 |
|---|---|---|
| 格式不完整 | 省略结束括号、截断在中间 | JSON 解析直接抛异常 |
| 类型不可靠 | 年龄返回 "28"(字符串)而非 28(数字) |
程序强类型校验失败 |
| 字段名漂移 | 约定 user_name,返回 username 或 name |
按字段取值拿不到数据 |
| 夹带噪音 | 前后缀”好的,以下是结果:```json” | 需要额外清洗 |
传统方案(”提示词里多加一句’只输出 JSON’“)只能降低概率,不能根治。Structured Outputs 的价值在于:把”格式保证”从模型自觉,变成 API 层面的硬性约束——返回的内容在服务端就用约束解码器保证合法,非法就直接拒发或强制修正。
二、三种实现方式:从”软约束”到”硬保证”
| 方案 | 原理 | 可靠性 | 适用场景 |
|---|---|---|---|
| 提示词约束 | Prompt 里写”必须返回 JSON” | 低(约 60-80%) | 快速原型、人读为主 |
| Function Calling / JSON Schema 校验 | 把输出约束声明为工具参数,调用后前端再校验重试 | 中(约 90-95%) | 兼容老模型、已有业务 |
| 原生 Structured Outputs | API 层内置约束解码(constrained decoding),逐 token 保证合法 | 高(99.9%+) | 生产环境、程序对接 |
关键区别在第三档:原生模式下,模型生成每个 token 时只允许产生”下一跳依然是合法 JSON”的候选,从根本上杜绝语法错误——这也是 2026 年主流厂商的做法(OpenAI response_format、Anthropic Tool Use 强约束、Gemini responseSchema、本地 Outlines 的 JSON Schema Grammar)。
三、实战:三大平台 + 本地开源,怎么写代码
1. OpenAI / 兼容接口:response_format + JSON Schema
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5",
response_format={"type": "json_schema", "json_schema": {
"name": "summary_result",
"strict": True,
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"rating": {"type": "number"},
"tags": {"type": "array", "items": {"type": "string"}}
},
"required": ["title", "rating", "tags"],
"additionalProperties": False
}
}},
messages=[{"role": "user", "content": "用 5 星制点评这篇教程"}]
)
data = json.loads(response.choices[0].message.content)
print(data["rating"] + 1) # 可靠:less是数字
strict: True 表示严格模式——要求所有字段都在 properties 中声明、required 全部列出、禁止额外字段,保证每个返回对象都精确匹配 Schema。
2. Anthropic:把输出约束声明为 Tool
import anthropic
c = anthropic.Anthropic()
resp = c.messages.create(
model="claude-opus",
tools=[{
"name": "extract_contact",
"description": "从文本中抽取联系方式",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"emails": {"type": "array", "items": {"type": "string"}}
},
"required": ["name", "emails"]
}
}],
messages=[{"role": "user", "content": "帮我提取:张三,邮箱 a@b.com 和 c@d.com"}]
)
# 读取 tool_use 块,直接拿到结构化参数
print(resp.content[-1].input) # {'name': '张三', 'emails': ['a@b.com', 'c@d.com']}
3. Google Gemini:responseSchema(最直观)
from google import genai
client = genai.Client()
resp = client.models.generate_content(
model="gemini-2.5-pro",
contents="给这篇文章生成 3 个 SEO 标题",
config={"response_mime_type": "application/json",
"response_schema": {"type": "ARRAY",
"items": {"type": "STRING"}}}
)
print(resp.text) # 直接是合法 JSON 数组
4. 本地开源模型:Outlines / Pydantic(结构化解码)
本地部署同样可以做到”硬保证”,代表工具是 Outlines(约束解码)和 Pydantic 2.x(类型定义 + 校验):
import outlines
# 用 JSON Schema 约束本地 vLLM / llama.cpp 的生成
generator = outlines.generate.json(model,
'{"type": "object", "properties": {"city": {"type": "string"}, "temp": {"type": "number"}}}')
result = generator("北京的今日气温?")
print(result) # {'city': '北京', 'temp': 32.5} —— 同步生成时就保证合法
from pydantic import BaseModel, Field
from openai import OpenAI
class Order(BaseModel):
id: int
amount: float = Field(gt=0)
client = OpenAI()
# 直接把 Pydantic 模型传进去,返回即强类型对象
order: Order = client.beta.chat.completions.parse(
model="gpt-5",
messages=[{"role": "user", "content": "订单:编号 1001,金额 99.9 元"}],
response_format=Order,
)
print(order.id, order.amount) # 1001 99.9 —— 无需手写 json.loads
四、踩坑与最佳实践:6 条落地清单
- Schema 越窄越稳:字段必须全部声明,能不用自由文本数组就不用;
additionalProperties: false+required全列,杜绝模型”自由发挥”。 - 区分”语法合法”与”语义正确”:Structured Outputs 只保证格式,不保证内容正确——返回的 JSON 合法但含义可能是幻觉,语义校验仍需业务层兜底。
- 务必处理拒答(refusal):OpenAI 等平台在模型拒绝时返回
message.refusal,字段为空,程序要单独判空而不是直接解析,否则静默失败。 - 不要与流式输出打架:部分平台 Strict 模式与
stream=True不兼容,生产环境要先验证组合可用性;本地 Outlines/SGLang 对解码有额外速度开销(通常 <20%),可接受。 - Schema 变更成本高:两套 Schema 之间的字段迁移会影响下游全部消费方,上线前用版本化(
v1.0)管理。 - 组合技更优:Structured Outputs 定格式 + Function Calling 定行为 + 业务端再做一次 Pydantic 二次校验,三层防线几乎不会出错。
总结
结构化输出解决的是 AI 落地中最实际的一环:让不可预测的自由文本,变成程序可直连的强类型数据。记住三句话:
- 提示词约束是”软”的,原生 Structured Outputs 是”硬”的——生产环境一律用硬约束;
- 格式有保证 ≠ 内容没幻觉——语义校验必须留在业务层;
- 企业级标配是”结构化输出 + 函数调用 + 二次校验”三层组合。
延伸阅读:
- 想理解结构化输出的应用前置(让 AI 调用外部工具),请看本站《怎么用 Function Calling?》(guide-28);
- 想了解如何让 Agent 组合工具完成复杂任务,请看《什么是 A2A 协议?Agent 之间的 TCP/IP 标准》(guide-33)与《怎么搭建 AI 工作流?》(guide-27);
- 想防止输出内容本身不可靠,请看《什么是 AI 幻觉?》(guide-88)。