Quem é dono das perguntas tipadas do Jev: produto ou engenharia?

Divisão de responsabilidade entre produto e engenharia nas perguntas tipadas do Jev
Resposta rápida

As perguntas tipadas do Jev não são só código. As opções de um Choice e os níveis de um Score são o campo criteria da API: texto de negócio que define o que o modelo decide, mesmo morando dentro do payload. A divisão que funciona: produto é dono do significado (opções, descrições, níveis e a ordem deles) e engenharia é dona do contrato (IDs, state, formato e a escolha entre typesafe/jev-1.13 e o alias ~typesafe/jev-latest). A regra que evita atrito: toda mudança de significado exige aprovação de produto, com registro do antes e do depois

Fala aí, beleza? A pergunta tipada do Jev parece código, mas o que ela decide é política de produto

E é exatamente aí que começa a briga 😛

A cena é clássica: alguém abre um PR pra dar uma "limpada" no payload, renomeia uma opção de um Choice ou reescreve a descrição de um nível de Score, e o revisor aprova porque o código está ok…

Na semana seguinte a métrica de produto muda, e ninguém de produto aprovou nada

Pra quem chegou agora: segundo o próprio OpenRouter, o Jev é um modelo de decisão criado pela TypeSafe AI, o primeiro da classe System One

Ele não gera texto: recebe um state e perguntas tipadas e devolve respostas tipadas com probabilidades calibradas

Se você ainda está avaliando se o Jev vale a pena, este post pula essa etapa e vai direto pra uma pergunta de time: quem é dono das perguntas tipadas do Jev, produto ou engenharia?

Bora ver 🙂

Por que as perguntas do Jev viram disputa entre produto e engenharia?

Primeiro o porquê, depois o como

Segundo a documentação da API da TypeSafe, existem três tipos de pergunta:

  • Noul: devolve a probabilidade de sim
  • Choice: escolhe entre opções nomeadas
  • Score: posiciona a resposta numa rubrica de níveis ordenados

Até aqui tudo tem cara de engenharia, né?

Agora se liga nisso: as opções do Choice e os níveis do Score são açúcar sintático pro campo criteria da API

No Choice, criteria é um mapa de opção pra descrição. No Score, é uma lista ordenada de níveis

E a requisição tem três campos obrigatórios no nível superior: model, state e questions

E onde está o problema?

O criteria é texto escrito em linguagem de negócio ("cliente pedindo reembolso", "problema que bloqueia o uso"), só que ele mora dentro do payload que o código monta

É como guardar a política de reembolso da empresa num comentário dentro de uma função: funciona, mas quem decide a política não é quem mexe na função

Por isso mudar a descrição de uma opção não é refatoração. É mudar a pergunta que o modelo responde

O que é de produto e o que é de engenharia em cada parte da requisição

A forma mais simples de acabar com a discussão é olhar campo por campo e perguntar: isso muda o SIGNIFICADO da decisão ou só o contrato técnico?

Elemento O que controla Dono Quem aprova mudança
Texto da pergunta O que está sendo decidido Produto Produto, com revisão técnica de engenharia
Opções do Choice e descrições As respostas possíveis (até 255 opções, cada uma recebe uma probabilidade, além de um valor de confiança) Produto Produto
Níveis do Score A escala: de 2 a 10 níveis descritos em palavras. A ordem importa porque o retorno é uma posição contínua que pode cair entre níveis (o exemplo da doc é 1.035) Produto Produto
ID da pergunta A chave no mapa de respostas. Quem escolhe é a aplicação, e ele nunca é enviado ao modelo Engenharia Engenharia, avisando quem consome os dados
state O que o modelo vê. É o mesmo pra todas as perguntas Engenharia, com produto definindo o que pode entrar Os dois
model ID fixo typesafe/jev-1.13 ou alias ~typesafe/jev-latest (detalhes no passo 5) Engenharia Engenharia, avisando produto

Repara no ID: como o modelo nunca vê o ID, renomear um ID não altera o comportamento do Jev

É assunto 100% de engenharia (e de quem lê os dados depois)

Já as descrições do criteria são o contrário: é exatamente o texto que o modelo usa pra decidir

Ou seja, quem garante que o significado não muda escondido é o processo do time, e é isso que a gente monta mais abaixo

Mudanças que parecem técnicas mas são decisão de produto

Todas estas mudanças cabem num PR de duas linhas, e quase todas mexem numa métrica

Adicionar ou fundir uma opção num Choice de triagem

O Choice devolve a probabilidade de cada opção

Se você adiciona reembolso separado de cobranca, ou funde bug com erro_de_uso, a distribuição passa a ser calculada sobre outro conjunto de opções

O dashboard que mostrava "% de tickets de cobrança" por mês perde a comparação com o histórico

Quem aprova: produto

Reescrever a descrição de um nível do Score

O número de níveis continua igual, mas o texto que define cada nível mudou

Como a resposta é uma posição contínua na escala, a régua que o modelo usa pra posicionar o caso agora é outra

Não há dado publicado sobre quanto isso desloca o resultado, então não dá pra tratar como "mudança pequena" por padrão

Quem aprova: produto

Reordenar os níveis do Score

Esse é o mais perigoso, porque o código continua rodando liso

Se o nível "bloqueia o uso" vira o primeiro da lista em vez do último, um valor alto passa a significar o oposto do que significava ontem

Todo alerta do tipo "score acima de X" fica invertido sem dar erro nenhum. Tome cuidado!

Quem aprova: produto, e engenharia revisa todo código que interpreta o número

Renomear o ID de uma pergunta

O modelo não vê o ID, então a decisão não muda

O que muda é a chave no mapa de respostas, então quem lê esse mapa (código, pipeline de dados, dashboard) precisa ser atualizado junto

Quem aprova: engenharia

Trocar o alias latest pela versão fixa (ou o contrário)

Trocar ~typesafe/jev-latest por typesafe/jev-1.13, ou fazer o caminho inverso, é decisão de engenharia

Mas as respostas podem mudar de uma versão pra outra, então essa troca não é só detalhe de config

Quem aprova: engenharia decide, produto é avisado antes

E mexer no state?

Como explicado no post sobre workflow com o Jev, todas as perguntas veem o mesmo state e rodam em paralelo na mesma requisição

Então adicionar ou tirar um campo do state não afeta uma pergunta só: afeta TODAS de uma vez

Uma mudança pensada pra melhorar a triagem pode mexer junto na pergunta de urgência

Quem aprova: os dois, olhando a lista completa de perguntas que consomem aquele state

Como montar um fluxo de aprovação para mudar perguntas do Jev

Nada de ferramenta mágica aqui, é processo de time

Os trechos abaixo são ilustrativos e usam só os campos model, state, questions e criteria. O formato exato de cada pergunta segue a documentação da API

  1. Separe o conteúdo das perguntas da lógica que monta a requisição

O texto das perguntas, as opções e os níveis vão pra um arquivo ou módulo próprio

O código que monta e envia a requisição só importa esse conteúdo

# perguntas_jev.py: CONTEÚDO (dono: produto)
TRIAGEM_CRITERIA = {
    'bug': 'O cliente relata algo que deveria funcionar e não funciona',
    'cobranca': 'O cliente questiona um valor cobrado',
    'duvida_de_uso': 'O cliente não sabe como fazer algo no produto',
}

URGENCIA_NIVEIS = [
    'Nenhum impacto no uso do produto',
    'Atrapalha, mas existe alternativa',
    'Bloqueia o uso do produto',
]
# jev_requisicao.py: CONTRATO (dono: engenharia)
from perguntas_jev import TRIAGEM_CRITERIA, URGENCIA_NIVEIS

def montar_requisicao(ticket):
    return {
        'model': 'typesafe/jev-1.13',
        'state': ticket,
        # montar_perguntas é função da sua aplicação: monta cada
        # pergunta no formato da doc usando o criteria importado
        'questions': montar_perguntas(TRIAGEM_CRITERIA, URGENCIA_NIVEIS),
    }

O erro comum deste passo: deixar uma descrição "temporária" escrita direto no código que monta a requisição. Ela escapa de toda revisão de produto, e o temporário vira permanente

  1. Defina um dono de produto pra cada pergunta, pelo ID

Como quem escolhe o ID é a aplicação, use ele como identidade da pergunta dentro do time

# perguntas_jev.py
DONOS = {
    'triagem_ticket': 'produto: suporte',
    'urgencia_ticket': 'produto: suporte',
}

O erro comum deste passo: reaproveitar o mesmo ID depois de mudar o sentido da pergunta. A chave no mapa de respostas continua igual, e a série histórica passa a misturar duas perguntas diferentes sem ninguém perceber

Mudou o sentido? ID novo

  1. Exija revisão de produto em qualquer diff que toque o criteria

Com o conteúdo isolado no passo 1, dá pra configurar a revisão obrigatória do seu repositório só pra esse arquivo

E deixe isso explícito no próprio arquivo:

# perguntas_jev.py
# Mudar este arquivo muda o SIGNIFICADO das decisões do Jev
# Toda mudança precisa da aprovação do dono de produto de cada ID afetado

O erro comum deste passo: o revisor de produto olhar só o nome da opção e não ler a descrição. Quem decide de verdade é a descrição

  1. Trate mudança de opção ou de nível como mudança de métrica

Toda alteração no criteria ganha registro do antes e do depois, com data e quem aprovou

# registro_mudancas_jev.py
REGISTRO = [
    {
        'id': 'triagem_ticket',
        'data': 'AAAA-MM-DD',
        'criteria_antes': {'cobranca': 'O cliente questiona um valor cobrado'},
        'criteria_depois': {'cobranca': 'O cliente questiona um valor cobrado ou pede reembolso'},
        'aprovado_por': 'produto: suporte',
    },
]

O erro comum deste passo: registrar só no histórico do git e esquecer de marcar a data da virada no dashboard. Aí alguém vê o degrau no gráfico três meses depois e vai investigar um problema que não existe

  1. Decida explicitamente entre versão fixa e alias latest

No OpenRouter, o Jev tem o ID de modelo typesafe/jev-1.13 e o alias ~typesafe/jev-latest, então dá pra fixar a versão ou usar o alias

# Opção A: versão fixa, a troca de versão vira uma decisão do time
'model': 'typesafe/jev-1.13'

# Opção B: alias latest
'model': '~typesafe/jev-latest'

Qualquer que seja a escolha, ela precisa estar escrita e combinada com produto

O erro comum deste passo: usar o alias porque "veio no exemplo" e ninguém saber disso. Se as respostas mudarem, ninguém vai saber de onde veio a mudança

Veredito: produto ou engenharia?

Nenhum dos dois sozinho

Produto é dono do significado: o que cada opção do Choice quer dizer, o que cada nível do Score descreve e em que ordem eles ficam

Engenharia é dona do contrato e da estabilidade: IDs, state, formato da requisição e qual modelo está rodando

E a regra que evita boa parte do atrito é simples: quem muda o significado precisa da assinatura de produto

Não precisa de comitê nem de reunião semanal, só dessa regra aplicada no PR

Faz sentido deixar tudo com engenharia quando o time é pequeno e a pergunta é interna, sem métrica de negócio pendurada nela (tipo uma pergunta de Noul que só decide se um log vai pra revisão manual)

Não faz sentido quando a resposta alimenta dashboard, meta de time, SLA ou qualquer número que alguém apresenta numa reunião

Aí a taxonomia é política de produto, e política de produto mudando escondida num PR é receita pra dor de cabeça haha

Se você ainda está entendendo onde o modelo se encaixa, vale ler para quem o Jev serve antes de montar todo esse processo

Próximo passo para o seu time

Dá pra começar hoje, em três ações:

  • Liste todas as perguntas Choice e Score que estão em produção
  • Atribua um dono de produto pra cada ID
  • Marque no repositório quais arquivos exigem revisão de produto

E uma coisa que ajuda a convencer o time: rodar perguntas extras sai barato

No OpenRouter, o Jev custa US$ 0,042 por 1M de tokens de entrada e US$ 0 na saída, com janela de 32.000 tokens

Ou seja, o gargalo não é preço, é governança

Separou quem decide o significado de quem cuida do contrato, e as perguntas tipadas do Jev param de virar briga no code review 🙂

Até o próximo post!

Perguntas frequentes

Quem deve aprovar a mudança de uma opção num Choice do Jev?

Produto, porque a opção afeta a probabilidade calculada e a métrica que depende dela. O Choice aceita até 255 opções, e cada uma recebe sua própria probabilidade, então adicionar ou fundir opções muda a distribuição inteira. Engenharia só entra pra revisar o impacto técnico do payload.

Renomear o ID de uma pergunta tipada do Jev muda a resposta do modelo?

Não. O ID é escolhido pela aplicação e nunca é enviado ao modelo, então o Jev não vê esse valor. O que muda é a chave no mapa de respostas, o que torna essa alteração uma decisão de engenharia, não de produto.

Quantos níveis uma pergunta Score do Jev pode ter?

De 2 a 10 níveis ordenados, cada um descrito em palavras. A resposta não cai necessariamente num nível exato: ela é uma posição contínua, e a documentação traz o exemplo de 1.035 entre dois níveis.

O que acontece se eu reordenar os níveis de uma pergunta Score sem avisar ninguém?

O código continua rodando sem erro, mas o significado do número inverte. Se o nível que antes era o último vira o primeiro, um valor alto passa a representar o oposto do que representava antes. Por isso essa mudança precisa de aprovação de produto e revisão de qualquer código que leia esse número.

O campo criteria do Jev é parte de qual campo da requisição?

As opções do Choice e os níveis do Score são açúcar sintático para o campo criteria dentro da requisição. No Choice, criteria é um mapa de opção para descrição. No Score, é uma lista ordenada de níveis.

Trocar o alias jev-latest pela versão fixa 1.13 é decisão de produto?

Não, essa troca entre typesafe/jev-1.13 e ~typesafe/jev-latest é decisão de engenharia. Como as respostas do modelo podem mudar de versão pra versão, o ideal é avisar produto antes de fazer a troca.



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