Publicado em 30 de abril de 2026
Com a IA integrada, seu site ou aplicativo da Web pode realizar tarefas com tecnologia de IA sem precisar implantar, gerenciar ou hospedar modelos. Pode ser difícil passar de uma demonstração para um recurso pronto para produção. Este documento aborda considerações técnicas e de UX para ajudar você a evitar erros comuns.
Prepare o modelo com antecedência
Aplica-se a: todas as APIs, por exemplo, Summarizer, Translator e Writer.
Faça o seguinte:inicialize a sessão assim que reconhecer a intenção do usuário. Como a ativação do usuário é necessária para inicializar uma sessão, você pode usar qualquer interação, por exemplo, um clique em qualquer lugar da página que ofereça um recurso com tecnologia de IA. Isso prepara o modelo e o ambiente de execução enquanto o usuário interage com a interface. Quando relevante, inicie a próxima tarefa de IA mais provável assim que começar a renderizar o resultado.
Não faça o seguinte: espere até que o usuário clique em "Gerar" para inicializar a sessão. Isso leva a um atraso de inicialização a frio de vários segundos, porque o modelo precisa primeiro ser carregado na memória e preparar o pipeline de execução.
Defina comandos iniciais durante a criação
Aplica-se a: API Prompt.
Faça o seguinte:forneça instruções do sistema durante a inicialização da sessão para melhorar a velocidade do primeiro comando.
Não faça o seguinte: comece com uma sessão vazia e envie instruções do sistema como parte de
a primeira chamada prompt(). Isso aumenta a latência porque força o modelo a processar essas instruções no último momento.
// ✅ DO: Create the session as early as possible (tip on warming up the model early) and use initialPrompts for system instructions in the create call
const session = await LanguageModel.create({
initialPrompts: [
{ role: 'system', content: 'You are a helpful assistant specialized in code reviews.' }
]
});
// A few moments later, when the user triggers the AI feature
const review = await session.prompt(`Review the following code:\n\n${code}`);
// ❌ DON'T: Send instructions using prompt() after creation
// const slowerSession = await LanguageModel.create();
// await slowerSession.prompt(`You are a helpful assistant specialized in code reviews.\n\nReview the following code:\n\n${code}`); // Higher latency
Clonar sessões para tarefas repetitivas
Aplica-se a: API Prompt.
Para a API Prompt, cada sessão acompanha o contexto da conversa, considerando todas as interações anteriores. Como um clone herda tudo da sessão pai, incluindo comandos iniciais e todo o histórico de interações até o ponto de clonagem, estruture o uso para herdar apenas o que você precisa.
Faça o seguinte :
- Crie uma sessão básica: para processar tarefas não relacionadas com eficiência, crie uma sessão básica que contenha apenas as instruções do sistema e nenhum contexto conversacional anterior.
- Clone a linha de base: use
clone()nessa sessão básica para novas tarefas para economizar a sobrecarga de analisar novamente instruções pesadas do sistema. Isso permite criar conversas paralelas ou redefinir uma tarefa para a linha de base.
Não faça o seguinte:
- Não reutilize a mesma sessão para tarefas não relacionadas e evite clonar qualquer sessão que já contenha um histórico de interações desnecessário. Ambos os padrões podem fazer com que o contexto anterior não relacionado interfira na tarefa atual.
- Não chame
create()repetidamente com instruções idênticas e pesadas do sistema. Use o padrão de clonagem para otimizar a performance.
// ✅ DO: Create a baseline session and clone it for each new task
const baseSession = await LanguageModel.create({
initialPrompts: [{
role: 'system',
content: 'You are a technical editor...',
}],
});
// Clone the base session once for the first task
const task1 = await baseSession.clone();
const response1 = await task1.prompt("Review this first draft...");
// ... Repeat the cloning pattern for subsequent independent tasks
// Each task starts fresh from the baseline system instructions
// ❌ DON'T:
// Bad performance pattern: repeated create() calls for identical tasks.
// This forces the model to re-parse instructions every time, increasing latency.
// const sessionA = await LanguageModel.create({ initialPrompts: [...] });
// await sessionA.prompt("Task 1...");
// const sessionB = await LanguageModel.create({ initialPrompts: [...] });
// await sessionB.prompt("Task 2...");
// Bad quality pattern: reusing the same session for unrelated tasks.
// const session = await LanguageModel.create();
// await session.prompt("Analyze this financial report...");
// Unrelated task in the same session:
// await session.prompt("Now write a children's story...");
Destruir sessões não usadas
Aplica-se a: todas as APIs.
Faça o seguinte: chame destroy() em
sessões que não são mais necessárias para liberar memória quando um recurso
não estiver mais em uso. Se você usar um padrão de clonagem, mantenha a sessão básica e destrua os clones que não são mais necessários.
Não faça o seguinte: mantenha várias sessões grandes ativas. Cada sessão consome memória, o que cria um uso desnecessário de recursos e pode se tornar um problema. As sessões serão limpas naturalmente pelo coletor de lixo, mas chamar destroy() libera memória mais rapidamente.
// ✅ DO: Use the clone and destroy it immediately after
const clone = await baseSession.clone();
const response = await clone.prompt("Quick task...");
// Free memory right away: destry the clone, keep the baseSession
clone.destroy();
Renderizar respostas de streaming com segurança e eficiência
Aplica-se a: todas as APIs com suporte a streaming (Prompt, Summarizer, Writer, Rewriter e Translator).
Faça o seguinte:trate toda a saída do LLM como conteúdo não confiável. Higienize a saída combinada completa, não apenas blocos, porque o código malicioso pode ser dividido em atualizações. Antes da renderização, use a Sanitizer API quando ela for compatível. Para evitar uma diminuição na performance, use um analisador de Markdown de streaming como streaming-markdown.
Não faça o seguinte: defina innerHTML diretamente em cada atualização de bloco. Isso é lento, especialmente com formatação complexa, como destaque de sintaxe, e vulnerável a injeção.
import * as smd from "streaming-markdown";
// Set up virtual buffer and Sanitizer API
const sanitizer = new Sanitizer({
allowElements: ['figure', 'figcaption', 'p', 'br', 'strong', 'em', 'img', 'a'],
allowAttributes: {
'loading': ['img'], 'decoding': ['img'], 'src': ['img'], 'href': ['a']
}
});
// Create an off-screen fragment so the parser doesn't cause flicker
// or trigger XSS in the live DOM during the building process.
const buffer = new DocumentFragment();
const parser = smd.parser_new(buffer);
// Use sanitizer as a gatekeeper / cleaner function so we can combine it with the streaming Markdown parser
function syncSanitized(target, sourceFragment) {
// .sanitize() returns a fresh, clean DocumentFragment
const cleanFragment = sanitizer.sanitize(sourceFragment);
// replaceChildren is the modern high-performance way to swap DOM content
target.replaceChildren(cleanFragment);
}
// Streaming Logic
// `chunks` keeps track of the raw string (useful for logs/debug)
chunks += chunk;
// Let the parser build the DOM incrementally in the buffer.
// This is high-performance because the buffer is not live
smd.parser_write(parser, chunk);
// Use the Sanitizer API to port the content safely to the container.
syncSanitized(container, buffer);
Otimizar a entrada para velocidade
Aplica-se a: todas as APIs.
Faça o seguinte:transmita apenas o que for estritamente necessário para o modelo. Remova tudo o que for irrelevante para a tarefa em questão. Para conjuntos de dados grandes, forneça uma visão geral breve e uma pequena seleção de itens relevantes.
Não faça o seguinte: envie texto bruto não processado, metadados desnecessários, tags HTML ou listas grandes não filtradas para as APIs. A latência aumenta significativamente com o tamanho da entrada, o que pode fazer com que o recurso de IA pareça quebrado em muitos dispositivos.
// ✅ DO: Send only relevant text
const cleanText = document.querySelector('#article').innerText;
const summary = await Summarizer.summarize(cleanText);
// ❌ DON'T: Send the entire DOM structure
// const dirtyText = document.querySelector('#article').innerHTML;
Usar saída estruturada para resultados previsíveis
Aplica-se a: API Prompt.
Faça o seguinte: quando precisar que o modelo retorne dados em um formato específico, use a saída
estruturada
fornecendo um campo responseConstraint para fornecer um esquema JSON. Isso garante que a saída seja previsível e evita a necessidade de pós-processamento complexo ou análise manual.
Não faça o seguinte: confie apenas em instruções de linguagem natural (como "saída apenas JSON") sozinho. Os modelos podem incluir preenchimento conversacional que quebra o analisador.
// ✅ DO: Use a JSON Schema for predictable results
const schema = {
type: "object",
properties: {
isTopicCats: { type: "boolean" }
}
};
const result = await session.prompt(`Is this post about cats?\n\n${post}`, {
responseConstraint: schema,
});
console.log(JSON.parse(result).isTopicCats);
Desvincular a geração de restrições de comprimento
Aplica-se a: API Prompt, já que é a única API que oferece suporte a esquemas de saída estruturada.
Faça o seguinte:deixe o modelo gerar a resposta naturalmente e use a lógica do lado do cliente para truncar o texto e ajustá-lo à interface.
Não faça o seguinte:aplique limites de caracteres estritos, como maxLength: 125, usando
esquemas de saída estruturada. Quando a resposta de um modelo é maior que o limite definido, o modelo pode mudar para tokens de alta densidade, como idiomas estrangeiros ou emoji, para compactar o significado, resultando em uma saída sem sentido.
/* DO: Handle overflow using CSS */
.result {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis; /* Displays '…' */
}
// ❌ DON'T: Force length in the prompt
const result = await session.prompt("Write a bio in exactly 50 characters.");
Gerenciar a paciência do usuário
Aplica-se a: todas as APIs.
Faça o seguinte:use animações e técnicas de interface para gerenciar a paciência do usuário. A abordagem ideal depende do seu caso de uso e do comprimento esperado da saída da API. Algumas ideias:
- Streaming para conteúdo longo: para resumos ou chats, o streaming cria um efeito de máquina de escrever por token por padrão. Isso pode parecer natural e fornecer feedback imediato.
- Não streaming para tarefas curtas (ou tarefas assíncronas longas): para saídas curtas, por exemplo, texto alternativo, o não streaming pode criar uma interface mais refinada. Ele também oferece tempo para preparar especulativamente a próxima tarefa da IA enquanto a atual é renderizada. Essa abordagem também funciona para tarefas assíncronas ou em segundo plano mais longas. Se o usuário não estiver bloqueado na saída para continuar a jornada, não haverá necessidade urgente de produzir a saída conforme ela acontece. Indique que o processo está em andamento na interface.
- Transições visuais para atualizações: ao traduzir ou reescrever texto, use animações, por exemplo, a transformação de palavras.
Não faça o seguinte: atualize a interface sem pistas visuais.
Alinhar com o modelo mental de tempo e trabalho do usuário
Aplica-se a: todas as APIs.
Faça o seguinte:considere um atraso artificial de um ou dois segundos se uma resposta for quase instantânea. Paradoxalmente, os usuários podem achar os resultados mais confiáveis quando percebem um processo de geração que se alinha à dificuldade percebida da tarefa. Use animações para indicar que um processo de IA ocorreu.
Não faça o seguinte: surpreenda os usuários com substituições instantâneas da interface.
Permitir que os usuários naveguem e desfaçam edições de IA rapidamente
Aplica-se a: todas as APIs.
Faça o seguinte:equipe sua interface com um stepper ou histórico de navegação que permita que os usuários explorem resultados diferentes com confiança e desfaçam rapidamente as edições de IA. Isso garante que versões diferentes ainda estejam disponíveis.
Não faça o seguinte: substitua o rascunho anterior do usuário ou um resultado de IA que ele possa ter gostado sem uma maneira de voltar, reverter ou comparar versões.
Capacitar o controle e as substituições do usuário
Aplica-se a: todas as APIs.
Faça o seguinte:sempre deixe o usuário ter a palavra final. Forneça uma maneira de substituir manualmente as sugestões. As APIs podem produzir resultados incorretos.
Não faça o seguinte: force um resultado gerado por IA como a única opção.
Armazenar resultados em cache para tarefas repetidas
Aplica-se a: todas as APIs.
Faça o seguinte:implemente um cache de resultados local (por exemplo, usando sessionStorage ou IndexedDB) para entradas ou consultas repetidas. Normalize a entrada cortando espaços em branco e letras minúsculas para aumentar os acertos de cache. Para entradas pesadas, por exemplo, imagens, gere um hash para usar como chave de cache. Defina um tempo de vida (TTL) conservador para o cache (ou veicule resultados armazenados em cache enquanto os atualiza em segundo plano). Permita que o usuário acione uma nova inferência se o resultado for insatisfatório.
Não faça o seguinte: execute a mesma inferência novamente para uma consulta de pesquisa repetida ou entrada de dados idêntica, por exemplo, quando um usuário navega para frente e para trás entre os resultados da pesquisa. Embora a inferência no dispositivo seja sem custo financeiro em termos de custos de nuvem, ela é cara em termos de tempo do usuário e duração da bateria.
// ✅ DO: Check a local cache before running inference
async function getAiResponse(userInput, forceRefresh = false) {
// Normalize the query to increase cache hits
const query = userInput.trim().toLowerCase();
const cacheKey = `ai_results_${query}`;
const TTL_MS = 3600000; // 1 hour conservative TTL
if (!forceRefresh) {
const itemStr = localStorage.getItem(cacheKey);
if (itemStr) {
const item = JSON.parse(itemStr);
const now = Date.now();
// Check if the item has expired
if (now < item.expiry) {
// Lightweight safety check before rendering
if (isValid(item.value)) return item.value;
} else {
// Delete the stale entry if the TTL has passed
localStorage.removeItem(cacheKey);
}
}
}
// Fallback: Run inference if no valid cache exists
const session = await LanguageModel.create();
const response = await session.prompt(userInput);
// Store the result for future use (with an expiration)
const cacheData = {
value: response,
expiry: Date.now() + TTL_MS
};
localStorage.setItem(cacheKey, JSON.stringify(cacheData));
return response;
}