Como usar o Jev para personalizar a experiência do usuário em tempo real?

diagrama mostrando como o Jev personaliza a experiência do usuário em tempo real
Resposta rápida

O Jev é o System One Model da TypeSafe AI: você manda o estado não estruturado do usuário e ele devolve decisão tipada com probabilidade, sem gerar texto. Pra personalizar em tempo real, você modela cada variante de tela como um Choice, usa Score pra ordem de conteúdo e Noul pra liberar (ou não) uma oferta, tudo numa requisição só, porque as perguntas rodam em paralelo. Regra determinística continua no código, o modelo entra só onde precisa de julgamento. Preço: US$ 0,042 por 1 milhão de tokens de entrada, saída grátis, contexto de 32 mil tokens

Fala aí, beleza? Personalização em tempo real tem um inimigo só, e não é o modelo: é o relógio

Você precisa decidir QUAL variante de tela mostrar antes da tela pintar, e qualquer coisa que demore acaba virando spinner na cara do usuário

É aí que entra o Jev, o modelo da TypeSafe AI da categoria System One Model, anunciado em 15 de setembro de 2026

A ideia é simples de entender e meio diferente do que a gente tá acostumado: ele recebe estado não estruturado (o que você sabe do usuário, em texto ou dado bruto) e devolve decisões tipadas com probabilidade, em vez de gerar strings livres

Ou seja: nada de parsear JSON que o modelo "prometeu" devolver, nada de regex em cima de texto

Você pergunta "qual dessas 4 variantes?" e ele responde com a escolha e a confiança dela

A própria TypeSafe posiciona o Jev como tendo inteligência comparável à de LLMs em tarefas System One, sendo duas ordens de magnitude mais rápido e eficiente, com um sampler paralelo que gera todas as probabilidades de uma vez em vez de token a token

Bora ver na prática?

O que você precisa antes de começar

A boa notícia é que a barreira caiu: a TypeSafe cancelou a waitlist em 21 de setembro de 2026

Hoje qualquer pessoa cria uma chave no console e já chama a API

Checklist mínimo:

  • Chave de API: criada em console.typesafe.ai, na seção API Keys
  • Variável de ambiente: os clientes leem a chave de TYPESAFE_API_KEY
  • SDK Python (se for esse o seu lado): pip install typesafe-sdk ou uv add typesafe-sdk, exige Python 3.10 ou superior
  • SDK JavaScript/TypeScript: npm install @typesafe-ai/sdk
export TYPESAFE_API_KEY="sua-chave"

O modelo padrão dos clientes é jev-latest

E aqui vale saber onde você tá pisando: a versão publicada atual é a jev-1.13.0, e tanto jev-latest quanto jev-preview apontam pra ela

Então não espere comportamento diferente entre os aliases, é o mesmo modelo

A decisão de arquitetura (essa é a parte que ninguém faz e depois chora):

Antes de escrever a primeira linha, decida ONDE na sua stack essa chamada acontece

Render no servidor? Borda? Um serviço de sessão que já é chamado no login e guarda a decisão?

Porque personalização em tempo real é um orçamento de latência, e cada hop na rede come um pedaço dele

A TypeSafe reporta latência ponta a ponta do Jev na faixa de 70 a 500 ms, conforme números reportados por ela

Tome cuidado com um detalhe que a própria empresa registra no post de lançamento: os evals publicados são rodados dos laptops do time na costa oeste dos EUA, onde o serviço está baseado

Traduzindo pro nosso lado do mundo: meça do SEU servidor, não confie no número de marketing pra dimensionar UX

Dois limites pra anotar agora:

A janela de contexto do jev-1.13 é de 32 mil tokens

Parece muito até você começar a jogar histórico de navegação inteiro dentro do state

Não jogue… state grande cheio de detalhe irrelevante é justamente onde o modelo degrada (falo disso lá embaixo)

O preço é cobrado só por token de entrada: US$ 0,042 por 1 milhão de tokens de entrada e US$ 0,00 por 1 milhão de tokens de saída

Ou seja, o que custa é o que VOCÊ manda, não o tamanho da decisão que volta

Se você já usa OpenRouter como camada de acesso, o Jev também está listado lá, com páginas de modelo pra typesafe/jev-1.13 e typesafe/jev-latest

Passo a passo: personalizando a experiência com uma decisão tipada do Jev

O endpoint da API System One é um POST único:

POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <API_KEY>
Content-Type: application/json

O corpo tem três campos: state, model e questions

E a resposta traz uma Answer por pergunta, com os mesmos ids que você usou em questions

Isso é o coração da coisa: você nomeia a decisão, ele devolve a decisão com aquele nome. Sem surpresa, sem parse

  1. Separe o que é regra determinística do que precisa de julgamento

A documentação da TypeSafe é bem explícita nisso: fluxo de controle, regras determinísticas e efeitos colaterais ficam no CÓDIGO

O modelo entra só onde é preciso senso comum programável ou interpretar dado não estruturado

// isso é if, não é modelo
if (!user.isLoggedIn) return renderVariant('anonimo')
if (user.plan === 'enterprise') return renderVariant('enterprise')

// daqui pra frente, aí sim, o julgamento
const decision = await askJev(user)

O erro comum deste passo: mandar pro Jev perguntas que um if responde melhor, mais barato e com 0 ms. Plano pago? País? Logado? Isso é código

  1. Modele as variantes como um Choice, com criteria por opção

O Jev trabalha com três tipos de pergunta (as primitivas): Choice, Score e Noul

O Choice escolhe uma opção de um conjunto fixo, aceita até 255 opções e usa criteria como um mapa de opção para descrição de rubrica (aceita null quando a opção dispensa detalhe)

Criteria é a rubrica, não é enfeite: é ali que você explica o que faz uma variante ser a certa

{
  "model": "jev-latest",
  "state": "Usuário chegou por busca orgânica sobre 'controle de estoque para loja pequena'. Já visitou a página de preços duas vezes na sessão. Nunca abriu a documentação técnica. Sessão em celular.",
  "questions": {
    "variante_home": {
      "type": "choice",
      "instructions": "Escolha a variante da home que melhor atende a intenção demonstrada nesta sessão.",
      "options": ["prova_social", "demo_tecnica", "preco_direto", "conteudo_educativo"],
      "criteria": {
        "prova_social": "Usuário comparando fornecedores, sinais de dúvida sobre confiança na empresa",
        "demo_tecnica": "Sinais de perfil técnico: documentação, integração, API, termos de implementação",
        "preco_direto": "Usuário já demonstrou intenção de compra e busca valor, não explicação",
        "conteudo_educativo": null
      }
    }
  }
}

Os nomes exatos dos campos de cada primitiva você confere na doc da API antes de subir, beleza?

O erro comum deste passo: criar 40 variantes porque "cabe 255". Cabe, mas cada opção que você não consegue descrever com uma rubrica clara vira ruído na decisão

  1. Monte o state com o sinal do usuário, e só com o sinal

O state aceita string ou dado estruturado, e é aqui que mora o dado não estruturado que nenhum if consegue ler: comportamento na sessão, histórico, contexto de entrada

Mas vale a régua do enxuto: o que entra é o que ajuda a decidir

Id interno, timestamp de criação de linha, flag de feature que não muda nada na decisão… tudo isso só ocupa contexto e atrapalha

O erro comum deste passo: despejar o objeto do usuário inteiro serializado. Você paga por token de entrada E piora a qualidade. Dois prejuízos pelo preço de um 😛

  1. Agrupe TODAS as perguntas da tela numa requisição só

Esse passo é o que salva o seu orçamento de latência

Perguntas enviadas na mesma requisição são avaliadas em paralelo

O cookbook oficial da TypeSafe mostra o tamanho do ganho: um checklist de 13 perguntas sobre um artigo, feito em lote, ficou 12,2x mais barato e 10,0x mais rápido que 13 chamadas separadas, sem mudar as respostas

Então não faça uma chamada pra variante, outra pra ordem do feed e outra pro banner. Uma só

{
  "model": "jev-latest",
  "state": "...",
  "questions": {
    "variante_home": { "type": "choice", "options": ["..."] },
    "intensidade_onboarding": { "type": "score", "levels": ["..."] },
    "mostrar_oferta_upgrade": { "type": "noul", "instructions": "..." }
  }
}

O erro comum deste passo: manter a arquitetura de "uma pergunta, um serviço" que você usava com LLM. Aqui isso é dinheiro e milissegundo jogados fora

  1. Use Score pra ordem/intensidade e Noul pra gate de oferta

Cada primitiva serve pra uma coisa:

Primitiva Pra que serve Limites O que volta
Choice Escolher uma opção de um conjunto fixo até 255 opções, criteria como mapa opção -> descrição (aceita null) a opção escolhida, com probabilidades
Score Posição em uma escala descrita em níveis mínimo 2 e máximo 10 níveis, array ordenado de descrições o nível, com probabilidades
Noul Probabilidade de um sim/não ser verdadeiro pergunta binária um número de 0 (não) a 1 (sim)

Para ordenar blocos de conteúdo, Score é a ferramenta: você pergunta "quanto esse usuário tende a se interessar por conteúdo técnico?" com níveis descritos, e ordena o feed com o resultado no seu código

Para liberar ou segurar oferta, Noul: volta um número entre 0 e 1 e VOCÊ decide o corte

O erro comum deste passo: criar um Score de 10 níveis quando 3 resolvem. Nível que você não sabe descrever é nível que não deveria existir

  1. Defina o limiar de confiança e o caminho de fallback

O treino do Jev usa RLCD (Reinforcement Learning for Calibrated Decisions), e a doc orienta usar essas probabilidades calibradas pra definir limiares, testando confiança contra acurácia nos SEUS dados

A receita é: ação diferente pra resposta confiante e pra resposta não confiante

Caso incerto escala pra uma pessoa ou pra um modelo de raciocínio mais caro

Em personalização, "escalar" geralmente é mais simples e mais barato: cai na variante padrão

const { variante_home } = await askJev(state)

const variante = variante_home.confidence >= 0.7
  ? variante_home.value
  : 'default'

O erro comum deste passo: chutar o limiar (0.7 porque é bonitinho) e nunca mais olhar. O 0.7 do exemplo é ilustrativo, o seu número sai dos seus dados

  1. Trate 429 e 529 com backoff exponencial

Os limites de taxa são medidos em tokens por segundo e requisições por minuto, e quando estoura você toma 429 Too Many Requests

A doc orienta retry com backoff exponencial em 429 e em 529 Overloaded

Só que atenção ao contexto: em personalização, retry tem custo de UX

Se a tela tá esperando, backoff virou tela branca

async function decidirComFallback(state, deadlineMs = 400) {
  try {
    return await Promise.race([
      askJev(state),
      new Promise((_, rej) => setTimeout(() => rej(new Error('deadline')), deadlineMs))
    ])
  } catch (e) {
    return { variante_home: { value: 'default' } }
  }
}

O erro comum deste passo: aplicar backoff exponencial no caminho síncrono do render. Retry serve pro que é assíncrono (pré-computar a decisão da próxima sessão, por exemplo). No render, o certo é deadline e variante padrão

Três personalizações que compensam (e uma que não)

1. Escolher a variante de landing ou de onboarding:

Esse é o caso mais redondo pro Choice

Você tem um conjunto fixo de telas, tem um estado de sessão que é puro sinal não estruturado (de onde veio, o que leu, o que ignorou) e tem uma decisão única a tomar antes de pintar

O criteria faz o trabalho pesado aqui: escrever a rubrica de cada variante é, na prática, escrever a sua hipótese de produto

2. Ordem dos blocos de conteúdo do feed:

Aqui o Score brilha, porque você não quer uma escolha, quer uma posição numa escala

Um Score por tema ("quanto esse usuário se inclina pra conteúdo prático vs conceitual", em 3 ou 4 níveis descritos) e o SEU código ordena os blocos

Repare na divisão: o modelo dá o julgamento, o algoritmo de ordenação continua sendo seu, determinístico e testável

3. Liberar ou segurar uma oferta:

Noul, batata

"Esse usuário demonstrou intenção suficiente pra ver a oferta de upgrade agora?"

Volta um número de 0 a 1 e você corta onde quiser, com política diferente por superfície (mais conservador no onboarding, mais agressivo na tela de limite de plano)

Se você já usa o Jev para moderar conteúdo enviado por usuários, vai reconhecer o padrão na hora: é a mesma mecânica de pergunta binária com limiar, mudando só o que tá em jogo

E a que NÃO compensa:

Usuário está logado? Plano é pago? País é BR? Tem feature flag ligada?

Isso é if

A doc da TypeSafe orienta exatamente isso: manter fluxo de controle e regras determinísticas no código e chamar o modelo só onde é preciso senso comum programável ou interpretar dado não estruturado

Mandar regra booleana pro modelo é pagar token, gastar latência e trocar uma resposta certa por uma resposta provável

Não é esperto, é caro 🙂

Quando a personalização sai errada: sintomas e o que causou

A TypeSafe publica uma página de jaggedness do jev-1.13 listando onde o modelo é fraco

Traduzi os itens pro nosso contexto de personalização:

Sintoma: a decisão muda sem motivo aparente entre sessões parecidas

Causa provável: state grande cheio de detalhe irrelevante. O modelo degrada nesse cenário

Solução: corte o state até sobrar só sinal de decisão

Como prevenir: trate o state como payload de API, com contrato. Campo novo entra só se alguém consegue explicar como ele muda a decisão

Sintoma: a rubrica diz uma coisa e o resultado entrega outra

Causa provável: conflito entre instructions e criteria. O modelo confunde quando os dois pedem coisas diferentes

Solução: leia os dois juntos em voz alta. Se instructions diz "priorize quem tem perfil técnico" e o criteria da variante técnica fala de intenção de compra, você mesmo escreveu a contradição

Como prevenir: instructions define a TAREFA, criteria define cada OPÇÃO. Não repita política nos dois

Sintoma: regra de "usuário inativo há X dias" personaliza errado

Causa provável: o Jev lê datas como texto, não como quantidade ordenada

Solução: calcule o intervalo no seu código e mande já digerido ("inativo há 47 dias" ou melhor ainda: "faixa: inativo entre 30 e 60 dias")

Como prevenir: nenhuma data crua no state quando o que importa é a distância no tempo

Sintoma: números da personalização não batem

Causa provável: alguém delegou contagem ao modelo. Ele não é calculadora e não conta de forma confiável

Solução: aritmética é do backend, sempre

Como prevenir: pergunta que começa com "quantos" é bandeira vermelha. Reescreva como Choice ou Score sobre uma faixa que você já calculou

Sintoma: usuário conseguiu "pedir" a variante premium

Causa provável: o Jev não trata o state como hostil por padrão, e conteúdo adversarial pode mover a resposta

Se você joga bio, nome de projeto ou mensagem digitada pelo usuário direto no state, alguém vai escrever ali o que quer que aconteça

Solução: sanitize e delimite claramente o que é conteúdo de usuário dentro do state

Como prevenir: nunca deixe uma decisão com consequência comercial ou de permissão depender SÓ de campo livre preenchido pelo usuário. Gate de verdade é código

Vídeo: contexto sobre orquestrar vários modelos

A lógica de limiar do passo 6 abre uma porta interessante: o Jev decide rápido e barato o caso comum, e o caso incerto escala pra um modelo de raciocínio mais caro

Ou seja, você acaba com mais de um modelo trabalhando no mesmo fluxo, cada um no papel que faz bem

Pra começar do zero com a ideia de usar vários modelos ao mesmo tempo, este vídeo do canal mostra o Sakana Fugu:

Conclusão: calibrar o limiar nos seus próprios dados

Se tem uma coisa pra levar daqui, é essa: o valor do Jev em personalização não tá no prompt, tá na calibração e na fronteira

Calibração porque o treino em RLCD existe justamente pra que a probabilidade signifique alguma coisa, e a doc orienta testar confiança contra acurácia nos seus próprios dados antes de fixar limiar

Fronteira porque metade dos problemas de personalização com modelo vem de mandar pro modelo o que era if

O próximo passo prático é chato e funciona:

Instrumente UMA tela

Um Choice, no máximo um Score e um Noul junto, tudo na mesma requisição

Meça a latência real do seu lado (lembrando que os evals da TypeSafe rodam dos laptops do time na costa oeste dos EUA, então o seu número vai ser o seu número)

Guarde a decisão, a confiança e o que aconteceu depois

Essa terceira coluna é a que importa: sem ela você não tem como medir o impacto do Jev e vai ficar no achismo

Com uma tela calibrada e medida, aí sim dá pra ampliar pro resto do produto sem medo

Espero que ajude, e até o próximo post!

Perguntas frequentes

Quanto custa usar o Jev pra personalizar a experiência do usuário em produção?

O preço é só por token de entrada: US$ 0,042 por 1 milhão de tokens. A saída é gratuita, então o custo cresce com o tamanho do state que você manda, não com a quantidade de decisões que voltam.

O Jev serve pra gerar o texto que aparece pro usuário, tipo um copy personalizado?

Não é esse o uso dele. O Jev devolve decisões tipadas e probabilísticas (Choice, Score ou Noul), sem gerar strings livres. Quem gera o texto final continua sendo seu código ou template, usando a decisão do Jev como input.

Existe diferença entre jev-latest e jev-preview pra quem tá começando?

Na prática, nenhuma. A versão publicada atual é a jev-1.13.0, e os dois aliases (jev-latest e jev-preview) apontam pro mesmo modelo. Não espere comportamento diferente entre eles.

Posso jogar todo o histórico de navegação do usuário no state pra melhorar a personalização?

Não é recomendado. A janela de contexto do jev-1.13 é de 32 mil tokens, e a própria documentação de jaggedness lista state grande cheio de detalhe irrelevante como um dos pontos onde o modelo degrada. O melhor é mandar só o que importa pra decisão específica.

Dá pra chamar o Jev sem usar os SDKs oficiais da TypeSafe?

Dá sim, o endpoint é um POST único em api.typesafe.ai/v1/systemone com autenticação Bearer, então qualquer cliente HTTP funciona. O Jev também está listado no OpenRouter, com páginas de modelo pra typesafe/jev-1.13 e typesafe/jev-latest.

O que fazer se a API do Jev retornar erro de limite de requisições durante um pico de tráfego?

É o passo 7 lá do tutorial: o excesso retorna 429 Too Many Requests e a documentação orienta retry com backoff exponencial em 429 e em 529 Overloaded. Só vale a ressalva que já dei ali: no caminho síncrono do render, backoff vira tela branca, então nessa parte o certo é deadline e variante padrão, deixando o retry pro que é assíncrono.




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