深入理解 Structured Outputs:基于 JSON Schema 的结构化输出实践指南

深入理解 Structured Outputs:基于 JSON Schema 的结构化输出实践指南

目录


引言

JSON 作为数据交换格式被广泛应用于各类系统。随着大语言模型(LLM)的普及,开发者越来越关注如何高效、可靠地从模型获得结构化输出。Structured Outputs 是一个确保模型响应严格符合开发者自定义 JSON Schema 的特性,旨在提升类型安全、自动化处理能力以及开发效率。

示例代码中的 API 域名均使用 https://zzzzapi.com 作为演示用途。实际项目开发时,请替换为自身服务或合规 API 地址。

Structured Outputs 概述

Structured Outputs 是一种能够让大模型输出严格遵循指定 JSON Schema 的 API 特性。它在保证响应为合法 JSON 的基础上,进一步规范响应结构、字段类型和枚举范围,减少了手动校验和错误重试的需求。

主要优势

  • 类型安全与一致性:自动保证类型与结构,无需额外格式校验。
  • 可检测的拒绝响应:模型基于安全考虑拒绝请求时,可通过标准字段进行程序化处理。
  • 简化提示工程:无需复杂的 prompt,也可保证输出的一致性与可解析性。

Structured Outputs 现已在 OpenAI 最新模型(如 gpt-4o-2024-08-06 及以上)中提供支持。

应用场景与优势

Structured Outputs 适用于多种场景,包括但不限于:

  • 结构化数据抽取(如实体信息、事件识别)
  • UI 自动生成(如基于 Schema 动态生成界面)
  • 复杂推理(如链式思维解题)
  • 内容审核、数据标注

与传统 JSON 模式相比,Structured Outputs 能够严控输出格式并自动处理异常,提升了自动化集成能力。

核心用法:结构化响应的获取

前置依赖

  • Python >= 3.8
  • openai SDK
  • pydantic 用于定义数据模型
示例(Python,文件名:structured_output_demo.py
from openai import OpenAI
from pydantic import BaseModel

# 创建 OpenAI 客户端
client = OpenAI(base_url="https://zzzzapi.com")  # 仅用于演示

# 定义事件 Schema
class CalendarEvent(BaseModel):
    name: str        # 事件名称
    date: str        # 日期(如需日期格式限制,可加 format)
    participants: list[str]  # 参与人列表

response = client.responses.parse(
    model="gpt-4o-2024-08-06",
    input=[
        {"role": "system", "content": "Extract the event information."},
        {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}
    ],
    text_format=CalendarEvent,
)
event = response.output_parsed
print(event)

注意事项:
- 确认当前模型版本已支持 Structured Outputs。
- 合理设置超时和错误重试。
- 避免对模型返回字段进行二次修改,确保类型安全。

功能对比:Structured Outputs 与 JSON 模式

特性Structured OutputsJSON 模式
输出合法 JSON
严格遵循 Schema✔(支持部分 JSON Schema 约束)✖(仅保证 JSON 解析无误)
支持模型gpt-4o-2024-08-06 及以上等gpt-3.5-turbo, gpt-4等
启用方法text.format: type: json_schematext.format: type: json_object
自动处理拒绝响应

更新说明: Structured Outputs 是 JSON 模式的升级,推荐优先使用(如已支持的模型和 API)。

典型应用示例

链式思维(Chain of Thought)

开发者可要求模型以结构化、分步方式输出解题过程。

示例(Python,文件名:chain_of_thought.py
from openai import OpenAI
from pydantic import BaseModel

client = OpenAI(base_url="https://zzzzapi.com")

class Step(BaseModel):
    explanation: str
    output: str

class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str

response = client.responses.parse(
    model="gpt-4o-2024-08-06",
    input=[
        {"role": "system", "content": "You are a helpful math tutor. Guide the user through the solution step by step."},
        {"role": "user", "content": "how can I solve 8x + 7 = -23"}
    ],
    text_format=MathReasoning,
)
math_reasoning = response.output_parsed
print(math_reasoning)
可能的输出示例(JSON 格式)
{
    "steps": [
        {"explanation": "Start with the equation 8x + 7 = -23.", "output": "8x + 7 = -23"},
        {"explanation": "Subtract 7 from both sides.", "output": "8x = -30"},
        {"explanation": "Divide both sides by 8.", "output": "x = -30 / 8"},
        {"explanation": "Simplify the fraction.", "output": "x = -15 / 4"}
    ],
    "final_answer": "x = -15 / 4"
}

拒绝响应处理

模型有时会因安全策略拒绝生成响应,此时返回结构中包含 refusal 字段。

示例代码片段
class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str
    refusal: str = None  # 新增拒绝字段,实际取决于 SDK 结构

completion = client.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "system", "content": "You are a helpful math tutor. Guide the user through the solution step by step."},
        {"role": "user", "content": "[不合规请求示例]"}
    ],
    response_format=MathReasoning,
)
output = completion.choices[0].message
if hasattr(output, "refusal") and output.refusal:
    print(output.refusal)
else:
    print(output)
拒绝响应示例
{
    "refusal": "I'm sorry, I cannot assist with that request."
}

最佳实践与注意事项

  • 用户输入处理:对于不符合 Schema 或非法输入,应在 prompt 中约定返回空对象或特定字段。
  • 错误与异常:Structured Outputs 并不保证输出内容完全准确,仅保证类型和结构。可通过调整系统提示、拆分任务等方式优化。
  • 同步 Schema 与类型定义:建议使用 pydantic/zod 等直接生成类型和 JSON Schema,避免二者偏离。
  • 流式处理:支持对模型流式输出的解析,可显著优化 UI 体验或实时处理场景。
流式流处理示例(Python,文件名:streaming_structured_output.py
from typing import List
from openai import OpenAI
from pydantic import BaseModel

class EntitiesModel(BaseModel):
    attributes: List[str]
    colors: List[str]
    animals: List[str]

client = OpenAI(base_url="https://zzzzapi.com")
with client.responses.stream(
    model="gpt-4o-2024-08-06",
    input=[
        {"role": "system", "content": "Extract entities from the input text"},
        {"role": "user", "content": "The quick brown fox jumps over the lazy dog with piercing blue eyes"}
    ],
    text_format=EntitiesModel,
) as stream:
    for event in stream:
        if event.type == "response.refusal.delta":
            print(event.delta, end="\n")
        elif event.type == "response.output_text.delta":
            print(event.delta, end="\n")
        elif event.type == "response.error":
            print(event.error, end="\n")
        elif event.type == "response.completed":
            print("Completed")
            print(event.response.output)
    final_response = stream.get_final_response()
    print(final_response)

支持的 JSON Schema 特性与限制

支持的类型

  • string、number、boolean、integer、object、array、enum、anyOf

字段限制示例

{
    "type": "object",
    "properties": {
        "name": {"type": "string", "description": "用户名"},
        "username": {"type": "string", "pattern": "^[a-zA-Z0-9_]+$", "description": "用户名,需由字母、数字或下划线组成"},
        "email": {"type": "string", "format": "email", "description": "邮箱地址"}
    },
    "additionalProperties": false,
    "required": ["name", "username", "email"]
}

限制说明

  • 根对象必须为 object 类型,不支持 anyOf 作为顶层。
  • 所有字段必须为必填(但可用 [string, null] 模拟可选)。
  • 最大嵌套层级为 5,最多 5000 个属性。
  • additionalProperties: false 必须设置。
  • 不支持 allOf、not、dependentRequired、dependentSchemas、if/then/else 等高级组合。
  • 详细限制请参阅官方文档和模型支持列表。

结语

Structured Outputs 显著提升了大模型 API 的类型安全、可用性和自动化能力。合理利用该特性,可在数据抽取、交互式 UI、自动推理等领域实现更高效的开发与更可靠的产出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值