讓模型只回 JSON:從提示約束到結構化輸出參數
要模型輸出 JSON,光在提示裡拜託是不夠的。這篇整理三個層次的做法,以及各自會在什麼情況下失效。
把模型接進系統時,第一個踩到的坑幾乎都是「回傳格式不穩定」。今天正常,明天多了一句「好的,以下是您要的結果:」,解析就炸了。處理方式有三個層次,成本與可靠度遞增。
層次一:提示約束
在提示中明確寫出「僅輸出 JSON,不要有任何說明文字或程式碼區塊標記」,並附上一個完整範例。這能解決大多數情況,但在輸入異常時仍會退化。
層次二:容錯解析
不要假設模型只回 JSON,寫一個寬鬆解析器:先嘗試直接解析,失敗就抓第一個 { 到最後一個 } 之間的內容再試一次。
import json, re
def loads_loose(text):
try:
return json.loads(text)
except json.JSONDecodeError:
pass
m = re.search(r'\{.*\}', text, re.S)
if not m:
raise ValueError('回應中找不到 JSON 物件')
return json.loads(m.group(0))層次三:由 API 保證結構
現在主流 API 都支援結構化輸出:把 JSON Schema 交給模型,由解碼端保證格式合法。這一層才是真正的保證,因為它不依賴模型「願意配合」,而是在生成時就限制了可選的 token。
結構化輸出保證的是格式合法,不保證內容正確。schema 通過不代表欄位值有意義,該做的欄位值驗證一樣不能省。
實務建議三層都做:提示寫清楚、API 開結構化輸出、解析端仍保留容錯。三層任一層失效時,系統都還撐得住。