本文要點
- 症狀:模型回傳的 JSON 明明可以解析,下一次卻少了欄位、改了型別,甚至把工具參數填成不可執行的值。
- 最快解法:人讀內容保留自然語言;弱約束交換使用普通 JSON;只要結果會被程式、資料庫或 Tool Calling 消費,就用 Structured Output 搭配 JSON Schema,並在執行前加上業務規則與權限驗證。
- 這篇適合三類讀者:需要分清三個概念的 AI 應用初學者、正在選擇輸出約束方式的後端開發者,以及需要設計工具參數、狀態傳遞與最終回應格式的 Agent 架構師。
症狀:模型回傳的 JSON 明明可以解析,下一次卻少了欄位、改了型別,甚至把工具參數填成不可執行的值。 最快解法:人讀內容保留自然語言;弱約束交換使用普通 JSON;只要結果會被程式、資料庫或 Tool Calling 消費,就用 Structured Output 搭配 JSON Schema,並在執行前加上業務規則與權限驗證。
這篇適合三類讀者:需要分清三個概念的 AI 應用初學者、正在選擇輸出約束方式的後端開發者,以及需要設計工具參數、狀態傳遞與最終回應格式的 Agent 架構師。
一個「可解析」但不能放心使用的 JSON
假設你要從客服訊息抽取訂單資料,提示詞要求模型輸出:
{
"order_id": "A1024",
"priority": "high",
"items": ["USB-C hub"]
}
第一次測試看起來沒有問題,但在不同輸入下,模型可能改成 orderId、把 priority 寫成 1,或把 items 從陣列改成一段文字。這些回應仍可能是合法 JSON,解析器不一定報錯;真正出問題的地方,是前端、資料庫欄位映射或後續工作流程不知道該如何處理。
因此,普通 JSON 不是錯誤格式,而是缺少資料契約的交換格式。它只表示內容按照 JSON 語法排列,並沒有自動說明哪些欄位必填、欄位必須是什麼型別,或字串只能從哪些值中選擇。
JSON Schema 官方入門資料將 JSON 文件稱為待驗證的 instance,而 Schema 是描述其結構、型別與限制的文件;JSON Schema 本身也是一份 JSON 文件,但用途不是承載業務資料,而是描述資料規則。現行規格版本為 2020-12,實際採用時仍應確認驗證器與模型介面的相容範圍。JSON Schema 規格說明 (json-schema.org)
JSON Schema 是不是一種 JSON 格式? 是,但不能把兩者視為同一件事。普通 JSON 是「資料本身」;JSON Schema 是「描述資料應該長什麼樣子的規則」。例如 {"name":"Alex"} 是資料,{"type":"object","properties":{"name":{"type":"string"}}} 則是約束這份資料的 Schema。
三種輸出方式的責任邊界
你可以把模型輸出分成三個層級,而不是把 JSON mode、普通 JSON 和 Structured Output 當作同義詞。
第一層是提示詞要求的普通 JSON。你只在指令中說「請以 JSON 回答」,模型可能產生看似正確的物件,但欄位漂移、額外文字、型別不一致與遺漏欄位仍要由你的程式處理。
第二層是 JSON mode。它主要解決「輸出是否為合法 JSON」這個語法問題,並不等同於完整 Schema 約束。以官方 API 文件的說法,較新的 JSON Schema 格式是用來讓回應符合指定 Schema;較舊的 json<em>object 方法則只處理 JSON 輸出,而且仍需要在訊息中明確要求模型輸出 JSON。API 回應格式官方文件 (platform.openai.com)
第三層是 Structured Output。你提供 Schema,模型介面再以受支援的嚴格模式約束欄位與型別。這通常適合資料抽取、分類、UI 元件描述、工作流程狀態及工具參數;不過不同平台支援的 JSON Schema 子集並不完全相同,不能看到「支援 Schema」就假設所有關鍵字都能使用。
Structured Output 和 JSON mode 有什麼區別? JSON mode 的核心問題是「能不能解析」;Structured Output 的核心問題是「是否符合指定資料結構」。前者可以降低 JSON 語法錯誤,後者才進一步約束欄位、型別、必填項與部分枚舉規則。即使使用 Structured Output,你仍然要檢查值是否合理。
Google 的官方文件明確指出,其結構化輸出只支援 JSON Schema 的一部分,而且即使語法正確,應用程式仍須自行驗證數值與語意;過大或過深的 Schema 也可能不被接受。Structured Output 官方文件 (ai.google.dev)
不同消費場景的選用原則
人讀回答
如果你要的是產品說明、除錯建議、研究摘要或客服解釋,強制 Schema 可能讓內容變得僵硬,還會增加欄位設計、錯誤處理與版本維護成本。此時自然語言通常更適合,因為讀者需要的是上下文、取捨與理由,而不是固定欄位。
資料抽取
當結果要寫入 CRM、資料庫或搜尋索引,應從「提示詞要求 JSON」升級到 Schema 約束。至少要固定:
- 欄位名稱與是否必填;
- 字串、整數、布林值及陣列等型別;
- 狀態欄位可接受的枚舉值;
- 無法判斷時使用
null、空陣列或明確的未知狀態; - 額外欄位是否允許存在。
AI Agent 為什麼不能只輸出普通 JSON? 因為 Agent 的下一步通常不是給人閱讀,而是把結果交給另一個程式。只要下游依賴固定欄位,普通 JSON 的「格式看似正常」就不足以保證工作流程能繼續。Schema 可降低欄位漂移,但你仍要處理空值、來源不足與語意不合理等情況。
工具呼叫與權限控制
Tool Calling 的工具參數應該有明確 Schema,例如工具名稱、日期格式、資源識別碼、操作類型與必要欄位。這能讓模型產生較穩定的呼叫請求,也方便伺服器在進入執行層前驗證參數。工具使用文件通常會以 input<em>schema 描述預期輸入,並要求應用程式在收到工具呼叫後,再由自己的程式碼執行工具。工具輸入 Schema 官方文件 (docs.anthropic.com)
但格式正確不等於應該執行。你至少要做兩次檢查:
- Schema 驗證:確認欄位齊全、型別正確、枚舉值合法。
- 業務與權限驗證:確認使用者有權操作、資源確實存在、金額或範圍沒有超限,並判斷這次操作是否需要人工確認。
例如模型可能成功產生:
{
"resource_id": "server-203",
"action": "restart"
}
這份資料即使完全符合 Schema,也不代表 server-203 真的存在,更不代表提出請求的帳戶有重新啟動權限。Schema 只能處理資料契約,不能取代授權系統、資源查詢與交易防護。
動態介面與元件生成
如果模型輸出要驅動表單、卡片、篩選器或管理介面,Structured Output 可以把元件類型、標籤、選項、預設值與事件名稱整理成固定結構。這比讓前端自行猜測一段自然語言可靠得多。
不過,動態介面最容易忽略版本相容性。你新增欄位時,舊版客戶端可能忽略它;你把字串改成物件,舊版客戶端則可能直接失效。因此建議:
- 在輸出中保留
schema_version; - 新欄位盡量提供預設值;
- 不要任意改變既有欄位型別;
- 對未知元件保留回退文字;
- 前端與後端共同維護相容性測試。
多步驟 Agent 的雙層結構
多步驟 Agent 不應只設計一份「最後答案 Schema」。中間狀態通常包含工具事件、呼叫 ID、執行結果、重試次數、錯誤分類及下一步狀態;這些內容要讓程式可靠處理,因此應保持機器可讀。
最終回應則可以同時提供結構與文字,例如:
{
"status": "completed",
"answer": "已完成資料整理。",
"actions": [
{
"tool_call_id": "call_01",
"result": "success"
}
],
"next_step": null
}
這裡的 answer 供使用者閱讀,status 與 actions 供前端、記錄系統或工作流程使用。不要把模型內部推理過程設計成必須回傳的 JSON 欄位;你真正需要的是可驗證的事件、狀態與結果,而不是把不可穩定重現的思考內容當作 API 契約。
工具參數和最終回答都需要 Schema 嗎? 不一定。工具參數通常需要較嚴格的 Schema,因為它可能觸發外部動作;最終回答則視消費者而定。若只顯示給人看,可以使用自然語言;若要由前端、資料庫或工作流程接收,則應設計結果 Schema,並可額外保留一個文字欄位。
結構化輸出能否保證內容正確? 不能。它主要約束格式、欄位與部分型別,不會自動確認模型填入的日期、產品名稱、資源狀態或商業判斷是真實的。需要正確性的欄位,應透過資料庫查詢、外部 API、工具結果、規則引擎或人工覆核完成。
落地驗收流程
你可以按以下順序把一個自然語言模型流程改造成可維護的結構化流程:
- 先確認消費者:標記結果究竟由人、前端、資料庫、佇列、工作流程還是工具執行器使用。
- 拆出必要欄位:只保留下游真正需要的欄位,避免把說明文字、內部推理或暫時資訊硬塞進 Schema。
- 定義資料契約:寫出欄位型別、必填規則、枚舉值、空值策略與額外欄位政策。
- 確認平台子集:逐項核對目標介面支援哪些 JSON Schema 關鍵字,不要直接把完整規格當成平台保證。
- 加入應用程式驗證:模型回應通過結構驗證後,再檢查數值範圍、權限、資源存在性與業務狀態。
- 設計錯誤與回退:處理拒答、截斷、Schema 不相容、工具失敗及模型回傳未知值的情況。
- 建立版本測試:同一批輸入分別測試自然語言、提示詞 JSON、JSON mode 與嚴格 Schema,記錄模型、介面與測試日期,平台保證範圍改變時重新核對。
如果你正把模型結果接到前端或資料庫,可先參考 kvmboot 的說明中心,整理遠端開發環境、連線方式與權限管理的驗收項目;若團隊需要確認服務流程,也可以查看 kvmboot 的服務介紹。這些步驟的重點不是追求最複雜的 Schema,而是讓每個下游消費者都知道收到資料後可以安全做什麼。
選擇自然語言、JSON 或 Structured Output
| 使用方式 | 適合的消費者 | 可解決的問題 | 主要限制 | 建議 |
|---|---|---|---|---|
| 自然語言 | 人、客服人員、分析者 | 解釋、摘要、比較與上下文表達 | 不適合直接映射程式欄位 | 只供人讀時優先使用 |
| 普通 JSON | 簡單腳本、低風險交換流程 | 提供基本鍵值結構 | 欄位漂移、型別不一致仍可能發生 | 原型或弱約束場景使用 |
| JSON mode | 需要合法 JSON 的應用程式 | 降低語法解析失敗 | 通常不等於欄位與型別完整受控 | 先確認平台實際保證 |
| Structured Output + JSON Schema | 資料庫、前端、批次抽取、Agent 狀態 | 約束欄位、型別與部分值域 | 有平台子集、版本與語意正確性限制 | 生產資料與工具參數優先 |
| Tool Calling + Schema + 業務驗證 | 外部 API、交易、伺服器操作 | 將模型意圖轉成可驗證的工具請求 | Schema 不等於授權或執行成功 | 執行前必須雙重驗證 |
如果你目前把所有模型回應都交給提示詞控制,常見缺點是欄位規則散落在文字中、改版後難以測試,而且錯誤往往要到資料庫寫入或工具執行時才暴露。若改用固定的本機或雲端伺服器長期運行,又要自行處理環境安裝、版本一致性、權限隔離與閒置成本。對需要批量抽取、工具執行或持續工作流程的讀者,短期驗證時租用 kvmboot 的 Mac 環境,可以先把模型介面、Schema 驗證與執行器串接起來,再決定是否值得投入長期自建環境;若需要進一步確認適合的區域與連線方案,可透過 kvmboot 聯絡頁面取得下一步資訊。