Freigeben über


Strukturierte Ausgaben

Bei strukturierten Ausgaben befolgt das Modell eine JSON-Schemadefinition, die Sie als Teil des Rückschluss-API-Aufrufs bereitstellen. Dies steht im Gegensatz zum älteren Feature im JSON-Modus, bei dem garantiert gültiger JSON-Code generiert wurde, aber die strikte Einhaltung des bereitgestellten Schemas nicht sichergestellt werden konnte. Strukturierte Ausgaben werden für Funktionsaufrufe, für das Extrahieren strukturierter Daten und das Erstellen komplexer mehrstufiger Workflows empfohlen.

Hinweis

Unterstützte Modelle

Derzeit unterstützt nur die gpt-4o-Version 2024-08-06 strukturierte Ausgaben.

API-Unterstützung

Die Unterstützung für strukturierte Ausgaben wurde zuerst in der API-Version 2024-08-01-preview eingeführt.

Erste Schritte

Sie können zum Definieren von Objektschemas in Python Pydantic verwenden. Je nachdem, welche Version von OpenAI und Pydantic-Bibliotheken Sie ausführen, müssen Sie möglicherweise ein Upgrade auf eine neuere Version durchführen. Diese Beispiele wurden mit openai 1.42.0 und pydantic 2.8.2 getestet.

pip install openai pydantic --upgrade

Wenn Sie mit der Verwendung von Microsoft Entra ID für die Authentifizierung noch nicht vertraut sind, lesen Sie Konfigurieren von Azure OpenAI Service mit Microsoft Entra ID-Authentifizierung.

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-08-01-preview"
)


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

Output

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

Funktionsaufrufe mit strukturierten Ausgaben

Strukturierte Ausgaben für Funktionsaufrufe können mit einem einzelnen Parameter aktiviert werden, indem strict: truebereitgestellt wird.

Hinweis

Strukturierte Ausgaben werden bei parallelen Funktionsaufrufen nicht unterstützt. Legen Sie bei Verwendung strukturierter Ausgaben parallel_tool_calls auf false fest.

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-08-01-preview"
)


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

Unterstützte Schemas und Einschränkungen

Strukturierte Azure OpenAI-Ausgaben unterstützen dieselbe Teilmenge des JSON-Schemas wie OpenAI.

Unterstützte Typen

  • String
  • Zahl
  • Boolean
  • Ganzzahl
  • Objekt
  • Array
  • Enum
  • anyOf

Hinweis

Stammobjekte können nicht vom Typ anyOf sein.

Alle Felder müssen erforderlich sein.

Alle Felder oder Funktionsparameter müssen als erforderlich eingeschlossen werden. Im folgenden Beispiel werden location und unit unter "required": ["location", "unit"] angegeben.

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

Bei Bedarf können Sie einen optionalen Parameter emulieren, indem Sie einen Union-Typ mit null verwenden. In diesem Beispiel wird dies in der Zeile "type": ["string", "null"], umgesetzt.

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

Schachtelungstiefe

Ein Schema kann insgesamt bis zu 100 Objekteigenschaften mit maximal fünf Schachtelungsebenen enthalten.

„additionalProperties: false“ muss in Objekten immer festgelegt werden.

Diese Eigenschaft steuert, ob ein Objekt zusätzliche Schlüssel-Wert-Paare enthalten kann, die im JSON-Schema nicht definiert sind. Um strukturierte Ausgaben verwenden zu können, müssen Sie diesen Wert auf FALSE festlegen.

Schlüsselreihenfolge

Strukturierte Ausgaben werden wie im angegebenen Schema sortiert. Um die Ausgabereihenfolge zu ändern, ändern Sie die Reihenfolge im Schema, das Sie als Teil Ihrer Rückschlussanforderung übergeben.

Nicht unterstützte, typspezifische Schlüsselwörter

type Nicht unterstütztes Schlüsselwort
String minlength
maxLength
Muster
format
Anzahl minimum
maximum
multipleOf
Objekte patternProperties
unevaluatedProperties
propertyNames
minProperties
maxProperties
Arrays unevaluatedItems
contains
minContains
maxContains
minItems
maxItems
uniqueItems

Geschachtelte Schemas mit anyOf müssen der allgemeinen JSON-Schemateilmenge entsprechen.

Beispiel für ein unterstütztes anyOf-Schema:

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

Definitionen werden unterstützt.

Unterstütztes Beispiel:

{
	"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
}

Rekursive Schemas werden unterstützt.

Beispiel für die Verwendung von # für die Stammrekursion:

{
        "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
        }
    }

Beispiel für die explizite Rekursion:

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