Pular para o conteúdo principal

Structured Outputs

Structured Outputs ensure that the data generated by models adheres to predefined user-provided schemas, such as JSON, simplifying integrations into applications. When the response format is critical, strategies like regular expressions (regex) can be employed, but these approaches are often fragile, complex, and unable to guarantee that all fields are extracted accurately and consistently. On the other hand, Structured Outputs offer a more reliable solution, reducing errors and facilitating direct integration. However, in cases where narrative responses or flexibility are a priority, their use is not necessary.

Use Cases Examples​

1. Data Extraction​

Extract structured information from unstructured text:

from pydantic import BaseModel
import openai
import json

client = openai.OpenAI(
api_key="", #Your API_KEY
base_url="https://chat.maritaca.ai/api",
)

class EventDetails(BaseModel):
event_name: str
date: str
participants: list[str]
attire: list[str]

response = client.responses.create(
model="sabia-4",
instructions="Extract event details.",
input="João and Maria are going to a June festival on Saturday at 6 PM in Campina Grande. They will be dressed for the occasion: Maria in a floral dress and João in a plaid shirt and straw hat.",
text={
"format": {
"type": "json_schema",
"name": "event_details",
"schema": EventDetails.model_json_schema()
}
},
)

event_response = json.loads(response.output[0].content[0].text)

print(event_response)

2. Sentiment Analysis​

Identify sentiments in texts:

import openai
import json

client = openai.OpenAI(
api_key="", #Your API_KEY
base_url="https://chat.maritaca.ai/api",
)

sentiment_schema = {
"type": "object",
"properties": {
"text": {"type": "string"},
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
},
"required": ["text", "sentiment"],
}

response = client.responses.create(
model="sabia-4",
instructions="Classify the sentiment of the text as positive, negative, or neutral.",
input="I hated the job offered!",
text={
"format": {
"type": "json_schema",
"name": "sentiment_analysis",
"schema": sentiment_schema
}
},
)

result = json.loads(response.output[0].content[0].text)
print(result)

3. Reading Plan​

Generate a structured reading plan based on the user's request, validating the data with a JSON schema and displaying the books with their details.

from enum import Enum
from typing import List, Optional
from pydantic import BaseModel
import openai
import json

client = openai.OpenAI(
api_key="", #Your API_KEY
base_url="https://chat.maritaca.ai/api",
)

class ReadingType(str, Enum):
classic = "classic"
contemporary = "contemporary"

class Book(BaseModel):
type: ReadingType
title: str
author: str
description: str

Book.model_rebuild()

class ReadingPlan(BaseModel):
plan_name: str
books: List[Book]

response = client.responses.create(
model="sabia-4",
instructions="You are a reading plan generator. Convert the user's request into a structured reading plan.",
input="Create a reading plan to explore Brazilian literature, including classics and contemporary works.",
text={
"format": {
"type": "json_schema",
"name": "reading_plan",
"schema": ReadingPlan.model_json_schema()
}
},
)

reading_plan = ReadingPlan.model_validate(json.loads(response.output[0].content[0].text))

print("Plan Name:", reading_plan.plan_name)
print("Books:")
for book in reading_plan.books:
print(f" - {book.title} by {book.author}: {book.description}")


4. Usage with Stream​

In the case of stream usage, structured outputs can be processed in real time as they are generated, providing a more interactive experience. This method is particularly advantageous for handling tasks involving the generation of large volumes of data or extensive responses. Below, we present an example:

from typing import List
from pydantic import BaseModel
import openai
import json

class TypicalDishesModel(BaseModel):
dishes: List[str]

client = openai.OpenAI(
api_key="", #Your API_KEY
base_url="https://chat.maritaca.ai/api",
)

stream = client.responses.create(
model="sabia-4",
instructions="Identify the typical Brazilian dishes in the provided text.",
input="At the June festival, we have canjica, pamonha, curau, and quentão, along with lots of music and dancing.",
text={
"format": {
"type": "json_schema",
"name": "typical_dishes",
"schema": TypicalDishesModel.model_json_schema()
}
},
stream=True,
)

full_text = ""
for event in stream:
if event.type == "response.output_text.delta":
full_text += event.delta
print(event.delta, end="", flush=True)

print()
result = TypicalDishesModel.model_validate(json.loads(full_text))
print("Parsed result:", result)


How to Use the text.format Parameter​

The text.format parameter in the Responses API is used to instruct the model to generate responses that follow a predefined structured format. The values for text.format.type are:

  1. JSON Schema (json_schema): Define a JSON schema to validate the structure and data types of the response.
text={"format": {"type": "json_schema", "name": "my_schema", "schema": {...}}}
  1. Pydantic Models: Use Pydantic classes to generate the schema automatically.
text={"format": {"type": "json_schema", "name": "my_schema", "schema": MyModel.model_json_schema()}}
  1. Simple JSON Object: Also known as json mode, where a JSON object is requested without additional validations:
text={"format": {"type": "json_object"}}

Best Practices​

  • Define Clear Schemas: Use tools like JSON Schema or Pydantic to design appropriate schemas.
  • Validate Input: Ensure that user inputs are compatible with the schema.
  • Error Handling: Include logic to handle refusals or malformed responses programmatically.

💡
JSON MODE

The JSON mode only ensures that the model's output is valid JSON. Structured Outputs, on the other hand, reliably match the model's output to the schema you specify. We recommend using Structured Outputs if it is supported for your use case. When using JSON mode, if the instruction to produce a JSON object is not explicitly passed to the model, it may generate an endless stream of whitespace, and the request could run continuously until it reaches the token limit.


Supported Schemas​

Structured Outputs is compatible with a subset of JSON Schema, allowing you to use the following types: String, Number, Boolean, Integer, Object, Array, Enum, anyOf, and oneOf. To maintain stability and proper functionality, some JSON Schema features are not supported — for example: minLength, maxLength, pattern, format, minimum, maximum, multipleOf, minItems, maxItems, uniqueItems, minProperties, maxProperties, allOf, patternProperties, unevaluatedProperties, propertyNames, unevaluatedItems, and contains.

When working with objects, you can use up to 100 properties, with a maximum of 5 levels of nesting. To optimize your schema's structure, the total length of all property names, definitions, enum values, and const values must remain below 15,000 characters. For enum fields, you can include up to 500 values in total. However, if a single enum exceeds 250 values (all of type string), the total length of those values must stay below 7,500 characters. If any limit is exceeded or if any unsupported feature is encountered, an error will be generated.