Como aprovar ou reprovar imagens enviadas por usuários com pontuação por rubrica na Decisions API da OpenAI

diagrama de pontuação por rubrica aprovando e reprovando imagem de usuário na Decisions API
Resposta rápida

Para aprovar ou reprovar imagens enviadas por usuários com pontuação por rubrica, use uma pergunta do tipo score na Decisions API da OpenAI (beta pública desde 6 de outubro de 2026, rodando só no gpt-6-luna). Você escreve níveis ordenados com label e description, do mais baixo ao mais alto, envia a imagem como data URL base64 numa parte input_image para POST /v1/decisions e recebe um score (média ponderada), as probabilidades por nível e uma confidence. Quem define os limites entre aprovar, revisão humana e reprovar é você, na sua aplicação

Fala aí, beleza? Se o seu app recebe foto de produto, foto de perfil ou comprovante enviado por usuário, você já sabe a dor: ou alguém olha tudo no braço, ou a aprovação vira um sim ou não seco que erra justamente nos casos chatos 😛

A OpenAI abriu em beta pública, em 6 de outubro de 2026, a Decisions API, e ela tem um tipo de pergunta que encaixa muuuito bem nesse problema: o score

Em vez de perguntar "essa foto passa?", você descreve uma rubrica com níveis ordenados e a API devolve uma nota contra essa rubrica

Aí entra a pontuação por rubrica: você ganha uma zona cinzenta de verdade, e é nela que mora a revisão humana

Bora ver na prática?

O que você precisa antes de começar

Antes de escrever qualquer linha de código, se liga nesses pontos:

  • Acesso à Decisions API: ela está em beta, e a disponibilidade geral (GA) é esperada "nas próximas semanas", sem data definida
  • Modelo: a Decisions API roda apenas no gpt-6-luna, não tem escolha de modelo aqui
  • Imagens em base64: as imagens precisam ir como data URL base64 inline. URL HTTP/HTTPS hospedada e file_id não são suportados
  • Custo: US$ 0,10 por 1 milhão de tokens de entrada. Tokens de saída, leitura de cache e escrita de cache não são cobrados
  • Política de aprovação escrita: esse é o pré-requisito que mais gente pula
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

Por que a política vem antes?

Porque a rubrica é só a sua política traduzida em níveis

Se nem o seu time sabe dizer o que reprova uma foto de perfil, a API também não vai saber, e aí não tem modelo que salve haha

Score, predicate ou choice: qual tipo de pergunta usar para imagem?

A Decisions API aceita texto, imagens ou os dois juntos, e tem três tipos de pergunta

Cada um responde um formato diferente de decisão:

Tipo O que devolve Quando usar com imagem
predicate Probabilidade de 0 a 1 de uma condição ser verdadeira Uma checagem pontual, tipo "tem dano visível?"
choice Uma opção de um conjunto fixo, sem ordem Classificar em categoria ou departamento
score Nota contra níveis ordenados de uma rubrica Quando existe gradação entre passa e reprova

O exemplo de imagem da documentação oficial usa predicate: uma foto de produto vai em base64 numa pergunta que verifica dano visível (rachadura, rasgo ou amassado), e a resposta ilustrativa traz probabilidade 0,92

O app então pode mandar a foto para revisão quando o valor passa de um limite que o próprio desenvolvedor define

Massa, mas repara: predicate responde UMA condição

E o choice? Ele serve pra rotular, só que as opções não têm ordem, então "foto boa" e "foto ruim" viram categorias soltas, sem noção de distância entre elas

Já o score trabalha com níveis ordenados, como no exemplo oficial de severidade com ‘Cosmetic’, ‘Workaround available’ e ‘Fully blocked’

Quando a decisão tem meio de campo ("tá meio borrada", "o rosto aparece mas de lado"), a rubrica ordenada mostra ONDE a imagem caiu, e não só se caiu

Passo a passo: aprovar ou reprovar imagem com pontuação por rubrica:

Os códigos abaixo são exemplos ilustrativos

Os campos do objeto Score (name, type, instructions, levels, e label/description dentro de cada nível) são os que estão na referência do endpoint. O resto do envelope da requisição, confira lá antes de usar em produção

  1. Escreva a rubrica em linguagem de decisão

Cada nível precisa dizer o que a pessoa (ou o modelo) vê na imagem pra cair ali: o que reprova, o que é ambíguo e o que passa

Os levels vão ordenados do nível mais baixo para o mais alto. Aqui vou usar o mais baixo como "reprova" e o mais alto como "passa"

O erro comum deste passo: níveis fora de ordem ou descrições que se sobrepõem. Se "levemente desfocada" aparece em dois níveis, o modelo vai espalhar probabilidade entre eles e o seu score fica sem sentido

  1. Monte o objeto Score
{
  "name": "qualidade_foto_produto",
  "type": "score",
  "instructions": "Avalie a foto enviada pelo vendedor. Observe: se o produto aparece inteiro, se está nítido, se há dano visível (rachadura, rasgo, amassado) e se o fundo atrapalha a leitura do produto.",
  "levels": [
    {
      "label": "Reprova",
      "description": "Produto com dano visível, imagem muito borrada ou não é um produto."
    },
    {
      "label": "Revisao",
      "description": "Produto identificável, mas com nitidez baixa, corte parcial ou fundo que confunde."
    },
    {
      "label": "Passa",
      "description": "Produto inteiro, nítido, sem dano visível e com fundo limpo."
    }
  ]
}

Repara que as instructions dizem exatamente O QUE olhar na imagem

O erro comum deste passo: instructions vagas tipo "avalie se a foto é boa". Boa pra quem? Sem dizer o que observar, você joga a sua política no lixo e deixa o modelo adivinhar

  1. Codifique a imagem em base64 e envie como input_image

A imagem vai inline, como data URL, numa parte input_image dentro da mensagem do usuário, e a requisição vai para POST /v1/decisions

Gerando a data URL em Python:

import base64

# exemplo ilustrativo: ajuste o tipo MIME ao arquivo real
mime = "image/jpeg"

with open("foto_produto.jpg", "rb") as f:
    b64 = base64.b64encode(f.read()).decode("utf-8")

data_url = f"data:{mime};base64,{b64}"

Essa data_url é o que entra na parte input_image da mensagem do usuário, junto com a pergunta score do passo 2

Tome cuidado: confira na referência quais formatos de imagem são aceitos e valide com os seus arquivos reais antes de ir pra produção

O erro comum deste passo: mandar a URL HTTPS da imagem que já tá no seu bucket, ou um file_id. Nenhum dos dois é suportado, tem que ser base64 inline

  1. Leia a resposta do jeito certo

A pergunta score devolve três coisas:

  • score: a média dos índices dos níveis ponderada pelas probabilidades
  • probabilidades de cada nível
  • confidence

E o que significa "média ponderada" na prática?

Significa que o score pode cair ENTRE dois níveis. Se o modelo ficou dividido entre "Revisao" e "Passa", o número fica no meio do caminho

O erro comum deste passo: tratar o score como inteiro, com int() ou arredondando direto. Você perde justamente a informação de dúvida, que é o que te interessa pra mandar pra revisão

Confira na referência como os índices são contados (se começam em 0 ou em 1) antes de fixar qualquer limite

  1. Defina na aplicação os limites de aprovar, revisar e reprovar

A API devolve probabilidade, score e confidence. Quem decide onde fica a linha é você, no seu código

# exemplo ilustrativo: os limites abaixo são PONTO DE PARTIDA,
# calibre com um lote de imagens que você já sabe a resposta
# confira na referência se os índices começam em 0 ou em 1
# e ajuste INDICE_INICIAL antes de usar
INDICE_INICIAL = 0
LIMITE_REPROVA = INDICE_INICIAL + 0.6
LIMITE_APROVA = INDICE_INICIAL + 1.6
CONFIANCA_MINIMA = 0.7

def decidir(score: float, confidence: float) -> str:
    if confidence < CONFIANCA_MINIMA:
        return "revisao_humana"
    if score <= LIMITE_REPROVA:
        return "reprovar"
    if score >= LIMITE_APROVA:
        return "aprovar"
    return "revisao_humana"

Repara que os limites ficam presos ao INDICE_INICIAL: depois de conferir na referência como os índices são contados, você só ajusta essa variável e o resto acompanha

Nesse exemplo, tudo que fica no meio vai pra uma pessoa, e tudo que vem com confidence baixa também

O erro comum deste passo: usar só um limite (ou dois colados), sem faixa de revisão. Aí cada imagem ambígua vira aprovação errada ou reprovação injusta, e quem paga é o usuário (ou o seu suporte) xD

Exemplos de rubrica para foto de produto, foto de perfil e comprovante

Antes de tudo: essas rubricas são exemplos de REDAÇÃO de rubrica escritos por mim

Não são regras oficiais da OpenAI e não têm números testados por trás. A documentação oficial só traz exemplo de foto de produto, os outros dois são ilustrativos

Rubrica para foto de produto:

  • Reprova (nível mais baixo): dano visível (rachadura, rasgo, amassado), produto errado em relação ao anúncio ou imagem tão borrada que não dá pra identificar o item
  • Revisão humana: produto identificável, mas cortado, com nitidez baixa ou fundo poluído que pode esconder defeito
  • Passa (nível mais alto): produto inteiro, nítido, sem dano visível e com fundo que não atrapalha

Se o dano é o critério que mais pesa pra você, dá pra combinar com uma pergunta predicate separada, igual ao exemplo oficial, e tratar as duas respostas no seu código

Rubrica para foto de perfil:

  • Reprova: conteúdo impróprio pela sua política, imagem que claramente não é uma pessoa quando a política exige rosto
  • Revisão humana: rosto parcialmente visível, muito escuro, de longe, ou imagem com cara de foto genérica de banco de imagens
  • Passa: rosto visível, enquadrado e sem nada que fira a política da plataforma

Um cuidado aqui: não confirmei se a Decisions API tem classificação de conteúdo sensível ou moderação embutida

Então não trate essa rubrica como substituta de uma camada de moderação. Se esse é o seu caso, vale ver como montar um fluxo para moderar conteúdo enviado por usuários e deixar a rubrica cuidando do critério de qualidade

Rubrica para comprovante:

  • Reprova: ilegível, cortado a ponto de não mostrar nenhum campo, ou não é um comprovante
  • Revisão humana: legível, mas com campos importantes faltando ou parcialmente cobertos
  • Pronto para conferência (nível mais alto): legível e com os campos que a sua política exige visíveis

Repara que o nível mais alto NÃO é "aprovado"

Comprovante envolve dinheiro e risco de fraude, então o melhor que a rubrica faz é dizer "esse aqui está legível e completo". A aprovação final continua com uma pessoa ou com uma conferência no seu sistema

E sinais de edição (fonte diferente num campo, recorte estranho, valor sobreposto)? Eu colocaria numa pergunta predicate à parte, e qualquer sinal disso manda direto pra revisão humana, nunca pra aprovação automática

Quando mandar para revisão humana em vez de decidir automaticamente?

A pontuação por rubrica brilha justamente por mostrar a dúvida, então use isso a seu favor

Três critérios de desenho que fazem sentido:

  • Score entre dois níveis: se a média ficou no meio do caminho, o modelo estava dividido, e decisão dividida é trabalho pra gente
  • Confidence baixa: mesmo com score "bonito", se a confidence veio baixa, a nota não é confiável o bastante pra decidir sozinha
  • Risco alto por natureza: comprovante, suspeita de fraude e conteúdo sensível vão pra revisão mesmo com nota alta, porque o custo do erro é maior que o custo de uma pessoa olhar

E qual valor de confidence usar?

A OpenAI não publicou recomendação oficial de threshold pra isso. Os valores do passo 5 são só um ponto de partida, e você precisa calibrar com amostras reais do seu app

No fim das contas, a API devolve sinais. A responsabilidade do limite, e do que acontece com o usuário depois, é sua 🙂

Próximo passo:

Recapitulando o caminho prático:

  • Escolha UM tipo de imagem (comece pela foto de produto, que tem exemplo oficial)
  • Escreva a política e transforme em rubrica com níveis ordenados e descrições que não se sobrepõem
  • Rode sobre um lote de imagens que você já sabe a resposta certa
  • Compare o score e a confidence com a decisão esperada e ajuste níveis, instructions e limites
  • Só depois expanda pra foto de perfil e comprovante

E lembra: a Decisions API está em beta, com GA esperada nas próximas semanas e sem data definida

Vale acompanhar a documentação até lá, porque campo, comportamento e preço podem mudar no caminho…

É isso, até o próximo post! 😀

Perguntas frequentes

A Decisions API aceita imagem hospedada em URL HTTPS?

Não. As imagens precisam ir como data URLs base64 inline, dentro de partes input_image na mensagem do usuário. URL HTTP/HTTPS hospedada e file_id não são suportados

Quem decide o limite entre aprovar, revisar e reprovar uma foto?

A API só devolve score, probabilidades por nível e confidence. O threshold que separa aprovar, mandar pra revisão e reprovar é definido pelo próprio desenvolvedor dentro da aplicação

O score da pontuação por rubrica sempre cai certinho num nível?

Não necessariamente. O score é a média dos índices dos níveis ponderada pelas probabilidades, então ele pode cair entre dois níveis em vez de bater exatamente num deles

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

Não. A Decisions API roda apenas no gpt-6-luna, sem opção de troca de modelo nessa API

Quanto custa avaliar imagens com pontuação por rubrica na Decisions API?

O custo é US$ 0,10 por 1 milhão de tokens de entrada. Tokens de saída, leitura de cache e escrita de cache não são cobrados

A Decisions API já está disponível pra todo mundo em produção?

Ela abriu em beta pública em 6 de outubro de 2026 e segue em beta. A disponibilidade geral é esperada nas próximas semanas, sem data definida



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