OpenAI 相容 API 的 Structured Outputs:JSON Schema 指南

說明 Responses 與 Chat Completions 如何使用嚴格 JSON Schema,並涵蓋應用驗證、拒絕、截斷與路由相容測試。

Structured Outputs 讓應用要求模型回傳符合既定 Schema 的 JSON,而不只是用 Prompt 說「請輸出 JSON」。在 OpenAI-compatible API 中,同一份 JSON Schema 可用於 Responses 或 Chat Completions,但外層欄位不同,而且必須針對實際模型與路由驗證支援程度。

安全的生產模式有三層:模型支援時使用 strict Schema、應用端再次解析與驗證 JSON,最後再套用商業規則。符合 Schema 能消除大量格式錯誤,但不能證明內容在事實或語意上正確。

Structured Outputs 不等於 JSON Mode

方法 產生有效 JSON 強制符合 Schema 適用情境
只靠 Prompt 不保證 可以接受解析失敗的原型
JSON Mode 支援且完整生成時是 結構彈性、由應用驗證的 JSON
strict: true Structured Outputs 須處理完成狀態與拒絕 在支援的 JSON Schema 子集中是 型別化擷取與應用流程

OpenAI Structured Outputs 指南建議在模型與 Endpoint 支援時優先使用 Structured Outputs。若模型應回覆可預測的資料物件,使用 Structured Response Format;若模型要請求應用執行動作,則使用 Function Calling。兩者都可使用嚴格 Schema,但 Call ID 與結果訊息屬於不同協定。

先定義 Schema,再選擇 Endpoint

假設客服分流需要 categorypriorityrequires_humansummary

{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["billing", "technical", "account"]
    },
    "priority": { "type": "integer", "minimum": 1, "maximum": 3 },
    "requires_human": { "type": "boolean" },
    "summary": { "type": "string" }
  },
  "required": ["category", "priority", "requires_human", "summary"],
  "additionalProperties": false
}

將所有欄位列為 required,並設定 additionalProperties: false,能讓下游程式取得穩定物件。但這不代表所有 JSON Schema 關鍵字都可攜。OpenAI 支援文件列出的子集,其他 OpenAI-compatible 供應商可能支援不同子集,甚至完全沒有 Strict Schema Mode。

使用 Responses API 傳送 Schema

Responses API 將 Schema 放在 text.format

{
  "model": "<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>",
  "input": "The customer was charged twice and wants a refund.",
  "text": {
    "format": {
      "type": "json_schema",
      "name": "support_ticket",
      "schema": {
        "type": "object",
        "properties": {
          "category": { "type": "string", "enum": ["billing", "technical", "account"] },
          "priority": { "type": "integer", "minimum": 1, "maximum": 3 },
          "requires_human": { "type": "boolean" },
          "summary": { "type": "string" }
        },
        "required": ["category", "priority", "requires_human", "summary"],
        "additionalProperties": false
      },
      "strict": true
    }
  }
}

呼叫 POST https://modelflare.dev/v1/responses 時,使用 Authorization: Bearer <YOUR_API_KEY>Content-Type: application/json。Responses 的生成內容位於帶型別的 Output Items。SDK 可能提供聚合文字或 Parsed Output Helper,但直接使用 HTTP 時,不應假設結構化物件位於最上層;要先讀取完成的 Response、找到文字輸出,再執行 JSON 解析。

使用 Chat Completions 傳送同一份 Schema

Chat Completions 將相同 Schema 放在 response_format.json_schema

{
  "model": "<MODEL_WITH_VERIFIED_STRUCTURED_OUTPUT_SUPPORT>",
  "messages": [
    { "role": "user", "content": "The customer was charged twice and wants a refund." }
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "support_ticket",
      "schema": {
        "type": "object",
        "properties": {
          "category": { "type": "string", "enum": ["billing", "technical", "account"] },
          "priority": { "type": "integer", "minimum": 1, "maximum": 3 },
          "requires_human": { "type": "boolean" },
          "summary": { "type": "string" }
        },
        "required": ["category", "priority", "requires_human", "summary"],
        "additionalProperties": false
      },
      "strict": true
    }
  }
}

Chat Completions 通常在 choices[0].message.content 回傳 JSON 文字;它仍是字串,必須解析。

用途 Responses API Chat Completions
Schema 容器 text.format response_format.json_schema
Format Type text.format.type response_format.type
Schema 名稱 text.format.name response_format.json_schema.name
Schema 本文 text.format.schema response_format.json_schema.schema
Strict Flag text.format.strict response_format.json_schema.strict
結果位置 Typed Output Items / Helper choices[0].message.content

Modelflare 的 OpenAI 相容層會在支援的 OpenAI/Codex 路由中轉換兩種 Wrapper,但轉換不能為本身不支援 Structured Outputs 的上游模型創造能力。其他作為 Raw Chat Completions Pass-through 的模型家族,仍以上游供應商的精確協定為準。

分開驗證結構與語意

模型可能回傳:

{
  "category": "billing",
  "priority": 2,
  "requires_human": true,
  "summary": "Customer reports a duplicate charge and requests a refund."
}

結構驗證

使用 JSON Schema Validator 或 Typed SDK Helper 檢查 Required Properties、額外欄位、型別、Enum 與數值範圍。即使供應商承諾 Strict Adherence,應用端驗證仍能防範不支援的路由、整合錯誤、截斷與未來協定變更。

語意與商業規則驗證

Schema 無法判斷客戶是否真的重複扣款、priority: 2 是否正確,或退款是否必須人工核准。高影響流程應把模型物件視為建議分類,與權威資料比對,並在確定性程式碼中執行權限、財務限制與安全規則。結構正確的 JSON 絕不能繞過授權或計費邊界。

處理不完整與例外輸出

拒絕

模型可能因安全原因拒絕請求。應先檢查 Response Status 與 Refusal Representation,再尋找 JSON;不要把拒絕誤報為解析錯誤。

截斷與輸出限制

若生成在物件完成前停止,Schema 無法補回缺少的結尾。檢查 Completion Status 與 Stop Reason,並為最大合法物件設定足夠但有界的 Output Limit。

不支援的 Schema 關鍵字

Strict 實作通常只支援 JSON Schema 子集。先使用 Object、Array、Primitive、Enum、Required 與明確的 Additional Properties;導入 Reference、Recursive Shape、複雜 Union 或進階 Validation 前,查閱目前供應商文件。

首次使用 Schema 的延遲

部分供應商會預處理並快取新 Schema,第一次請求可能較慢。重複使用穩定且版本化的 Schema,不要每次動態產生唯一 Schema;效能比較也要分開首次與穩態資料。

模型或路由不相容

Endpoint 可能接受一般 Chat Completions,卻拒絕 json_schema、忽略 strict,或把欄位轉送給不支援的模型。200 加上看似 JSON 的內容仍不是 Strict Adherence 證明;必須使用邊界與無效輸入驗證。

生產前執行相容性測試

測試 應保存的證據
最小 Required Object Status、Model、Route、Parsed Object、Validation Result
每個 Enum Value 能否產生與解析每個允許值
資訊不足 使用有界替代值,或要求澄清
觸發安全政策 拒絕格式與應用處理
低 Output Limit Completion Status 與截斷處理
不支援 Schema Feature 明確錯誤或靜默忽略
Responses 與 Chat Wrapper 是否產生等價應用物件
重複穩定 Schema 首次與穩態時間

比較模型時必須固定 Schema、Prompt、Region、Streaming Mode 與 Output Limit,並記錄測試日期,因為模型可用性與供應商行為會改變。

測試工作流程後再選 Endpoint

應用已採用 Typed Output Items、Responses Streaming Events 或更大的 Responses Tool Workflow 時,選擇 Responses;既有 Message-based Integration 穩定且路由支援 response_format 時,可選 Chat Completions。更完整的取捨見 Responses API 與 Chat Completions

無論使用哪個 Endpoint:

  1. 只保留一份版本化 JSON Schema 真相來源;
  2. 轉成 Endpoint Wrapper 時不改變語意;
  3. 完成後再次驗證 Response;
  4. 結構驗證後才套用確定性的商業規則;
  5. 分開監控 Parse、Refusal、Truncation 與 Compatibility Failure。

初次遷移可先閱讀 OpenAI-Compatible API 指南,串流與不完整事件可參考 AI API Streaming 指南,並在模型與價格確認目前模型範圍,再針對 API Key 實際使用的路由驗證 Structured Outputs。

Structured Outputs 的價值,是把模型回應收斂成可靠的應用介面;它不會取代事實查核、授權與計費邏輯。「OpenAI-compatible」仍是必須逐項測試的主張,而不是從 Base URL 就能推導的保證。