For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
主要導覽

結構化模型輸出

確保模型的文字回應符合你定義的 JSON 結構描述。

JSON 是全球應用程式交換資料時最廣泛使用的格式之一。

結構化輸出這項功能可確保模型產生的回應一律符合你提供的 JSON Schema,因此你無須擔心模型遺漏必要的鍵,或因幻覺而產生無效的列舉值。

結構化輸出的優點包括:

  1. 可靠的型別安全性: 無須驗證回應格式,也無須因格式錯誤而重試
  2. 明確的拒絕回應: 現在可以透過程式偵測模型基於安全考量所做的拒絕回應
  3. 更簡單的提示詞: 無須使用語氣強烈的提示詞,就能讓輸出格式保持一致

除了 REST API 支援 JSON Schema 外,OpenAI 的 PythonJavaScript 程式庫也讓你能分別使用 pydantic.BaseModelz.object 定義物件結構描述。以下範例示範如何從非結構化文字中擷取資訊,並讓擷取結果符合以程式碼定義的結構描述。

Ruby SDK 支援使用 Sorbet T::Struct 定義的結構描述,並傳回具有型別的解析結果。

取得結構化回應
from openai import OpenAI
from pydantic import BaseModel

client = OpenAI()


class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]


response = client.responses.parse(
    model="gpt-6-astra",
    input=[
        {"role": "system", "content": "Extract the event information."},
        {
            "role": "user",
            "content": "Alice and Bob are going to a science fair on Friday.",
        },
    ],
    text_format=CalendarEvent,
)

event = response.output_parsed

支援的模型

從 GPT-4o 開始,我們的最新大型語言模型皆支援結構化輸出。新專案請從 gpt-6-astra 開始使用。gpt-4-turbo 及更早的舊版模型則可改用 JSON 模式

使用結構化輸出時,何時該透過函式呼叫,何時該透過 text.format

OpenAI API 提供兩種使用結構化輸出的方式:

  1. 使用函式呼叫
  2. 使用 json_schema 回應格式時

如果你正在開發的應用程式需要將模型與應用程式的功能串接起來,函式呼叫就能派上用場。

例如,你可以讓模型存取查詢資料庫的函式,藉此打造能協助使用者處理訂單的 AI 助理,或讓模型存取能與 UI 互動的函式。

相較之下,如果你想指定模型回應使用者時應遵循的結構描述,而非模型呼叫工具時使用的結構描述,就更適合透過 response_format 使用結構化輸出。

例如,如果你正在開發數學家教應用程式,可能會希望助理使用特定的 JSON Schema 回應使用者,以便產生 UI,將模型輸出的不同部分以各自的方式呈現。

實務上:

  • 如果你要將模型連接到系統中的工具、函式、資料等, 就應使用函式呼叫;如果你想讓模型回應使用者時的 輸出具有結構,就應使用結構化的 text.format

本指南接下來會聚焦於 Responses API 中 不使用函式呼叫的使用案例。若要進一步瞭解如何將結構化輸出 搭配函式呼叫使用,請參閱

函式呼叫

指南。

結構化輸出與 JSON 模式的比較

結構化輸出是 JSON 模式的進化版。兩者都能確保產生有效的 JSON,但只有結構化輸出能確保輸出符合結構描述。Responses API、Chat Completions API、Assistants API、微調 API 和批次處理 API 都支援結構化輸出與 JSON 模式。

我們建議盡可能使用結構化輸出,取代 JSON 模式。

不過,只有 gpt-4o-minigpt-4o-mini-2024-07-18gpt-4o-2024-08-06 及之後的模型快照,才支援透過 response_format: {type: "json_schema", ...} 使用結構化輸出。

結構化輸出JSON 模式
輸出有效的 JSON
符合結構描述是(請參閱支援的結構描述
相容模型gpt-4o-minigpt-4o-2024-08-06 及之後的模型gpt-3.5-turbogpt-4-*gpt-4o-* 及相容的 GPT-5 模型
啟用方式text: { format: { type: "json_schema", "strict": true, "schema": ... } }text: { format: { type: "json_object" } }

範例

思路鏈

你可以要求模型以結構化的方式逐步輸出答案,引導使用者了解解題過程。

將結構化輸出用於思路鏈數學輔導
from openai import OpenAI
from pydantic import BaseModel

client = OpenAI()


class Step(BaseModel):
    explanation: str
    output: str


class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str


response = client.responses.parse(
    model="gpt-6-astra",
    input=[
        {
            "role": "system",
            "content": "You are a helpful math tutor. Guide the user through the solution step by step.",
        },
        {"role": "user", "content": "how can I solve 8x + 7 = -23"},
    ],
    text_format=MathReasoning,
)

math_reasoning = response.output_parsed

回應範例

{
  "steps": [
    {
      "explanation": "Start with the equation 8x + 7 = -23.",
      "output": "8x + 7 = -23"
    },
    {
      "explanation": "Subtract 7 from both sides to isolate the term with the variable.",
      "output": "8x = -23 - 7"
    },
    {
      "explanation": "Simplify the right side of the equation.",
      "output": "8x = -30"
    },
    {
      "explanation": "Divide both sides by 8 to solve for x.",
      "output": "x = -30 / 8"
    },
    {
      "explanation": "Simplify the fraction.",
      "output": "x = -15 / 4"
    }
  ],
  "final_answer": "x = -15 / 4"
}

如何透過 text.format 使用結構化輸出

結構化輸出中的拒絕回應

使用結構化輸出處理使用者提供的輸入時,OpenAI 模型有時會基於安全理由拒絕執行請求。由於拒絕回應不一定符合你在 response_format 中提供的結構描述,API 回應會包含一個名為 refusal 的新欄位,表示模型拒絕執行該請求。

當輸出物件中出現 refusal 屬性時,你可以在 UI 中顯示拒絕回應,或在接收回應的程式碼中加入條件邏輯,處理請求遭拒的情況。

class Step(BaseModel):
    explanation: str
    output: str


class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str


response = client.responses.parse(
    model="gpt-6-astra",
    input=[
        {
            "role": "system",
            "content": "You are a helpful math tutor. Guide the user through the solution step by step.",
        },
        {"role": "user", "content": "how can I solve 8x + 7 = -23"},
    ],
    text_format=MathReasoning,
)

for output in response.output:
    if output.type != "message":
        continue

    for item in output.content:
        if item.type == "refusal":
            # If the model refuses to respond, you will get a refusal message
            print(item.refusal)
            continue

        if not item.parsed:
            raise Exception("Could not parse response")

        print(item.parsed)

請求遭拒時,API 回應會類似以下內容:

{
  "id": "resp_1234567890",
  "object": "response",
  "created_at": 1721596428,
  "status": "completed",
  "completed_at": 1721596429,
  "error": null,
  "incomplete_details": null,
  "input": [],
  "instructions": null,
  "max_output_tokens": null,
  "model": "gpt-4o-2024-08-06",
  "output": [{
    "id": "msg_1234567890",
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "refusal",
        "refusal": "I'm sorry, I cannot assist with that request."
      }
    ]
  }],
  "usage": {
    "input_tokens": 81,
    "output_tokens": 11,
    "total_tokens": 92,
    "output_tokens_details": {
      "reasoning_tokens": 0,
    }
  },
}

技巧與最佳實務

處理使用者提供的輸入

如果你的應用程式使用使用者提供的輸入,請務必在提示詞中說明:當輸入無法產生有效回應時,應如何處理。

模型會始終嘗試遵循提供的結構描述,因此,若輸入與結構描述完全無關,就可能產生幻覺。

你可以在提示詞中明確要求:如果模型偵測到輸入與任務不相容,就傳回空白參數或特定句子。

處理錯誤

結構化輸出仍可能包含錯誤。如果發現錯誤,可以嘗試調整指示、在系統指示中提供範例,或將任務拆分成更簡單的子任務。如需更多調整輸入的建議,請參閱提示工程指南

避免 JSON 結構描述與型別不一致

為了避免 JSON Schema 與程式語言中的對應型別不一致,我們強烈建議在 SDK 提供原生結構描述輔助工具時使用這些工具。

如果你偏好直接指定 JSON 結構描述,可以新增 CI 規則,在 JSON 結構描述或底層資料物件遭到修改時發出提醒;也可以新增 CI 步驟,根據型別定義自動產生 JSON Schema,或反過來根據 JSON Schema 產生型別定義。

串流

你可以使用串流,在模型回應或函式呼叫引數生成的過程中即時處理,並將其解析為結構化資料。

如此一來,你就不必等到整個回應完成後才開始處理。 如果你想逐一顯示 JSON 欄位,或在函式呼叫引數可用時立即處理,這種方式特別實用。

我們建議使用 SDK 來處理結構化輸出的串流。

from openai import OpenAI
from pydantic import BaseModel


class EntitiesModel(BaseModel):
    attributes: list[str]
    colors: list[str]
    animals: list[str]


client = OpenAI()

with client.responses.stream(
    model="gpt-6-astra",
    input=[
        {"role": "system", "content": "Extract entities from the input text"},
        {
            "role": "user",
            "content": "The quick brown fox jumps over the lazy dog with piercing blue eyes",
        },
    ],
    text_format=EntitiesModel,
) as stream:
    for event in stream:
        if event.type == "response.refusal.delta":
            print(event.delta, end="")
        elif event.type == "response.output_text.delta":
            print(event.delta, end="")
        elif event.type == "response.error":
            print(event.error, end="")
        elif event.type == "response.completed":
            print("Completed")  # print(event.response.output)

    final_response = stream.get_final_response()
    print(final_response)

支援的結構描述

結構化輸出支援 JSON Schema 語言的部分功能。

支援的型別

結構化輸出支援下列型別:

  • 字串
  • 數值
  • 布林值
  • 整數
  • 物件
  • 陣列
  • 列舉
  • anyOf

支援的屬性

除了指定屬性的型別,你還可以設定下列額外限制:

string 支援的屬性:

  • pattern:字串必須符合的正規表示式。
  • format:預先定義的字串格式。目前支援:
    • date-time
    • time
    • date
    • duration
    • email
    • hostname
    • ipv4
    • ipv6
    • uuid

number 支援的屬性:

  • multipleOf:數值必須是此值的倍數。
  • maximum:數值必須小於或等於此值。
  • exclusiveMaximum:數值必須小於此值。
  • minimum:數值必須大於或等於此值。
  • exclusiveMinimum:數值必須大於此值。

array 支援的屬性:

  • minItems:陣列的項目數不得少於此值。
  • maxItems:陣列的項目數不得超過此值。

以下範例示範如何使用這些型別限制:

{
    "name": "user_data",
    "strict": true,
    "schema": {
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "description": "The name of the user"
            },
            "username": {
                "type": "string",
                "description": "The username of the user. Must start with @",
                "pattern": "^@[a-zA-Z0-9_]+$"
            },
            "email": {
                "type": "string",
                "description": "The email of the user",
                "format": "email"
            }
        },
        "additionalProperties": false,
        "required": [
            "name", "username", "email"
        ]
    }
}

請注意,這些限制尚不適用於微調後的 模型

根層級必須是物件,且不得使用 anyOf

請注意,結構描述的根層級必須是物件,且不得使用 anyOf。以 Zod 為例,其中一種常見模式是使用可辨識聯集,這會在最上層產生 anyOf。因此,下列程式碼無法使用:

import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";

const BaseResponseSchema = z.object({
  /* ... */
});
const UnsuccessfulResponseSchema = z.object({
  /* ... */
});

const finalSchema = z.discriminatedUnion("status", [
  BaseResponseSchema,
  UnsuccessfulResponseSchema,
]);

// Invalid JSON Schema for Structured Outputs
const json = zodResponseFormat(finalSchema, "final_schema");

所有欄位都必須設為 required

若要使用結構化輸出,所有欄位或函式參數都必須指定為 required

{
    "name": "get_weather",
    "description": "Fetches the weather in the given location",
    "strict": true,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to get the weather for"
            },
            "unit": {
                "type": "string",
                "description": "The unit to return the temperature in",
                "enum": ["F", "C"]
            }
        },
        "additionalProperties": false,
        "required": ["location", "unit"]
    }
}

雖然所有欄位都必須是必填欄位(模型會為每個參數傳回一個值),但你可以使用包含 null 的聯集型別來模擬選填參數。

{
    "name": "get_weather",
    "description": "Fetches the weather in the given location",
    "strict": true,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to get the weather for"
            },
            "unit": {
                "type": ["string", "null"],
                "description": "The unit to return the temperature in",
                "enum": ["F", "C"]
            }
        },
        "additionalProperties": false,
        "required": [
            "location", "unit"
        ]
    }
}

物件的巢狀深度與大小限制

一份結構描述總共最多可包含 5000 個物件屬性,巢狀深度最多為 10 層。

字串總長度限制

在一份結構描述中,所有屬性名稱、定義名稱、enum 值和 const 值的字串總長度不得超過 120,000 個字元。

列舉大小限制

一份結構描述中,所有 enum 屬性合計最多可包含 1000 個列舉值。

對於值為字串的單一 enum 屬性,若列舉值超過 250 個,所有列舉值的字串總長度不得超過 15,000 個字元。

物件一律必須設定 additionalProperties: false

additionalProperties 控制物件是否可以包含 JSON Schema 中未定義的額外鍵值。

結構化輸出僅支援產生指定的鍵值,因此我們要求開發人員設定 additionalProperties: false,才能啟用結構化輸出。

{
    "name": "get_weather",
    "description": "Fetches the weather in the given location",
    "strict": true,
    "schema": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to get the weather for"
            },
            "unit": {
                "type": "string",
                "description": "The unit to return the temperature in",
                "enum": ["F", "C"]
            }
        },
        "additionalProperties": false,
        "required": [
            "location", "unit"
        ]
    }
}

鍵的順序

使用結構化輸出時,輸出內容會依照結構描述中鍵的順序產生。

部分型別專用的關鍵字尚未受到支援

  • 組合: allOfnotdependentRequireddependentSchemasifthenelse

微調後的模型另外也不支援下列項目:

  • 字串: minLengthmaxLengthpatternformat
  • 數值: minimummaximummultipleOf
  • 物件: patternProperties
  • 陣列: minItemsmaxItems

如果您透過提供 strict: true 啟用結構化輸出,卻使用不支援的 JSON Schema 呼叫 API,就會收到錯誤。

使用 anyOf 時,每個巢狀結構描述都必須是符合此子集的有效 JSON Schema

以下是受支援的 anyOf 結構描述範例:

{
    "type": "object",
    "properties": {
        "item": {
            "anyOf": [
                {
                    "type": "object",
                    "description": "The user object to insert into the database",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "The name of the user"
                        },
                        "age": {
                            "type": "number",
                            "description": "The age of the user"
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "name",
                        "age"
                    ]
                },
                {
                    "type": "object",
                    "description": "The address object to insert into the database",
                    "properties": {
                        "number": {
                            "type": "string",
                            "description": "The number of the address. Eg. for 123 main st, this would be 123"
                        },
                        "street": {
                            "type": "string",
                            "description": "The street name. Eg. for 123 main st, this would be main st"
                        },
                        "city": {
                            "type": "string",
                            "description": "The city of the address"
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "number",
                        "street",
                        "city"
                    ]
                }
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "item"
    ]
}

支援定義

您可以使用定義來建立子結構描述,並在結構描述的各處參照它們。以下是一個簡單的範例。

{
    "type": "object",
    "properties": {
        "steps": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/step"
            }
        },
        "final_answer": {
            "type": "string"
        }
    },
    "$defs": {
        "step": {
            "type": "object",
            "properties": {
                "explanation": {
                    "type": "string"
                },
                "output": {
                    "type": "string"
                }
            },
            "required": [
                "explanation",
                "output"
            ],
            "additionalProperties": false
        }
    },
    "required": [
        "steps",
        "final_answer"
    ],
    "additionalProperties": false
}

支援遞迴結構描述

以下遞迴結構描述範例使用 # 表示遞迴參照根結構描述。

{
    "name": "ui",
    "description": "Dynamically generated UI",
    "strict": true,
    "schema": {
        "type": "object",
        "properties": {
            "type": {
                "type": "string",
                "description": "The type of the UI component",
                "enum": ["div", "button", "header", "section", "field", "form"]
            },
            "label": {
                "type": "string",
                "description": "The label of the UI component, used for buttons or form fields"
            },
            "children": {
                "type": "array",
                "description": "Nested UI components",
                "items": {
                    "$ref": "#"
                }
            },
            "attributes": {
                "type": "array",
                "description": "Arbitrary attributes for the UI component, suitable for any element",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "The name of the attribute, for example onClick or className"
                        },
                        "value": {
                            "type": "string",
                            "description": "The value of the attribute"
                        }
                    },
                    "additionalProperties": false,
                    "required": ["name", "value"]
                }
            }
        },
        "required": ["type", "label", "children", "attributes"],
        "additionalProperties": false
    }
}

使用明確遞迴參照的結構描述範例:

{
    "type": "object",
    "properties": {
        "linked_list": {
            "$ref": "#/$defs/linked_list_node"
        }
    },
    "$defs": {
        "linked_list_node": {
            "type": "object",
            "properties": {
                "value": {
                    "type": "number"
                },
                "next": {
                    "anyOf": [
                        {
                            "$ref": "#/$defs/linked_list_node"
                        },
                        {
                            "type": "null"
                        }
                    ]
                }
            },
            "additionalProperties": false,
            "required": [
                "next",
                "value"
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "linked_list"
    ]
}

JSON 模式

JSON 模式是結構化輸出功能的基礎版本。JSON 模式可確保模型輸出為有效的 JSON,而結構化輸出則能可靠地讓模型輸出符合你指定的結構描述。如果你的使用情境支援結構化輸出,我們建議使用這項功能。

啟用 JSON 模式後,模型輸出可確保為有效的 JSON,但仍有少數邊界情況例外,你應偵測這些情況並妥善處理。

若要在 Responses API 中啟用 JSON 模式,可以將 text.format 設為 { "type": "json_object" }。如果你使用函式呼叫,JSON 模式一律會啟用。

重要注意事項:

  • 使用 JSON 模式時,你必須在對話中的某則訊息(例如系統訊息)中,明確指示模型產生 JSON。如果沒有明確要求產生 JSON,模型可能會持續輸出空白字元,導致請求不斷執行,直到達到 Token 上限。為了提醒你不要遺漏這項指示,如果上下文中完全沒有出現字串 "JSON",API 就會擲回錯誤。
  • JSON 模式只保證輸出為有效的 JSON 且能順利解析,不保證符合任何特定結構描述。你應使用結構化輸出,確保輸出符合你的結構描述。如果無法使用,則應透過驗證函式庫,並視需要重試,確保輸出符合所需的結構描述。
  • 你的應用程式必須偵測並處理可能導致模型輸出不完整 JSON 物件的邊界情況(見下方)。

資源

若要進一步了解結構化輸出,建議瀏覽以下資源: