{"id":739,"date":"2026-09-23T18:34:30","date_gmt":"2026-09-23T21:34:30","guid":{"rendered":"https:\/\/yellowkode.com\/blog\/problema-variancia-produtos-ia\/"},"modified":"2026-09-23T18:34:30","modified_gmt":"2026-09-23T21:34:30","slug":"problema-variancia-produtos-ia","status":"publish","type":"post","link":"https:\/\/yellowkode.com\/blog\/problema-variancia-produtos-ia\/","title":{"rendered":"O Problema da Vari\u00e2ncia em Produtos de IA: Impacto na Confian\u00e7a do Usu\u00e1rio"},"content":{"rendered":"<h2>O fato<\/h2>\n<p>Em 22 de setembro de 2026, o UX Collective publicou <em>The Variance Problem in AI Products: Latency and Trust<\/em>, de Adi Leviim. O ensaio parte de uma observa\u00e7\u00e3o simples e inc\u00f4moda para quem constr\u00f3i produtos com LLM: o mesmo prompt pode responder em um segundo hoje e em quarenta amanh\u00e3, e a interface trata os dois casos exatamente igual. O texto discute por que tempos de resposta vari\u00e1veis de IA erodem a confian\u00e7a, e por que nomear o trabalho \u00e9 melhor que estimativas de tempo e delays artificiais. Ele cruza isso com literatura cl\u00e1ssica de usabilidade, Nielsen, Myers, Maister e Tognazzini, que j\u00e1 resolveu esse problema para software determin\u00edstico d\u00e9cadas atr\u00e1s.<\/p>\n<p>Este artigo destrincha o mecanismo, mostra onde ele bate no c\u00f3digo e diz onde a solu\u00e7\u00e3o do Leviim ainda deixa buraco.<\/p>\n<h2>Como funciona o problema da vari\u00e2ncia<\/h2>\n<h3>O que \u00e9 vari\u00e2ncia aqui, em termos concretos<\/h3>\n<p>Num sistema tradicional, um clique em <code>Salvar<\/code> tem lat\u00eancia com desvio pequeno. Se o P50 \u00e9 200ms, o P99 talvez seja 800ms. Voc\u00ea projeta o spinner assumindo esse envelope. Em produto com LLM, o envelope estoura. O mesmo pedido pode ter P50 de 2s e P99 de 45s, dependendo de tamanho do prompt, tokens gerados, roteamento do provedor, fila do modelo, ferramenta chamada no meio do caminho. E n\u00e3o estamos falando s\u00f3 de tempo. N\u00e3o-determinismo n\u00e3o \u00e9 caso de borda em produtos com LLM, \u00e9 o padr\u00e3o. A sa\u00edda tamb\u00e9m varia: vari\u00e2ncia de output, drift comportamental e falha em n\u00edvel de racioc\u00ednio.<\/p>\n<p>O foco do Leviim \u00e9 a vari\u00e2ncia de <em>tempo<\/em>, e \u00e9 por a\u00ed que entramos.<\/p>\n<h3>As duas sa\u00eddas erradas que a maioria dos produtos escolhe<\/h3>\n<p>Segundo o autor, produtos de IA hoje lidam com vari\u00e2ncia de dois jeitos, e cada um troca uma falha por outra. Ou exp\u00f5em a vari\u00e2ncia crua, ou achatam com um piso artificial. Vari\u00e2ncia crua \u00e9 o spinner com a palavra &#8220;Thinking&#8221; que parece id\u00eantica em um segundo e em quarenta. O usu\u00e1rio n\u00e3o tem como distinguir uma tarefa longa de uma travada. O piso \u00e9 mais sutil. Alguns times adicionam um delay m\u00ednimo para que respostas r\u00e1pidas n\u00e3o criem uma \u00e2ncora irreal. Funciona, no sentido estrito de que rodadas lentas param de parecer quebradas. Mas apaga o lado positivo para prevenir o negativo.<\/p>\n<p>Traduzindo para c\u00f3digo, o &#8220;piso&#8221; \u00e9 isto aqui, e \u00e9 mais comum do que parece:<\/p>\n<pre><code>\/\/ anti-padr\u00e3o: piso artificial de 3s\nasync function askAI(prompt) {\n const start = Date.now();\n const answer = await llm.complete(prompt);\n const elapsed = Date.now() - start;\n if (elapsed &lt; 3000) {\n await sleep(3000 - elapsed);\n }\n return answer;\n}<\/code><\/pre>\n<p>Toda resposta que poderia ter chegado em 800ms passa a chegar em 3s. Voc\u00ea pagou lat\u00eancia real para comprar uniformidade percebida. Em produto onde a IA compete com uma alternativa r\u00e1pida, isso \u00e9 entregar terreno de gra\u00e7a.<\/p>\n<h3>Por que o spinner gen\u00e9rico falha, com Nielsen e Maister na m\u00e3o<\/h3>\n<p>A literatura de usabilidade j\u00e1 resolveu metade disso. Nielsen aponta que 10 segundos \u00e9 o limite para manter a aten\u00e7\u00e3o do usu\u00e1rio focada no di\u00e1logo. Para atrasos maiores, os usu\u00e1rios v\u00e3o querer fazer outras tarefas enquanto esperam, ent\u00e3o devem receber feedback indicando quando o computador espera terminar. Feedback durante o atraso \u00e9 especialmente importante se o tempo de resposta tende a ser altamente vari\u00e1vel, porque o usu\u00e1rio n\u00e3o saber\u00e1 o que esperar.<\/p>\n<p>Guarde essa \u00faltima frase. IA generativa \u00e9 o caso extremo de &#8220;altamente vari\u00e1vel&#8221;. Um <code>&lt;div class=\"spinner\"&gt;Thinking...&lt;\/div&gt;<\/code> n\u00e3o \u00e9 feedback, \u00e9 um placeholder animado. Ele diz apenas &#8220;n\u00e3o travei&#8221;, e nem isso com confian\u00e7a depois dos 30 segundos.<\/p>\n<p>Do outro lado, Maister, no cl\u00e1ssico <em>The Psychology of Waiting Lines<\/em> de 1985. Esperas incertas s\u00e3o mais longas que esperas conhecidas e finitas. As pessoas esperam mais calmamente quando ouvem &#8220;o m\u00e9dico atende voc\u00ea em trinta minutos&#8221; do que quando ouvem &#8220;o m\u00e9dico atende voc\u00ea em breve&#8221;. E ainda mais duro: esperar \u00e9 desmoralizante. Esperar na ignor\u00e2ncia cria uma sensa\u00e7\u00e3o de impot\u00eancia, que frequentemente resulta em irrita\u00e7\u00e3o vis\u00edvel.<\/p>\n<p>\u00c9 por isso que o piloto que repete &#8220;s\u00f3 mais alguns minutinhos&#8221; enfurece. O usu\u00e1rio n\u00e3o est\u00e1 bravo com o atraso, est\u00e1 bravo por n\u00e3o conseguir mais confiar na estimativa. Interface de IA que fica trocando de &#8220;Thinking&#8221; para &#8220;Almost there&#8221; para &#8220;Just a moment&#8221; est\u00e1 cometendo o mesmo erro.<\/p>\n<h3>A proposta: nomear o trabalho, n\u00e3o estimar o tempo<\/h3>\n<p>A sa\u00edda que o Leviim defende \u00e9 abandonar o placeholder animado e a estimativa de tempo, e em vez disso nomear a etapa real que est\u00e1 acontecendo. Nada disso exige remover a vari\u00e2ncia. Sistemas de IA v\u00e3o continuar sendo r\u00e1pidos \u00e0s vezes e lentos outras. O que os usu\u00e1rios precisam \u00e9 de um produto que diga qual dos dois est\u00e1 acontecendo, em palavras que continuem verdadeiras enquanto acontece.<\/p>\n<p>A analogia mais pr\u00f3xima \u00e9 a cozinha aberta de restaurante. Voc\u00ea n\u00e3o sabe quanto tempo seu prato demora, mas v\u00ea o chef pegar a carne, ver a chapa aquecer, montar. A espera continua igual, a sensa\u00e7\u00e3o muda porque o processo \u00e9 observ\u00e1vel e nomeado. A analogia quebra num ponto: no restaurante voc\u00ea v\u00ea o processo f\u00edsico. Na IA, o processo \u00e9 inventado pelo desenvolvedor, e essa \u00e9 justamente a decis\u00e3o de design.<\/p>\n<p>\u00c9 a diferen\u00e7a entre isto:<\/p>\n<pre><code>&lt;div role=\"status\" aria-live=\"polite\"&gt;Thinking...&lt;\/div&gt;<\/code><\/pre>\n<p>e isto:<\/p>\n<pre><code>&lt;div role=\"status\" aria-live=\"polite\"&gt;\n Lendo os 3 PDFs anexados\n&lt;\/div&gt;\n\/\/ depois:\n&lt;div role=\"status\" aria-live=\"polite\"&gt;\n Cruzando cl\u00e1usulas de rescis\u00e3o entre os documentos\n&lt;\/div&gt;\n\/\/ depois:\n&lt;div role=\"status\" aria-live=\"polite\"&gt;\n Escrevendo o resumo\n&lt;\/div&gt;<\/code><\/pre>\n<p>Os dois usam <code>aria-live=\"polite\"<\/code> para que o leitor de tela anuncie as mudan\u00e7as sem interromper a leitura em curso, o que j\u00e1 era o correto no primeiro exemplo, mas ali o leitor de tela n\u00e3o tem nada \u00fatil para anunciar.<\/p>\n<h2>O que isso significa na pr\u00e1tica<\/h2>\n<p>A implementa\u00e7\u00e3o depende de voc\u00ea conseguir emitir eventos do backend a cada transi\u00e7\u00e3o real da pipeline. Server-Sent Events ou WebSocket resolvem. O padr\u00e3o fica assim:<\/p>\n<pre><code>\/\/ backend emite eventos nomeados\nfor await (const step of agent.run(prompt)) {\n res.write(`event: step\\ndata: ${JSON.stringify(step)}\\n\\n`);\n}\n\n\/\/ frontend consome e troca o texto vivo\nconst es = new EventSource('\/ask');\nes.addEventListener('step', (e) =&gt; {\n const { label } = JSON.parse(e.data);\n statusEl.textContent = label; \/\/ \"Buscando na base de contratos\"\n});<\/code><\/pre>\n<p>Repare no que essa arquitetura for\u00e7a voc\u00ea a fazer no design: escrever o r\u00f3tulo humano de cada etapa <em>antes<\/em> de escrever a etapa. Voc\u00ea n\u00e3o pode dizer &#8220;lendo os 3 PDFs&#8221; se a pipeline n\u00e3o tem uma etapa isolada de leitura. A frase honesta vira uma press\u00e3o sobre a arquitetura. Isso \u00e9 bom.<\/p>\n<p>J\u00e1 num construtor de landing page que tirou a cria\u00e7\u00e3o de pagina da fila da engenharia, vi o oposto: a pipeline era r\u00e1pida o suficiente para que qualquer texto de espera acima de &#8220;salvando&#8221; fosse mentira. Ali, o certo era n\u00e3o inventar etapa nenhuma, e o spinner de 300ms bastava. Nomear trabalho que n\u00e3o existe \u00e9 t\u00e3o ruim quanto esconder trabalho que existe.<\/p>\n<h3>O caso em que a solu\u00e7\u00e3o do Leviim se apoia<\/h3>\n<p>Vale reconhecer o limite pr\u00e1tico que ele mesmo cita. Como Bilal disse na discuss\u00e3o sobre quanto disso um time pequeno consegue realmente construir: &#8220;A shipped sentence beats a coordinated system that never ships.&#8221; Se voc\u00ea n\u00e3o tem infraestrutura de streaming de eventos, comece por hardcode: quatro frases pr\u00e9-escritas trocando em intervalos plaus\u00edveis j\u00e1 \u00e9 melhor que &#8220;Thinking&#8221;. S\u00f3 saiba que isso vira d\u00edvida no dia que a pipeline mudar e as frases continuarem as mesmas.<\/p>\n<h2>Onde quebra<\/h2>\n<p><strong>Um.<\/strong> R\u00f3tulos honestos exigem que o backend saiba nomear o que est\u00e1 fazendo. Em pipelines com agente aut\u00f4nomo, o pr\u00f3ximo passo \u00e9 decidido pelo modelo em tempo de execu\u00e7\u00e3o. Voc\u00ea acaba emitindo o pensamento cru (&#8220;Calling tool: web_search&#8221;), que \u00e9 t\u00e9cnico demais, ou traduzindo em tempo real para linguagem humana, que introduz outra camada de lat\u00eancia.<\/p>\n<p><strong>Dois.<\/strong> Feedback frequente em <code>aria-live<\/code> pode virar polui\u00e7\u00e3o sonora para leitor de tela. Em dashboard denso em dados de medi\u00e7\u00e3o de m\u00eddia, aprendi que qualquer regi\u00e3o viva mal calibrada faz o NVDA anunciar de novo e de novo at\u00e9 o usu\u00e1rio desligar. Use <code>polite<\/code>, n\u00e3o <code>assertive<\/code>, e n\u00e3o atualize mais r\u00e1pido que cerca de dois segundos.<\/p>\n<p><strong>Tr\u00eas.<\/strong> Nomear o trabalho aumenta a expectativa de sucesso. Se o r\u00f3tulo diz &#8220;cruzando cl\u00e1usulas de rescis\u00e3o&#8221; e a resposta final n\u00e3o menciona rescis\u00e3o, o usu\u00e1rio percebe a mentira. O texto de espera vira contrato impl\u00edcito com o resultado. Time de design agora depende do time de modelo para manter esse contrato, e essa depend\u00eancia n\u00e3o \u00e9 gratuita.<\/p>\n<p><strong>Quatro.<\/strong> Para respostas de sub-segundo, nada disso importa. Nielsen lembra que 0.1 segundo d\u00e1 a sensa\u00e7\u00e3o de resposta instant\u00e2nea, o resultado parece ter sido causado pelo usu\u00e1rio, n\u00e3o pelo computador. N\u00e3o empilhe estados de progresso onde o usu\u00e1rio nem viu que houve espera.<\/p>\n<h2>O que n\u00e3o d\u00e1 para afirmar ainda<\/h2>\n<p>O ensaio do Leviim n\u00e3o traz estudo controlado que me\u00e7a, digamos, redu\u00e7\u00e3o de taxa de abandono entre spinner gen\u00e9rico e progresso nomeado em produto de IA. Ele apoia a tese em princ\u00edpios cl\u00e1ssicos v\u00e1lidos e em relatos de produ\u00e7\u00e3o citados por Bilal Skiani sobre um sistema chamado Genie 007, que eu n\u00e3o tenho como verificar. Portanto, o mecanismo \u00e9 s\u00f3lido pela ci\u00eancia de percep\u00e7\u00e3o de espera, e a aplica\u00e7\u00e3o em LLM \u00e9 razo\u00e1vel, mas o tamanho do efeito em cada tipo de produto continua sendo emp\u00edrico. Teste no seu.<\/p>\n<p>Tamb\u00e9m n\u00e3o est\u00e1 claro qual \u00e9 o custo cognitivo de trocar o r\u00f3tulo tr\u00eas, quatro, cinco vezes numa resposta longa. \u00c9 poss\u00edvel que abaixo de certa dura\u00e7\u00e3o o sil\u00eancio narrado seja melhor que a narra\u00e7\u00e3o.<\/p>\n<h2>Como testar isso voc\u00ea mesmo<\/h2>\n<p>Pegue seu chat interno com LLM, ou fa\u00e7a um pequeno com a API que voc\u00ea j\u00e1 usa. Fa\u00e7a tr\u00eas variantes da mesma tela:<\/p>\n<ul>\n<li><strong>A:<\/strong> spinner com &#8220;Pensando&#8230;&#8221;<\/li>\n<li><strong>B:<\/strong> spinner com barra de progresso falsa que enche em 20 segundos e trava em 95%<\/li>\n<li><strong>C:<\/strong> texto vivo em <code>aria-live=\"polite\"<\/code> que troca a cada etapa real da sua pipeline (ex.: &#8220;Lendo o documento&#8221;, &#8220;Procurando trechos relevantes&#8221;, &#8220;Redigindo resposta&#8221;)<\/li>\n<\/ul>\n<p>Rode com dez pessoas, use um prompt que voc\u00ea sabe que demora entre 15 e 40 segundos. Pergunte tr\u00eas coisas depois de cada tentativa: quanto tempo achou que demorou, se em algum momento pensou que travou, e se confiaria no sistema para uma tarefa mais cr\u00edtica. Voc\u00ea vai ter dados seus, n\u00e3o do post do Leviim, sobre onde vale nomear e onde n\u00e3o. Esse \u00e9 o \u00fanico jeito honesto de decidir.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Como projetar interfaces de IA para lidar com lat\u00eancia vari\u00e1vel e manter a confian\u00e7a do usu\u00e1rio.<\/p>\n","protected":false},"author":2,"featured_media":738,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-739","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/739","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/comments?post=739"}],"version-history":[{"count":0,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/739\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media\/738"}],"wp:attachment":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media?parent=739"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/categories?post=739"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/tags?post=739"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}