Como tornar resultados estruturados de LLM portáteis em OpenAI, Anthropic e Gemini
Um guia prático para projetar resultados LLM estruturados portáteis em OpenAI, Anthropic e Gemini usando esquemas canônicos, compilação específica do provedor, validação, limites de reparo e testes de contrato.
Os resultados do LLM estruturado tornam-se frágeis quando as equipes tratam o suporte do provedor como intercambiável. OpenAI, Anthropic e Gemini podem produzir dados estruturados, mas não expõem o mesmo contrato. A sintaxe do esquema, os envelopes de chamada de ferramenta, as garantias de rigor, o comportamento de recusa, o comportamento de streaming e os modos de falha de validação diferem o suficiente para que um analisador que funciona com um modelo possa falhar silenciosamente com outro.
A solução prática é parar de tratar os recursos de saída estruturados específicos do provedor como o contrato comercial. Defina um contrato de saída canônico para cada fluxo de trabalho, compile-o no formato de solicitação compatível de cada provedor, valide cada resposta em relação ao esquema canônico e teste cada modelo antes que ele possa servir o tráfego de produção.
O que é saída estruturada portátil?
A saída estruturada portátil significa que o aplicativo pode contar com o mesmo formato de resposta em nível de negócios, mesmo quando o provedor do modelo subjacente muda. Isso não significa que todos os provedores recebem exatamente o mesmo JSON esquema. Isso também não significa que a validação do lado do provedor seja suficiente.
Um contrato portátil tem cinco camadas:
- Esquema canônico: o formato de dados neutro em relação ao provedor do fluxo de trabalho.
- Linting de portabilidade: verifica se o esquema evita construções sem suporte, com aplicação fraca ou arriscadas entre provedores.
- Compilação do provedor: tradução do contrato canônico para OpenAI, Anthropic, Gemini ou para a superfície de saída estruturada nativa de outro provedor.
- Validação em tempo de execução: validação no lado do aplicativo do objeto retornado em relação ao esquema canônico.
- Testes de contrato: testes repetíveis que comprovam que cada modelo lida com campos obrigatórios, enumerações, recusas, truncamento, solicitações malformadas e casos extremos semânticos antes das alterações no roteamento de produção.
Esse padrão é especialmente importante para um LLM empresarial API onde várias equipes, inquilinos ou fluxos de trabalho de parceiros dependem de contratos de saída previsíveis.
Fatos: a saída estruturada do provedor não é um padrão
Antes de projetar a camada de portabilidade, separe o comportamento documentado do provedor das suposições.
OpenAI
OpenAI documenta saídas estruturadas como distintas do modo JSON. O modo JSON destina-se a garantir JSON válido, enquanto as saídas estruturadas destinam-se a corresponder a um esquema JSON fornecido. OpenAI suporta saída estruturada por meio de formatação de resposta e chamada de função com estrita adesão ao esquema, mas o comportamento documentado inclui restrições de modelo e versão e um subconjunto de esquema compatível. Esquemas não suportados no modo estrito podem produzir API erros, e os aplicativos ainda precisam lidar com casos extremos.
Anthropic
Anthropic documenta Claude o uso da ferramenta como chamadas de ferramenta estruturadas com base em ferramentas fornecidas pelo desenvolvedor com um input_schema. O modelo retorna um bloco tool_use e o aplicativo executa a ferramenta solicitada. Isso se assemelha à chamada de função, mas não é o mesmo contrato que uma resposta de esquema OpenAI formato de resposta JSON. A orientação de engenharia de Anthropic também observa que JSON o esquema pode definir estrutura, campos obrigatórios e enumerações, mas não pode expressar padrões de uso, como quando parâmetros opcionais devem ser incluídos ou quais combinações de campos fazem sentido para os negócios.
Gemini
A documentaçãoGoogle de Gemini API diz que a saída estruturada pode ser configurada para JSON respostas e que o modo de saída estruturada Gemini suporta um subconjunto da especificação JSON Schema. Isso é importante porque um esquema válido JSON Schema ainda pode ser inadequado como um esquema de solicitação de provedor portátil.
Observabilidade
As convenções semânticas do OpenTelemetry GenAI incluem atributos para provedor, modelo solicitado, modelo de resposta, tipo de saída, motivos de conclusão, uso de token, definições de ferramenta, argumentos de chamada de ferramenta e campos de solicitação e resposta GenAI relacionados. Esses campos podem oferecer suporte à depuração entre provedores quando é difícil distinguir falhas de saída estruturada de problemas de prompt, esquema, modelo ou provedor.
Etapa 1: definir o esquema comercial canônico
Comece com o fluxo de trabalho comercial, não com o provedor API. Um fluxo de trabalho de triagem de suporte, um fluxo de trabalho de extração de faturas, uma recomendação de aprovação ou um endpoint de automação voltado para o parceiro devem ter, cada um, um esquema canônico que represente o que o aplicativo precisa no downstream.
Por exemplo, um fluxo de trabalho de triagem de suporte pode usar esta forma canônica:
{
"type": "object",
"additionalProperties": false,
"required": ["category", "priority", "summary", "requires_human_review"],
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "security", "account", "other"]
},
"priority": {
"type": "string",
"enum": ["low", "normal", "high", "urgent"]
},
"summary": {
"type": "string",
"minLength": 1,
"maxLength": 500
},
"requires_human_review": {
"type": "boolean"
},
"customer_risk_signals": {
"type": "array",
"items": { "type": "string" },
"maxItems": 5
}
}
}
Esse esquema é o contrato em que o restante do aplicativo confia. A partir dele são gerados formatos de solicitação específicos do provedor; eles não são a fonte da verdade.
Use campos obrigatórios explícitos, matrizes limitadas, strings limitadas, enumerações fechadas e additionalProperties: false onde seu validador suportar. Evite aceitar objetos aninhados arbitrários, a menos que o sistema downstream seja projetado para lidar com chaves arbitrárias.
Etapa 2: adicionar um Lint de portabilidade de esquema Etapa
Um linter de portabilidade deve rejeitar esquemas que sejam tecnicamente válidos JSON Esquema, mas arriscado para uso em vários modelos. O objetivo não é a expressividade completa do JSON esquema. O objetivo é um contrato de saída estável que possa ser compilado em diversas superfícies de provedores sem enfraquecer a garantia do aplicativo.
As verificações de lint úteis incluem:
- Rejeite palavras-chave de composição não suportadas, a menos que seu compilador tenha mapeamentos de provedor explícitos para elas.
- Rejeite
objectcampos irrestritos que permitem propriedades arbitrárias. - Exige enumerações para campos de classificação que impulsionam roteamento, faturamento, aprovações ou estado de visibilidade do parceiro.
- Requer
maxItemspara matrizes usadas em automação ou exibição de IU. - Exige
maxLengthpara campos de texto que inserem bancos de dados, filas ou APIs de parceiros. - Sinalize campos opcionais cuja ausência altera o significado do negócio.
- Rejeite esquemas cujo aninhamento ou tamanho exceda os limites conhecidos do provedor em sua matriz de capacidade.
O linter deve ser executado no CI e antes da implantação do esquema. Não espere até que uma solicitação de produção atinja um erro de provedor porque uma palavra-chave do esquema não é suportada.
Etapa 3: compilar em formatos de solicitação específicos do provedor
A compilação do provedor traduz o esquema canônico na API superfície que cada modelo realmente suporta. O compilador deve ser determinístico e versionado. Ele também deve deixar uma trilha de auditoria mostrando qual versão do esquema canônico produziu qual carga útil da solicitação do provedor.
OpenAI compilação
Para OpenAI, o compilador pode direcionar saídas estruturadas por meio de formatação de resposta para tarefas de extração e classificação ou chamada de função estrita para fluxos de trabalho orientados à ação. A carga compilada deve incluir o subconjunto compatível do esquema e configurações de rigidez específicas do provedor, quando disponíveis.
Anthropic compilação
Para Anthropic, o compilador frequentemente representará a saída desejada como uma ferramenta com um input_schema. O aplicativo então espera um bloco de uso da ferramenta e valida a entrada da ferramenta em relação ao esquema canônico. Isso significa que o adaptador deve normalizar o envelope de resposta, não apenas analisar JSON.
Gemini compilação
Para Gemini, o compilador deve direcionar sua configuração de resposta estruturada JSON usando apenas o subconjunto de esquema suportado. Se um esquema canônico usar restrições que Gemini não são impostas nativamente, o compilador deverá registrar essas restrições como exigindo validação do lado do aplicativo.
A saída do adaptador deve ser normalizada em um tipo de resultado interno:
type StructuredResult = {
provider: "openai" | "anthropic" | "gemini";
model: string;
schema_version: string;
status: "ok" | "refusal" | "truncated" | "provider_error" | "invalid";
raw_response: unknown;
parsed_output?: unknown;
finish_reason?: string;
};
Essa normalização evita que o código do fluxo de trabalho downstream dependa dos envelopes do provedor.
Etapa 4: validar cada resposta em relação ao esquema canônico
A estrutura do lado do provedor é a primeira linha de defesa, não a verificação final de correção. Sempre valide a saída analisada em relação ao esquema canônico depois que o modelo responder.
A validação em tempo de execução deve produzir erros estruturados como:
missing_required_fieldinvalid_enumunexpected_propertytype_mismatcharray_too_longstring_too_longsemantic_rule_failed
Mantenha a validação estrutural separada da validação semântica. JSON O esquema pode verificar a forma, propriedades necessárias, enums e restrições de tipo básico. Ele não pode expressar totalmente regras de negócios, como transições de estado válidas, limites de aprovação, políticas específicas do cliente ou combinações de campos mutuamente dependentes.
Por exemplo, este é um validador semântico, não uma regra de esquema:
if (output.priority === "urgent" && output.requires_human_review !== true) {
throw new SemanticValidationError(
"urgent tickets must require human review"
);
}
Coloque essas verificações no código do aplicativo onde elas possam usar a configuração do cliente, o estado do fluxo de trabalho, o contexto de autorização e o controle de versão da política.
Etapa 5: use o reparo local e depois feche com falha
Um caminho de reparo pode se recuperar de pequenos defeitos de saída, mas também pode ocultar esquemas sistemáticos e gerar problemas. Use uma tentativa de reparo direcionada com o erro de validação incluído. Se a resposta reparada ainda falhar na validação, feche a falha ou encaminhe para revisão.
Uma política de reparo prática é semelhante a esta:
- Tente reparar apenas tipos de falha elegíveis, como campos obrigatórios ausentes, enumerações inválidas ou malformações JSON.
- Não repare recusas do provedor, bloqueios de segurança, falhas de autorização ou resultados sensíveis à política.
- Inclua a versão do esquema canônico e o erro de validação no prompt de reparo.
- Permitir no máximo uma tentativa de reparo para fluxos de trabalho visíveis ao cliente ou que acionam ações.
- Registre a contagem de reparos, o sucesso do reparo, o uso do token e o status final.
Para trabalhos de extração interna de baixo risco, uma segunda tentativa de reparo poderá ser aceitável se a latência não for importante. Para fluxos de trabalho que acionam pagamentos, alterações de acesso, respostas do parceiro API ou ações de conformidade, uma política de falha fechada geralmente é mais segura.
Etapa 6: criar testes de contrato para cada modelo de produção
Os testes de contrato decidem se um modelo é elegível para um fluxo de trabalho. Eles devem ser executados antes do lançamento inicial, antes das atualizações do modelo e antes das alterações na política de roteamento.
No mínimo, teste cada modelo e adaptador de provedor para:
- Saída de caminho feliz válida.
- Campos obrigatórios ausentes.
- Valores enum inválidos.
- Propriedades extras quando o esquema é fechado.
- Muitos itens da matriz.
- Sequências de caracteres muito longas.
- Recusa ou incapacidade de cumprimento.
- Saída truncada.
- Incompatibilidade de chamada de ferramenta ou chamada de ferramenta ausente.
- Saída estruturalmente válida, mas semanticamente errada.
Use avisos adversários que pressionem o modelo a violar o contrato. Por exemplo, peça para adicionar um campo explicativo extra, retornar uma prioridade fora da enumeração ou omitir um booleano obrigatório. O teste será aprovado somente se o provedor mais o adaptador mais o validador produzirem o status esperado do aplicativo.
Para cada fluxo de trabalho, mantenha um registro de compatibilidade simples:
{
"workflow": "support_triage",
"schema_version": "2026-09-24",
"model": "provider-model-name",
"supports_strict_schema": true,
"supports_tool_calling": true,
"supports_streaming_structured_output": false,
"refusal_signal_normalized": true,
"contract_tests_passed": true,
"known_limitations": ["max schema depth 4"]
}
Essa matriz de capacidade pertence ao plano de controle, não às constantes de aplicativos dispersas.
Etapa 7: Confiabilidade da saída estruturada do instrumento
Sem telemetria, as equipes não conseguem dizer se as falhas são causadas por incompatibilidade do provedor, desvio de modelo, defeitos de esquema, defeitos de prompt, truncamento ou validadores downstream.
Registre estes campos para cada solicitação de saída estruturada:
- Nome do fluxo de trabalho e versão do esquema.
- Provedor, modelo solicitado e modelo de resposta.
- Modo de saída, como esquema de resposta, chamada de ferramenta ou modo JSON.
- Status de validação e tipo de falha.
- Contagem e resultado do reparo.
- Concluir o motivo e o status da recusa.
- Tokens de prompt, tokens de conclusão, custo total e latência.
- Versão do adaptador e versão do compilador.
Use esses dados para comparar modelos antes de alterar o roteamento. Um modelo mais barato não será mais barato se aumentar as tentativas de reparo, a revisão manual, as falhas do parceiro API ou o tratamento de incidentes posteriores.
Compensações a serem decididas explicitamente
Esquemas de menor denominador comum melhoram a portabilidade, mas enfraquecem as restrições. Se o esquema de solicitação do provedor precisar ser simplificado, preserve verificações mais rigorosas na validação canônica e nos validadores semânticos.
A compilação específica do provedor preserva os pontos fortes nativos, mas adiciona manutenção. Isso geralmente vale a pena para fluxos de trabalho de produção, mas somente se os compiladores tiverem controle de versão e forem cobertos por testes de contrato.
Esquemas rígidos reduzem falhas do analisador, mas exigem melhor design de tarefas. Se a tarefa for subespecificada, o rigor expõe a ambiguidade mais cedo. Isso é útil, mas pode retardar o desenvolvimento inicial.
O reparo melhora as taxas de conclusão, mas aumenta o custo e a latência. O reparo limitado é um mecanismo de recuperação, não um substituto para o design do esquema.
A chamada de ferramenta e o formato de resposta JSON atendem a diferentes fluxos de trabalho. A chamada de ferramenta geralmente é mais adequada para fluxos de trabalho orientados à ação. O formato de resposta JSON é mais simples para extração, classificação e resumo. Uma plataforma multimodelo pode oferecer suporte a ambos, mas a política de fluxo de trabalho deve ser explícita.
Previsões: para onde vai a portabilidade de saída estruturada
O suporte do provedor para saída estruturada provavelmente continuará melhorando, mas JSON a portabilidade total do esquema entre modelos não deve ser assumida. Os provedores têm diferentes arquiteturas de modelos, API históricos, padrões de uso de ferramentas e comportamento de segurança. Mesmo quando o suporte ao esquema se tornar mais forte, os aplicativos ainda precisarão de validação canônica porque a correção do negócio depende de mais de JSON forma.
As equipes devem esperar que as decisões de roteamento de saída estruturada se tornem mais orientadas por dados. Confiabilidade, taxa de reparo, tratamento de recusas, latência e custo serão importantes juntamente com a qualidade do modelo. A questão operacional mudará de "este modelo suporta JSON?" para "este modelo satisfaz o contrato deste fluxo de trabalho a um custo e taxa de falhas aceitáveis?"
Lista de verificação de implementação
- Defina um esquema canônico por fluxo de trabalho.
- Verifique esquemas e mantenha as cargas úteis de solicitação do provedor reproduzíveis.
- Adicione linting de CI para recursos de esquema não suportados ou arriscados.
- Compile esquemas canônicos em formatos específicos do provedor.
- Normalize os envelopes do provedor em um tipo de resultado interno.
- Validar cada resposta analisada em relação ao esquema canônico.
- Adicione validadores semânticos para regras de negócios.
- Permitir apenas tentativas de reparo limitadas.
- Falha no fechamento ou roteamento para análise de fluxos de trabalho de alto risco.
- Execute testes de contrato antes de adicionar ou atualizar modelos de produção.
- Mantenha uma matriz de capacidade do modelo no plano de controle.
- Registre campos de validação, reparo, custo, latência, provedor e modelo para cada solicitação.
Conclusão acionável
A portabilidade de saída estruturada é um API problema de contrato, não um problema de formatação imediata. O padrão confiável é definir um esquema de negócios canônico, lintá-lo para portabilidade, compilá-lo na superfície nativa de cada provedor, validar cada resposta após o provedor devolvê-la e usar testes de contrato para decidir quais modelos são elegíveis para produção.
Esse design adiciona algum trabalho de engenharia inicial, mas evita o modo de falha mais caro: sistemas downstream assumindo um contrato estável enquanto o roteamento do modelo, o comportamento do provedor ou a aplicação do esquema mudam silenciosamente abaixo deles.