OpenAI 结构化输出教程:让模型稳定返回 JSON
OpenAI 结构化输出教程:用 Structured Outputs 和 JSON Schema 约束大模型的返回格式,告别解析失败和格式混乱,让 AI 输出可靠地接入你的应用。
这篇教程适合你吗
你用 OpenAI API 返回 JSON 时,是否遇到过:字段名拼错了、多了个字段、少了个字段、类型不对?生产环境中这些问题会导致解析崩溃。结构化输出就是来解决这个的。
不适合:没用过 OpenAI API 的读者。建议先看 OpenAI API 教程。 最终产物:能让大模型严格按照你定义的 JSON Schema 返回数据的完整代码。环境假设
- Python 3.9+
- OpenAI API Key
- openai SDK 1.40+
> 合规提醒:使用 OpenAI 等海外 API 服务时,请遵守所在地法律法规和服务条款。如遇网络连接不稳定,可参考我们的海外 AI 工具使用指南。
为什么需要结构化输出
传统方式让模型返回 JSON,靠的是 prompt 里说「请返回 JSON 格式」。但模型可能会:
- 多返回一个你没定义的字段
- 少返回一个你期望的字段
- 把数字写成字符串
- 把枚举值拼错
你的代码要写大量防御性解析逻辑。结构化输出从根源上解决这个问题。
第一步:定义 Pydantic 模型
用 Python 的 Pydantic 定义你期望的输出结构:
from pydantic import BaseModel
class MovieReview(BaseModel):
title: str
year: int
rating: float # 1-10
genre: str
summary: str
recommended: bool
第二步:使用结构化输出
from openai import OpenAI
client = OpenAI()
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个影评助手,根据用户描述返回结构化的影评。"},
{"role": "user", "content": "帮我分析一下《盗梦空间》这部电影"}
],
response_format=MovieReview
)
review = response.choices[0].message.parsed
print(f"电影:{review.title}")
print(f"评分:{review.rating}/10")
print(f"推荐:{'是' if review.recommended else '否'}")
关键点:
response_format直接传 Pydantic 模型- 使用
client.beta.chat.completions.parse()而不是.create() - 返回的
parsed属性直接是 Pydantic 对象,类型安全
第三步:使用枚举约束
限制模型只能从预定义选项中选择:
from enum import Enum
class Sentiment(str, Enum):
positive = "positive"
negative = "negative"
neutral = "neutral"
class SentimentResult(BaseModel):
sentiment: Sentiment
confidence: float # 0-1
keywords: list[str]
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "user", "content": "这个产品太好用了,强烈推荐!"}
],
response_format=SentimentResult
)
result = response.choices[0].message.parsed
# sentiment 只会是 positive/negative/neutral 三个值之一
第四步:嵌套结构
支持复杂的嵌套 JSON:
class Experience(BaseModel):
company: str
role: str
years: int
class Resume(BaseModel):
name: str
email: str
skills: list[str]
experience: list[Experience]
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "user", "content": "张三,zhangsan@email.com,会 Python 和机器学习,在百度做了 3 年算法工程师,后来在字节做了 2 年技术负责人"}
],
response_format=Resume
)
与 Function Calling 结合
结构化输出也可以用在 Function Calling 的参数中:
tools = [{
"type": "function",
"function": {
"name": "create_task",
"description": "创建一个待办任务",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
"due_date": {"type": "string", "description": "格式 YYYY-MM-DD"}
},
"required": ["title", "priority"]
},
"strict": True # 启用结构化输出约束
}
}]
加了 "strict": True 后,工具调用的参数也会严格符合 Schema。
最佳实践
Schema 设计原则
- 字段尽量少:只定义真正需要的字段,减少模型负担
- 用 enum 约束:能用枚举就不用自由文本
- description 要写:每个字段加 description,帮助模型理解含义
- 类型要准确:
int不要用string,减少后处理
常见坑
- 不要在 Schema 里用
anyOf:某些模型对复杂联合类型支持不好 - list 元素也要定义类型:
list[str]比list好 - float 精度:模型返回的浮点数可能精度很高,必要时在代码里 round
常见问题与排错
报错 Schema 不支持
原因:某些 JSON Schema 特性在 Structured Outputs 中不支持。 解决:简化 Schema,避免anyOf、oneOf、not 等复杂逻辑。参考 OpenAI 官方文档中的支持列表。
模型忽略某些字段
原因:字段的 description 不够清晰。 解决:在 description 中明确说明「必须填写」,并给出示例值。进阶学习
- 想了解工具调用?看 Function Calling 教程
- 想了解 Claude 的工具调用?看 Claude Tool Use 教程
- 想了解大模型如何理解工具?看 AI 工具调用是什么
总结
- Structured Outputs 保证模型严格按 Schema 返回 JSON
- 用 Pydantic 定义结构,类型安全且易用
- 支持枚举、嵌套、列表等复杂结构
- 和 Function Calling 结合使用效果更好
---
本文最后更新于 2026-07-27。代码示例基于当前常见版本,请根据最新 API 文档调整。保障 API 调用稳定性
调用 OpenAI、Anthropic 等海外 API 时,网络波动可能导致请求超时或失败。稳定的网络环境有助于提升开发效率。
⚠️ 请遵守所在地的法律法规和服务条款。使用 AI API 时请遵守各平台的使用政策。
了解安全上网方案 →常见问题
相关推荐
OpenAI API 调用教程:Python 集成指南
OpenAI API 怎么用?本文从申请 API Key 到 Python 调用,手把手教你使用 GPT-4o、DALL-E、Whisper 等 OpenAI API,含完整代码和最佳实践。
Function Calling 教程:用工具调用搭建可执行 AI 助手
Function Calling 教程:从工具定义到多轮调用,手把手教你让大模型调用外部函数、查询数据库和执行操作,搭建真正能做事的 AI 助手。
Claude Tool Use 教程:从工具定义到多轮调用
Claude Tool Use 教程:手把手教你用 Anthropic Claude API 实现工具调用,从工具定义、单轮调用到多轮对话中的工具使用,含完整 Python 代码示例。
AI 工具调用是什么?Function Calling、插件和 API 怎么区分
AI 工具调用是什么?解释 Function Calling 的原理、与插件和 API 调用的区别,以及工具调用在 AI Agent 中的作用。
获取更多 AI 内容
订阅更新,第一时间获取新教程和工具推荐。