深入理解 Structured Outputs:基于 JSON Schema 的結構化輸出實踐指南
目錄
- 引言
- Structured Outputs 概述
- 應用場景與優勢
- 核心用法:結構化響應的獲取
- 功能對比:Structured Outputs 與 JSON 模式
- 典型應用示例
- 鏈式思維(Chain of Thought)
- 拒絕響應處理
- 最佳實踐與注意事項
- 支持的 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
SDKpydantic
用于定義數據模型
示例(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 Outputs | JSON 模式 |
---|---|---|
輸出合法 JSON | ? | ? |
嚴格遵循 Schema | ?(支持部分 JSON Schema 約束) | ?(僅保證 JSON 解析無誤) |
支持模型 | gpt-4o-2024-08-06 及以上等 | gpt-3.5-turbo, gpt-4等 |
啟用方法 | text.format: type: json_schema | text.format: type: json_object |
自動處理拒絕響應 | ? | ? |
更新說明: Structured Outputs 是 JSON 模式的升級,推薦優先使用(如已支持的模型和 API)。
典型應用示例
鏈式思維(Chain of Thought)
開發者可要求模型以結構化、分步方式輸出解題過程。
示例(Python,文件名:chain_of_thought.py
)
from openai import OpenAI
from pydantic import BaseModelclient = OpenAI(base_url="https://zzzzapi.com")class Step(BaseModel):explanation: stroutput: strclass MathReasoning(BaseModel):steps: list[Step]final_answer: strresponse = 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: strrefusal: 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 BaseModelclass 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、自動推理等領域實現更高效的開發與更可靠的產出。