Intermediário 12 minPlano diário

WebLLM: um modelo de IA no navigateur

WebLLM: um modelo de IA no navigateur

O WebLLM é uma biblioteca JavaScript que executa um LLM na aba do navegador, na GPU da máquina, graças ao WebGPU. Nada a instalar no sistema, mas três condições a verificar: a compatibilidade do navegador, o download do modelo e o comportamento real da página. Um cálculo executado na sua GPU não prova nem que a página funciona offline nem que suas mensagens ficam com você. Este guia explica como verificar isso; ele não contém nenhum benchmark.

Por Mohamed Meguedmi·Atualização 2026-11-09·Testado no Windows, macOS e Linux
!
Limite deste guia
O repositório do WebLLM e sua documentação não puderam ser revisados no dia da redação, 9 de novembro de 2026, e nenhum código deste guia foi executado pelo QuelLLM. Os trechos do WebLLM descrevem a API como a conhecemos, sem versão garantida: o README do repositório prevalece se divergir. As informações sobre WebGPU, armazenamento e política de segurança vêm do MDN, relido em 9 de novembro de 2026.

#WebLLM: o que a biblioteca faz

Com o Ollama, um programa instalado na máquina carrega o modelo e responde em http://localhost:11434. Com o WebLLM, tudo passa por uma página web: ela carrega o código JavaScript e WebAssembly do motor, obtém os pesos do modelo e depois envia os cálculos para a GPU via WebGPU. Não há serviço para iniciar nem porta para abrir.

Do lado do desenvolvedor, a API segue o formato da API da OpenAI: cria-se um engine e depois chama-se engine.chat.completions.create com uma lista de mensagens. Um aplicativo escrito para esse formato se adapta, portanto, com bastante rapidez. O engine, no entanto, vive na página: não é um servidor HTTP ao qual Open WebUI, um editor de código ou um script Python poderiam se conectar.

WebGPU
API do navegador que dá acesso à GPU para computação. Sem ela, ou sem um adaptador disponível, o motor não consegue funcionar na GPU.
WebAssembly
Formato no qual parte do engine é entregue. Ele faz parte do que a página precisa carregar, assim como o JavaScript.
Os pesos do modelo
Arquivos volumosos, separados do código da página. Eles são baixados do endereço indicado na configuração e depois armazenados em cache pelo navegador.
O formato MLC
O WebLLM usa modelos compilados para o seu motor, identificáveis pelo sufixo MLC nos seus identificadores. Um arquivo GGUF baixado para Ollama ou LM Studio não carrega do jeito que está.

#WebLLM ou Ollama: qual ferramenta para qual necessidade?

O kit completo para criar o seu próprio assistente de IA.

Aproveite a nossa experiência e um percurso guiado para criar o seu assistente local e usar a sua IA no dia a dia.

  • Espaço online vitalício
  • PDF + arquivos
  • Reembolsado em 30 dias

O WebLLM não substitui uma instalação local tradicional. O valor dele está em outro lugar: oferecer um recurso de IA numa página para pessoas que não vão instalar nada.

O WebLLM é indicado para
Uma demonstração pública, uma ferramenta web interna, um assistente integrado a um aplicativo, um teste rápido em um computador onde não se pode instalar nada.
Ollama ou LM Studio servem para
Uso diário, escolha em um amplo catálogo, modelos maiores, uma API reutilizável por outras ferramentas, um funcionamento que não depende dos limites de uma aba.
Os custos a aceitar
O catálogo depende dos modelos compilados no formato MLC, a memória disponível também depende dos limites do navegador, e o cache pode ser apagado sem aviso.

Não apresentamos comparação de velocidade: nenhuma medição com protocolo e hardware documentados embasa este guia. Se isso for importante para o seu projeto, meça nas suas máquinas-alvo, com o mesmo modelo e a mesma quantização, anotando a versão do navegador e do driver.

#Pré-requisitos e compatibilidade com WebGPU

O MDN ainda classificava o WebGPU como de disponibilidade limitada, portanto não Baseline, em sua página modificada em 2 de setembro de 2026: a API não funciona em alguns navegadores muito usados. O suporte depende da combinação de navegador, sistema e driver gráfico. Um navegador pode, portanto, expor o WebGPU em um sistema e não em outro. Em vez de uma lista de versões que logo fica desatualizada, consulte a tabela de compatibilidade do MDN e depois teste cada máquina-alvo.

Contexto seguro
Segundo o MDN, a API inteira só está disponível em contexto seguro: sirva a página via HTTPS, ou em localhost durante o desenvolvimento. Uma página aberta via HTTP em um endereço de rede local não serve.
Navegador e driver
Ambos atualizados. Uma GPU recente não basta se o driver ou o navegador bloquear o acesso.
Memória da GPU
Referências do QuelLLM em Q4 na stack habitual: 3B cerca de 2 GB, 7B cerca de 5 GB. São ordens de grandeza, não medições do WebLLM.
Espaço em disco e conexão
Espaço para armazenar o modelo e baixá-lo pelo menos uma vez. Confira o tamanho real no acompanhamento do carregamento.

Este teste deve ser colado no console das ferramentas de desenvolvedor, em uma página em HTTPS ou em localhost. Ele se baseia na API padrão e não carrega nenhum modelo. Segundo o MDN, requestAdapter retorna null quando nenhum adaptador adequado está disponível: a presença de navigator.gpu, portanto, não basta para tirar conclusões.

Console do navegador: testar o WebGPU
if (!navigator.gpu) {
  console.log('WebGPU absent : navigateur non compatible, API désactivée ou contexte non sécurisé');
} else {
  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    console.log('API présente, mais aucun adaptateur disponible');
  } else {
    console.log('shader-f16 :', adapter.features.has('shader-f16'));
    console.log('maxBufferSize :', adapter.limits.maxBufferSize);
    console.log('maxStorageBufferBindingSize :', adapter.limits.maxStorageBufferBindingSize);
  }
}

A linha shader-f16 ajuda a escolher a variante. Os identificadores do WebLLM geralmente distinguem modelos q4f16, que exigem esse recurso, e q4f32, que o dispensam. Os dois limites de buffer indicam o que o navegador aceita alocar; eles podem bloquear um modelo grande mesmo que a placa tenha memória suficiente.

#O que o download implica

No primeiro carregamento, a página obtém os arquivos do modelo e o código compilado associado a partir dos endereços da sua configuração. Na lista pré-construída do WebLLM, esses endereços apontam, até onde sabemos, para repositórios externos como Hugging Face e GitHub: verifique isso na aba Rede. Esses hosts veem então seu endereço IP e o modelo solicitado, mesmo que nenhuma mensagem tenha sido enviada ainda.

Os arquivos ficam então armazenados no armazenamento do navegador, vinculado à origem da página. O MDN detalha as regras que você precisa conhecer: por padrão, esse armazenamento funciona em modo best-effort, e o navegador pode removê-lo quando há pouco espaço em disco, sem interromper o usuário, começando pelas origens usadas há mais tempo. Uma origem removida perde todos os seus dados de uma vez. O Safari também pode excluir os dados criados por script de uma origem sem interação há sete dias de uso do navegador, quando a prevenção de rastreamento entre sites está ativa.

Console da página: cota e armazenamento persistente
const { usage, quota } = await navigator.storage.estimate();
console.log('Utilisé :', usage, 'octets sur un quota estimé de', quota);

const persistant = await navigator.storage.persist();
console.log('Stockage persistant accordé :', persistant);
→
Solicitar a persistência não garante nada
O Firefox exibe uma solicitação ao usuário; Chrome, Edge e Safari decidem sozinhos, com base no histórico de interação com o site (MDN, página modificada em 5 de janeiro de 2026). Se persist retornar false, considere que o modelo pode precisar ser baixado novamente.

#Instalar o WebLLM em uma página: as etapas

Este passo a passo pressupõe um projeto JavaScript com uma ferramenta de build, por exemplo o Vite. Instalar o pacote no projeto, em vez de importá-lo de uma CDN, evita adicionar um domínio de terceiros ao carregamento da página e facilita o funcionamento offline.

Terminal, no seu projeto
npm install @mlc-ai/web-llm
  1. 01
    Fixar a versão
    Anote a versão instalada no package-lock.json e leia o README correspondente. Nesse momento, verifique a licença do pacote e a do modelo, que são duas coisas distintas.
  2. 02
    Listar os modelos disponíveis
    Não copie um identificador de um artigo: a lista muda. Leia-a na versão instalada, com o primeiro trecho abaixo. O campo de memória que ela indica serve como ponto de partida, não como garantia.
  3. 03
    Começar com pouco
    Escolha primeiro o menor modelo útil, em q4f32 se o teste anterior indicar que falta shader-f16. Um primeiro teste bem-sucedido separa os problemas de código dos problemas de memória.
  4. 04
    Exibir o progresso
    O download pode ser demorado. Sem feedback visual, a página parece travada: o initProgressCallback fornece o texto de progresso a ser exibido.
  5. 05
    Mover para um Web Worker
    O carregamento e a geração podem travar a interface se forem executados na thread principal. Para isso, o WebLLM oferece o CreateWebWorkerMLCEngine, com o handler WebWorkerMLCEngineHandler do lado do worker. Planeje isso antes de colocar no ar.
  6. 06
    Testar nas máquinas-alvo
    Um resultado numa estação de desenvolvimento não diz nada sobre um notebook com GPU integrada. Preveja uma mensagem clara caso o WebGPU não esteja disponível, em vez de uma página em branco.
Listar os modelos da versão instalada
import { prebuiltAppConfig } from '@mlc-ai/web-llm';

console.table(prebuiltAppConfig.model_list.map((m) => ({
  id: m.model_id,
  vramMo: m.vram_required_MB,
})));
Carregar um modelo e ler a resposta em streaming
import { CreateMLCEngine } from '@mlc-ai/web-llm';

// Remplacez par un identifiant relevé dans la liste ci-dessus
const modelId = 'IDENTIFIANT_DU_MODELE';

const engine = await CreateMLCEngine(modelId, {
  initProgressCallback: (p) => console.log(p.text),
});

const stream = await engine.chat.completions.create({
  messages: [{ role: 'user', content: 'Explique WebGPU en deux phrases.' }],
  stream: true,
});

let reponse = '';
for await (const chunk of stream) {
  reponse += chunk.choices[0]?.delta?.content || '';
}
console.log(reponse);

#Verificar uma página WebLLM: rede, scripts, offline

O WebLLM garante, no máximo, onde o cálculo é executado. O resto depende da página que o incorpora: um script de análise de audiência, um widget ou uma função de envio pode ler o conteúdo do campo de entrada e transmiti-lo, pois todo script carregado na página tem acesso a ela. Essa verificação vale para qualquer site que anuncie uma IA no navegador, inclusive o seu.

  1. 01
    Preparar um perfil limpo
    Abra um perfil de navegador sem extensões: uma extensão autorizada na página pode ler o que é exibido nela e distorce o resultado. Abra a aba Rede e ative a preservação do log.
  2. 02
    Registrar o carregamento
    Carregue a página e anote cada domínio contatado e a função dele: página, motor, modelo, fonte, medição de audiência, publicidade. Qualquer domínio sem uma função clara ainda precisa ser explicado.
  3. 03
    Registrar o envio de uma mensagem
    Depois que o modelo carregar, limpe o log. Envie uma mensagem contendo um marcador inventado, por exemplo TEST-MARQUEUR-7Q2X, e procure-o no log usando a busca da aba Rede. Examine também cada requisição enviada durante a geração, incluindo as mensagens WebSocket.
  4. 04
    Inspecionar os scripts e o cabeçalho de segurança
    Na aba Sources, liste os domínios de origem dos scripts. Nos cabeçalhos de resposta do documento, procure Content-Security-Policy: uma diretiva connect-src restritiva reduz os destinos possíveis; a ausência dela não prova nada.
  5. 05
    Ver o que fica no disco
    Na aba Aplicativo ou Armazenamento, abra IndexedDB, Cache e o armazenamento local. O modelo normalmente está lá, mas suas conversas também podem estar, em texto claro para qualquer pessoa que use essa sessão.
  6. 06
    Desligar a rede de verdade
    Feche a página, desative o Wi-Fi ou desconecte o cabo, depois reabra o endereço e envie uma nova mensagem. A página deve carregar e responder. Repita depois de fechar o navegador.
!
Um modelo em cache não torna a página offline
Se o HTML, o JavaScript ou o WebAssembly da página também não forem armazenados, normalmente por um service worker, o endereço não abrirá mais sem rede, mesmo com o modelo inteiro no disco. Um engine já aberto que continua respondendo depois da desconexão não prova, portanto, o funcionamento offline: só o teste de reabertura conta.

Essas verificações têm seus limites. Um marcador não encontrado não exclui um envio criptografado ou codificado por um script. As conexões WebRTC não aparecem como requisições comuns na aba Rede: no Chrome, chrome://webrtc-internals permite identificá-las. Por fim, o resultado só vale para a versão testada, pois o operador do site pode mudar seus scripts a qualquer momento.

Você pode dizer “funciona offline”
Se reabrir a página e enviar uma nova mensagem funcionar com a rede desconectada, no navegador testado, na data do teste. Deixe claro que o cache pode ser removido.
Você pode dizer “nenhum envio observado”
Se o log não mostrar nenhuma requisição ligada à mensagem, na versão testada e conforme o protocolo descrito. É uma observação datada.
Você não pode dizer “totalmente privado”
A menos que você domine todo o código servido e suas atualizações, sem nenhum script de terceiros, e complemente essa verificação com uma leitura do código. Mesmo nesse caso, o host do modelo vê o download e as extensões continuam sendo um risco.

#Servir tudo a partir do seu domínio

Para uma ferramenta interna, a configuração mais fácil de controlar consiste em servir a página, o engine e o modelo a partir da mesma origem, sem nenhum script de terceiros. O WebLLM aceita uma configuração personalizada na qual cada modelo indica o endereço de seus pesos e o de sua biblioteca compilada. Os caminhos abaixo são exemplos a adaptar.

Configuração personalizada (endereços de exemplo)
import { CreateMLCEngine } from '@mlc-ai/web-llm';

const appConfig = {
  model_list: [{
    model: 'https://outil.example.fr/modeles/mon-modele/',
    model_id: 'mon-modele',
    model_lib: 'https://outil.example.fr/libs/mon-modele.wasm',
  }],
};

const engine = await CreateMLCEngine('mon-modele', { appConfig });

O próprio motor monta os endereços dos arquivos a partir desse prefixo. Ele pode esperar uma estrutura de diretórios semelhante à do Hugging Face: se algumas requisições falharem com 404, veja na aba Rede os caminhos exatos solicitados e reproduza-os no seu servidor. A biblioteca compilada deve corresponder ao modelo: não a combine com outro modelo aleatoriamente.

Depois de trazer tudo para o seu próprio servidor, uma política de segurança pode transformar uma promessa em restrição técnica: segundo o MDN, connect-src limita, entre outros, fetch, XMLHttpRequest, WebSocket, EventSource e sendBeacon, e recorre a default-src se estiver ausente. O exemplo a seguir não foi testado com o WebLLM. Implante-o primeiro no modo Content-Security-Policy-Report-Only e leia o console.

Cabeçalho HTTP, a adaptar à sua página
Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'

Esse cabeçalho também bloqueia downloads do Hugging Face: isso é intencional, e o modelo precisa então ser servido pelo seu domínio. Ele não cobre todas as saídas possíveis, como uma navegação para outro endereço. Para funcionar offline, adicione um service worker que armazene em cache os arquivos da página. O WebLLM também oferece um motor para esse contexto, o CreateServiceWorkerMLCEngine: consulte o README dele.

#Solução de problemas

navigator.gpu é undefined
Primeiro, verifique o endereço: HTTPS ou localhost. Em seguida, consulte a tabela de compatibilidade do MDN para o seu navegador e o seu sistema e depois atualize os dois.
requestAdapter retorna null
A API existe, mas nenhum adaptador adequado está disponível. Atualize o driver e verifique se a aceleração de hardware do navegador está ativada. Experimente outro navegador para isolar a causa.
Erro relacionado a shader-f16
O modelo escolhido exige um recurso que o seu adaptador não tem. Use a variante q4f32 dele, se existir.
QuotaExceededError
A cota da origem foi excedida: o MDN indica esse erro para IndexedDB, Cache e OPFS. Libere espaço ou escolha um modelo menor, e capture o erro no código.
Travamento no fim do carregamento ou perda da GPU
Provavelmente memória insuficiente ou limite de buffer atingido. Feche as abas pesadas, use um tamanho de modelo menor e confira a mensagem exata no console.
O modelo é baixado de novo
Navegação privada, remoção do armazenamento, dados do site apagados ou mudança de origem, pois cada domínio tem seu próprio armazenamento. O pacote expõe, até onde sabemos, hasModelInCache para verificar isso antes de iniciar o carregamento.
A interface trava durante a geração
O engine roda na thread principal. Mude para CreateWebWorkerMLCEngine.
Erro de política de segurança no console
A mensagem indica a diretiva e o endereço bloqueados. Verifique se esse endereço é legítimo antes de ampliar a regra, sobretudo se você anuncia uma página sem envio externo.

#Para se aprofundar

Se você procura um assistente para uso próprio em vez de um recurso integrado a uma página, uma instalação local clássica será mais simples de controlar: o comparativo das soluções gratuitas é o ponto de partida certo. Para um uso sensível, complemente as verificações deste guia com o checklist de privacidade.

Este guia ajudou você?

Um comentário, um erro ou uma observação? Avise-nos; isso ajuda a melhorar o guia para todos.