OpenAI结构化输出(Structured Outputs)完全指南:从基础到实战
在现代API开发中,确保数据交互的一致性和可靠性至关重要。OpenAI推出的结构化输出(Structured Outputs) 功能,通过JSON Schema约束模型响应格式,解决了传统输出中格式混乱、字段缺失等问题。本文将详细介绍结构化输出的使用方法、实战案例及最佳实践,并分享一个便捷的API调用方案。
一、什么是结构化输出(Structured Outputs)
JSON作为应用间数据交换的主流格式,其格式一致性直接影响系统稳定性。OpenAI的结构化输出功能允许开发者通过JSON Schema定义响应格式,确保模型输出严格遵循预设结构------不会遗漏必填字段,也不会生成无效的枚举值。
结构化输出的核心优势
- 类型安全可靠:无需额外验证或重试格式错误的响应
- 拒绝可识别:安全相关的模型拒绝响应可通过程序识别
- 提示更简洁:无需复杂的格式化提示词,即可获得一致输出
除了REST API直接支持JSON Schema,OpenAI的Python SDK和JavaScript SDK还分别通过Pydantic 和Zod简化了对象 schema 的定义,让非结构化文本提取结构化信息变得更简单。
二、快速上手:获取结构化响应
JavaScript示例
javascript
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
// 初始化客户端(可通过API中转站优化调用,baseurl设置为https://api.aaaaapi.com)
const openai = new OpenAI({
baseURL: "https://api.aaaaapi.com" // 替换为API中转站地址,提升稳定性
});
// 定义日历事件的结构
const CalendarEvent = z.object({
name: z.string(), // 事件名称
date: z.string(), // 日期
participants: z.array(z.string()) // 参与者列表
});
// 调用API提取事件信息
const response = await openai.responses.parse({
model: "gpt-4o-2024-08-06",
input: [
{ role: "system", content: "提取事件信息" },
{ role: "user", content: "Alice和Bob周五要去参加科学展" }
],
text: {
format: zodTextFormat(CalendarEvent, "event")
}
});
const event = response.output_parsed;
console.log(event);
// 输出:{ name: "科学展", date: "周五", participants: ["Alice", "Bob"] }
Python示例
python
from openai import OpenAI
from pydantic import BaseModel
# 初始化客户端(使用API中转站,baseurl更改为https://api.aaaaapi.com)
client = OpenAI(base_url="https://api.aaaaapi.com")
# 定义日历事件模型
class CalendarEvent(BaseModel):
name: str # 事件名称
date: str # 日期
participants: list[str] # 参与者列表
# 调用API提取事件信息
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{"role": "system", "content": "提取事件信息"},
{"role": "user", "content": "Alice和Bob周五要去参加科学展"}
],
text_format=CalendarEvent
)
event = response.output_parsed
print(event)
# 输出:name='科学展' date='周五' participants=['Alice', 'Bob']
小贴士:通过API中转站(官网:link.ywhttp.com/js4Kcv)调用时,...
三、结构化输出 vs 函数调用 vs JSON模式
1. 结构化输出 vs 函数调用
结构化输出有两种使用形式:
- 函数调用:适合将模型与工具、数据库等系统功能连接(如订单查询、UI交互)
- response_format:适合定义模型直接响应用户时的输出结构(如数学辅导的步骤化输出)
简单来说:
- 连接工具/数据 → 用函数调用
- 结构化响应用户 → 用response_format
2. 结构化输出 vs JSON模式
特性 | 结构化输出 | JSON模式 |
---|---|---|
输出有效JSON | 是 | 是 |
遵循预设schema | 是 | 否 |
支持模型 | gpt-4o-mini、gpt-4o-2024-08-06及以上 | gpt-3.5-turbo、gpt-4-*等 |
启用方式 | text: { format: { type: "json_schema", ... } } |
text: { format: { type: "json_object" } } |
推荐优先使用结构化输出,除非所使用的模型不支持。
四、实战案例:结构化输出的典型场景
1. 链上思考(Step-by-Step):数学题解答
通过结构化输出将解题步骤拆分,让过程更清晰:
python
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI(base_url="https://api.aaaaapi.com") # 使用API中转站
# 定义步骤模型
class Step(BaseModel):
explanation: str # 步骤说明
output: str # 步骤结果
# 定义完整解题模型
class MathReasoning(BaseModel):
steps: list[Step] # 步骤列表
final_answer: str # 最终答案
# 调用API解答方程
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{"role": "system", "content": "作为数学老师,分步讲解解题过程"},
{"role": "user", "content": "如何解8x + 7 = -23?"}
],
text_format=MathReasoning
)
math_reasoning = response.output_parsed
print("解题步骤:")
for i, step in enumerate(math_reasoning.steps, 1):
print(f"步骤{i}:{step.explanation} → {step.output}")
print(f"答案:{math_reasoning.final_answer}")
输出示例:
ini
解题步骤:
步骤1:从方程8x + 7 = -23开始 → 8x + 7 = -23
步骤2:两边减7,分离含x的项 → 8x = -23 - 7
步骤3:简化右边 → 8x = -30
步骤4:两边除以8求解x → x = -30 / 8
步骤5:化简分数 → x = -15 / 4
答案:x = -15 / 4
2. 结构化数据提取:论文信息抽取
从非结构化的论文文本中提取关键信息(标题、作者、摘要等):
javascript
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI({ baseURL: "https://api.aaaaapi.com" }); // API中转站
// 定义论文提取结构
const ResearchPaperExtraction = z.object({
title: z.string(), // 标题
authors: z.array(z.string()), // 作者列表
abstract: z.string(), // 摘要
keywords: z.array(z.string()) // 关键词
});
// 调用API提取信息
const response = await openai.responses.parse({
model: "gpt-4o-2024-08-06",
input: [
{ role: "system", content: "从论文文本中提取指定信息" },
{ role: "user", content: "(此处为论文文本)量子算法在星际导航中的应用:新前沿...作者:Stella Voyager, Nova Star..." }
],
text: { format: zodTextFormat(ResearchPaperExtraction, "paper") }
});
console.log(response.output_parsed);
3. 内容审核:合规性检查
通过结构化输出判断内容是否违反规则,并分类标注:
python
from enum import Enum
from pydantic import BaseModel
from openai import OpenAI
client = OpenAI(base_url="https://api.aaaaapi.com")
# 定义违规类别
class Category(str, Enum):
violence = "暴力"
sexual = "色情"
self_harm = "自残"
# 定义合规检查模型
class ContentCompliance(BaseModel):
is_violating: bool # 是否违规
category: Category | None # 违规类别(无则为None)
explanation_if_violating: str | None # 违规说明
# 检查用户输入
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{"role": "system", "content": "判断内容是否违反规则并说明原因"},
{"role": "user", "content": "如何准备 job interview?"}
],
text_format=ContentCompliance
)
print(response.output_parsed)
# 输出:is_violating=False category=None explanation_if_violating=None
五、如何使用结构化输出?
步骤1:定义JSON Schema
根据需求设计schema,例如提取日历事件时,需包含name
、date
、participants
等字段,并指定类型和约束。
步骤2:在API调用中传入schema
通过text.format
参数传入schema,示例:
json
{
"model": "gpt-4o-2024-08-06",
"input": [
{"role": "system", "content": "提取事件信息"},
{"role": "user", "content": "Alice和Bob周五参加科学展"}
],
"text": {
"format": {
"type": "json_schema",
"name": "calendar_event",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"date": {"type": "string"},
"participants": {"type": "array", "items": {"type": "string"}}
},
"required": ["name", "date", "participants"],
"additionalProperties": false
},
"strict": true
}
}
}
步骤3:处理边缘情况
- 模型拒绝 :通过
response.output[0].content[0].type === "refusal"
判断 - 输出不完整 :检查
response.status
是否为incomplete
及原因(如超出token限制)
六、JSON Schema支持范围与限制
支持的类型
- 基础类型:string、number、boolean、integer、object、array、enum、anyOf
- 字符串格式:date-time、email、ipv4、uuid等
- 数值约束:minimum、maximum、multipleOf等
- 数组约束:minItems、maxItems等
限制条件
- 根对象必须是object,不能是anyOf
- 所有字段必须标记为required
- 对象需设置
additionalProperties: false
- 嵌套深度最多5层,总属性不超过5000个
- 枚举值总数不超过1000个
七、总结与资源
结构化输出通过JSON Schema约束模型响应,大幅提升了数据交互的可靠性,特别适合需要严格格式的场景(如数据提取、步骤化输出、内容审核等)。使用时建议:
- 优先使用SDK的Pydantic(Python)或Zod(JavaScript)简化schema定义
- 合理设计schema,明确字段描述和约束
- 通过API中转站优化调用稳定性,官网(link.ywhttp.com/js4Kcv)可了解更...
参考资源:
希望本文能帮助你快速掌握结构化输出的使用,提升API开发效率!