Como a IA gera JSON conforme ao JSON Schema: do Prompt ao Structured Output

Do JSON só no prompt e JSON Mode aos Structured Outputs — restrições JSON Schema, comparação OpenAI / Gemini / Anthropic, pipeline de validação e diferença do Tool Calling.

Postagens anteriores desta série abordadaspor que os agentes precisam de JSON(Chamada de ferramenta para fluxo de dados MCP),por que JSON Schema⟧ se tornou infraestrutura(Esquema, Chamada de Função e evolução MCP), eConfiguração Structured Output específica do Gemini(Guia Gêmeos API).

Este artigo diminui o zoom:independentemente de qual modelo API você usa, como você passa de “responda em JSON” para “a saída deve corresponder a este JSON esquema⟧”? Os fornecedores convergiram para isso em 2024-2026 sob nomes como Structured Outputs⟧ / JSON Schema⟧ mode - mesma ideia, nomes de campo ligeiramente diferentes, subconjuntos de esquema e limites com Tool Calling.

Quatro níveis, cada um estritoer que o anterior

As equipes normalmente usam quatro abordagens para obter JSON de um modelo – a confiabilidade difere em uma ordem de grandeza:

NívelAbordagemO que você controlaFalha típica
L0Somente prompt: “saída JSON”Restrição suave```json fences, prose, single quotes, trailing commas
L1Prompt + exemplos JSON de algumas fotosMolde pelo exemplo, sem regras rígidasDesvio de nome de campo, campos ausentes, tipos mistos
L2JSON Mode⟧ (response_format: json_object, etc.)A saída deve ser válida JSONParses, but price may be a string
L3Saída Estruturada+ JSON Esquema⟧Campos, tipos, enum, obrigatóriosAlucinação semântica, truncamento, palavras-chave ignoradas

For production extraction, classification, or form filling, aim for L3. L0–L1 suit exploration; L2 when shape varies and you only need JSON.parse. L3 is the contract programs can consume directly.

O que o JSON Schema⟧ controla — e o que não controla

JSON Esquema⟧descreve a estrutura do documento: campos, tipos, chaves obrigatórias, enumerações, intervalos, formato do item da matriz. As Structured Outputs do fornecedor compilam esse esquema na geração - não apenas cola-o no prompt.

Schema can enforce: syntax shape (object / array / string / integer), required, enum, minimum / maximum, additionalProperties: false, nested objects and arrays.

Schema cannot enforce business correctness. Example: “total_cents must equal sum of line items” — assert that in code after Schema validation. Schema also does not fact-check: a well-typed fabricated invoice number is still hallucination.

Tool inputSchema uses the same language; Structured Output constrains the final reply, Tool Calling constrains tool arguments. See guia de fluxo de dados.

Decodificação restrita: por que o Schema supera o Prompt

As solicitações apenas aumentam as chances de conformidade. Saída Estruturada usadecodificação restrita: em cada token, o decodificador suprime tokens que quebrariam a sintaxe JSON ou violariam o esquema.

Você geralmente obtém JSON analisável e com formato correto, sem barreiras de marcação de remoção de regex. As implementações diferem (FSM, gramática, máscaras logit), mas o contrato do desenvolvedor é o mesmo:passe o esquema para a API, não apenas para o prompt.

Garantias de decodificação restritasestrutura, nãosemântica. Sempre revalide com o mesmo esquema e adicione regras de negócio em produção.

Comparação OpenAI, Gemini, Anthropic

Mesmo conceito, nomes de campo diferentes. Exemplo: extrair um objeto de fatura.

FornecedorJSON Modo⟧Saída Estruturada / EsquemaNotas
OpenAIresponse_format: { type: "json_object" }response_format: { type: "json_schema", json_schema: { name, schema, strict: true } }strict: true rejects undeclared fields; works with Pydantic model_json_schema()
Google GêmeosresponseMimeType: "application/json"Above + responseJsonSchema or SDK response_schemaVerartigo dedicado Gemini API
AntrópicoSolicitar + analisaroutput_format (Claude structured output) or schema in Messages APIOs campos evoluem com o SDK; manter o esquema plano

When migrating vendors, keep the Schema itself standard JSON Schema⟧ (type, properties, required, enum); SDKs only wrap the request. Do not mix OpenAPI 3.0 uppercase types (OBJECT) with JSON Schema⟧ lowercase (object).

Escrevendo um bom esquema: do Pydantic à produção

Recommended flow: define types in Pydantic / Zod → export JSON Schema⟧ → tune → send to API. Put semantics in description — it enters model context and disambiguates “qty = pieces vs boxes”; type: integer alone cannot.

from pydantic import BaseModel, Field


class LineItem(BaseModel):
    name: str = Field(description="Product name")
    qty: int = Field(description="Quantity, positive integer", ge=1)
    unit_price_cents: int = Field(description="Unit price in cents", ge=0)


class Invoice(BaseModel):
    vendor: str
    currency: str = Field(description="ISO 4217, e.g. CNY")
    items: list[LineItem]
    total_cents: int

schema = Invoice.model_json_schema()
# In production add additionalProperties: false

Regras práticas:

  • Prefer object root over root-level array; { "items": [...] } is more stable on some APIs.
  • Start with type / properties / required / enum, then add additionalProperties, min/max; do not dump full Draft 2020-12 — some keywords are ignored.
  • Continue aninhando superficialmente; referências circulares são rejeitadas - nivelar o esquema.
  • Esquema dividido vs prompt: Esquema = forma; Prompt = semântica (“extrair fatura do texto abaixo…”).

OpenAI Saída Estruturadas⟧ exemplo

Chat Completions supports json_schema response format since 2024. With strict: true, output should only contain Schema fields:

from openai import OpenAI
from pydantic import BaseModel

client = OpenAI()

class Invoice(BaseModel):
    vendor: str
    total_cents: int

response = client.chat.completions.create(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "user", "content": "Extract invoice: Acme sold 2 keyboards for 398 CNY."}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "invoice",
            "strict": True,
            "schema": Invoice.model_json_schema(),
        },
    },
)

data = response.choices[0].message.content  # JSON string
import json
invoice = json.loads(data)

Gemini uses response_mime_type + response_json_schema — see the dedicated Gemini API article. For Anthropic, check current SDK structured output docs — same idea, official field names.

Pipeline de produção: gerar → analisar → validar → tentar novamente

Saída Estruturada não é “uma chamada de API e pronto”. Corrija estas quatro etapas:

  1. Generate: call model with Schema; log prompt, Schema version, raw content.
  2. Parse: JSON.parse (or SDK parsed); on failure, retry whole response — no half-parse.
  3. Schema validate: run same JSON Schema⟧ via AJV / jsonschema / Pydantic; retry or degrade on failure.
  4. Validação de negócios: declarações personalizadas (totais, chaves estrangeiras); mecanismo humano ou de regras em caso de falha.

No desenvolvimento, armazene o Schema mais 2–3 amostras positivas/negativas no repositório; use JSON Toolbox⟧ localmente para estrutura e Diff - mesma mentalidade dos testes de contrato REST, o consumidor é o LLM.

Armadilhas comuns: pedir “explique então JSON” enquanto o JSON Mode⟧ está ativado; truncamento (aumentar o máximo de tokens ou dividir tarefas); Chaves API em demonstrações de frontend; Desvio da versão do esquema no prompt.

Como isso difere de Tool Calling

Saída EstruturadaChamada de ferramenta / MCP
RestriçõesResposta final JSON ao usuárioTool argument JSON (inputSchema)
Efeitos colateraisNenhum – apenas dadosHost / MCP Servidor é executado
Uso típicoExtrair, classificar, preencher formulários, transferir agentesInventário, arquivos, APIs externas
Em caso de falhaTente novamente ou humanoErro na mensagem da ferramenta → perguntar novamente ao modelo

Um loop de agente completo geralmente se parece com:Saída Estruturada extrai intenção → Chamada de Ferramenta atos → Saída Estruturada ou resumos em prosa para o usuário. Não use Structured Output para fingir que “o API de pagamento foi chamado” – o modelo não o chamou.

Perguntas frequentes

“Por favor, envie JSON” no prompt é suficiente?

Não. Os prompts apenas aumentam as chances de conformidade – barreiras de redução, vírgulas finais e desvios de campo ainda acontecem. Na produção, habilite pelo menos JSON Mode⟧; idealmente, passe JSON Schema⟧ através do canal API Structured Output para que a decodificação exclua tokens ilegais.

Qual é a diferença entre JSON Mode⟧ e Structured Output?

O modo JSON garante apenas texto JSON válido, não nomes de campos, tipos ou chaves obrigatórias. Structured Output adiciona JSON Schema⟧ e filtra tokens durante a geração - a forma se estabiliza para que você possa armazenar ou passar diretamente para o próximo salto.

Os campos de configuração OpenAI, Gemini e Anthropic são iguais?

Mesmo conceito, nomes diferentes. OpenAI: formato_de_resposta com json_schema e strict; Gemini: responseMimeType + responseJsonSchema; Anthropic: output_format ou saída estruturada em ferramentas. Mantenha o padrão do Schema; Os SDKs agrupam solicitações.

A Saída Estruturada pode substituir a Chamada de Ferramenta?

Não. Saída Estruturada restringe a resposta JSON final; Tool Calling restringe o argumento da ferramenta JSON e requer que o host execute ferramentas. Use o primeiro para extrair/classificar/preencher; o último para inventário, arquivos, MCP. Cadeias completas de agentes geralmente usam ambos.

Ainda preciso validar a saída do modelo?

Sim. A decodificação restrita elimina erros de sintaxe e desvio de tipo, mas não a correção semântica (tipos válidos, valores fabricados). Execute novamente o mesmo JSON Schema⟧ em produção; tentar novamente, degradar ou revisar em caso de falha.

Como valido o esquema e a amostra de saída localmente?

Salve JSON Schema⟧ e alguns exemplos de saída do modelo como arquivos JSON; use JSON Toolbox⟧ no navegador para verificações de sintaxe e estrutura - nada é carregado.

Resumo

Para obter JSON que corresponda ao JSON Schema⟧ da IA, o pedido é importante:defina o esquema primeiro, habilite JSON Mode⟧ / Structured Output e, em seguida, escreva o prompt. Prompt = semântica; Esquema = forma; Pydantic / Zod são frentes amigas do autor; APIs do fornecedor expõem canais de esquema.

Execute uma fatura real ou transcrição de suporte de ponta a ponta: Esquema → chamada API → cole a saída em um validador. Quando corresponder, conecte o banco de dados ou o próximo agente. Os argumentos da ferramenta ainda passam por Tool Calling / MCP - não se fundem em um API.