Decisão tipada com probabilidade: Jev, Clef e o que medimos
Modelos de decisão tipada devolvem uma probabilidade por opção em vez de texto. Medimos o Clef, da Cloudflare, contra dois LLMs generativos em 24 tickets: o que não muda e o que passa a ser possível.
Num lote de 24 tickets de suporte rotulados à mão, o Clef marcou como urgentes quatro tickets que não eram. Um deles: "Quero excluir minha conta e meus dados". Os quatro erros tinham algo em comum que não aparece olhando só a resposta: a certeza do modelo ficou abaixo de 0,9 em todos. Os tickets acima de 0,9 estavam todos certos. A resposta de um LLM com JSON mode, no mesmo teste, trouxe só o rótulo, sem nada que separasse o ticket seguro do duvidoso.
O que apareceu em setembro e outubro
Em 15/09/2026,
a TypeSafe lançou o Jev, primeiro de uma classe que chama de "System One
Models". Em vez de gerar texto token a token, o modelo recebe um estado e
perguntas tipadas e devolve uma probabilidade para cada resposta permitida,
numa passada só. Há três tipos de pergunta: choice (escolher entre opções),
score (nota numa escala) e noul (sim ou não).
Em 01/10/2026,
a Cloudflare publicou no Workers AI o Clef (@cf/cloudflare/clef, 27B) e o
Clef-flash (@cf/cloudflare/clef-flash, 9B), com a mesma interface de
perguntas tipadas. A Cloudflare declara que a API é compatível com a do Jev,
que o Clef tem mediana de 209 ms no servidor e que supera o Jev em 7 de 10
benchmarks. O teste abaixo não verifica essas afirmações: o Jev não entrou
(cadastro pausado na época e instabilidade no site depois), e a latência
medida aqui inclui a rede.
O padrão é o que interessa, e ele cabe em qualquer modelo desse tipo.
O conceito, não o produto
Structured output em LLM generativo é uma restrição aplicada sobre um processo que continua gerando texto token a token. O modelo escreve a decisão como se escrevesse um parágrafo, e o formato é conferido depois ou imposto durante a geração. Um modelo de decisão tipada tem a decisão como saída direta: o contrato (opções, escala, sim ou não) faz parte da chamada, e o retorno traz uma probabilidade por opção. Na prática, isso muda duas coisas na integração.
A primeira é que o contrato fica na requisição, e não no prompt:
# bench.py (trecho). DEPARTAMENTOS e NIVEIS estão em tickets.py e no topo do arquivo.
def decidir_clef(modelo: str, ticket: str) -> tuple[dict, dict]:
corpo = {
"model": modelo.rsplit("/", 1)[-1],
"state": ticket,
"questions": {
"departamento": {"type": "choice", "instructions": INSTRUCAO_DEPTO,
"criteria": DEPARTAMENTOS},
"urgente": {"type": "noul", "instructions": INSTRUCAO_URGENTE},
"frustracao": {"type": "score", "instructions": INSTRUCAO_FRUSTRACAO,
"criteria": NIVEIS},
},
}
r = post(modelo, corpo)
a = r["answers"]
decisao = {
"departamento": a["departamento"]["choice"],
"urgente": a["urgente"]["noul"] >= 0.5,
"frustracao": NIVEIS[round(a["frustracao"]["score"])],
}
return decisao, r["usage"]
A segunda é que a resposta traz números. Para o ticket "O checkout está falhando para todos os clientes há uma hora", o Clef devolveu:
"departamento": {"choice": "tecnico",
"probabilities": {"cobranca": 0.0982, "tecnico": 0.8898, "conta": 0.012},
"confidence": 0.7024},
"urgente": {"noul": 0.9715}
O que não mudou
O experimento usou 24 tickets em português, rotulados à mão (departamento certo e
urgente ou não), cada um rodado 3 vezes por modelo. Os dois lados receberam a
mesma tarefa: três decisões por ticket. Os generativos usaram JSON mode do
Workers AI, com json_schema no Llama 3.3 70B. O Llama 3.1 8B não aceita
json_schema (a API devolve "This model doesn't support JSON Schema"), então ele
rodou com json_object e o contrato descrito no prompt.
| modelo | p50 | p95 | acerto depto | acerto urgência | tokens entrada/saída | custo por 1000 decisões |
|---|---|---|---|---|---|---|
| Clef | 704 ms | 1382 ms | 1,00 | 0,80 | 356 / 0 | US$ 0,086 |
| Clef-flash | 575 ms | 1084 ms | 1,00 | 0,88 | 356 / 0 | US$ 0,032 |
Llama 3.3 70B (json_schema) | 1118 ms | 2665 ms | 1,00 | 0,67 | 164 / 27 | US$ 0,109 |
Llama 3.1 8B (json_object) | 2042 ms | 2869 ms | 1,00 | 0,79 | 174 / 31 | US$ 0,035 |
Custo calculado com a tabela de preços do Workers AI na data da medição.
- Contrato: zero respostas fora do contrato nos dois generativos, nas 72
chamadas de cada um, inclusive no 8B sem
json_schema. Nesse teste, o formato não foi o problema. O Clef teve 1 erro HTTP 529 (sobrecarga) em 72 chamadas. - Departamento: 1,00 em todos. A tarefa é fácil demais para separar modelos.
- Custo: Clef 20% abaixo do Llama 70B, Clef-flash 9% abaixo do 8B. Nada perto de uma ordem de grandeza.
- Latência: o Clef foi 1,6x mais rápido que o 70B e o Clef-flash 3,5x mais que o 8B, medido da máquina do autor, pela internet. Os 209 ms e 39 ms que a Cloudflare declara são de servidor e não aparecem aqui.
- Urgência: de 0,67 a 0,88, com 24 tickets e rótulos subjetivos. Com
temperature: 0, as repetições do generativo não ampliam a amostra. Diferença dessa ordem não dá para tratar como ranking.
O que muda: decidir só o que passa de um limiar
Com a probabilidade, a pergunta deixa de ser "o modelo acertou?" e vira "quais tickets posso deixar o modelo decidir sozinho?". O script junta a probabilidade da pergunta de urgência de cada ticket e calcula, para cada limiar de certeza, o acerto entre os tickets que o passam:
# calibracao.py (trecho)
for lim in LIMIARES:
decididos = [x for x in linhas if x["certeza"] >= lim]
acertos = sum(x["previsto"] == x["esperado"] for x in decididos)
acerto = acertos / len(decididos) if decididos else float("nan")
Saída para o Clef, em que certeza é max(p, 1 - p) da pergunta de urgência:
limiar_certeza decididos acerto_nos_decididos vao_para_humano
0.0 24 0.833 0
0.7 22 0.818 2
0.8 20 0.850 4
0.9 17 1.000 7
0.95 14 1.000 10
E para o Clef-flash:
limiar_certeza decididos acerto_nos_decididos vao_para_humano
0.0 24 0.917 0
0.7 23 0.913 1
0.8 19 1.000 5
0.9 17 1.000 7
0.95 7 1.000 17
No Clef, os quatro erros ficaram em certezas de 0,761 a 0,886. Com limiar de 0,9, 17 tickets saem decididos com acerto de 100% e 7 vão para uma pessoa. No Clef-flash, os dois erros ficaram abaixo de 0,8, e um limiar de 0,8 já deixa 19 decididos sem erro. O custo do limiar aparece na última coluna: quanto mais alto, mais trabalho humano. Em 0,95, o Clef-flash manda 17 de 24.
O LLM generativo, na configuração do teste, devolve só o rótulo. Isso não prova que ele não possa expressar dúvida: logprobs ou pedir um nível de confiança no próprio JSON são caminhos que este teste não mediu.
Quando essa medição não serve
Os limiares foram escolhidos olhando os mesmos 24 tickets. O valor 0,9 que zera os erros aqui é o resultado de uma amostra pequena e não um parâmetro pronto. Em outro conjunto, a faixa de certeza dos erros muda. O procedimento é o que se leva: rotular um lote que represente o tráfego real, medir a curva limiar versus acerto e escolher o ponto pelo custo de errar contra o custo de um revisor.
Os rótulos são do autor. Os quatro erros do Clef são todos falsos positivos de urgência. "Quero excluir minha conta e meus dados" é um pedido de privacidade que muita equipe trataria como prioritário, e o modelo pode estar certo onde o rótulo está errado.
Há variação entre rodadas. O acerto de urgência do Clef foi 0,80 no lote de 72 chamadas e 0,83 na rodada de calibração. Uma segunda rodada pode mudar quais tickets ficam abaixo do limiar.
O Jev não foi medido. Tudo acima vale para o Clef, o Clef-flash e os dois Llamas. Comparar com o Jev exige rodar o mesmo script contra a API da TypeSafe, e a interface compatível deve tornar isso uma troca de URL e de chave.
Poucas classes e saída fechada. Resposta ao cliente, resumo e decisões que dependem de raciocínio em várias etapas continuam sendo trabalho de LLM generativo. A decisão tipada serve a escolhas com opções conhecidas na hora da chamada, e as categorias entram no contrato da requisição.
O que levar para amanhã
Antes de trocar de modelo para decidir mais rápido, meça se a resposta traz uma probabilidade que separe acerto de erro: com ela, o limiar de certeza decide o que roda sozinho e o que vai para uma pessoa, e o resto da escolha de modelo vira detalhe de latência e custo.
A trilha AI Engineer (R$ 697) ensina structured output, model routing e os trade-offs de decisão automatizada em produção, com testes automatizados a cada etapa. O código deste artigo está em greenlitlabs/structured-vs-generative-decisions.