Intermedio 12 minPiano giornaliero

WebLLM: un modello di IA nel navigateur

WebLLM: un modello di IA nel navigateur

WebLLM è una libreria JavaScript che esegue un LLM nella scheda del browser, sulla GPU della macchina, grazie a WebGPU. Niente da installare a livello di sistema, ma tre condizioni da verificare: la compatibilità del browser, il download del modello e il comportamento reale della pagina. Un calcolo eseguito sulla tua GPU non dimostra né che la pagina funzioni offline né che i tuoi messaggi restino sul tuo dispositivo. Questa guida spiega come verificarlo; non contiene alcun benchmark.

Di Mohamed Meguedmi·Agg. 2026-11-09·Testato su Windows, macOS e Linux
!
Limite di questa guida
Non è stato possibile rileggere il repository di WebLLM e la sua documentazione il giorno della stesura, il 9 novembre 2026, e nessun codice di questa guida è stato eseguito da QuelLLM. Gli estratti WebLLM descrivono l'API così come la conosciamo, senza una versione garantita: se il README del repository differisce, fa fede quest'ultimo. Le informazioni su WebGPU, sull'archiviazione e sulla policy di sicurezza provengono da MDN, riletto il 9 novembre 2026.

#WebLLM: cosa fa la libreria

Con Ollama, un programma installato sulla macchina carica il modello e risponde su http://localhost:11434. Con WebLLM, tutto passa da una pagina web: questa carica il codice JavaScript e WebAssembly del motore, recupera i pesi del modello, poi invia i calcoli alla GPU tramite WebGPU. Non c'è alcun servizio da avviare né porta da aprire.

Lato sviluppatore, l'API ricalca quella di OpenAI: si crea un motore, poi si chiama engine.chat.completions.create con un elenco di messaggi. Un'applicazione scritta per questo formato si adatta quindi abbastanza in fretta. Il motore però vive nella pagina: non è un server HTTP a cui Open WebUI, un editor di codice o uno script Python potrebbero collegarsi.

WebGPU
API del browser che dà accesso alla GPU per il calcolo. Senza di essa, o senza un adattatore disponibile, il motore non può funzionare sulla GPU.
WebAssembly
Formato in cui viene distribuita una parte del motore. Fa parte di ciò che la pagina deve caricare, al pari del JavaScript.
I pesi del modello
File voluminosi, separati dal codice della pagina. Vengono scaricati dall'indirizzo indicato nella configurazione, poi memorizzati nella cache dal browser.
Il formato MLC
WebLLM usa modelli compilati per il suo motore, riconoscibili dal suffisso MLC nei loro identificatori. Un file GGUF scaricato per Ollama o LM Studio non si carica così com'è.

#WebLLM o Ollama: quale strumento per quale esigenza?

Il kit completo per creare il tuo assistente IA.

Approfitta della nostra esperienza e di un percorso guidato per creare il tuo assistente locale e usare la tua IA ogni giorno.

  • Spazio online a vita
  • PDF + file
  • Garanzia di rimborso di 30 giorni

WebLLM non sostituisce un'installazione locale classica. Il suo valore è altrove: offrire una funzione di IA in una pagina a persone che non installeranno nulla.

WebLLM è adatto per
Una demo pubblica, uno strumento web interno, un assistente integrato in un'applicazione, una prova rapida su una postazione in cui non si può installare nulla.
Ollama o LM Studio vanno bene per
Un uso quotidiano, la scelta all'interno di un ampio catalogo, modelli più grandi, un'API riutilizzabile da altri strumenti, un funzionamento che non dipende dai limiti di una scheda.
I costi da accettare
Il catalogo dipende dai modelli compilati in formato MLC, la memoria disponibile dipende anche dai limiti del browser e la cache può essere cancellata senza avvisarti.

Non forniamo un confronto di velocità: nessuna misurazione con protocollo e hardware documentati supporta questa guida. Se per il tuo progetto è importante, misura sulle tue macchine di destinazione, con lo stesso modello e la stessa quantizzazione, annotando la versione del browser e del driver.

#Prerequisiti e compatibilità WebGPU

MDN classificava ancora WebGPU come a disponibilità limitata, quindi non Baseline, nella sua pagina modificata il 2 settembre 2026: l'API non funziona in alcuni browser molto diffusi. Il supporto dipende dalla combinazione di browser, sistema e driver grafico. Un browser può quindi esporre WebGPU su un sistema e non su un altro. Invece di un elenco di versioni che invecchia presto, consulta la tabella di compatibilità di MDN, poi testa ogni macchina di destinazione.

Contesto sicuro
Secondo MDN, l'intera API è disponibile solo in un contesto sicuro: servi la pagina in HTTPS, oppure su localhost durante lo sviluppo. Una pagina aperta in HTTP su un indirizzo di rete locale non va bene.
Browser e driver
Entrambi aggiornati. Una GPU recente non basta se il driver o il browser bloccano l'accesso.
Memoria GPU
Riferimenti QuelLLM in Q4 sullo stack abituale: 3B circa 2 GB, 7B circa 5 GB. Sono ordini di grandezza, non misurazioni di WebLLM.
Spazio su disco e connessione
Quanto basta per archiviare il modello e scaricarlo almeno una volta. Controlla la dimensione reale nel monitoraggio del caricamento.

Questo test va incollato nella console degli strumenti per sviluppatori, su una pagina in HTTPS o su localhost. Si basa sull'API standard e non carica alcun modello. Secondo MDN, requestAdapter restituisce null quando non è disponibile alcun adattatore adatto: la presenza di navigator.gpu non basta quindi per trarre conclusioni.

Console del browser: testare 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);
  }
}

La riga shader-f16 aiuta a scegliere la variante. Gli identificativi WebLLM distinguono in genere i modelli q4f16, che richiedono questa funzione, e q4f32, che ne fanno a meno. I due limiti dei buffer indicano quanto il browser accetta di allocare; possono bloccare un modello grande anche se la scheda video ha abbastanza memoria.

#Cosa comporta il download

Al primo caricamento, la pagina recupera i file del modello e il relativo codice compilato dagli indirizzi della sua configurazione. Nell'elenco predefinito di WebLLM, questi indirizzi puntano, per quanto ne sappiamo, a repository esterni come Hugging Face e GitHub: verificalo nella scheda Rete. Questi servizi di hosting vedono quindi il tuo indirizzo IP e il modello richiesto, anche se non è ancora partito alcun messaggio.

I file vengono poi conservati nello storage del browser, legato all'origine della pagina. MDN precisa le regole da conoscere: per impostazione predefinita questo storage è in modalità best-effort, e il browser può eliminarlo in caso di poco spazio su disco senza interrompere l'utente, a partire dalle origini usate meno di recente. Un'origine eliminata perde tutti i suoi dati in un colpo solo. Safari può anche cancellare i dati creati da script di un'origine senza interazione da sette giorni di utilizzo del browser, quando la prevenzione del tracciamento cross-site è attiva.

Console della pagina: quota e archiviazione 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);
→
Richiedere la persistenza non garantisce nulla
Firefox mostra una richiesta all'utente; Chrome, Edge e Safari decidono da soli, in base alla cronologia di interazione con il sito (MDN, pagina modificata il 5 gennaio 2026). Se persist restituisce false, metti in conto che il modello possa essere scaricato di nuovo.

#Installare WebLLM in una pagina: i passaggi

Questo percorso presuppone un progetto JavaScript con uno strumento di build, per esempio Vite. Installare il pacchetto nel progetto, anziché importarlo da una CDN, evita di aggiungere un dominio di terze parti al caricamento della pagina e facilita il funzionamento offline.

Terminale, nel tuo progetto
npm install @mlc-ai/web-llm
  1. 01
    Bloccare la versione
    Annota la versione installata in package-lock.json e leggi il README corrispondente. Verifica in quel momento la licenza del pacchetto e quella del modello, che sono due cose distinte.
  2. 02
    Elencare i modelli disponibili
    Non copiare un identificatore da un articolo: l'elenco cambia. Leggilo nella versione installata, con il primo estratto qui sotto. Il campo di memoria che indica è un punto di partenza, non una garanzia.
  3. 03
    Iniziare in piccolo
    Scegli prima il modello più piccolo che sia utile, in q4f32 se il test precedente indica che manca shader-f16. Un primo tentativo riuscito separa i problemi di codice da quelli di memoria.
  4. 04
    Mostrare l'avanzamento
    Il download può essere lungo. Senza un riscontro visivo, la pagina sembra bloccata: initProgressCallback fornisce il testo di avanzamento da mostrare.
  5. 05
    Passare a un Web Worker
    Il caricamento e la generazione possono rallentare l'interfaccia se vengono eseguiti nel thread principale. Per questo WebLLM offre CreateWebWorkerMLCEngine, con il gestore WebWorkerMLCEngineHandler lato worker. Prevedilo prima della messa online.
  6. 06
    Testare sulle macchine di destinazione
    Un risultato su una workstation di sviluppo non dice nulla di un portatile con GPU integrata. Prevedi un messaggio chiaro se WebGPU manca, invece di una pagina vuota.
Elencare i modelli della versione installata
import { prebuiltAppConfig } from '@mlc-ai/web-llm';

console.table(prebuiltAppConfig.model_list.map((m) => ({
  id: m.model_id,
  vramMo: m.vram_required_MB,
})));
Caricare un modello e leggere la risposta in 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);

#Verificare una pagina WebLLM: rete, script, offline

WebLLM garantisce al massimo dove viene eseguito il calcolo. Il resto dipende dalla pagina che lo integra: uno script di analisi del traffico, un widget o una funzione di invio può leggere il contenuto del campo di input e trasmetterlo, perché ogni script caricato nella pagina vi ha accesso. Questo controllo vale per qualsiasi sito che dichiari un'IA nel browser, compreso il tuo.

  1. 01
    Preparare un profilo pulito
    Apri un profilo del browser senza estensioni: un'estensione autorizzata sulla pagina può leggere ciò che vi viene mostrato e falsa il risultato. Apri la scheda Rete e attiva la conservazione del log.
  2. 02
    Annotare il caricamento
    Carica la pagina, poi annota ogni dominio contattato e il suo ruolo: pagina, motore, modello, font, analisi del traffico, pubblicità. Ogni dominio senza un ruolo chiaro resta da spiegare.
  3. 03
    Rilevare l'invio di un messaggio
    Una volta caricato il modello, svuota il log. Invia un messaggio contenente un marcatore inventato, per esempio TEST-MARQUEUR-7Q2X, poi cercalo nel log con la ricerca della scheda Rete. Esamina anche ogni richiesta partita durante la generazione, compresi i messaggi WebSocket.
  4. 04
    Ispezionare gli script e l'intestazione di sicurezza
    Nella scheda Sources, elenca i domini di origine degli script. Nelle intestazioni di risposta del documento, cerca Content-Security-Policy: una direttiva connect-src restrittiva riduce le destinazioni possibili, la sua assenza non prova nulla.
  5. 05
    Verificare cosa resta sul disco
    Nella scheda Applicazione o Archiviazione, apri IndexedDB, Cache e l'archiviazione locale. Normalmente il modello si trova lì, ma possono esserci anche le tue conversazioni, in chiaro per chiunque usi questa sessione.
  6. 06
    Staccare davvero la rete
    Chiudi la pagina, disattiva il Wi-Fi o scollega il cavo, poi riapri l'indirizzo e invia un nuovo messaggio. La pagina deve caricarsi e rispondere. Ripeti la prova dopo aver chiuso il browser.
!
Un modello in cache non rende la pagina offline
Se anche l'HTML, il JavaScript o il WebAssembly della pagina non vengono conservati, tipicamente da un service worker, l'indirizzo non si aprirà più senza rete, anche con tutto il modello sul disco. Un motore già aperto che continua a rispondere dopo l'interruzione della connessione non dimostra quindi il funzionamento offline: conta solo il test di riapertura.

Questi controlli hanno i loro limiti. Un marcatore non trovato non esclude un invio cifrato o codificato da uno script. Le connessioni WebRTC non compaiono come normali richieste nella scheda Rete: su Chrome, chrome://webrtc-internals permette di individuarle. Infine, il risultato vale solo per la versione testata, perché il gestore del sito può cambiare i suoi script in qualsiasi momento.

Puoi dire «funziona offline»
Se la riapertura e un nuovo messaggio riescono con la rete disattivata, sul browser testato, alla data del test. Specifica che la cache può essere eliminata.
Puoi dire «nessun invio osservato»
Se il log non mostra alcuna richiesta legata al messaggio, sulla versione testata e secondo il protocollo descritto. È un'osservazione datata.
Non puoi dire «totalmente privato»
A meno di controllare tutto il codice servito e i suoi aggiornamenti, senza alcuno script di terze parti, e di completare questa verifica con una lettura del codice. Anche in questo caso, chi ospita il modello vede il download e le estensioni restano un rischio.

#Servire tutto dal proprio dominio

Per uno strumento interno, la configurazione più facile da controllare consiste nel servire pagina, motore e modello dalla stessa origine, senza alcuno script di terze parti. WebLLM accetta una configurazione personalizzata in cui ogni modello indica l'indirizzo dei propri pesi e quello della propria libreria compilata. I percorsi qui sotto sono esempi da adattare.

Configurazione personalizzata (indirizzi di esempio)
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 });

Il motore costruisce da solo gli indirizzi dei file a partire da questo prefisso. Potrebbe aspettarsi una struttura di directory simile a quella di Hugging Face: se alcune richieste falliscono con un 404, controlla nella scheda Rete i percorsi esatti richiesti e riproducili sul tuo server. La libreria compilata deve corrispondere al modello: non abbinarla a caso a un altro.

Una volta riportato tutto in locale, una policy di sicurezza può trasformare una promessa in un vincolo tecnico: secondo MDN, connect-src limita in particolare fetch, XMLHttpRequest, WebSocket, EventSource e sendBeacon, e ripiega su default-src se è assente. L'esempio seguente non è stato testato con WebLLM. Distribuiscilo prima in modalità Content-Security-Policy-Report-Only e leggi la console.

Header HTTP, da adattare alla tua pagina
Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'

Questa intestazione blocca anche i download da Hugging Face: è voluto, e il modello deve quindi essere servito dal tuo dominio. Non copre tutte le possibili uscite, come una navigazione verso un altro indirizzo. Per l'uso offline, aggiungi un service worker che metta in cache i file della pagina. WebLLM fornisce anche un motore per questo contesto, CreateServiceWorkerMLCEngine: consulta il suo README.

#Risoluzione dei problemi

navigator.gpu vale undefined
Verifica prima l'indirizzo: HTTPS o localhost. Poi consulta la tabella di compatibilità di MDN per il tuo browser e il tuo sistema, quindi aggiorna entrambi.
requestAdapter restituisce null
L'API esiste, ma non è disponibile alcun adattatore adatto. Aggiorna il driver e verifica che l'accelerazione hardware del browser sia attiva. Prova un altro browser per isolare la causa.
Errore legato a shader-f16
Il modello scelto richiede una funzionalità assente nel tuo adattatore. Usa la sua variante q4f32, se esiste.
QuotaExceededError
La quota dell'origine è stata superata: MDN segnala questo errore per IndexedDB, Cache e OPFS. Libera spazio o scegli un modello più piccolo, e intercetta l'errore nel codice.
Crash a fine caricamento o perdita della GPU
Memoria probabilmente insufficiente o limite del buffer raggiunto. Chiudi le schede pesanti, scendi di una taglia di modello e consulta il messaggio esatto nella console.
Il modello viene scaricato di nuovo
Navigazione privata, eviction dello storage, dati del sito cancellati o cambio di origine, perché ogni dominio ha il proprio spazio di archiviazione. Il pacchetto espone, per quanto ne sappiamo, hasModelInCache per verificarlo prima di avviare il caricamento.
L'interfaccia si blocca durante la generazione
Il motore gira nel thread principale. Passa a CreateWebWorkerMLCEngine.
Errore di policy di sicurezza nella console
Il messaggio indica la direttiva e l'indirizzo bloccati. Verifica se questo indirizzo è legittimo prima di allargare la regola, soprattutto se dichiari che la pagina non effettua invii esterni.

#Per approfondire

Se cerchi un assistente per te anziché una funzione integrata in una pagina, un'installazione locale classica sarà più semplice da controllare: il confronto delle soluzioni gratuite è il punto di partenza giusto. Per un uso sensibile, completa i controlli di questa guida con la checklist sulla riservatezza.

Questa guida ti è stata utile?

Un feedback, un errore, una precisazione? Facci sapere, così la guida migliora per tutti.