Como usar logprobs na API da OpenAI para medir a confiança de uma classificação

Ilustração de medidor de confiança representando logprobs na API da OpenAI
Resposta rápida

Na Chat Completions, você ativa logprobs: true e top_logprobs (0 a 20). Na Responses API, inclui "message.output_text.logprobs" no include. Depois converte o logprob do rótulo escolhido em probabilidade com exp(logprob) e manda pra revisão humana o que ficar abaixo de um limiar ajustado por você. No gpt-6-luna isso só funciona com reasoning effort "none", e o valor serve como sinal de confiança, não como probabilidade calibrada de acerto

Fala aí, beleza? Teu backend manda um ticket pro LLM, ele responde cobranca e segue o baile…

Mas e se ele estava em dúvida entre cobrança e cancelamento? 🤔

Pra quem integra LLM em produção, saber a categoria não basta: tu precisa saber o quanto o modelo apostou nela

Existe modelo especializado que já devolve a escolha com probabilidade, como o JEV, mas aqui o caminho é outro: um recurso da própria API da OpenAI, sem modelo dedicado nenhum

E já deixo claro desde o começo: logprob mede a aposta do modelo no token, NÃO garante que essa aposta bate com a taxa real de acerto

O que você precisa antes de pedir logprobs

Você precisa de três coisas: um endpoint que aceite o parâmetro, um modelo que não esteja com raciocínio ativo e um prompt que force uma resposta curta

Endpoint: POST /v1/chat/completions (o caminho principal deste post) ou POST /v1/responses, com a variante no último passo

Modelo: gpt-6-luna, que a OpenAI descreve como o modelo mais eficiente para tarefas focadas e de alto volume, bem o perfil de classificação em lote

Reasoning effort em none: obrigatório! No Luna o padrão é medium, e segundo o guia do modelo mais recente, com effort diferente de none você precisa tirar temperature, top_p e top_logprobs (e, na Chat Completions, o próprio logprobs)

SDK: os exemplos usam o SDK oficial de Python da OpenAI, seguindo a referência da Chat Completions

Se liga no aviso de modelos, porque muito tutorial antigo ainda usa os modelos abaixo:

  • gpt-4.1-nano saiu da API em 23/10/2026, então nem adianta tentar
  • GPT-4o (gpt-4o-2024-08-06, gpt-4o-2024-11-20), GPT-4o mini (gpt-4o-mini-2024-07-18), GPT-4.1 (gpt-4.1-2025-04-14) e GPT-4.1 mini (gpt-4.1-mini-2025-04-14) saem da API em 14/01/2027, conforme aviso de 14/10/2026 na página de deprecations
  • O substituto recomendado pela OpenAI pra esses modelos é o gpt-6-luna

Passo a passo: medindo a confiança de uma classificação com logprobs

A ideia é simples: o modelo responde só o rótulo, você lê o logprob do primeiro token e decide se confia ou se manda pra um humano

Os códigos abaixo são exemplos didáticos, sem saída medida, beleza?

  1. Force a resposta a um rótulo curto de uma lista fechada

Por que isso importa? Porque você quer que o primeiro token já carregue a decisão

Se o modelo escreve um parágrafo, a "certeza" fica espalhada por dezenas de tokens e você não sabe qual deles olhar

from openai import OpenAI

client = OpenAI()

ROTULOS = ["cobranca", "tecnico", "cancelamento"]

prompt_sistema = (
    "Classifique o ticket em UMA destas categorias: cobranca, tecnico, cancelamento. "
    "Responda somente com a categoria, em minúsculas, sem pontuação e sem explicação."
)

Dica de design: escolha rótulos que comecem diferente entre si, assim o primeiro token já separa uma categoria da outra

O erro comum deste passo: deixar a resposta em texto livre ("Acredito que seja um caso de cobrança porque…"), o que dilui o sinal entre muitos tokens

  1. Chame a Chat Completions com logprobs ligado

Aqui entram model="gpt-6-luna", o reasoning effort em none (reasoning={"effort": "none"}), logprobs=True e top_logprobs (de 0 a 20, e ele exige logprobs=True)

resposta = client.chat.completions.create(
    model="gpt-6-luna",
    reasoning={"effort": "none"},
    logprobs=True,
    top_logprobs=3,
    messages=[
        {"role": "system", "content": prompt_sistema},
        {"role": "user", "content": "Fui cobrado duas vezes este mês"},
    ],
)

O erro comum deste passo: esquecer o reasoning effort e deixar o padrão (medium). Aí a API devolve erro 400 com a mensagem logprobs are not supported with reasoning models, como relatado na comunidade da OpenAI

Com effort diferente de none, você teria que remover temperature, top_p, top_logprobs e logprobs, ou seja, ficaria sem o sinal que veio buscar haha

  1. Leia o token, o logprob e as alternativas

Cada item de logprobs traz token, bytes, logprob e uma lista top_logprobs com os tokens alternativos e os logprobs deles

primeiro = resposta.choices[0].logprobs.content[0]

print("escolhido:", primeiro.token, primeiro.logprob)

for alt in primeiro.top_logprobs:
    print("alternativa:", alt.token, alt.logprob)

Por precaução, normalize o token (.strip().lower()) antes de comparar com a lista ROTULOS

O erro comum deste passo: supor que sempre volta a quantidade pedida em top_logprobs. A referência avisa que às vezes vem menos, então o código não pode quebrar se a lista tiver 2 itens em vez de 3

  1. Converta logprob em probabilidade e compare

Que logprob é esse? É o logaritmo da probabilidade do token

Por isso ele vai de números negativos até 0.0, e 0.0 significa 100%. Pra voltar à escala de 0 a 1, aplica a exponencial (o cookbook oficial usa np.exp, aqui vai math.exp que dá no mesmo)

import math

prob_escolhida = math.exp(primeiro.logprob)

alternativas = {
    alt.token.strip().lower(): math.exp(alt.logprob)
    for alt in primeiro.top_logprobs
}

print(prob_escolhida, alternativas)

Olhar as alternativas ajuda MUITO: uma escolha com a segunda opção quase colada é bem diferente de uma escolha sozinha lá em cima

  1. Aplique o limiar e mande o resto pra revisão humana

Esse é o uso que o próprio cookbook sugere: classificar automaticamente o que passa de um limiar e mandar os casos menos certos pra revisão manual

LIMIAR = 0.80  # valor ilustrativo, ajuste com as tuas amostras rotuladas

if prob_escolhida >= LIMIAR:
    destino = "automatico"
else:
    destino = "revisao_humana"

O erro comum deste passo: copiar o 0.80 como se fosse regra. O cookbook não fixa um número universal, esse valor existe só pra mostrar a lógica e tu deve ajustar com casos que tu mesmo rotulou

  1. Variante na Responses API

Na Responses API não tem logprobs=True: você pede incluindo "message.output_text.logprobs" no array include, junto com top_logprobs (de 0 a 20)

resposta = client.responses.create(
    model="gpt-6-luna",
    reasoning={"effort": "none"},
    instructions=prompt_sistema,
    input="Fui cobrado duas vezes este mês",
    include=["message.output_text.logprobs"],
    top_logprobs=3,
)

for item in resposta.output:
    if item.type == "message":
        for parte in item.content:
            if parte.type == "output_text":
                primeiro = parte.logprobs[0]
                print(primeiro.token, primeiro.logprob)

O formato de cada item é o mesmo: token, bytes, logprob e top_logprobs

Checagem final: antes de confiar no pipeline, garante que os números fazem sentido

assert primeiro.logprob <= 0
assert 0 <= math.exp(primeiro.logprob) <= 1

Se algum desses asserts falhar, tem coisa errada na leitura da resposta, não no modelo 😛

Como escolher o limiar e o que logprobs não garantem

O limiar sai dos teus dados, não de um número mágico

Segundo o cookbook, logprob alto na categoria escolhida sugere mais confiança, e logprob baixo sugere menos. Repara no "sugere": é um sinal relativo, não uma promessa

Logprob é probabilidade calibrada de acerto?

Não dá pra afirmar isso

Nenhuma fonte oficial garante que uma probabilidade alta vira a mesma taxa de acerto na prática. O logprob mostra o quanto o modelo apostou naquele token, e o modelo pode apostar alto e errar

Como validar o limiar na prática?

Roda o classificador numa amostra revisada por humanos e olha onde os erros caem na escala de probabilidade

Se os erros se concentram abaixo de certo ponto, esse ponto é um bom candidato a limiar. Se aparecem erros com probabilidade alta, o limiar sozinho não vai te salvar e vale revisar prompt e rótulos

Preciso reajustar quando trocar de modelo?

Sim! O limiar vale pro modelo em que ele foi medido

Isso pega direto quem vai migrar do GPT-4o ou do GPT-4.1 pro gpt-6-luna até 14/01/2027: o limiar antigo não vem junto na mudança, tem que medir de novo

Recurso de API ou modelo especializado?

Logprobs são um recurso genérico: funciona em qualquer classificação que tu montar, mas o trabalho de prompt, limiar e validação é teu

Um modelo especializado como o JEV já entrega a escolha com a probabilidade pronta, só que preso ao propósito dele. Pra quem tem um backend com categorias próprias, o recurso da API costuma ser o caminho mais direto

Vídeo: a Decisions API e o JEV

Se esse papo de modelo que devolve decisão estruturada te interessou, no canal tem um vídeo sobre a Decisions API da OpenAI e o que ela muda pro JEV

Conteúdo complementar do Hora de Codar para conhecer o canal; não é uma demonstração específica desta notícia ou versão.

Próximo passo: rode o classificador numa amostra rotulada

Separa algumas dezenas de casos que tu já sabe a categoria certa, de preferência tirados do teu tráfego real

Roda o pipeline com logprobs ligado, guarda a probabilidade de cada resposta e marca quais erraram

Aí ordena tudo pela probabilidade e vê em que faixa os erros aparecem: é dali que sai o teu limiar de revisão humana

E não esquece: no gpt-6-luna, reasoning effort em none, senão o 400 aparece e tu fica sem os logprobs xD

até o próximo post! 😀

Quer aprender mais sobre inteligência artificial e programação na prática? Conheça o canal Hora de Codar no YouTube e acompanhe os próximos vídeos.

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.

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 30min

Blog | Mais populares