Jev com mais de 255 opções: como modelar a decisão quando a lista é grande

diagrama mostrando como o Jev lida com mais de 255 opções em duas passadas de decisão
Resposta rápida

No Jev, 255 opções é o teto de uma pergunta Choice, e catálogo real quase sempre passa disso. A documentação recomenda mandar a lista completa de categorias, não um shortlist, porque cada opção custa poucos tokens. Quando há mais candidatos que o limite, o padrão prescrito é duas passadas: uma pergunta escolhe a seção ou grupo, outra escolhe o item dentro dele. Cada opção é descrita no campo criteria (mapa nome para descrição) com escopo, contraste e exemplos. A resposta traz choice, probabilities e confidence de 0 a 1 pra aplicar limiar.

Fala aí, beleza? Você levanta a lista de categorias do seu catálogo, vai jogar tudo dentro de uma pergunta Choice do Jev e esbarra no teto: uma pergunta Choice aceita no máximo 255 opções

Aí bate aquela vontade de cortar a lista no chute, deixar só as 30 categorias "mais prováveis" e seguir a vida

Péssima ideia 😅

A documentação vai exatamente no sentido contrário: manda enviar a lista completa de categorias, times ou produtos em vez de um shortlist, porque cada opção adicional custa poucos tokens

O que muda quando o conjunto passa de 255 não é o tamanho da lista, é o FORMATO da decisão. Em vez de uma pergunta gigante, você recorta o problema em estágios

Neste post eu mostro como fazer esse recorte: montar o criteria direito, quando dá pra resolver em uma passada só, como funciona o padrão de duas passadas (grupo primeiro, item depois) e quando o pré-filtro no seu próprio código resolve antes de a requisição sair

O que você precisa antes de modelar a decisão

A parte de infra é rápida, a parte de modelagem é onde mora o trabalho de verdade

Do lado técnico:

  • SDK Python instalado com pip install typesafe-sdk
  • Python 3.10 ou superior
  • a chave na variável de ambiente TYPESAFE_API_KEY, que é de onde o cliente lê
  • o modelo: por padrão as chamadas vão pro jev-latest
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

Quer saber o que a sua conta pode usar? Chama GET /v1/models, que lista os modelos e aliases disponíveis. IDs versionados tipo jev-1.13.0 são aceitos no campo model mesmo sem aparecer na lista, e o jev-preview aponta hoje pro mesmo modelo que o jev-latest

Do lado da modelagem, o pré-requisito é um só, e é ele que decide a qualidade do resultado: ter a lista de opções com nome e descrição

Não é uma lista de strings soltas. Cada opção de um Choice é descrita no campo criteria, que é um mapa onde a chave é o nome da opção e o valor é a descrição dela

Se você chegou aqui com um array de 800 nomes de categoria e nenhuma descrição, o trabalho começa antes do código

Como modelar uma decisão com mais de 255 opções, passo a passo

  1. Monte o criteria como mapa nome para descrição

A chave é o nome da opção, o valor é a descrição dela. Simples assim:

criteria = {
    "Notebooks": "Computadores portateis completos, com tela e teclado integrados. Nao inclui acessorios vendidos separados, que vao em Perifericos. Exemplos: ultrabook 14 polegadas, notebook gamer, MacBook Air",
    "Perifericos": "Acessorios ligados a um computador por cabo ou sem fio. Nao inclui o computador em si, que vai em Notebooks ou Desktops. Exemplos: mouse sem fio, teclado mecanico, headset USB",
}

O erro comum deste passo: tratar o criteria como rótulo. "Notebooks: categoria de notebooks" não ajuda o modelo em nada

  1. Escreva escopo, contraste e exemplos, com os mesmos campos em todas as opções

A orientação da documentação é descrever, pra cada opção, o que pertence a ela, o que pertence à opção vizinha e alguns exemplos representativos, usando os mesmos campos em todas as opções

Repare no bloco acima: as duas descrições seguem a mesma receita (escopo, o que NÃO é, exemplos)

O erro comum deste passo: descrições desiguais. Cinco opções com três exemplos cada e as outras duzentas com uma frase seca. O modelo passa a decidir pela riqueza do texto, não pelo conteúdo do seu state

  1. Confira se a lista cabe em 255

Se cabe, acabou. Manda tudo em uma pergunta só e não invente estágio nenhum

print(len(criteria))  # tem que ser <= 255

O erro comum deste passo: encurtar a lista por conta própria "pra economizar". A recomendação é o inverso, mandar a lista completa, já que cada opção custa poucos tokens

  1. Não coube? Agrupe as opções em seções e faça a primeira passada escolher o grupo

Esse é o padrão prescrito pela documentação quando há mais candidatos do que o limite: estreitar em dois estágios, primeiro a seção, depois o item dentro dela

Então o seu criteria da primeira passada não tem 800 produtos, tem os 12 grupos. E cada grupo é descrito com a mesma régua do passo 2: o que cai nele, o que cai no grupo vizinho, exemplos

O erro comum deste passo: grupo com fronteira mal definida. Se "Eletrônicos" e "Informática" se sobrepõem na sua cabeça, vão se sobrepor na decisão também, e o estrago da primeira passada não tem conserto na segunda

  1. Segunda passada só com as opções daquele grupo

Agora sim o criteria vira o subconjunto: só os itens que pertencem ao grupo escolhido. E de novo, dentro do grupo, a lista completa, não um recorte

O erro comum deste passo: montar o subconjunto no código e esquecer de incluir itens que pertencem àquele grupo. Cada item mora em um grupo só, nunca em dois. Se você não consegue dizer em qual ele mora, o problema não está aqui, está na descrição dos grupos do passo 4 pedindo conserto

  1. Leia a resposta e use a confiança como limiar

A resposta de um Choice traz a opção escolhida em choice, a probabilidade de cada opção em probabilities e um valor de confiança pra opção escolhida

response = client.system_one(
    state=texto_do_produto,
    questions={"categoria": pergunta_choice},
)

escolha = response.answers["categoria"].choice

O confidence é um número de 0 a 1 derivado do formato da distribuição de probabilidades, o que te deixa aplicar um limiar sem calcular nada na mão

Na prática é isso que salva pipeline de catálogo: acima do limiar, grava; abaixo, manda pra fila de curadoria humana

O erro comum deste passo: olhar só o choice e ignorar o resto. O choice sempre vem preenchido, inclusive quando a decisão foi no fio do bigode

Duas passadas, pré-filtro no código ou agrupamento de categorias: qual usar

As três estratégias resolvem o mesmo problema por caminhos diferentes, e dá pra combinar duas delas numa boa

Estratégia Quando ela cabe O que exige de você Custo em chamadas
Duas passadas (padrão da doc) Sempre que há mais candidatos do que o limite de 255 Definir seções ou janelas com fronteira clara e escrever descrição pra cada seção 2 requisições por item
Pré-filtro determinístico no código Quando existe regra de negócio objetiva que elimina candidatos (loja, idioma, faixa de preço, tipo de SKU) Manter a regra do filtro no seu código e garantir que ela não corte a opção certa 1 requisição, se o filtro deixar 255 ou menos
Agrupamento na taxonomia Quando a lista é grande mas naturalmente hierárquica (categoria pai e filha já existem) Trabalho de modelagem na taxonomia, não no código 2 requisições, mas a primeira passada é reaproveitável entre itens

A leitura curta: o pré-filtro é o mais barato, porém ele só vale quando o corte é determinístico. Filtro baseado em palpite é o mesmo shortlist que a documentação pede pra você não fazer, só que escondido dentro de um if

Já o agrupamento e as duas passadas são a mesma ideia vista de ângulos diferentes: uma olha pra taxonomia, a outra olha pro fluxo de requisição

Problemas comuns quando a lista é grande (e como prevenir)

Sintoma: confiança baixa na primeira passada, quase sempre nos mesmos itens

Causa: grupos com fronteira ambígua. O modelo está distribuindo probabilidade entre dois grupos porque os dois descrevem a mesma coisa com palavras diferentes

Prevenção: reescreva a descrição dos dois grupos incluindo o contraste explícito com o vizinho, que é justamente o que a documentação orienta a fazer em cada opção

Sintoma: a acurácia piora conforme você enriquece o state

Causa: a página de jaggedness do jev-1.13 documenta que o modelo perde acurácia conforme o state cresce com conteúdo não relacionado à decisão

Prevenção: mande no state o que é relevante pra ESSA decisão. Descrição do produto, ficha técnica, título. Histórico de pedidos e log de navegação não entram só porque estavam no mesmo objeto

Sintoma: a decisão erra quando depende de "qual é o mais recente" ou "quantos itens tem"

Causa: também está documentado no jaggedness do jev-1.13: o modelo não conta de forma confiável e lê datas como texto, não como quantidades ordenadas

Prevenção: conte e ordene no seu código, e mande o resultado pronto no state. Falando em data, aquela sensação de "pedi uma coisa e veio outra" tem parente no front também, tipo quando o date picker do Ponytail volta como input nativo

Sintoma: a requisição estoura o orçamento de contexto

Causa: o orçamento é de 64k tokens pro state mais todas as perguntas somadas, e 32k pro state mais a pergunta isolada mais longa. Uma lista enorme de opções com descrição longa é uma pergunta longa

Prevenção: é o mesmo remédio das duas passadas. Quebrar em estágios diminui o tamanho da pergunta mais longa, e não só o número de opções

Sintoma: 429 Too Many Requests ao processar o catálogo inteiro

Causa: rate limit. Erros da API usam códigos HTTP padrão com um corpo JSON descrevendo o problema, e o 429 é o de limite de taxa

Prevenção: os SDKs já trazem retry e backoff embutidos, então o caminho é não reinventar isso por cima. Se você vem de ferramenta de IA com teto de uso, já conhece a dança de até onde vai um plano gratuito antes de travar

Onde esse recorte aparece na prática

Catálogo e taxonomia. É o caso mais óbvio: classificar produto, chamado de suporte ou documento numa árvore de categorias que passa de 255 folhas. Primeira passada no nível de cima, segunda dentro do ramo escolhido

Busca linha a linha. O cookbook de busca semântica cobre documentos de até 255 linhas em uma requisição. Acima disso ele faz duas passadas: uma pergunta Choice escolhe a janela de linhas e outra ranqueia as linhas dentro dela

Repare que é exatamente a mesma receita. Muda o domínio, não o padrão 😀

Alinhamento de entidades. O cookbook que decide entre 450 pares candidatos de dois catálogos de cerveja fez uma escolha interessante: a decisão principal virou uma pergunta Score (mesclar, deixar sem ligação ou mandar pra curadoria), e não um Choice

O motivo é que um Choice perderia a relação de ordem entre os três desfechos

Ou seja, nem toda lista grande vira Choice recortado. Às vezes o problema não é cardinalidade, é o tipo de decisão estar errado desde o começo

E tem um detalhe que muda o desenho do pipeline: várias perguntas podem ir na mesma requisição e são avaliadas em paralelo contra o mesmo state, de modo que adicionar perguntas quase não muda o tempo de resposta

Então perguntar "qual grupo", "qual idioma" e "qual tom" de uma vez, no mesmo request, é bem diferente de fazer três chamadas em fila

Vídeo: introdução ao assunto

Pra quem tá começando do zero e quer entrar no assunto de gastar menos token nas chamadas, tem esse vídeo do canal:

Próximo passo

A regra prática cabe em duas linhas

Se a sua lista cabe em 255, manda ela inteira, com nome e descrição no criteria, escopo, contraste com o vizinho e exemplos, sempre com os mesmos campos em todas as opções

Se não cabe, duas passadas: grupo primeiro, item depois, e o confidence de 0 a 1 como limiar pra mandar o que ficou duvidoso pra revisão humana

O próximo passo é bem concreto: pega a sua taxonomia, escreve o criteria de verdade (essa é a parte chata e é a que define o resultado) e roda um lote de amostra medindo o custo

O preço divulgado no lançamento do Jev é de US$ 0,042 por milhão de tokens de entrada, com tokens de saída não medidos e gratuitos, o que explica por que a documentação insiste em mandar a lista completa em vez de um shortlist

Depois é só olhar a fila de baixa confiança e ver o que ela te conta sobre as fronteiras dos seus grupos, porque é ali que a modelagem pede conserto…

até o próximo post! =)

Perguntas frequentes

Qual o limite máximo de opções em uma pergunta Choice do Jev?

Uma pergunta Choice aceita no máximo 255 opções. Passou disso, a saída é dividir em estágios (grupo primeiro, item depois) em vez de tentar forçar tudo numa pergunta só.

Dá pra rodar várias perguntas Choice na mesma requisição sem o tempo de resposta explodir?

Dá sim. Várias perguntas podem ir na mesma requisição e são avaliadas em paralelo contra o mesmo state, então adicionar mais perguntas quase não muda o tempo de resposta.

Qual o limite de tokens do state quando a lista de opções é grande?

O orçamento é de 64k tokens somando o state com todas as perguntas, e 32k pro state mais a pergunta isolada mais longa. Vale de olho principalmente quando o criteria de uma seção cresce demais nas descrições.

O jev-1.13 consegue contar quantos itens tem numa lista de opções?

Não. A página de jaggedness do jev-1.13 documenta que o modelo não conta de forma confiável, lê datas como texto em vez de quantidade ordenada, e perde acurácia conforme o state fica poluído com conteúdo fora da decisão.

Existe um exemplo prático de busca com mais de 255 linhas usando esse padrão de duas passadas?

O cookbook de busca linha a linha cobre documentos de até 255 linhas numa única requisição. Acima disso ele faz duas passadas: uma pergunta Choice escolhe a janela de linhas primeiro, depois outra ranqueia as linhas dentro dela.

Quando faz mais sentido usar Score em vez de Choice pra um conjunto grande de candidatos?

Quando o desfecho tem relação de ordem entre as opções. O cookbook de alinhamento de entidades decide entre 450 pares candidatos de dois catálogos de cerveja usando Score, com três desfechos possíveis (mesclar, deixar sem ligação, mandar pra curadoria), porque um Choice perderia essa relação de ordem.




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