结构化输出使模型遵循你在推理 API 调用中提供的 JSON 架构定义。 这与旧的 JSON 模式功能形成鲜明对比,该功能保证将生成有效的 JSON,但无法确保严格遵循提供的架构。 建议使用结构化输出进行函数调用、提取结构化数据以及生成复杂的多步骤工作流。
注意
目前不支持结构化输出的有:
- 自带数据场景。
- 助手 或 Azure AI 代理服务。
gpt-4o-audio-preview
和gpt-4o-mini-audio-preview
版本:2024-12-17
。
支持的模型
gpt-4.5-preview
版本2025-02-27
o3-mini
版本2025-01-31
o1
版本:2024-12-17
gpt-4o-mini
版本:2024-07-18
gpt-4o
版本:2024-08-06
gpt-4o
版本:2024-11-20
gpt-4.1
版本2025-04-14
gpt-4.1-nano
版本2025-04-14
gpt-4.1-mini
版本:2025-04-14
o4-mini
版本:2025-04-16
o3
版本:2025-04-16
API 支持
在 API 版本 2024-08-01-preview
中首次添加了对结构化输出的支持。 它在最新的预览版 API 以及最新的 GA API 中提供:2024-10-21
。
入门
可使用 Pydantic
在 Python 中定义对象架构。 根据你运行的 OpenAI 和 Pydantic
库的版本,你可能需要升级到较新版本。 这些示例是针对 openai 1.42.0
和 pydantic 2.8.2
进行测试的。
pip install openai pydantic --upgrade
如果不熟悉如何使用 Microsoft Entra ID 进行身份验证,请参阅 如何使用 Microsoft Entra ID 身份验证在 Azure AI Foundry 模型中配置 Azure OpenAI。
import os
from pydantic import BaseModel
from openai import AzureOpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
)
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
azure_ad_token_provider=token_provider,
api_version="2024-10-21"
)
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
completion = client.beta.chat.completions.parse(
model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
messages=[
{"role": "system", "content": "Extract the event information."},
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
],
response_format=CalendarEvent,
)
event = completion.choices[0].message.parsed
print(event)
print(completion.model_dump_json(indent=2))
输出
name='Science Fair' date='Friday' participants=['Alice', 'Bob']
{
"id": "chatcmpl-A1EUP2fAmL4SeB1lVMinwM7I2vcqG",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"logprobs": null,
"message": {
"content": "{\n \"name\": \"Science Fair\",\n \"date\": \"Friday\",\n \"participants\": [\"Alice\", \"Bob\"]\n}",
"refusal": null,
"role": "assistant",
"function_call": null,
"tool_calls": [],
"parsed": {
"name": "Science Fair",
"date": "Friday",
"participants": [
"Alice",
"Bob"
]
}
}
}
],
"created": 1724857389,
"model": "gpt-4o-2024-08-06",
"object": "chat.completion",
"service_tier": null,
"system_fingerprint": "fp_1c2eaec9fe",
"usage": {
"completion_tokens": 27,
"prompt_tokens": 32,
"total_tokens": 59
}
}
使用结构化输出进行函数调用
可以通过一个参数来启用函数调用的结构化输出,方法是提供 strict: true
。
注意
并行函数调用不支持结构化输出。 使用结构化输出时,将 parallel_tool_calls
设置为 false
。
from enum import Enum
from typing import Union
from pydantic import BaseModel
import openai
from openai import AzureOpenAI
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-10-21"
)
class GetDeliveryDate(BaseModel):
order_id: str
tools = [openai.pydantic_function_tool(GetDeliveryDate)]
messages = []
messages.append({"role": "system", "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user."})
messages.append({"role": "user", "content": "Hi, can you tell me the delivery date for my order #12345?"})
response = client.chat.completions.create(
model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
messages=messages,
tools=tools
)
print(response.choices[0].message.tool_calls[0].function)
print(response.model_dump_json(indent=2))
入门
将以下包添加到项目以用于 Azure OpenAI:
- Azure.AI.OpenAI:为 Azure OpenAI 客户端提供基于标准 OpenAI 库依赖项构建的 Azure 特定功能。
- Azure.Identity:提供跨 Azure SDK 库的 Microsoft Entra ID 令牌身份验证支持。
- Newtonsoft.Json.Schema:为处理 JSON 架构提供有用的实用工具。
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Newtonsoft.Json.Schema
如果不熟悉如何使用 Microsoft Entra ID 进行身份验证,请参阅 如何使用 Microsoft Entra ID 身份验证在 Azure AI Foundry 模型中配置 Azure OpenAI。
using Azure.AI.OpenAI;
using Azure.Identity;
using Newtonsoft.Json.Schema.Generation;
using OpenAI.Chat;
using System.ClientModel;
// Create the clients
string endpoint = GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
AzureOpenAIClient openAIClient = new(
new Uri(endpoint),
new DefaultAzureCredential());
var client = openAIClient.GetChatClient("gpt-4o");
// Create a chat with initial prompts
var chat = new List<ChatMessage>()
{
new SystemChatMessage("Extract the event information and projected weather."),
new UserChatMessage("Alice and Bob are going to a science fair in Seattle on June 1st, 2025.")
};
// Get the schema of the class for the structured response
JSchemaGenerator generator = new JSchemaGenerator();
var jsonSchema = generator.Generate(typeof(CalendarEvent)).ToString();
// Get a completion with structured output
var chatUpdates = client.CompleteChatStreamingAsync(
chat,
new ChatCompletionOptions()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"calenderEvent",
BinaryData.FromString(jsonSchema))
});
// Write the structured response
await foreach (var chatUpdate in chatUpdates)
{
foreach (var contentPart in chatUpdate.ContentUpdate)
{
Console.Write(contentPart.Text);
}
}
// The class for the structured response
public class CalendarEvent()
{
public string Name { get; set; }
public string Date { get; set; }
public List<string> Participants { get; set; }
}
使用结构化输出进行函数调用
可以通过一个参数来启用函数调用的结构化输出,方法是提供 strict: true
。
using Azure.AI.OpenAI;
using Newtonsoft.Json.Schema.Generation;
using OpenAI.Chat;
using System.ClientModel;
// Create the clients
string endpoint = GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
AzureOpenAIClient openAIClient = new(
new Uri(endpoint),
new DefaultAzureCredential());
var chatClient = openAIClient.GetChatClient("gpt-4o");
// Local function to be used by the assistant tooling
string GetTemperature(string ___location, string date)
{
// Placeholder for Weather API
if(___location == "Seattle" && date == "2025-06-01")
{
return "75";
}
return "50";
}
// Create a tool to get the temperature
ChatTool GetTemperatureTool = ChatTool.CreateFunctionTool(
functionName: nameof(GetTemperature),
functionSchemaIsStrict: true,
functionDescription: "Get the projected temperature by date and ___location.",
functionParameters: BinaryData.FromBytes("""
{
"type": "object",
"properties": {
"___location": {
"type": "string",
"description": "The ___location of the weather."
},
"date": {
"type": "string",
"description": "The date of the projected weather."
}
},
"required": ["___location", "date"],
"additionalProperties": false
}
"""u8.ToArray())
);
// Create a chat with prompts
var chat = new List<ChatMessage>()
{
new SystemChatMessage("Extract the event information and projected weather."),
new UserChatMessage("Alice and Bob are going to a science fair in Seattle on June 1st, 2025.")
};
// Create a JSON schema for the CalendarEvent structured response
JSchemaGenerator generator = new JSchemaGenerator();
var jsonSchema = generator.Generate(typeof(CalendarEvent)).ToString();
// Get a chat completion from the AI model
var completion = chatClient.CompleteChat(
chat,
new ChatCompletionOptions()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"calenderEvent",
BinaryData.FromString(jsonSchema)),
Tools = { GetTemperatureTool }
});
Console.WriteLine(completion.Value.ToolCalls[0].FunctionName);
// Structured response class
public class CalendarEvent()
{
public string Name { get; set; }
public string Date { get; set; }
public string Temperature { get; set; }
public List<string> Participants { get; set; }
}
入门
response_format
设置为 json_schema
并设置了 strict: true
。
curl -X POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_MODEL_DEPLOYMENT_NAME/chat/completions?api-version=2024-10-21 \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "system", "content": "Extract the event information."},
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "CalendarEventResponse",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"date": {
"type": "string"
},
"participants": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"date",
"participants"
],
"additionalProperties": false
}
}
}
}'
输出:
{
"id": "chatcmpl-A1HKsHAe2hH9MEooYslRn9UmEwsag",
"object": "chat.completion",
"created": 1724868330,
"model": "gpt-4o-2024-08-06",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\n \"name\": \"Science Fair\",\n \"date\": \"Friday\",\n \"participants\": [\"Alice\", \"Bob\"]\n}"
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 33,
"completion_tokens": 27,
"total_tokens": 60
},
"system_fingerprint": "fp_1c2eaec9fe"
}
使用结构化输出进行函数调用
curl -X POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_MODEL_DEPLOYMENT_NAME/chat/completions?api-version=2024-10-21 \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are a helpful assistant. The current date is August 6, 2024. You help users query for the data they are looking for by calling the query function."
},
{
"role": "user",
"content": "look up all my orders in may of last year that were fulfilled but not delivered on time"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "query",
"description": "Execute a query.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"table_name": {
"type": "string",
"enum": ["orders"]
},
"columns": {
"type": "array",
"items": {
"type": "string",
"enum": [
"id",
"status",
"expected_delivery_date",
"delivered_at",
"shipped_at",
"ordered_at",
"canceled_at"
]
}
},
"conditions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"column": {
"type": "string"
},
"operator": {
"type": "string",
"enum": ["=", ">", "<", ">=", "<=", "!="]
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "object",
"properties": {
"column_name": {
"type": "string"
}
},
"required": ["column_name"],
"additionalProperties": false
}
]
}
},
"required": ["column", "operator", "value"],
"additionalProperties": false
}
},
"order_by": {
"type": "string",
"enum": ["asc", "desc"]
}
},
"required": ["table_name", "columns", "conditions", "order_by"],
"additionalProperties": false
}
}
}
]
}'
支持的架构和限制
Azure OpenAI 结构化输出支持与 OpenAI 相同的 JSON 架构子集。
支持的类型
- 字符串
- 数字
- 布尔
- 整数
- 对象
- 数组
- 枚举
- anyOf
注意
根对象不能是 anyOf
类型。
所有字段都必须是必填的
必须根据需要包含所有字段或函数参数。 在下面的示例中,___location
和 unit
都在 "required": ["___location", "unit"]
下指定。
{
"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
一起使用来模拟可选参数。 在此示例中,这是通过 "type": ["string", "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"
]
}
}
嵌套深度
一个架构总共最多可以有 100 个对象属性,最多五个嵌套级别
additionalProperties: false 必须始终在对象中设置
此属性控制对象是否可以具有 JSON 架构中未定义的附加键值对。 若要使用结构化输出,必须将此值设置为 false。
键排序
结构化输出的排序方式与提供的架构相同。 若要更改输出顺序,请修改你在推理请求中发送的架构的顺序。
不支持的与类型相关的关键字
类型 | 不支持的关键字 |
---|---|
字符串 | minlength 最大长度 (maxLength) pattern 格式 |
数字 | 最小值 最大值 multipleOf |
对象 | patternProperties unevaluatedProperties propertyNames minProperties maxProperties |
数组 | unevaluatedItems contains minContains maxContains minItems maxItems uniqueItems |
使用 anyOf 的嵌套架构必须遵循整个 JSON 架构子集
支持的 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"
]
}