Structured Output
Garanta respostas em JSON válido com esquemas definidos e saída estruturada.
Visão Geral
Structured Output permite obter respostas do modelo em formato JSON garantidamente válido, seguindo um esquema que você define. Isso elimina a necessidade de parsing frágil e garante integração confiável com sistemas downstream.
Endpoint
POST https://api.polar-ai.com/v1/chat/completionsUse o endpoint de Chat Completions com o parâmetro response_format.
Tipos de response_format
| Tipo | Descrição |
|---|---|
{"type": "text"} | Resposta em texto livre (padrão) |
{"type": "json_object"} | JSON válido sem esquema definido |
{"type": "json_schema", "json_schema": {...}} | JSON válido seguindo um esquema específico |
JSON Object (Sem Esquema)
O modelo retorna JSON válido, mas sem um esquema específico:
Python
from openai import OpenAI
client = OpenAI(
base_url="https://api.polar-ai.com/v1",
api_key="pk-your-key-here"
)
response = client.chat.completions.create(
model="urso-base",
messages=[
{
"role": "system",
"content": "Você sempre responde em formato JSON."
},
{
"role": "user",
"content": "Liste 3 estados brasileiros com suas capitais e população estimada."
}
],
response_format={"type": "json_object"}
)
import json
data = json.loads(response.choices[0].message.content)
print(json.dumps(data, indent=2, ensure_ascii=False))TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.polar-ai.com/v1",
apiKey: "pk-your-key-here",
});
const response = await client.chat.completions.create({
model: "urso-base",
messages: [
{
role: "system",
content: "Você sempre responde em formato JSON.",
},
{
role: "user",
content: "Liste 3 estados brasileiros com suas capitais e população estimada.",
},
],
response_format: { type: "json_object" },
});
const data = JSON.parse(response.choices[0].message.content!);
console.log(JSON.stringify(data, null, 2));curl
curl -X POST https://api.polar-ai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer pk-your-key-here" \
-d '{
"model": "urso-base",
"messages": [
{"role": "system", "content": "Você sempre responde em formato JSON."},
{"role": "user", "content": "Liste 3 estados brasileiros com suas capitais e população estimada."}
],
"response_format": {"type": "json_object"}
}'JSON Schema (Com Esquema)
Defina exatamente a estrutura do JSON que o modelo deve retornar:
Python
from openai import OpenAI
client = OpenAI(
base_url="https://api.polar-ai.com/v1",
api_key="pk-your-key-here"
)
response = client.chat.completions.create(
model="urso-pro",
messages=[
{
"role": "user",
"content": "Extraia as informações da seguinte nota fiscal: Emitente ACME LTDA, CNPJ 12.345.678/0001-90, valor total R$1.500,00, data 15/03/2024, 3 itens."
}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "nota_fiscal",
"strict": True,
"schema": {
"type": "object",
"properties": {
"emitente": {
"type": "object",
"properties": {
"razao_social": {"type": "string"},
"cnpj": {"type": "string"}
},
"required": ["razao_social", "cnpj"],
"additionalProperties": False
},
"valor_total": {"type": "number"},
"data_emissao": {"type": "string"},
"numero_itens": {"type": "integer"}
},
"required": ["emitente", "valor_total", "data_emissao", "numero_itens"],
"additionalProperties": False
}
}
}
)
import json
nfe = json.loads(response.choices[0].message.content)
print(f"Emitente: {nfe['emitente']['razao_social']}")
print(f"CNPJ: {nfe['emitente']['cnpj']}")
print(f"Valor: R${nfe['valor_total']:.2f}")TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.polar-ai.com/v1",
apiKey: "pk-your-key-here",
});
const response = await client.chat.completions.create({
model: "urso-pro",
messages: [
{
role: "user",
content:
"Extraia as informações: Emitente ACME LTDA, CNPJ 12.345.678/0001-90, valor total R$1.500,00, data 15/03/2024.",
},
],
response_format: {
type: "json_schema",
json_schema: {
name: "nota_fiscal",
strict: true,
schema: {
type: "object",
properties: {
emitente: {
type: "object",
properties: {
razao_social: { type: "string" },
cnpj: { type: "string" },
},
required: ["razao_social", "cnpj"],
additionalProperties: false,
},
valor_total: { type: "number" },
data_emissao: { type: "string" },
},
required: ["emitente", "valor_total", "data_emissao"],
additionalProperties: false,
},
},
},
});
const nfe = JSON.parse(response.choices[0].message.content!);
console.log(`Emitente: ${nfe.emitente.razao_social}`);
console.log(`Valor: R$${nfe.valor_total.toFixed(2)}`);curl
curl -X POST https://api.polar-ai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer pk-your-key-here" \
-d '{
"model": "urso-pro",
"messages": [
{
"role": "user",
"content": "Extraia: Emitente ACME LTDA, CNPJ 12.345.678/0001-90, valor R$1.500,00, data 15/03/2024."
}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "nota_fiscal",
"strict": true,
"schema": {
"type": "object",
"properties": {
"emitente": {
"type": "object",
"properties": {
"razao_social": {"type": "string"},
"cnpj": {"type": "string"}
},
"required": ["razao_social", "cnpj"],
"additionalProperties": false
},
"valor_total": {"type": "number"},
"data_emissao": {"type": "string"}
},
"required": ["emitente", "valor_total", "data_emissao"],
"additionalProperties": false
}
}
}
}'Casos de Uso
Extração de Dados
Extraia informações estruturadas de texto não estruturado:
schema = {
"type": "object",
"properties": {
"nome": {"type": "string"},
"cpf": {"type": "string"},
"endereco": {
"type": "object",
"properties": {
"rua": {"type": "string"},
"cidade": {"type": "string"},
"estado": {"type": "string"},
"cep": {"type": "string"}
},
"required": ["rua", "cidade", "estado", "cep"],
"additionalProperties": False
},
"telefones": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["nome", "cpf", "endereco", "telefones"],
"additionalProperties": False
}
response = client.chat.completions.create(
model="urso-base",
messages=[
{"role": "user", "content": "João Silva, CPF 123.456.789-00, mora na Rua das Flores 100, São Paulo-SP, CEP 01001-000. Telefones: (11) 99999-0000 e (11) 3333-4444."}
],
response_format={
"type": "json_schema",
"json_schema": {"name": "pessoa", "strict": True, "schema": schema}
}
)Classificação
Classifique textos em categorias predefinidas:
response = client.chat.completions.create(
model="urso-base",
messages=[
{"role": "user", "content": "Classifique: 'O produto chegou quebrado e o vendedor não responde.'"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "classificacao",
"strict": True,
"schema": {
"type": "object",
"properties": {
"categoria": {
"type": "string",
"enum": ["reclamacao", "elogio", "duvida", "sugestao"]
},
"sentimento": {
"type": "string",
"enum": ["positivo", "negativo", "neutro"]
},
"urgencia": {
"type": "string",
"enum": ["baixa", "media", "alta"]
},
"resumo": {"type": "string"}
},
"required": ["categoria", "sentimento", "urgencia", "resumo"],
"additionalProperties": False
}
}
}
)Restrições com Regex
Para campos que precisam seguir um padrão específico, use pattern:
{
"cpf": {
"type": "string",
"pattern": "^[0-9]{3}\\.[0-9]{3}\\.[0-9]{3}-[0-9]{2}$"
}
}Dicas de Uso
- Sempre defina
"additionalProperties": falsepara respostas previsíveis - Use
"strict": truepara garantir aderência ao esquema - Inclua
enumpara campos com valores fixos - O modelo respeita o esquema mesmo em respostas longas e complexas
- Combine com Vision para extração de dados de imagens
Próximos Passos
- Function Calling — use com ferramentas externas
- Document AI — extração estruturada de documentos
- Batch API — processamento em lote com saída estruturada