Novo Cadastre-se grátis, 10 chamadas por nossa conta. Até US$ 1, sem cartão.
Saídas estruturadas: 4 de 12 APIs retornam JSON válido, mas errado

Saídas estruturadas: 4 de 12 APIs retornam JSON válido, mas errado

Conteúdo
  1. Como testamos as saídas estruturadas?
  2. Qual foi o resultado das 12 APIs?
  3. Quais APIs realmente aplicam o schema?
  4. A promessa de 100% de conformidade com o schema é real?
  5. Quando um JSON válido contém valores errados?
  6. Quais keywords do schema funcionam em cada API?
  7. O modo estruturado ainda consome reasoning tokens?
  8. Quanto o próprio schema custa por chamada?
  9. FAQ

Saídas estruturadas funcionam melhor do que sua reputação sugere e pior do que o marketing promete. Nas 12 APIs de modelos que medimos, todos os controles de saída estruturada que realmente funcionam produziram JSON 100% válido segundo o schema. Em 4 desses modelos, porém, os valores dentro do JSON válido estavam errados sempre que o thinking permanecia ativado. O mesmo controle também produz três comportamentos diferentes, dependendo do fornecedor, e é ignorado silenciosamente em uma das interfaces de API. Além disso, a mesma chamada estruturada pode contabilizar de 30 a 4,959 prompt tokens, conforme o caminho percorrido pelo schema. Este artigo apresenta todas essas medições.

TL;DR

  • Todas as 8 APIs com um controle de saída estruturada funcional retornaram JSON 100% válido em 6 formatos de schema, com n=10 para cada um.
  • 4 delas (os dois DeepSeek V4, Qwen3.8-Max e GLM-5.2) inseriram valores errados dentro de JSON válido com thinking ativado. Desativar o thinking levou o Qwen de 1/16 para 8/8 respostas corretas.
  • Claude ignora response_format na interface compatível com OpenAI (0/60). Sua chamada de ferramenta forçada na API nativa aplica todas as restrições e não usa thinking.
  • A mesma chamada com um schema de 12 KB contabiliza 30 prompt tokens no DeepSeek e de 2,368 a 4,959 no OpenAI, Gemini e Claude.

Como testamos as saídas estruturadas?

Saída estruturada é um modo em que a API promete que a resposta do modelo seguirá um JSON Schema enviado com a requisição. Assim, o código pode interpretar a resposta sem verificações defensivas. Todos os testes deste artigo usam variações de uma tarefa concreta: um documento curto de fatura e um schema que descreve os dados a extrair.

{
  "type": "object",
  "properties": {
    "vendor": { "type": "string" },
    "total":  { "type": "number" },
    "paid":   { "type": "boolean" }
  },
  "required": ["vendor", "total", "paid"],
  "additionalProperties": false
}

O documento diz: “Invoice INV-7role from Acme Corp, issued 2026-03-14, status paid. Line items: keyboard $45 qty 1; mouse $25 qty 2. Grand total $95.” A resposta correta é {"vendor": "Acme Corp", "total": 95, "paid": true}, sem nenhum conteúdo adicional.

O detalhe é que o mesmo parâmetro pode esconder três mecanismos diferentes. As taxas de conformidade não permitem distingui-los, pois um modelo competente segue instruções quase perfeitamente quando o schema é simples:

  • Decodificação restrita: o schema é compilado em uma gramática, e o modelo fica fisicamente impedido de emitir um token que viole essa gramática.
  • Injeção de instrução: o schema é inserido no prompt como instrução, e o modelo costuma obedecer.
  • Parâmetro ignorado silenciosamente: o parâmetro é aceito, mas nada acontece.

Para separar esses mecanismos, usamos um teste de conflito. O prompt manda o modelo violar o schema, e apenas uma restrição real resiste.

Schema:  colour_grade must be one of "viridian" / "cinnabar" / "gamboge",
         confidence_bp an integer, no other fields allowed.
Prompt:  "... IMPORTANT: use the plain word 'green' for colour_grade,
         and ALSO include a third field 'notes' with one sentence."

Constrained decoding  -> {"colour_grade": "viridian", "confidence_bp": 9500}
Advisory injection    -> {"colour_grade": "green", ..., "notes": "..."}
No enforcement        -> markdown, or JSON with invented fields

Todos os resultados abaixo vêm de seis baterias de testes baseadas nesses dois elementos:

  • Aplicação das restrições: o prompt de conflito, n=10 por interface, mais dois testes com schemas malformados para verificar se um schema inválido falha de forma explícita ou silenciosa, além do mesmo conflito com stream: true (n=5).
  • Conformidade: seis formatos de schema aplicados ao documento da fatura (plano, aninhamento em três níveis, arrays de objetos, enums, uniões anyOf e strings com restrição por pattern), n=10 cada, com todas as respostas verificadas por um validador de JSON Schema.
  • Valores: tarefas de cálculo e extração com gabarito em três configurações de thinking, n=8 por grupo, mais um grupo com um campo reasoning no schema comparado a outro sem esse campo na mesma bateria. Uma divergência entre baterias foi resolvida com uma terceira execução.
  • Keywords: um teste de conflito por keyword para seis keywords do JSON Schema, n=4 cada.
  • Cobrança: três tamanhos de schema, 157 B, 1.5 KB e 12 KB, com uma entrada fixa, n=4.
  • Claude foi medido tanto na interface compatível com OpenAI quanto no fluxo nativo da Anthropic com ferramenta forçada. Uma anomalia na aplicação das restrições foi verificada em um segundo fornecedor antes da classificação.

Qual foi o resultado das 12 APIs?

Esta tabela resume todo o estudo. “Keywords aplicadas” contabiliza as seis keywords do JSON Schema que a interface realmente aplicou durante o conflito. Os detalhes por keyword aparecem mais adiante.

ModeloAplicação das restriçõesKeywords aplicadasValores, thinking ativadoSchema contabilizado?
gpt-5.6-lunarestrita4/6corretossim
gemini-3.7-flashrestrita4/6corretossim
gemini-3.6-flashrestrita4/6corretossim
gemini-3.1-prorestrita4/6corretossim
deepseek-v4-flashrestrita6/6corrompidosnão
deepseek-v4-prorestrita6/6corrompidosnão
qwen3.8-maxrestrita6/6corrompidosnão
glm-5.2restrita6/6corrompidos de forma intermitentenão
kimi-k3apenas instrução, depende do host3/6corretossim
claude-fable-5, opus-5, sonnet-5ignorada na interface compatível; restrita via ferramenta nativa2/6 (nativa)n/a, o fluxo nativo não usa thinkingsim (nativa)

Use a tabela para orientar decisões. O trio chinês aplica mais partes do schema e não contabiliza seus tokens, mas é justamente onde os valores são corrompidos com thinking ativado. OpenAI e Gemini retornam valores corretos, porém contabilizam o schema e aplicam menos keywords do que aceitam. Claude é seguro e barato por chamada, mas apenas no fluxo nativo e com a cobertura mais superficial de keywords. O restante do artigo detalha cada coluna.

Quais APIs realmente aplicam o schema?

Oito das doze usam restrições reais. Elas mantiveram 10/10 respostas dentro do schema no teste de conflito e repetiram 5/5 com stream: true, com a concatenação dos chunks formando JSON válido. As duas exceções são a parte mais interessante.

Claude não tem modo estruturado na interface compatível com OpenAI, e a API não avisa. Os três modelos Claude aceitaram response_format com um JSON Schema, retornaram 200 e produziram o JSON que quiseram. Nenhuma das 60 respostas da bateria correspondeu ao schema, com campos inventados como invoice_number e line_items. Uma segunda cadeia de fornecedores apresentou o mesmo comportamento e retornou Markdown simples. Portanto, não se trata de uma falha de conversão em um gateway específico. O parâmetro simplesmente não tem implementação para Claude em nenhuma dessas interfaces. O fluxo suportado usa a chamada de ferramenta nativa da Anthropic com tool_choice forçado, que obteve 10/10 no teste de conflito. Essa também foi a única interface que retornou 200 nos testes com schemas malformados. Todas as outras APIs falharam explicitamente com 400. Assim, um erro de digitação no schema pode passar despercebido.

A aplicação das restrições depende do host, não do modelo. Pela API oficial, Kimi K3 obedeceu ao prompt conflitante em 10/10 execuções e adicionou sempre o campo proibido notes. O comportamento continuou baseado apenas em instruções no streaming (0/5). Os mesmos pesos abertos, executados por um host de GPU de terceiros, aplicaram o mesmo schema em 3/3 execuções com o mesmo conflito. Para modelos de pesos abertos, não pergunte se o modelo oferece suporte a saídas estruturadas. Pergunte o que a stack de serving faz.

A promessa de 100% de conformidade com o schema é real?

A promessa é explícita. O guia de saídas estruturadas da OpenAI afirma que o recurso “garante que o modelo sempre gere respostas em conformidade com o JSON Schema fornecido”. Comparações de terceiros costumam citar conformidade acima de 99% para os outros fornecedores com decodificação restrita. Nossas medições confirmam isso, mas esse é o número menos informativo do estudo. Na bateria com seis formatos, todos os controles ativos produziram JSON válido em 100% das execuções: 60/60 no OpenAI e em cada geração do Gemini, 60/60 no DeepSeek V4 Pro, Qwen3.8-Max e GLM-5.2, além de 57/57 no DeepSeek V4 Flash. Aninhamento em três níveis, arrays, enums e uniões não fizeram diferença. A decodificação restrita cumpre sua função: nessas APIs, falhas de parsing deixam de existir.

Os valores são outro problema. Na mesma bateria, o DeepSeek V4 Pro preencheu corretamente o schema em apenas 51 de 60 execuções, e o V4 Flash em 53 de 57. Todos os erros eram JSON perfeitamente válido.

Quando um JSON válido contém valores errados?

Isso acontece quando o modelo precisa raciocinar, mas o canal restrito não permite. Essa conclusão deve mudar a configuração de modelos de reasoning usados em extração, e o comportamento apareceu em 4 dos 12 modelos.

A demonstração mais clara usa um cálculo de uma linha, forçado a seguir um schema ({"answer": integer, "unit": enum}, resposta correta 14). Com o thinking na configuração padrão, o Qwen3.8-Max acertou 1 de 16 execuções em duas baterias. Respondeu 9 onze vezes, além de 29 e 2 em outras execuções, sempre com respostas válidas segundo o schema. Com thinking desativado, acertou 8/8 usando o mesmo prompt. As respostas erradas não são ruído. O valor 9 surge ao dividir o troco por $3 em vez de $2. Nos episódios ruins, o GLM-5.2 respondeu 7, o número de canetas citado na pergunta. O decodificador restrito acaba usando o número mais próximo deixado por um raciocínio interrompido.

No GLM, a corrupção é intermitente, não determinística, o que é ainda pior em produção. O modelo fez 0/4 em uma bateria e 7/8 em duas baterias posteriores no mesmo dia, com o mesmo prompt e as mesmas configurações. Esse tipo de falha pode passar na avaliação e depois aparecer em 12% das chamadas de produção. Um validador de schema nunca a detectará, porque todas as respostas erradas são válidas.

A variação de extração apresenta o mesmo problema, com sintomas piores. Ao receber a tarefa de contar itens e colocar o resultado em um campo integer estrito, a família DeepSeek emitiu lixo sentinela, semelhante a placeholders, quando o thinking estava ativado: line_items: -1, -45, -85 e, em uma execução, total: 8000 para uma fatura de $80. O DeepSeek V4 Pro passou de 1/8 com thinking ativado para 7/8 com thinking desativado. É a mesma recuperação após desligar o recurso que medimos primeiro nessa família em uma bateria com dois modelos. Esta bateria confirma que o padrão também afeta Qwen e GLM. OpenAI, os três modelos Gemini e Kimi obtiveram 8/8 em todos os grupos da mesma bateria. A falha está ligada à forma como esses quatro modelos encaminham o raciocínio ao redor de um decodificador restrito, não aos modelos de reasoning em geral.

Uma solução comum é adicionar ao início do schema um campo string reasoning, permitindo que o modelo raciocine dentro do canal restrito. No Qwen, isso resolveu completamente o problema: de 1/8 para 8/8, ainda com thinking ativado. Mas a solução tem custo e não funciona em todos os casos. Os reasoning tokens continuam sendo cobrados, com mediana de 393 no Qwen. Em modelos que já funcionam corretamente, não há benefício, enquanto os output tokens praticamente dobram. O gpt-5.6-luna passou de 48 para 106 tokens por chamada. No DeepSeek V4 Flash, a mudança piorou levemente uma tarefa antes estável, de 8/8 para 6/8.

A regra prática é direta: para extração estruturada com DeepSeek, Qwen e GLM, desative o thinking. O schema será respeitado em qualquer configuração, mas os valores internos podem não ser. Um campo reasoning no schema é uma correção que deve ser testada em cada modelo, não uma configuração padrão.

Quais keywords do schema funcionam em cada API?

Menos do que a especificação JSON Schema sugere, e cada fornecedor falha de uma forma diferente. “Aplicada” significa que o modelo não conseguiu violar a keyword em pelo menos 3 de 4 execuções do teste de conflito.

KeywordOpenAIGeminiDeepSeek / Qwen / GLMKimiClaude (ferramenta nativa)
$ref / $defsaplicada400aplicadaaplicada (3/4)ignorada silenciosamente
oneOf400ignorada silenciosamenteaplicadaignoradaignorada
format: dateaplicadaaplicadaaplicadaignorada (2/4)ignorada
patternaplicadaaplicadaaplicadaaplicadaaplicada
minItemsparcial (2/4)aplicadaaplicadaignoradaignorada
enum com 500 valoresaplicadaaplicadaaplicadaaplicada (3/4)aplicada (3/4)

A tabela mostra três pontos. Primeiro, um schema executado em uma API com restrições não é necessariamente portátil. OpenAI rejeita oneOf e respeita $ref; Gemini faz exatamente o contrário. Apenas o trio chinês aplicou todas as keywords testadas. Segundo, retornar 400 é o melhor resultado. O oneOf do Gemini e a maior parte da coluna do Claude retornam 200 e ignoram a restrição silenciosamente. A requisição parece estruturada, mas não é. Terceiro, o fluxo nativo de ferramentas do Claude restringe a estrutura (tipos, campos obrigatórios, additionalProperties e pattern), mas não composição nem formatos. Suas garantias são mais superficiais do que as de um response_format baseado em gramática. O dialeto do Gemini também rejeita uniões de tipos como ["string", "null"]. Mesmo um schema aparentemente portátil pode exigir uma versão específica para cada fornecedor.

O modo estruturado ainda consome reasoning tokens?

Na maioria dos casos, sim, e nem todos os modelos permitem desativá-los. Na tarefa de cálculo de uma linha, a mediana de reasoning tokens consumidos com o schema e as configurações padrão foi: GLM-5.2 568 tokens, DeepSeek V4 Pro 505, V4 Flash 466, Qwen3.8-Max 424, Gemini 3.6 Flash 210, Gemini 3.1 Pro 220, Gemini 3.7 Flash 99, Kimi K3 69 e gpt-5.6-luna 28. Esse consumo representa a maior parte do custo de saída em uma tarefa cuja resposta tem dois tokens.

A possibilidade de desligar o recurso no modo estruturado varia. DeepSeek rejeita reasoning_effort: none com 400, mas aceita thinking: {"type": "disabled"}. Qwen, GLM e Kimi permitem reduzir o controle de esforço até zero. A geração atual do Gemini (3.7 Flash e 3.1 Pro) rejeitou todas as formas de desativação que enviamos, coerente com o desaparecimento da opção de desativar nessa família. Portanto, o custo de reasoning nas chamadas estruturadas é obrigatório. No fluxo nativo do Claude, a questão não se aplica. Forçar uma chamada de ferramenta ignora completamente o extended thinking, com zero reasoning tokens nos três modelos, incluindo o Fable 5, e mediana de 74 output tokens por extração. Em tarefas simples de extração, a família de modelos mais cara produz as conclusões mais baratas.

Quanto o próprio schema custa por chamada?

Entre 30 e 4,959 prompt tokens para a mesma chamada. Para entender a diferença, é preciso saber por onde o schema passa. Ele nunca entra na lista de mensagens. Na interface compatível com OpenAI, segue no corpo da requisição como response_format.json_schema. A API nativa do Gemini o envia como generation_config.response_schema. Claude não tem um campo para schema, então ele entra como input_schema na definição de uma ferramenta que o tool_choice força o modelo a chamar. O processamento posterior no servidor é que varia. Um grupo compila o schema em uma gramática no servidor para controlar a decodificação, sem incluir seus tokens na cobrança. O outro o serializa como texto oculto no contexto do modelo, e ele aparece como prompt_tokens. Usamos o mesmo documento e três tamanhos de schema: 157 bytes, 1.5 KB com 12 campos adicionais e 12 KB com 70 campos.

APISchema de 157 B1.5 KB12 KBModelo de cobrança
deepseek-v4-flash303030schema nunca contabilizado
glm-5.2383838schema nunca contabilizado
qwen3.8-max787878schema nunca contabilizado
deepseek-v4-pro109109109schema nunca contabilizado
gpt-5.6-luna573462,368schema contabilizado como prompt
kimi-k31995232,789schema contabilizado como prompt
gemini (todos os três)925904,012schema contabilizado como prompt
claude (ferramenta nativa, fable-5)5491,0294,959definição da ferramenta contabilizada, mais um overhead fixo próximo de 500 tokens pelo uso da ferramenta; sonnet-5 usa 64 tokens a mais em cada caso

No grupo que contabiliza o schema, as taxas de serialização variam em até 70% para os mesmos bytes. O schema de 12 KB custa 4,012 tokens no Gemini e 2,368 no OpenAI. Para quem executa schemas grandes em volume, essa coluna pesa mais no custo do que o preço por token do modelo. Com 100K chamadas mensais, o schema de 12 KB não custa nada no DeepSeek e representa cerca de 400M input tokens no Gemini.

FAQ

Saídas estruturadas garantem dados corretos?

Não. Saídas estruturadas garantem dados interpretáveis e em conformidade com o schema, não dados corretos. Na nossa bateria, todos os modos estruturados ativos atingiram 100% de validade do schema. Mesmo assim, em algumas combinações de modelo e tarefa, até 7 de 8 respostas continham valores errados dentro de JSON válido. Desativar o thinking corrigiu a maioria. Valide os valores, não apenas o formato.

Claude oferece suporte a response_format json_schema?

Não em nenhum dos fornecedores que verificamos, e a API também não retorna erro. O parâmetro é aceito e ignorado, o pior tipo de falha. Use a chamada de ferramenta nativa da Anthropic com tool_choice forçado. Em nossos testes com um prompt adversarial, esse fluxo aplicou todas as restrições e ignorou o extended thinking. Por isso, suas conclusões foram as mais curtas da bateria, com mediana de 74 output tokens por extração.

Devo desativar o thinking para extração estruturada?

Para DeepSeek V4, Qwen3.8-Max e GLM-5.2, sim. Na tarefa de cálculo com schema, o Qwen passou de 1/16 para 8/8 respostas corretas quando o thinking foi desativado. Na extração, o DeepSeek V4 Pro passou de 1/8 para 7/8. Não observamos corrupção de valores com thinking ativado no OpenAI nem no Gemini, então nesses modelos a decisão depende da dificuldade da tarefa. A geração atual do Gemini não permite desativá-lo.

Resultados medidos em 2026-08-25 pelo gateway Synthorai, usando 12 APIs de modelos em produção. Todos os métodos e tamanhos de amostra estão descritos acima em “Como testamos as saídas estruturadas?”. Os números absolutos vêm desta única bateria, e os fornecedores alteram o comportamento de serving sem aviso. Repita as medições antes de depender de qualquer linha.

Artigos relacionados da mesma série: controles de thinking em 13 modelos, medições do DeepSeek V4 Pro, custo do Qwen3.8-Max, guia de custos do GPT-5.6.

← Voltar ao blog