Структурированные выходные данные

Структурированные выходные данные позволяют модели соответствовать определению схемы JSON , предоставленному в рамках вызова API вывода. Это отличается от более старой функции режима JSON , которая гарантирует, что будет создано допустимое JSON, но не удалось обеспечить строгое соблюдение предоставленной схемы. Структурированные выходные данные рекомендуется использовать для вызова функций, извлечения структурированных данных и создания сложных многофакторных рабочих процессов.

Начало работы

Для определения схем объектов в Python можно использовать Pydantic. В зависимости от версии OpenAI и Pydantic библиотек , которые вы используете, может потребоваться обновить до более новой версии. Эти примеры были проверены на openai 1.42.0 и pydantic 2.8.2.

pip install openai pydantic azure-identity --upgrade

Если вы не знакомы с использованием Microsoft Entra ID для проверки подлинности, ознакомьтесь с Как настроить Azure OpenAI в моделях Microsoft Foundry с аутентификацией Microsoft Entra ID.

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))

Выход

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.

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))

Начало работы

Добавьте в проект следующие пакеты:

  • OpenAI: библиотека Standard OpenAI .NET.
  • Azure. Identity: предоставляет поддержку проверки подлинности маркеров Microsoft Entra ID в библиотеках Azure SDK.
dotnet add package OpenAI
dotnet add package Azure.Identity

Если вы не знакомы с Microsoft Entra ID для проверки подлинности, ознакомьтесь с руководством по настройке Azure OpenAI в моделях Microsoft Foundry с использованием проверки подлинности с помощью Microsoft Entra ID.

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")}");
}

Начало работы

response_format устанавливается на json_schema, с установленным strict: true.

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
                    }
                }
          }
  }'

Выход:

{
  "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/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
        }
      }
    }
  ]
}'

Поддержка и ограничения схемы JSON

Поддержка структурированных выходных данных Azure OpenAI охватывает то же подмножество схемы JSON, что и OpenAI.

Поддерживаемые типы

  • Строка
  • Номер
  • Логических
  • Целое число
  • Объект
  • Массив
  • Перечисление
  • любой из

Примечание

Корневые объекты не могут быть типом 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.

Порядок ключей

Структурированные выходные данные упорядочены так же, как и указанная схема. Чтобы изменить порядок вывода, измените порядок схемы, которую вы отправляете в рамках запроса вывода.

Ключевые слова неподдерживаемого типа

Тип Неподдерживаемое ключевое слово
Строка минимальная_длина
макс. длина
Узор
Формат
Номер минимум
Максимальная
multipleOf
Объекты patternProperties
неоценённыеСвойства
propertyNames
минимумСвойств (minProperties)
maxProperties
Массивы неоценённыеЭлементы
Содержит
minContains
maxContains
minItems
maxItems
уникальныеЭлементы

Вложенные схемы, использующие 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"
    ]
}

Примечание

В настоящее время структурированные выходные данные не поддерживаются:

Поддерживаемые модели

  • gpt-5.1-codex Версия: 2025-11-13
  • gpt-5.1-codex mini Версия: 2025-11-13
  • gpt-5.1 Версия: 2025-11-13
  • gpt-5.1-chat Версия: 2025-11-13
  • gpt-5-pro Версия 2025-10-06
  • gpt-5-codex Версия 2025-09-11
  • gpt-5 Версия 2025-08-07
  • gpt-5-mini Версия 2025-08-07
  • gpt-5-nano Версия 2025-08-07
  • codex-mini Версия 2025-05-16
  • o3-pro Версия 2025-06-10
  • 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

Поддержка структурированных выходных данных была добавлена в версию 2024-08-01-previewAPI. Он доступен в последних предварительных версиях API, а также в последней общедоступной версии API: v1.