跳转到正文
技术教程·

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,避免 anyOfoneOfnot 等复杂逻辑。参考 OpenAI 官方文档中的支持列表。

模型忽略某些字段

原因:字段的 description 不够清晰。 解决:在 description 中明确说明「必须填写」,并给出示例值。

进阶学习

总结

  • Structured Outputs 保证模型严格按 Schema 返回 JSON
  • 用 Pydantic 定义结构,类型安全且易用
  • 支持枚举、嵌套、列表等复杂结构
  • 和 Function Calling 结合使用效果更好

---

本文最后更新于 2026-07-27。代码示例基于当前常见版本,请根据最新 API 文档调整。

保障 API 调用稳定性

调用 OpenAI、Anthropic 等海外 API 时,网络波动可能导致请求超时或失败。稳定的网络环境有助于提升开发效率。

⚠️ 请遵守所在地的法律法规和服务条款。使用 AI API 时请遵守各平台的使用政策。

了解安全上网方案 →

常见问题

相关推荐

获取更多 AI 内容

订阅更新,第一时间获取新教程和工具推荐。