Pular para o conteúdo
fernando.moretes.com
BlogEstudosCursosE-booksOpen SourcePodcasts
Loading…
Fernando Azevedo

Arquiteto de TI Especialista

Arquitetura, AWS, IA em produção, sistemas financeiros e FinOps, escritos a partir do que foi operado, com os números.

  • LinkedIn
  • GitHub
  • E-mail

Conteúdo

  • Blog
  • Estudos de arquitetura
  • Cursos
  • E-books
  • Open Source
  • Podcasts
  • Assuntos
  • Trilhas

Ferramentas

  • Well-Architected self-check
  • Arquitetura deste site
  • Números públicos
  • Histórico de estudo

Sobre

  • Comunidade
  • IA Builder
  • Perfil
  • Currículo (CV)
  • Trabalhe comigo
  • Media kit
  • RSS do blog
  • RSS dos estudos
  • Artigos narrados (podcast)
  • llms.txt
  • Termos, privacidade e uso de IA

(c) 2026 Fernando Francisco Azevedo

Trilha Arquiteto de IA/Saída estruturada: JSON confiável e validação
Módulo 2 · Do modelo à aplicação· Aula 08/22

Saída estruturada: JSON confiável e validação

Como obter saídas em formato fixo que o resto do sistema consegue consumir com segurança.

5 min de leitura

Escolha como aprender

combine como quiser

Dica: o vídeo é um resumo visual rápido; o áudio e o texto trazem a aula completa. Terminar o áudio ou o vídeo, ou passar no quiz, já conta a aula como concluída.

Assista a esta aula
Narrado por Fernando AzevedoMP4PDF
Ouça esta aula
0:0010:04
Velocidade
Baixar

Você integrou o modelo, a resposta chegou, e agora precisa fazer o parse. Se o modelo devolveu texto livre, você está no território do improviso: regex frágil, split por linha, esperança. Saída estruturada existe para eliminar esse improviso e fazer o modelo se comportar como uma API que retorna JSON previsível, validável e consumível pelo resto do sistema.

Por que texto livre quebra sistemas

Quando o modelo responde em linguagem natural, ele está otimizando para legibilidade humana, não para parsers. A mesma informação pode aparecer como "R$ 42,00", "42 reais" ou "quarenta e dois reais" dependendo do humor do modelo, da temperatura, da versão. Para um humano lendo, tudo bem. Para um sistema downstream tentando extrair um número, é um pesadelo.

O problema escala quando você encadeia chamadas. Na aula 07 vimos tool calling: o modelo precisa decidir qual ferramenta chamar e com quais argumentos. Se os argumentos chegam como texto livre, a ferramenta não sabe o que fazer com eles. Schema é o contrato entre o modelo e o código que o consome.

A regra prática é simples: se outra parte do sistema vai consumir a saída programaticamente, exija estrutura. Se a saída é para exibição direta ao usuário final, texto livre pode ser aceitável. Em sistemas de agentes, pipelines de extração, classificação, roteamento, você quase sempre está no primeiro caso.

Pipeline de saída estruturada: do prompt à aplicação

Fluxo de como um schema entra no request, o modelo produz JSON constrangido e a aplicação valida antes de usar.

📝 Aplicação: Lado do cliente
  • Aplicação · código do sistema
  • JSON Schema · (Pydantic / Zod / dict)
  • Validação · parse + assert
  • Fallback · retry / default
🤖 Provedor: Inferência
  • API do modelo · (Bedrock / OpenAI / etc.)
  • Decoding constrangido · ou instrução de schema
  • Resposta JSON · (pode ter erros)
⚙️ Sistema downstream
  • Ferramenta / DB · / próxima etapa

Como pedir saída estruturada, e por que validar mesmo assim

Existem três abordagens principais, em ordem crescente de confiabilidade:

1. Instrução no prompt. Você escreve "Responda APENAS com JSON válido seguindo este schema: {...}". Funciona razoavelmente bem com modelos grandes e temperatura baixa, mas é frágil, o modelo pode adicionar texto antes do JSON, usar aspas erradas ou omitir campos opcionais.

2. Modo JSON / response_format. Provedores como OpenAI e Amazon Bedrock (via Converse API) permitem passar um parâmetro que força o modelo a emitir JSON válido. Isso elimina o texto extra, mas não garante que o JSON segue seu schema específico, apenas que é JSON parseável.

3. Structured outputs com schema explícito. A abordagem mais robusta: você passa o JSON Schema completo no request e o provedor usa decoding constrangido (ou equivalente) para garantir que a saída respeita a estrutura campo a campo. OpenAI response_format: {type: "json_schema"}, Anthropic tool-use com schema, Bedrock tool use, todos seguem esse padrão.

Mesmo com a opção 3, sempre valide no seu código. O modelo pode preencher um campo com o tipo errado, retornar null onde você esperava string, ou o provedor pode ter um bug. Use Pydantic (Python), Zod (TypeScript) ou equivalente. Se a validação falhar, você tem duas saídas: retry com a mensagem de erro incluída no contexto, ou degradar para um valor padrão seguro. Nunca deixe um objeto não validado entrar no sistema downstream.

Exemplo prático: extraindo dados de uma nota fiscal

  1. 1

    Defina o schema com Pydantic

    ``python from pydantic import BaseModel from typing import List class ItemNota(BaseModel): descricao: str quantidade: int valor_unitario: float class NotaFiscal(BaseModel): numero: str data_emissao: str # ISO 8601 fornecedor: str itens: List[ItemNota] total: float ``

  2. 2

    Passe o schema no request e valide a resposta

    ```python import json from pydantic import ValidationError def extrair_nota(texto: str, client, model_id: str) -> NotaFiscal | None: schema = NotaFiscal.model_json_schema() response = client.converse( modelId=model_id, messages=[{"role": "user", "content": [{"text": texto}]}], toolConfig={ "tools": [{ "toolSpec": { "name": "extrair_nota_fiscal", "description": "Extrai campos estruturados de uma nota fiscal.", "inputSchema": {"json": schema} } }], "toolChoice": {"tool": {"name": "extrair_nota_fiscal"}} } ) raw = response["output"]["message"]["content"][0]["toolUse"]["input"] try: return

FA
Na prática: tool use como atalho para saída estruturada
Arquiteto de TI Especialista

Na prática, eu uso tool calling como mecanismo principal de saída estruturada, mesmo quando não existe ferramenta real a ser chamada. Você define uma 'ferramenta' cujo único propósito é receber os campos que quer extrair, força o modelo a chamá-la com toolChoice, e recebe os argumentos já parseados. É o padrão mais portável entre provedores (Bedrock, Anthropic, OpenAI todos suportam), elimina o texto extra e te dá o schema no mesmo lugar onde você define a lógica. O custo é um pouco mais de boilerplate, vale cada linha.

A ligação com tool calling e o princípio geral

Na aula 07 você viu que tool calling usa JSON Schema para descrever os argumentos de cada ferramenta. Saída estruturada e tool calling são o mesmo mecanismo visto de ângulos diferentes: em ambos os casos, você está passando um schema para o modelo e esperando que ele produza JSON que respeite esse contrato.

A diferença é semântica: tool calling implica que o modelo está decidindo chamar uma ação externa; saída estruturada implica que você quer extrair informação em formato fixo. Na implementação, muitos provedores usam exatamente o mesmo endpoint e os mesmos parâmetros para os dois casos, por isso o exemplo acima usa toolConfig no Bedrock mesmo para extração pura.

O princípio que unifica tudo: schema é o contrato, validação é a garantia. O modelo é um colaborador probabilístico, ele tenta seguir o contrato, mas pode errar. Seu código é o guardião que decide o que entra no sistema. Nunca transfira essa responsabilidade para o modelo.

Um detalhe de design importante: mantenha seus schemas simples. Schemas com muitos campos opcionais, anyOf aninhados ou estruturas recursivas aumentam a chance de o modelo errar. Se precisar de algo complexo, quebre em múltiplas chamadas com schemas menores, é mais confiável e mais fácil de debugar.

Pontos-chave desta aula

Texto livre quebra sistemas downstream, use saída estruturada sempre que outra parte do código vai consumir a resposta programaticamente.
A abordagem mais confiável é passar o JSON Schema explícito no request (via structured outputs ou tool use), não apenas instruir no prompt.
Sempre valide a saída com Pydantic, Zod ou equivalente, o modelo pode errar o schema mesmo com decoding constrangido.
Falha de validação tem duas saídas: retry com o erro no contexto, ou degradação segura com valor padrão. Nunca propague um objeto não validado.
Tool calling e saída estruturada usam o mesmo mecanismo de schema, você pode usar tool use como atalho para extração estruturada mesmo sem ferramenta real.
Mantenha schemas simples: menos campos opcionais, sem aninhamento excessivo. Schemas complexos aumentam a taxa de erro do modelo.

Abordagens para saída estruturada

AbordagemConfiabilidadePortabilidadeQuando usar
Instrução no promptBaixaAlta (qualquer modelo)Prototipagem rápida, modelos sem suporte a schema
Modo JSON (response_format)Média (JSON válido, schema não garantido)Média (OpenAI, alguns outros)Quando você só precisa de JSON parseável
Schema explícito / Tool useAlta (decoding constrangido ou equivalente)Alta (Bedrock, OpenAI, Anthropic)Produção, pipelines, agentes, padrão recomendado

Dúvidas frequentes

O modelo pode recusar a gerar JSON se o conteúdo for sensível?

Sim. Guardrails e filtros de conteúdo atuam antes do decoding constrangido, se o modelo recusar a resposta, você receberá um erro ou resposta vazia, não JSON malformado. Trate isso como um caso separado na sua lógica de fallback. Veremos guardrails em detalhe na aula 10.

Devo incluir exemplos de JSON no prompt mesmo usando schema explícito?

Às vezes ajuda, especialmente para campos com semântica não óbvia (ex: formato de data esperado, unidades de medida). Mas não substitui o schema, exemplos guiam o conteúdo, schema garante a estrutura. Use os dois quando o domínio for ambíguo.

Quantas vezes devo tentar o retry antes de desistir?

Na maioria dos casos, 1-2 retries com o erro de validação no contexto são suficientes. Se depois de 2 tentativas o modelo ainda errar o schema, o problema provavelmente é o schema em si (muito complexo) ou o modelo escolhido (fraco para a tarefa). Não faça retry infinito, defina um limite e degrade com segurança.

Quiz

Checagem rápida

1. Por que validar a saída estruturada do modelo?

Referências

Amazon Bedrock: Converse API with tool useOpenAI: Structured outputsPydantic: Data validation with PythonZod: TypeScript-first schema validationJSON Schema: Specification
Concluir e ir para a próxima Aula anterior