Mesma entrada, resposta diferente? Como verificar a repetibilidade das decisões do Jev

teste de repetibilidade do Jev comparando confidence e rótulo em várias execuções
Resposta rápida

A repetibilidade do Jev se mede repetindo a mesma requisição (model jev-latest, state e questions congelados) várias vezes e registrando, por pergunta, as probabilidades de cada opção, a confidence e o rótulo vencedor. Variar um pouco a probabilidade é esperado: a TypeSafe informa que o rótulo raramente muda. O que importa é a taxa de troca de rótulo e se a confidence cruza a fronteira entre faixas de ação. Depois, embaralhe a ordem das opções e use o estado montado em produção para separar a variação do modelo da variação do seu prompt e do seu contexto

Fala aí, beleza? Mandou o mesmo estado e as mesmas perguntas pro Jev e voltaram probabilidades diferentes?

Calma, não é bug no seu código 😀

Isso é comportamento esperado

O Jev é o modelo de decisão da TypeSafe AI, empresa de San Francisco fundada em 2024, e foi lançado em early access limitado em 15 de setembro de 2026

Se liga num detalhe importante: ele NÃO gera texto

Ele recebe um estado e perguntas tipadas e devolve uma distribuição de probabilidade sobre as opções que você mesmo define

Ou seja, ele é feito pra decidir dentro do seu software, e não pra conversar

Então, antes de plugar essa decisão num fluxo automático, tu precisa saber o quanto ela oscila

Neste tutorial eu te mostro um método simples pra medir a repetibilidade do Jev e separar o que é variação do modelo do que é variação do seu prompt e do seu contexto 🙂

Por que a mesma entrada pode dar resposta diferente no Jev?

Existem três fontes de variação, e o método inteiro serve pra isolar cada uma delas

1. Variação do próprio modelo: o Jev não é totalmente determinístico, e o mesmo pedido pode devolver probabilidades diferentes em chamadas repetidas

A boa notícia é que essas probabilidades raramente mudam o suficiente pra trocar o rótulo

2. Sensibilidade à ordem das opções: desenvolvedores relataram publicamente que as mesmas entradas dão probabilidades diferentes em execuções repetidas e que a ORDEM das opções muda as probabilidades de saída

Tem até issue registrada em projeto de terceiro sobre isso, com o título "Jev’s answers depend on option order", no repositório cocodedk/graph-loop

3. Variação do seu lado: estado montado dinamicamente a cada chamada, pergunta reescrita, opção renomeada e por aí vai

Essa é a mais traiçoeira, porque parece culpa do modelo e não é…

Por que dá pra testar pergunta por pergunta?

Cada pergunta de uma requisição usa o mesmo estado e é avaliada de forma independente e em paralelo

E o que isso significa na prática?

Que a resposta de uma pergunta nunca vira contexto pra outra, então uma pergunta instável não contamina as vizinhas

Isso deixa a análise muiiito mais simples, porque tu mede cada pergunta isolada

Benchmark alheio substitui a sua medição?

Não

A TypeSafe treina o Jev com um método chamado RLCD (Reinforcement Learning for Calibrated Decisions), que otimiza pra que as probabilidades batam com os resultados reais

Porém a calibração dele é debatida: tem análise independente dizendo que ela se mantém em certas tarefas e outras dizendo que o modelo é mal calibrado ou superconfiante

Assim sendo, medir no SEU caso vale mais do que confiar no benchmark de qualquer um

O que você precisa antes de começar

A lista é curta:

  • Acesso ao Jev: hoje ainda exige entrar na lista de espera do early access
  • Playground no navegador: a TypeSafe oferece um, e ele é ótimo pra um primeiro teste manual antes de escrever qualquer script
  • Uma requisição real do seu fluxo: com os três campos obrigatórios de nível superior, model, state e questions, usando o alias documentado jev-latest
  • Um script simples: que repita a chamada e salve as respostas em JSON ou CSV

Endpoint, autenticação e formato exato das perguntas ficam por conta da documentação oficial da API

Quanto custa repetir a mesma entrada várias vezes?

No preço de early access são US$ 0,042 por milhão de tokens de entrada, e a saída é gratuita (sujeito a mudança)

Então o custo do teste é basicamente o tamanho da sua entrada multiplicado pelo número de repetições

E como a TypeSafe informa que o Jev responde entre 70 e 500 milissegundos, um lote de repetições roda rapidinho 🙂

Como medir a repetibilidade das decisões do Jev, passo a passo

A ideia é mudar UMA coisa por vez e comparar com uma linha de base

Bora ver na prática?

Passo 1: congele a entrada

Salve o estado e as perguntas exatamente como serão enviados, num arquivo fixo, tipo entrada_ordem_a.json

Nada de montar o estado na hora: o arquivo é a fonte da verdade do teste

Erro comum deste passo: gerar o estado a cada execução e achar que a variação é do modelo

Se o estado tem timestamp, ID novo ou lista que vem em ordem diferente do banco, tu já está medindo o seu código, não o Jev

Passo 2: repita a mesma requisição e registre tudo

Agora tu manda a mesma requisição várias vezes e grava, por pergunta, as probabilidades de cada opção, a confidence e o rótulo de maior probabilidade

No script abaixo, o corpo da requisição leva model, state e questions, e as funções enviar e extrair seguem o endpoint, a autenticação e os nomes de campo da documentação oficial da API

import json
import sys

# uso: python repetir.py entrada_ordem_a.json execucoes_ordem_a.jsonl
arquivo_entrada, arquivo_saida = sys.argv[1], sys.argv[2]

N_REPETICOES = 20  # ajuste conforme o seu orçamento

with open(arquivo_entrada, encoding="utf-8") as f:
    entrada = json.load(f)

corpo = {
    "model": "jev-latest",
    "state": entrada["state"],
    "questions": entrada["questions"],
}

def enviar(corpo):
    # Faça a chamada HTTP com o endpoint e a autenticação
    # exatamente como descritos na documentação oficial da TypeSafe
    raise NotImplementedError

def extrair(resposta):
    # Devolva uma lista de dicts neste formato:
    # {"pergunta": id, "probs": {opcao: probabilidade}, "confidence": valor}
    # usando os nomes de campo da documentação oficial
    raise NotImplementedError

with open(arquivo_saida, "w", encoding="utf-8") as saida:
    for i in range(N_REPETICOES):
        resposta = enviar(corpo)
        for item in extrair(resposta):
            rotulo = max(item["probs"], key=item["probs"].get)
            registro = {"execucao": i, **item, "rotulo": rotulo}
            saida.write(json.dumps(registro, ensure_ascii=False) + "\n")

Cada linha do .jsonl é uma pergunta de uma execução, com a distribuição completa

Erro comum deste passo: guardar só o rótulo e perder a distribuição

Sem as probabilidades tu não enxerga o caso que está quase virando, e é justamente ele que vai te morder em produção

Passo 3: calcule a variação

Duas métricas resolvem o grosso:

  • Amplitude: máximo menos mínimo da probabilidade de cada opção entre as execuções
  • Taxa de troca de rótulo: em quantas execuções o rótulo vencedor foi diferente do mais comum
import json
import sys
# uso: python analisar.py execucoes_ordem_a.jsonl
probs, confs, rotulos = {}, {}, {}

with open(sys.argv[1], encoding="utf-8") as f:
    for linha in f:
        r = json.loads(linha)
        pid = r["pergunta"]
        dist = probs.setdefault(pid, {})
        for opcao, valor in r["probs"].items():
            dist.setdefault(opcao, []).append(valor)
        confs.setdefault(pid, []).append(r["confidence"])
        rotulos.setdefault(pid, []).append(r["rotulo"])

for pid, lista in rotulos.items():
    conf = confs.get(pid)
    dominante = max(set(lista), key=lista.count)
    trocas = sum(1 for x in lista if x != dominante)
    print(f"Pergunta {pid}")
    print(f"  rótulo dominante: {dominante} | taxa de troca: {trocas / len(lista):.0%}")
    print(f"  confidence: mín {min(conf):.3f} | máx {max(conf):.3f}")
    for opcao, valores in probs.get(pid).items():
        print(f"  {opcao}: amplitude {max(valores) - min(valores):.3f}")

E a confidence, como ler?

Ela vai de 0 a 1 e indica o quanto as probabilidades estão concentradas: é 1.0 quando toda a probabilidade está numa opção e fica menor quando se espalha

Então observe o mínimo e o máximo dela: se oscila perto do limite onde o seu código muda de comportamento, acende o alerta

Erro comum deste passo: olhar só a média e ignorar as execuções que trocaram de rótulo

Média bonita esconde a execução que mandou o pedido pro lugar errado

Passo 4: teste a ordem das opções

Copie o arquivo congelado pra entrada_ordem_b.json e embaralhe a lista de opções de cada pergunta, sem mudar mais nada

Rode o mesmo lote e analise:

python repetir.py entrada_ordem_b.json execucoes_ordem_b.jsonl
python analisar.py execucoes_ordem_b.jsonl

Se a diferença entre as ordens for maior que a variação entre repetições do passo 2, a fonte principal é a ordem

Erro comum deste passo: concluir que o modelo é instável quando o problema é a ordem

Passo 5: isole a variação do seu prompt e do seu contexto

Agora rode com o estado de produção montado de verdade, pelo seu código, a cada repetição (e não pelo arquivo congelado)

Salve também a entrada que foi enviada em cada execução, pra conseguir comparar depois

Compare o resultado com o passo 2: o que exceder a variação base vem do seu lado

Erro comum deste passo: mudar duas coisas ao mesmo tempo

Trocou a ordem E o template do estado no mesmo lote? Pronto, tu não sabe mais quem causou o quê xD

Passo 6: e as perguntas do tipo Score?

O tipo Choice escolhe entre opções nomeadas e devolve a probabilidade de cada opção e uma confidence

Já o Score usa uma rubrica ordenada e devolve uma nota ponderada pela probabilidade, a distribuição e a confidence

Pra Score o processo é o mesmo, só que tu acompanha também a amplitude da nota ponderada e o quanto a distribuição se mexe entre as execuções

Resumo das comparações:

Comparação O que muda Se a variação crescer, a fonte é
Passo 2 (repetições) Nada O próprio modelo (sua linha de base)
Passo 4 contra passo 2 Ordem das opções A ordem das opções
Passo 5 contra passo 2 Montagem do estado e das perguntas O seu prompt e o seu contexto

Repara que eu não te dei nenhum número de referência

É de propósito: a régua é a sua, definida pelo fluxo que consome a decisão 🙂

Quando a variação é aceitável e quando ela quebra o fluxo

O critério central é simples:

  • Aceitável: o rótulo não muda e a confidence fica dentro da mesma faixa de ação
  • Quebra o fluxo: a decisão cruza a fronteira entre faixas, mesmo que a variação pareça pequena

Como definir as faixas de confidence?

A recomendação prática é usar a confiança em faixas no código, e não num valor exato:

  • Alta: o sistema age sozinho
  • Meio: pede confirmação
  • Baixa: passa pra uma pessoa

Quem define ONDE cada faixa começa é o custo do erro, e quem define os números são exemplos rotulados do seu próprio fluxo

Exemplos de fluxo

Triagem com revisão humana: tolera bem a oscilação, porque alguém olha o resultado no final de qualquer jeito

Ação automática irreversível: aqui não tem moleza, exige faixa alta e estável entre as repetições

Pensa nos rm -rf da vida: tu não quer uma decisão que às vezes cai de um lado e às vezes do outro apertando o botão sozinha

Se nem com faixas bem ajustadas o fluxo aguenta a oscilação, vale comparar com a alternativa de treinar seu próprio classificador

O que a análise da Arize diz sobre a confidence?

Na análise da Arize, a confidence do Jev teve ROC AUC de 0,95 pra identificar os próprios erros, contra 0,62 a 0,84 de LLMs em dez reexecuções

É um bom sinal, mas é uma análise só, e a calibração do Jev segue sendo debatida

A mesma análise traz um alerta importante: nos erros em que o Jev estava mais confiante, cerca de 96% dos veredictos de juízes LLM repetiram a resposta errada dele

Tradução: erros correlacionados

Então não use outro LLM como único verificador das decisões do Jev, porque ele tende a errar junto

O rótulo do Jev mudou entre execuções: o que fazer?

Troubleshooting rápido, por sintoma:

Sintoma A: o rótulo troca entre repetições idênticas

Causa: caso na fronteira, com probabilidades próximas entre duas opções

Solução: tratar como faixa do meio (confirmação ou pessoa), sem forçar decisão automática

Sintoma B: o resultado muda quando as opções são reordenadas

Causa: a sensibilidade à ordem relatada publicamente

Solução: fixar uma ordem canônica no código e testar ordens alternativas antes de ir pra produção

Sintoma C: a variação só é grande em produção

Causa: estado ou perguntas montados de forma diferente a cada chamada

Solução: versionar o template do estado e das perguntas e registrar a entrada enviada

Esse registro é a base pra monitorar as decisões em produção sem ficar no escuro

Como prevenir?

Rode o teste de repetibilidade de novo sempre que mudar:

  • O template do estado ou das perguntas
  • As opções (nome, quantidade ou ordem)
  • A versão que está por trás do alias jev-latest

Tome cuidado com esse último: o alias pode apontar pra outra coisa amanhã sem tu mexer em uma linha de código

Próximo passo: transforme o teste em rotina

Recapitulando: variação de probabilidade é esperada no Jev

O que importa de verdade é troca de rótulo e travessia de faixa

O próximo passo concreto é pegar de 10 a 20 entradas reais e rotuladas do seu fluxo, rodar o método, definir as faixas de confidence a partir delas e deixar o script como teste de regressão

E lembra que o produto está em early access, então preço e comportamento podem mudar

Repita a medição de tempos em tempos, beleza?

Até o próximo post! 😀

Perguntas frequentes

Por que o Jev dá probabilidades diferentes se eu mando a mesma pergunta duas vezes?

Porque o Jev não é totalmente determinístico, e o mesmo pedido pode devolver probabilidades diferentes em chamadas repetidas. A boa notícia é que essas probabilidades raramente mudam o suficiente pra trocar o rótulo de maior probabilidade.

Mudar a ordem das opções no Jev muda o resultado da decisão?

Sim, desenvolvedores relataram publicamente que a ordem das opções muda as probabilidades de saída. Tem até issue registrada sobre isso no repositório cocodedk/graph-loop, com o título ‘Jev’s answers depend on option order’.

Como saber se a variação que eu vi é do Jev ou do meu próprio código?

Congele o estado e as perguntas num arquivo fixo antes de testar, sem montar nada na hora. Se o seu estado tem timestamp, ID novo ou lista em ordem diferente a cada chamada, a variação é do seu código e não do modelo.

Quanto custa rodar vários testes de repetibilidade no Jev?

No preço de early access, a entrada custa US$ 0,042 por milhão de tokens e a saída é gratuita (sujeito a mudança). Então o custo de um lote de repetições é basicamente o tamanho da sua entrada multiplicado pelo número de vezes que tu repete a chamada.

Dá pra confiar na confidence do Jev pra decidir sozinho sem revisão?

A confidence vai de 0 a 1 e indica o quanto a probabilidade está concentrada numa opção. Na prática, ela funciona melhor em faixas no código: agir sozinho na faixa alta, pedir confirmação no meio e passar pra uma pessoa na faixa baixa, com o custo do erro definindo onde cada faixa começa e exemplos rotulados do seu fluxo definindo os números.

A calibração do Jev já foi validada por alguma análise externa?

Validada de vez, não: a calibração do Jev segue debatida, com análises dizendo que ela se mantém em certas tarefas e outras dizendo que o modelo é mal calibrado ou superconfiante. A análise da Arize citada no post é um bom sinal, mas é uma análise só e ainda aponta erros correlacionados com juízes LLM, então o melhor é medir no seu próprio caso.



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 Claude Code

Formação Claude Code

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

  • 120 aulas
  • 4 projetos
  • 9h 48min

Blog | Mais populares