Como saber se a Decisions API acerta no seu caso: montando um conjunto de casos rotulados antes de ir pra produção

tabela de confusão comparando respostas da Decisions API com casos rotulados por humanos
Resposta rápida

Pra saber se a Decisions API acerta no seu caso, monte um conjunto de casos rotulados antes de ir pra produção: separe decisões reais já tomadas por humanos, inclua casos de borda etiquetados por tipo, rode tudo via POST /v1/decisions com o gpt-6-luna guardando a resposta inteira e compare com o gabarito, total e por tipo de caso, com uma tabela de confusão. Quando o erro se repete num grupo, revise as opções, a pergunta e o próprio gabarito, e mande os casos ambíguos pra revisão humana usando confidence ou probabilities

Fala aí, beleza? Uma demo bonita no Playground não prova que a Decisions API acerta nos SEUS casos

E é exatamente isso que tu precisa descobrir antes de plugar ela no sistema 🙂

A Decisions API é da OpenAI e entrou em beta pública pra todos os desenvolvedores em 6 de outubro de 2026, depois de um preview no DevDay de 29 de setembro

A OpenAI diz que a versão estável (GA) sai nas próximas semanas, mas ainda sem data

Ou seja: é beta. E beta é justamente o momento em que validar antes de produção pesa MUITO mais

Se liga num detalhe que facilita a vida: ela não gera texto livre

Você manda uma entrada (texto ou imagem) e perguntas, e ela devolve respostas tipadas

Isso deixa a comparação com um gabarito humano direta, sem ficar interpretando parágrafo de resposta, legal né? 😀

Então bora pro passo a passo: montar casos rotulados, incluir bordas de propósito, comparar com o gabarito e agir quando o erro aparece sempre no mesmo lugar

O que você precisa antes de começar

Nada de PC da Nasa aqui, a lista é curta:

  • Acesso à API da OpenAI: ela está em beta pública pra todos os desenvolvedores
  • O modelo gpt-6-luna: hoje é o único modelo disponível nela
  • Uma fonte de decisões humanas já tomadas: tickets classificados, pedidos roteados ou filas priorizadas, que batem com os casos de uso que a própria OpenAI indica (classificar conteúdo, rotear pedidos e priorizar trabalho)
  • Uma planilha ou CSV pra guardar o gabarito
  • A documentação oficial da Decisions API aberta do lado, porque o formato da requisição vem de lá

Sobre custo: com o gpt-6-luna a API cobra US$ 0,10 por 1 milhão de tokens de entrada, sem cobrança de tokens de saída nem de leitura ou escrita de cache

Na prática isso deixa barato rodar o conjunto inteiro várias vezes, e tu VAI rodar várias vezes haha

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

Passo a passo: montando e rodando seu conjunto de casos rotulados

1. Defina a decisão e escolha o tipo de pergunta

Antes de juntar qualquer exemplo, escreve numa frase qual decisão a API vai tomar

Aí escolhe o tipo de pergunta que encaixa nela, porque são três:

  • predicate: devolve uma estimativa de 0 a 1 de que uma condição é verdadeira (ex: "este ticket é reclamação de cobrança?")
  • choice: escolhe uma das opções que você forneceu (ex: rotear pra "financeiro", "suporte técnico" ou "comercial")
  • score: avalia a entrada em níveis ordenados e devolve a média ponderada por probabilidade dos índices desses níveis (ex: prioridade baixa, média, alta)

E o que é essa tal média ponderada? É um número entre os índices dos níveis, não o nome do nível

Então no score tu vai precisar converter esse número de volta pra um nível na hora de comparar (a gente faz isso no passo 6)

O erro comum deste passo: criar opções de choice diferentes dos rótulos que os humanos usaram

Se o time marcava "Financeiro" e tu passa "cobrança" como opção, a comparação quebra logo de cara

Usa exatamente o vocabulário do gabarito, beleza?

2. Separe exemplos reais já decididos por humanos

Aqui mora o coração do método: casos que alguém do time já decidiu, com a decisão anotada

Monta um CSV com uma coluna de id, a entrada e uma coluna rotulo_esperado, algo assim:

id entrada rotulo_esperado tipo_de_caso
1 Fui cobrado duas vezes no cartão financeiro normal
2 O app fecha quando abro o relatório suporte técnico normal
3 Quero mudar de plano e o botão não funciona comercial duas categorias
4 ajuda suporte técnico curto demais

A coluna tipo_de_caso já fica preparada pro próximo passo

O erro comum deste passo: pegar só os casos fáceis ou só os mais recentes

Caso fácil todo mundo acerta, inclusive a API

E os mais recentes podem esconder sazonalidade, então espalha a amostra no tempo e entre as categorias

3. Inclua casos de borda de propósito

Caso de borda é onde a classificação costuma escorregar, então tu vai CAÇAR esses casos:

  • ambíguos, que até o time discutiria
  • curtos demais, tipo "ajuda" ou "???"
  • com imagem, já que a API aceita texto ou imagem como entrada
  • que caberiam em duas categorias

Cada um ganha uma etiqueta na coluna tipo_de_caso ("ambíguo", "curto demais", "com imagem", "duas categorias")

Os casos comuns ficam como "normal"

O erro comum deste passo: misturar as bordas no meio do conjunto sem etiqueta

Sem a etiqueta, depois tu não consegue separar o erro por grupo e a análise vira um chute

Já vi muita planilha morrer por causa disso 😛

4. Teste algumas entradas no Playground antes de escrever código

A API está disponível no Playground da OpenAI, com perguntas e entradas, sem precisar de uma linha de código

Usa isso pra ajustar a pergunta e as opções com uns exemplos do gabarito antes de automatizar

É aqui que tu pega o problema bobo, tipo opção com nome confuso, sem gastar tempo montando script

O erro comum deste passo: tirar conclusão com meia dúzia de exemplos

O Playground serve pra calibrar a pergunta, não pra dizer se a API acerta

Quem diz isso é o conjunto inteiro rodando no passo seguinte

5. Rode o conjunto via POST /v1/decisions e guarde a resposta inteira

Agora sim, código! A chamada vai pro endpoint POST /v1/decisions

O script abaixo lê o CSV, chama a API caso a caso e grava a resposta COMPLETA de cada um num arquivo respostas.jsonl

Se liga: o corpo da requisição e a autenticação tu monta seguindo a documentação oficial, por isso eles aparecem como pontos a preencher

import csv
import json
import requests

# Base da API e autenticação: preencha conforme a documentação oficial
BASE_URL = "PREENCHA_CONFORME_A_DOCUMENTACAO"
HEADERS = {}


def montar_payload(linha):
    # Monte aqui o corpo da requisição seguindo a documentação oficial
    # da API: modelo gpt-6-luna, a entrada (texto ou imagem)
    # e a pergunta definida no passo 1
    raise NotImplementedError("preencha conforme a documentação")


with open("gabarito.csv", newline="", encoding="utf-8") as f, \
        open("respostas.jsonl", "w", encoding="utf-8") as saida:
    for linha in csv.DictReader(f):
        resp = requests.post(
            f"{BASE_URL}/v1/decisions",
            json=montar_payload(linha),
            headers=HEADERS,
            timeout=60,
        )
        corpo = resp.json() if resp.ok else resp.text
        registro = {"id": linha["id"], "status": resp.status_code, "resposta": corpo}
        saida.write(json.dumps(registro, ensure_ascii=False) + "\n")

No tipo choice, a resposta traz o valor escolhido (sempre um dos que você forneceu), um array probabilities com as probabilidades por opção e um campo confidence separado

Guarda tudo, porque é esse material que salva tua vida na hora de investigar erro

E pra testar o próprio script sem gastar chamada de verdade, vale aplicar a ideia de mocks, fixtures e casos de borda no teste do código

O erro comum deste passo: salvar só o valor final e jogar fora probabilities e confidence

Sem eles tu não consegue ver se o erro foi uma escolha apertada ou uma escolha errada "com convicção", e são problemas bem diferentes

6. Compare as decisões com o gabarito, no total e por tipo de caso

Último passo do ciclo: cruzar esperado com obtido

O script abaixo calcula acertos no total, acertos por tipo_de_caso e monta uma tabela de confusão simples (quantas vezes o rótulo X virou Y)

Pra predicate e score, o corte é decisão SUA: o predicate vira sim/não comparando a estimativa com um limite que tu escolhe, e o score é arredondado pro índice de nível mais próximo

import csv
import json
from collections import Counter

TIPO = "choice"   # "choice", "predicate" ou "score"
CORTE = 0.5       # só pra predicate: ajuste ao seu caso
NIVEIS = ["baixa", "media", "alta"]  # só pra score: os níveis na ordem que você definiu


def extrair_valor(resposta):
    # Ajuste os caminhos dos campos ao formato de resposta da documentação oficial
    if TIPO == "choice":
        return resposta["choice"]
    if TIPO == "predicate":
        estimativa = resposta["CAMPO_DA_ESTIMATIVA"]
        return "sim" if estimativa >= CORTE else "nao"
    if TIPO == "score":
        media = resposta["CAMPO_DA_MEDIA"]
        return NIVEIS[round(media)]


esperado, grupo_de = {}, {}
with open("gabarito.csv", newline="", encoding="utf-8") as f:
    for linha in csv.DictReader(f):
        esperado[linha["id"]] = linha["rotulo_esperado"]
        grupo_de[linha["id"]] = linha["tipo_de_caso"] or "normal"

total, acertos, falhas_api, confusao = Counter(), Counter(), 0, Counter()
with open("respostas.jsonl", encoding="utf-8") as f:
    for linha in f:
        r = json.loads(linha)
        if r["status"] != 200:
            falhas_api += 1
            continue
        obtido = extrair_valor(r["resposta"])
        esp = esperado[r["id"]]
        for grupo in ("TOTAL", grupo_de[r["id"]]):
            total.update((grupo,))
            if obtido == esp:
                acertos.update((grupo,))
        if obtido != esp:
            confusao[(esp, obtido)] += 1

print(f"Chamadas com erro: {falhas_api}")
for grupo, n in sorted(total.items(), key=lambda par: par[0] != "TOTAL"):
    ok = acertos.get(grupo, 0)
    print(f"{grupo}: {ok}/{n} ({ok / n:.0%})")

print("\nConfusões (esperado -> obtido):")
for (esp, obt), n in confusao.most_common():
    print(f"{esp} -> {obt}: {n}")

Repara que a saída lista cada grupo separado do TOTAL

É isso que mostra se a API vai bem nos casos normais e tropeça, por exemplo, nos curtos demais

O erro comum deste passo: olhar só a média geral

Um número geral bonito pode esconder um grupo inteiro errando, e se esse grupo é justamente o que importa pro teu negócio… já era

O que fazer quando a Decisions API erra sempre no mesmo tipo de caso

O sintoma clássico: os erros se concentram num grupo só

Uma categoria que vira sempre outra na tabela de confusão, ou o grupo "com imagem" bem abaixo do resto

Antes de sair trocando tudo, se liga nas causas mais prováveis e no que fazer com cada uma:

  1. Opções do choice sobrepostas ou mal nomeadas. Se "suporte" e "suporte técnico" convivem, a confusão vem do teu enunciado, não da API. Reescreve as opções pra que cada uma tenha uma fronteira clara
  2. A pergunta mistura duas decisões. "É urgente e de cobrança?" são duas perguntas disfarçadas de uma. Quebra em perguntas separadas ou troca o tipo: de choice pra predicate quando a decisão é sim/não, ou pra score quando existe ordem entre os níveis
  3. O gabarito humano é inconsistente nesse grupo. Às vezes o time rotulou casos parecidos de jeitos diferentes. Revisa os rótulos daquele grupo antes de culpar a API, porque gabarito zoado gera erro que não existe
  4. O caso é genuinamente ambíguo. Tem coisa que nem gente concorda. Aqui o caminho é usar o confidence ou as probabilities pra mandar esses casos pra revisão humana em vez de automatizar tudo

No item 4, tome cuidado: a documentação oficial não detalha como interpretar o campo confidence

Então o limite que separa "automatiza" de "manda pra humano" tu define olhando os teus próprios resultados no conjunto rotulado, não por achismo

E a regra de ouro: depois de CADA mudança, roda o conjunto inteiro de novo

Ajeitar um grupo e quebrar outro sem perceber é mais comum do que parece haha

Como prevenir que o erro volte

Mantém o conjunto rotulado vivo

Toda vez que aparecer um erro em produção, ele entra no CSV como caso novo, com rótulo e tipo de caso

Assim o gabarito vai ficando cada vez mais parecido com a vida real do teu sistema 🙂

E revalida quando a API sair da beta pra versão estável, já que a GA ainda não tem data e o comportamento pode mudar

Esse é o mesmo raciocínio de montar um eval de regressão a cada atualização: o conjunto que tu montou hoje vira teu alarme amanhã

Próximo passo: comece com 50 casos reais antes de qualquer integração

Recapitulando o caminho:

  • gabarito com decisões que humanos já tomaram
  • casos de borda incluídos de propósito e etiquetados
  • comparação no total E por tipo de caso, com tabela de confusão
  • ação focada no grupo que erra, rodando tudo de novo a cada ajuste

O próximo passo concreto é simples: separa hoje um lote pequeno de decisões reais (uns 50 é um bom ponto de partida pra começar, não uma regra da API), joga alguns no Playground e só depois escreve a integração

A OpenAI afirma que a Decisions API decide até 10x mais rápido que o GPT-6 Luna chamado pela Responses API

Mas velocidade e acerto no TEU caso só o teu conjunto rotulado responde, e é por isso que ele vem antes de qualquer linha de integração

Faça o teste e me conta onde ela tropeçou! 😀

Até o próximo post!

Perguntas frequentes

Quanto custa usar a Decisions API em produção?

Com o gpt-6-luna, a API cobra US$ 0,10 por 1 milhão de tokens de entrada. Não tem cobrança de tokens de saída nem de leitura ou escrita de cache. Isso torna barato rodar um conjunto de testes inteiro várias vezes antes de ir pra produção.

Quando a Decisions API deixa de ser beta e vira GA?

A OpenAI diz que espera lançar a versão estável (GA) nas próximas semanas, mas ainda sem data confirmada. Hoje ela está em beta pública, que começou em 6 de outubro de 2026 depois de um preview no DevDay de 29 de setembro. Enquanto não vira GA, vale mais ainda validar com casos rotulados antes de confiar em produção.

Dá pra usar outro modelo além do gpt-6-luna na Decisions API?

Não, hoje o gpt-6-luna é o único modelo disponível nela. Então todo o conjunto de casos rotulados que você montar vai ser testado com ele.

Qual a diferença entre os tipos predicate, choice e score na Decisions API?

O predicate devolve uma estimativa de 0 a 1 de que uma condição é verdadeira. O choice escolhe uma das opções que você forneceu e ainda devolve probabilidades por opção e um confidence separado. Já o score avalia a entrada em níveis ordenados e devolve a média ponderada por probabilidade dos índices desses níveis, por isso precisa converter de volta pra um nível na hora de comparar com o gabarito.

A Decisions API é mais rápida que chamar o GPT-6 Luna direto?

Segundo a OpenAI, sim: ela decide até 10x mais rápido que o GPT-6 Luna chamado pela Responses API, como a gente cita no fechamento do post. Mas velocidade não diz se ela acerta no teu caso: isso só o conjunto de casos rotulados responde.

Preciso escrever código pra começar a testar a Decisions API?

Não necessariamente no começo. Dá pra testar a API no Playground da OpenAI, com perguntas e entradas, antes de escrever qualquer código. Isso ajuda a calibrar a pergunta e as opções com uns exemplos do gabarito, mas o conjunto completo de casos só valida de fato rodando via POST /v1/decisions.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares