微調 JSON 輸出:讓語言模型始終輸出有效 JSON
語言模型的 JSON 可靠性問題及其解決方案。了解為何小型模型在 JSON 格式上失敗、微調如何將有效 JSON 率從 64% 提升至 99%,以及如何構建訓練資料集以實現可靠的結構化輸出。
結構化輸出是實際生產 AI 應用程式的基礎。如果你正在構建任何需要將 LLM 輸出連接到下游系統的東西——API、資料庫、工作流程自動化——你需要 JSON。你需要它每次都有效。
問題是:小型模型在 JSON 格式上失敗的頻率高得驚人。
失敗有多嚴重
在 Llama 3.1 8B 基礎模型上的基準測試:
| 任務 | 有效 JSON 率 |
|---|---|
| 簡單鍵值提取 | 64.2% |
| 嵌套對象 | 41.7% |
| 帶驗證的數組 | 38.9% |
| 複雜的多層架構 | 22.4% |
這些數字對於生 產使用來說太低了。即使是 64% 的成功率也意味著每三個請求中就有一個失敗,需要重試、回退或手動干預。
為什麼小型模型在 JSON 上苦苦掙扎
小型模型有三個使 JSON 生成困難的問題:
1. 嚴格的語法要求
JSON 沒有容錯空間。一個缺失的逗號、一個未轉義的引號或一個錯誤放置的括號就會破壞解析器。自然語言是容忍錯誤的;JSON 不是。小型模型習慣於生成自然語言並不斷「修正」自己——這種能力在 JSON 中會產生反效果。
2. 上下文追蹤
有效的 JSON 需要正確的括號配對、正確的逗號放置以及從開頭到結尾一致的架構遵循。對於長輸出,小型模型失去對其所在結構位置的追蹤,並開始以語義上合理但語法上無效的方式關閉對象。
3. Token 邊界
JSON 中的某些字符序列在訓練資料中出現的頻率低於自然語言——特別是嵌套結構和轉義字符。模型對這些 token 序列的信心較低,並且更可能生成替代序列。
微調如何修復這個問題
微調直接解決了這三個問題。你在你的目標架構的有效 JSON 範例上訓練模型,模型學習:
- 哪些 token 序列對你的特定架構有效
- 如何正確追蹤括號深度
- 如何在整個輸出中保持架構一致性
在 2,000 個訓練範例之後,同樣的 Llama 3.1 8B 模型達到了 99.2% 的有效 JSON 率——跨越簡單和複雜架構。
建構訓練資料集
第一步:定義你的架構
首先精確定義你需要的 JSON 輸出。使用 JSON Schema 語法:
{
"type": "object",
"properties": {
"entity_type": {
"type": "string",
"enum": ["person", "organization", "location", "date"]
},
"value": {"type": "string"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
"context": {"type": "string"}
},
"required": ["entity_type", "value", "confidence"]
}對你的所有目標輸出格式執行此操作。如果你有十種不同的輸出類型,定義十個架構。
第二步:生成多樣化的範例
創建覆蓋你的輸入空間的訓練範例。對於每種架構類型:
{"messages": [{"role": "user", "content": "從以下文字中提取命名實體:\n\n'蘋果公司首席執行官 Tim Cook 昨天在加利福尼亞庫比蒂諾宣布了新產品。'"}, {"role": "assistant", "content": "{\"entities\": [{\"entity_type\": \"organization\", \"value\": \"Apple Inc.\", \"confidence\": 0.98, \"context\": \"首席執行官\"}, {\"entity_type\": \"person\", \"value\": \"Tim Cook\", \"confidence\": 0.99, \"context\": \"CEO\"}, {\"entity_type\": \"location\", \"value\": \"Cupertino, California\", \"confidence\": 0.97, \"context\": \"公告地點\"}]}"}]}包含邊緣案例:
- 未找到實體(空數組)
- 同一類型的多個實體
- 跨越多個句子的實體
- 模糊的實體(低置信度分數)
第三步:使用 jsonschema 驗證
在添加到訓練集之前,針對你的架構驗證每個訓練範例:
import jsonschema
import json
def validate_training_example(example, schema):
try:
output = json.loads(example["messages"][-1]["content"])
jsonschema.validate(output, schema)
return True
except (json.JSONDecodeError, jsonschema.ValidationError) as e:
print(f"無效的訓練範例:{e}")
return False
# 過濾到有效範例
valid_examples = [ex for ex in examples if validate_training_example(ex, schema)]永遠不要在無效範例上訓練。 即使是幾個格式錯誤的訓練範例也可能向模型教授錯誤的模式。
第四步:覆蓋失敗案例
有目的地為你知道基礎模型失敗的案例創建範例:
- 需要轉義的字符串值(引號、反斜線、換行符)
- 深度嵌套的對象(3 層以上)
- 包含空對象或空值的數組
- 具有長字符串值的架構
這些失敗案例通常只佔你的訓練集的 10-20%,但它們不成比例地提高了可靠性。
訓練參數
JSON 可靠性微調的推薦設置:
| 參數 | 值 |
|---|---|
| 基礎模型 | Llama 3.1 8B 或 Qwen 2.5 7B |
| LoRA rank | 16 |
| Alpha | 32 |
| 學習率 | 2e-4 |
| 批次大小 | 8 |
| Epochs | 3 |
| 訓練範例 | 1,000-3,000 |
較小的 rank(16)對於 JSON 格式通常就足夠了——你在教授語法模式,而不是域知識。更多的訓練範例通常比更高的 rank 有更多好處。
作為補充的受約束解碼
微調之外,受約束解碼是另一種保證 JSON 有效性的技術。它通過在生成時強制執行語法規則——物理上不可能生成無效 JSON——來工作。
工具如 Outlines(Python 庫)和 llama.cpp 的語法支援(--grammar 標誌)實現了這一點。
何時使用微調 vs 受約束解碼:
-
微調: 當你想要模型理解架構並生成語義有意義的輸出時。微調模型在不需要外部約束的情況下正確填充字段,因為它已經學習了架構。
-
受約束解碼: 作為後備或額外的安全網。在微調的模型上添加受約束解碼提供了防禦性保障,但不能替代正確的格式訓練。
-
兩者都用: 對於高可靠性要求,在微調模型上使用受約束解碼。99% 變成 99.99%。
對工具使用和函數調用的影響
JSON 可靠性不僅僅是格式問題——它是工具使用的基礎。
當模型生成工具調用時,它正在生成 JSON(函數名稱、參數、值)。微調後 JSON 可靠性的提升直接轉化為工具調用可靠性的提升。
在類似工具調用任務的基準測試中:
- 基礎 Llama 3.1 8B:71% 的工具調用格式正確
- 微調後(在 JSON 訓練資料上):97% 的工具調用格式正確
如果你正在建構依賴工具使用的代理,JSON 微調是你可以進行的最高影響力的改進之一。
Ship AI that runs on your users' devices.
Free plan with 30 credits/mo, no card required. Paid plans from $10/mo USD.
Keep reading
微調小型模型實現 AI 代理工具調用
通用模型會幻覺函數名稱,也會寫錯參數。針對你自己的工具 schema 微調小型模型,即可獲得可靠的工具調用,成本接近於零。
微調結構化輸出:JSON Schema 合規
JSON 模式讓你得到有效的 JSON。微調讓你得到有保證的 schema 合規性:每個欄位、每種類型、每次都正確。以下是訓練模型的方法。
Llama 3 微調:從資料準備到部署的完整指南
使用 LoRA/QLoRA 微調 Meta 的 Llama 3 模型的實用指南。涵蓋模型變體選擇、資料格式化、訓練配置、評估方法,以及使用 Ollama 和 llama.cpp 進行本地部署。