Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las salidas estructuradas hacen que un modelo siga una definición de esquema JSON que proporcione como parte de la llamada API de inferencia. Este enfoque contrasta con la característica de modo JSON anterior, que garantizaba JSON válido, pero no podía garantizar un cumplimiento estricto del esquema proporcionado. Use salidas estructuradas para llamar a funciones, extraer datos estructurados y crear flujos de trabajo complejos de varios pasos.
Introducción
Puede usar Pydantic para definir esquemas de objeto en Python. En función de la versión de OpenAI y Pydantic las bibliotecas que ejecute, es posible que tenga que actualizar a una versión más reciente. Estos ejemplos se probaron con openai 1.42.0 y pydantic 2.8.2.
pip install openai pydantic azure-identity --upgrade
Si no está familiarizado con el uso de Microsoft Entra ID para la autenticación, consulte How to configure Azure OpenAI in Microsoft Foundry Models with Microsoft Entra ID authentication.
from pydantic import BaseModel
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider,
)
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))
Salida
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
}
}
Llamada a funciones con salidas estructuradas
Las salidas estructuradas para las llamadas a funciones se pueden habilitar con un único parámetro, proporcionando strict: true.
Nota
Las salidas estructuradas no son compatibles con llamadas de función paralelas. Cuando se utilizan salidas estructuradas, fije parallel_tool_calls a false.
import openai
from pydantic import BaseModel
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider,
)
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))
Introducción
Agregue los siguientes paquetes al proyecto:
- OpenAI: biblioteca de .NET OpenAI estándar.
- Azure. Identity: proporciona compatibilidad con la autenticación de tokens Microsoft Entra ID en las bibliotecas de SDK de Azure.
dotnet add package OpenAI
dotnet add package Azure.Identity
Si no está familiarizado con el uso de Microsoft Entra ID para la autenticación, consulte How to configure Azure OpenAI in Microsoft Foundry Models with Microsoft Entra ID authentication.
using Azure.Identity;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel.Primitives;
using System.Text.Json;
#pragma warning disable OPENAI001
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ChatClient client = new(
model: "gpt-4.1",
authenticationPolicy: tokenPolicy,
options: new OpenAIClientOptions()
{
Endpoint = new Uri("https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1")
}
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
jsonSchemaFormatName: "math_reasoning",
jsonSchema: BinaryData.FromBytes("""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""u8.ToArray()),
jsonSchemaIsStrict: true)
};
// Create a list of ChatMessage objects
ChatCompletion completion = client.CompleteChat(
[
new UserChatMessage("How can I solve 8x + 7 = -23?")
],
options);
using JsonDocument structuredJson = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine($"Final answer: {structuredJson.RootElement.GetProperty("final_answer")}");
Console.WriteLine("Reasoning steps:");
foreach (JsonElement stepElement in structuredJson.RootElement.GetProperty("steps").EnumerateArray())
{
Console.WriteLine($" - Explanation: {stepElement.GetProperty("explanation")}");
Console.WriteLine($" Output: {stepElement.GetProperty("output")}");
}
Introducción
response_format se configura en json_schema con strict: true establecido.
curl -X POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_DEPLOYMENT_NAME",
"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
}
}
}
}'
Salida:
{
"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"
}
Llamada a funciones con salidas estructuradas
curl -X POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_DEPLOYMENT_NAME",
"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
}
}
}
]
}'
Compatibilidad y limitaciones del esquema JSON
Azure OpenAI admite las mismas salidas estructuradas y el mismo subconjunto del esquema JSON que OpenAI.
Tipos admitidos
- Cadena
- Número
- Boolean
- Entero
- Objeto
- Matriz
- Enumeración
- anyOf
Nota
Los objetos raíz no pueden ser el anyOf tipo .
Todos los campos deben ser obligatorios
Incluya todos los campos o parámetros de función según sea necesario. En el ejemplo siguiente, tanto location como unit aparecen bajo "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"]
}
}
Si es necesario, puede emular un parámetro opcional mediante un tipo de unión con null. En este ejemplo, este enfoque se representa mediante la línea "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"
]
}
}
Profundidad de anidamiento
Un esquema puede tener hasta 100 propiedades de objeto totales, con hasta cinco niveles de anidamiento.
Establezca siempre additionalProperties: false en los objetos
Esta propiedad controla si un objeto puede tener otros pares de valores de clave que no se definieron en el esquema JSON. Para usar salidas estructuradas, establezca este valor en false.
Ordenación de claves
Las salidas estructuradas siguen el mismo orden que el esquema proporcionado. Para cambiar el orden de salida, modifique el orden del esquema que envía como parte de la solicitud de inferencia.
No admitidas palabras clave específicas del tipo
| Tipo | Palabra clave no admitida |
|---|---|
| Cadena | longitud mínima longitudMáxima patrón formato |
| Número | mínimo máximo multipleOf |
| Objetos | patternProperties propiedades no evaluadas propertyNames minProperties maxProperties |
| Arreglos | elementos no evaluados contiene minContains maxContains minItems maxItems uniqueItems |
Los esquemas anidados que usan anyOf deben ajustarse al subconjunto de esquema JSON general
Esquema anyOf admitido de ejemplo:
{
"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"
]
}
Se admiten definiciones
Ejemplo soportado:
{
"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
}
Se admiten esquemas recursivos
Ejemplo con # para la recursividad raíz:
{
"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
}
}
Ejemplo de recursividad explícita:
{
"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"
]
}
Nota
Actualmente, las salidas estructuradas no son compatibles con:
- Traiga sus propios escenarios de datos .
- Asistentes o Foundry Agents Service.
-
gpt-4o-audio-previewygpt-4o-mini-audio-previewVersión:2024-12-17.
Modelos admitidos
-
gpt-5.1-codexVersión:2025-11-13 -
gpt-5.1-codex miniVersión:2025-11-13 -
gpt-5.1Versión:2025-11-13 -
gpt-5.1-chatVersión:2025-11-13 -
gpt-5-proVersión2025-10-06 -
gpt-5-codexVersión2025-09-11 -
gpt-5Versión2025-08-07 -
gpt-5-miniVersión2025-08-07 -
gpt-5-nanoVersión2025-08-07 -
codex-miniVersión2025-05-16 -
o3-proVersión2025-06-10 -
o3-miniVersión2025-01-31 -
o1Versión:2024-12-17 -
gpt-4o-miniVersión:2024-07-18 -
gpt-4oVersión:2024-08-06 -
gpt-4oVersión:2024-11-20 -
gpt-4.1Versión2025-04-14 -
gpt-4.1-nanoVersión2025-04-14 -
gpt-4.1-miniVersión:2025-04-14 -
o4-miniVersión:2025-04-16 -
o3Versión:2025-04-16
Compatibilidad con API
La versión 2024-08-01-preview de API es la primera versión que admite salidas estructuradas. Las API de versión preliminar más recientes y la API de disponibilidad general más reciente, v1, también admiten salidas estructuradas.