
微調結構化輸出:從 JSON 模式到有保證的 Schema
JSON 模式讓你得到有效的 JSON。微調讓你得到有保證的 schema 合規性——每個欄位、每種類型、每次都正確。以下是如何訓練模型輸出你的應用程式所期望的確切結構。
你的應用程式期望一個包含確切 8 個欄位的 JSON 物件,每個欄位有特定類型,其中兩個為枚舉值,以及一個帶有自身 schema 的巢狀物件陣列。你要求 GPT-4 生成它。大多數時候,你得到了你想要的。有時你得到 7 個欄位。偶爾你得到一個字串而不是預期的整數。偶爾模型會發明一個不存在的枚舉值。
在 95% 的 schema 合規率下,每 20 次 API 呼叫就有 1 次產生你的解析器無法處理的輸出。如果你的應用程式每天進行 10,000 次結 構化輸出呼叫,那就是每天 500 次失敗。每天都是。你的錯誤處理代碼變得比你的實際業務邏輯更複雜。你添加重試、備用提示、後處理修復器。系統可以工作,但很脆弱——靠膠帶和重試循環維持。
微調改變了這個方程式。一個在 500-1,000 個你確切 schema 範例上訓練的模型不會偏移、不會幻覺欄位、不會發明枚舉值。Schema 合規率從提示的 95% 提升到微調後的 99.5% 以上。在每天 10,000 次呼叫的情況下,這是 500 次失敗和 50 次之間的差異。
結構化輸出的層次
結構化輸出有一個層次體系,從最不可靠到最可靠:
第 1 級:基於提示(「請輸出 JSON」)
在提示中要求模型生成 JSON。包含範例。期望最好的結果。
- 合規率: 80-90%
- 失敗模式: 無效的 JSON(缺少引號、尾部逗號)、缺少欄位、錯誤類型、額外欄位、Markdown 包裝
- 何時使用: 僅用於原型開發
第 2 級:JSON 模式
OpenAI 的 JSON 模式,或其他 API 中的等效設定。強制模型輸出語法有效的 JSON。
- 合規率: 95-98%(有效 JSON,但 schema 合規性有所不同)
- 失敗模式: 不符合你的 schema 的有效 JSON——缺少必填欄位、錯誤欄位名稱、類型不匹配、額外欄位
- 何時使用: 當你需要有效 JSON 但可以容忍 schema 偏移時
第 3 級:Function Calling / Structured Outputs API
OpenAI 搭配 JSON schema 的結構化輸出,或 function-calling 端點。API 在解碼層面強制執行 schema。
- 合規率: schema 結構 99% 以上
- 失敗模式: 結構正確但值錯誤——幻覺的枚 舉值、語義錯誤的內容、預期有內容的地方卻是空字串
- 何時使用: 當你需要來自雲端 API 的 schema 合規性,且可以接受每 token 成本時
第 4 級:微調模型
在數百個你確切 schema 範例上訓練的模型。了解欄位名稱、類型、有效值和語義期望。
- 合規率: 99.5-99.9%
- 失敗模式: 訓練分佈之外的遠端輸入上的罕見邊緣案例
- 何時使用: 高流量的生產系統,可靠性和成本很重要
第 5 級:微調模型 + 約束解碼
帶有約束解碼的微調模型(llama.cpp grammar、Outlines 或 guidance),使無效 token 成為不可能。
- 合規率: 100% 結構合規性
- 失敗模式: 結構完美的 JSON,但值在語義上錯誤(微調後很少見)
- 何時使用: 當你需要零結構失敗且正在運行本地推論時
為何提示有上限
基於提示的結構化輸出的根本問題:模型按順序生成 token,沒有任何機制阻止它生成違反你的 schema 的 token。
當你提示 GPT-4 輸出 {"status": "approved" | "denied" | "pending"} 時,模型可能在一次呼叫中生成 "status": "approved",在下一次生成 "status": "Approved"。或者 "status": "approve"。每個都是有效的 JSON 字串——模型沒有限制說「只有這三個確切值是可接受的」。
更詳細的提示有更詳細的 schema 有幫助,但它們達到收益遞減:
- 1 行 schema 描述:約 85% 合規率
- 詳細 schema 帶範例:約 92% 合規率
- Schema + 少樣本範例 + 明確約束:約 95-97% 合規率
你無法通過提示達到 99.5%。模型的 token 生成是概率性的。無論你的提示多好,生成錯誤 token 的概率永遠不會恰好為零。
微調直接改變模型的概率分佈。在 500 個範例訓練後,其中 status 始終恰好是 "approved"、"denied" 或 "pending",模型為該欄位的任何其他值分配接近零的概率。合規性來自權重,而不是提示。
構建符合 Schema 的訓練資料集
訓練資料的品質決定了你的 schema 合規性品質。以下是如何構建產生可靠結構化輸出的資料集。
第 1 步:正式定義你的 Schema
從 JSON Schema 規範開始:
{
"type": "object",
"required": ["id", "status", "score", "category", "findings", "metadata"],
"properties": {
"id": {"type": "string", "pattern": "^RPT-[0-9]{6}quot;},
"status": {"type": "string", "enum": ["approved", "denied", "pending", "review"]},
"score": {"type": "number", "minimum": 0, "maximum": 100},
"category": {"type": "string", "enum": ["financial", "operational", "compliance", "technical"]},
"findings": {
"type": "array",
"items": {
"type": "object",
"required": ["description", "severity", "recommendation"],
"properties": {
"description": {"type": "string"},
"severity": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
"recommendation": {"type": "string"}
}
}
},
"metadata": {
"type": "object",
"required": ["analyst", "date", "version"],
"properties": {
"analyst": {"type": "string"},
"date": {"type": "string", "format": "date"},
"version": {"type": "string"}
}
}
}
}
第 2 步:生成多樣化的有效範例
你需要 500-1,000 個訓練範例。每個都必須是你的 schema 的完全有效實例。生成它們有三種方法:
來自生產資料: 如果你有遵循此 schema 的現有資料(來自資料庫、來自之前的 API 輸出),將其轉換為訓練範例。這是最 佳來源,因為它反映了真實世界的值分佈。
來自 GPT-4 加驗證: 使用 GPT-4 生成多樣化範例,然後根據你的 JSON Schema 驗證每個範例。丟棄任何未通過驗證的範例。在 GPT-4 95% 合規率下,你將丟棄約 1/20——對資料集生成來說可以接受。通過你的實際解析器再次檢查已驗證的範例。
程序化生成: 編寫一個腳本,隨機生成你的 schema 的有效實例。這保證了結構有效性,但可能缺乏語義連貫性。用它來補充真實範例,而不是作為唯一來源。
第 3 步:讓輸入多樣化,而不僅僅是輸出
你的訓練資料需要與符合 schema 的輸出配對的多樣化輸入。如果每個輸入都是「分析這份財務報告」,模型學到了 schema 但無法泛化到新的輸入措辭。
包含變體:
- 不同的輸入長度(一句話到三段)
- 不同的輸入格式(正式請求、隨意問題、結構化指令)
- 不同的上下文級別(完整資訊 vs. 部分資訊)
- 邊緣案例(模糊輸入、缺少資訊的輸入、應該生成空陣列的輸入)