
Come integrare un LLM locale nel browser web con WebLLM
L' generativa, in particolare i Large Language Model (LLM), sta rapidamente uscendo dai confini dei potenti data center per avvicinarsi agli utenti finali. Mentre servizi cloud come dominano il panorama, emerge con forza un'esigenza parallela: l'elaborazione locale. Privacy, costi ridotti, latenza zero e indipendenza dalla connettività di rete sono driver potenti. In questo contesto, WebLLM si presenta come una tecnologia rivoluzionaria che permette di eseguire modelli di linguaggio di grandi dimensioni direttamente all'interno del browser web, sfruttando le API moderne come WebGPU. Questo articolo è una guida completa e pratica all'integrazione di un LLM locale nelle tue applicazioni web utilizzando WebLLM.
Prima di immergerci nel codice, è cruciale comprendere il valore proposition di un LLM eseguito lato client. Spostare l'onere computazionale dal server al dispositivo dell'utente non è una scelta da poco e comporta vantaggi e considerazioni specifiche.
WebLLM non è un in sé, ma piuttosto un sistema di runtime di machine learning. È un progetto open-source sviluppato da MLC AI che fornisce un'API JavaScript/TypeScript per eseguire efficientemente modelli LLM nel browser.
WebLLM utilizza principalmente modelli nel formato GGUF ( Unified Format), un'evoluzione del formato GGML. Questo formato è progettato specificamente per l'esecuzione efficiente su hardware consumer. I modelli sono "quantizzati", ovvero ridotti in precisione (es. da 16 bit a 4 bit) per ridurre drasticamente le dimensioni e i requisiti di memoria, con una perdita minima di qualità.
Modello (esempio) | Parametri | Dimensione approssimativa (quantizzato 4-bit) | Hardware consigliato |
|---|---|---|---|
2 | 7 miliardi | ~4 GB | GPU desktop moderna / Laptop di fascia alta |
7B | 7.2 miliardi | ~4 GB | GPU desktop moderna / Laptop di fascia alta |
Phi-2 | 2.7 miliardi | ~1.6 GB | Laptop moderno / Tablet potenti |
TinyLlama | 1.1 miliardi | ~700 MB | Dispositivi mobili moderni / Computer più datati |
Per iniziare a sviluppare con WebLLM, hai bisogno di un ambiente Node.js configurato sul tuo computer. L'approccio più semplice è utilizzare un framework come Vite o un bundler come Webpack.
Crea una nuova directory per il tuo progetto e inizializzala:
npm create vite@latest my-webllm-app -- --template vanilla-tscd my-webllm-appnpm installSuccessivamente, installa il pacchetto WebLLM:
npm install @mlc-ai/web-llmLa struttura del progetto sarà simile a questa:
index.htmlsrc/main.tspackage.jsonPrima di procedere, è fondamentale verificare che il browser di sviluppo supporti WebGPU. Apri il file main.ts e aggiungi un controllo iniziale.
// src/main.tsif (!navigator.gpu) { alert("WebGPU non è supportato da questo browser. Prova con Chrome o Edge versione 113+."); throw new Error("WebGPU non supportato");} else { console.log("WebGPU è supportato!");}Ora passiamo alla parte pratica. Costruiremo una semplice interfaccia che permetta di caricare un modello e chattare con esso.
Modifica il file index.html per includere gli elementi dell'interfaccia utente necessari.
La Mia App WebLLMOra scriviamo il codice TypeScript in src/main.ts che gestirà il caricamento del modello e l'interazione.
// Importa il pacchetto WebLLMimport * as webllm from '@mlc-ai/web-llm'; // Elementi del DOMconst modelSelect = document.getElementById('model-select') as HTMLSelectElement;const loadButton = document.getElementById('load-btn') as HTMLButtonElement;const statusElement = document.getElementById('status') as HTMLDivElement;const chatOutput = document.getElementById('chat-output') as HTMLDivElement;const inputArea = document.getElementById('input-area') as HTMLDivElement;const userInput = document.getElementById('user-input') as HTMLInputElement;const sendButton = document.getElementById('send-btn') as HTMLButtonElement; // Variabile per memorizzare l'istanza del chatbotlet chatbot: webllm.ChatWorkerClient | null = null; // Funzione per aggiornare lo stato dell'interfacciafunction updateStatus(message: string) { statusElement.textContent = message; console.log(message);} // Funzione per aggiungere un messaggio alla chatfunction addMessage(sender: string, message: string) { const messageDiv = document.createElement('div'); messageDiv.classList.add('message', sender); messageDiv.textContent = `${sender}: ${message}`; chatOutput.appendChild(messageDiv); chatOutput.scrollTop = chatOutput.scrollHeight; // Scroll automatico in basso} // Gestione del caricamento del modelloloadButton.addEventListener('click', async () => { const selectedModel = modelSelect.value; if (!selectedModel) { alert('Seleziona un modello dalla lista.'); return; } updateStatus(`Inizializzazione e caricamento del modello "${selectedModel}". Questo potrebbe richiedere alcuni minuti...`); try { // Inizializza il chatbot. WebLLM scaricherà automaticamente il modello. // 'webllm' è l'ID predefinito del worker, puoi personalizzarlo. chatbot = new webllm.ChatWorkerClient(new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' })); // Opzioni di configurazione avanzate possono essere passate qui const initProgressCallback = (initProgress: webllm.InitProgressReport) => { updateStatus(`Caricamento modello: ${(initProgress.progress * 100).toFixed(1)}%`); }; // Carica il modello selezionato await chatbot.reload(selectedModel, initProgressCallback); updateStatus(`Modello "${selectedModel}" caricato con successo! Ora puoi chattare.`); inputArea.style.display = 'flex'; // Mostra l'area di input userInput.focus(); // Messaggio di benvenuto dall'assistente addMessage('assistant', 'Ciao! Sono un LLM eseguito localmente nel tuo browser. Con cosa posso aiutarti?'); } catch (error) { console.error('Errore durante il caricamento del modello:', error); updateStatus(`Errore: Impossibile caricare il modello. Controlla la console per i dettagli.`); }}); // Gestione dell'invio dei messaggisendButton.addEventListener('click', async () => { await handleSendMessage();}); userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { handleSendMessage(); }}); async function handleSendMessage() { if (!chatbot) { alert('Il modello non è ancora caricato.'); return; } const message = userInput.value.trim(); if (message === '') return; // Aggiungi il messaggio dell'utente alla chat e pulisci l'input addMessage('user', message); userInput.value = ''; // Disabilita l'input durante la generazione userInput.disabled = true; sendButton.disabled = true; updateStatus('Assistente sta pensando...'); try { // Invia il messaggio al modello e ricevi lo stream di risposta const response = await chatbot.generate(message); // Aggiungi la risposta dell'assistente alla chat addMessage('assistant', response); updateStatus('Pronto.'); } catch (error) { console.error('Errore durante la generazione:', error); addMessage('assistant', 'Mi dispiace, si è verificato un errore.'); updateStatus('Errore durante la generazione.'); } finally { // Riabilita l'input userInput.disabled = false; sendButton.disabled = false; userInput.focus(); }}WebLLM richiede l'uso di un Web Worker per eseguire il modello in un thread separato, evitando di bloccare l'interfaccia utente. Crea un file src/worker.ts.
// Importa la funzione per inizializzare il worker di WebLLMimport { ChatWorkerHandler } from '@mlc-ai/web-llm'; // Crea un handler per il workerconst handler = new ChatWorkerHandler(self);// Avvia l'handler, che si mette in ascolto dei messaggi dal thread principalehandler.start();Ora puoi avviare il server di sviluppo di Vite:
npm run devApri l'URL mostrato nel terminale (solitamente ) in un browser supportato (Chrome/Edge 113+). Seleziona un modello, clicca "Carica Modello" e, dopo il download, inizia a chattare!
L'esempio base funziona, ma per un'applicazione robusta è necessario considerare aspetti più avanzati.
WebLLM memorizza nella cache del browser i modelli scaricati. Per gestire meglio lo spazio o forzare un re-download, puoi interagire con l'API di cache.
// Per cancellare la cache di un modello specifico (dopo il caricamento del chatbot)await chatbot.engine.deleteModelAllCache(selectedModel); // Per ottenere lo stato della cacheconst cacheStatus = await chatbot.engine.cacheStats();Puoi controllare il comportamento del modello modificando i parametri di generazione, come la temperatura (creatività) o la lunghezza massima dei token.
// Crea un oggetto di configurazioneconst generationConfig: webllm.GenerationConfig = { temperature: 0.7, // Valori più alti = più creativo/imprevedibile (range: 0.0 - 1.0+) top_p: 0.95, // Nucleus sampling: considera solo i token con probabilità cumulativa superiore a top_p max_gen_len: 512, // Lunghezza massima della risposta in token}; // Applica la configurazione prima di generarechatbot.setGenerationConfig(generationConfig);Invece di aspettare l'intera risposta, puoi riceverla token per token, creando un'esperienza più dinamica.
async function handleSendMessageWithStreaming() { // ... (stesso setup precedente) try { addMessage('assistant', ''); // Crea un messaggio vuoto per l'assistente const assistantMessageElement = chatOutput.lastElementChild; let fullResponse = ''; // La funzione `generateStream` restituisce un AsyncIterable for await (const chunk of chatbot.generateStream(message)) { fullResponse += chunk; if (assistantMessageElement) { assistantMessageElement.textContent = `assistant: ${fullResponse}`; } chatOutput.scrollTop = chatOutput.scrollHeight; } updateStatus('Pronto.'); } catch (error) { // ... gestione errori } finally { // ... riabilita input }}Estendiamo l'esempio per creare un chatbot che mantenga la memoria della conversazione, un aspetto cruciale per interazioni coerenti.
WebLLM gestisce internamente la "chat history" (la lista dei messaggi) per modelli chat-aware come 2 Chat. Tuttavia, per un controllo più fine, puoi resettare la conversazione.
// Aggiungi un pulsante "Nuova Conversazione" nell'HTML// Nuova Conversazione const resetButton = document.getElementById('reset-btn') as HTMLButtonElement; resetButton.addEventListener('click', () => { if (chatbot) { // Resetta la storia della conversazione mantenuta dal modello chatbot.resetChat(); // Svuota l'interfaccia chat chatOutput.innerHTML = ''; addMessage('assistant', 'Conversazione resettata. Ciao di nuovo!'); }});Usa i pannelli Console per i log di errore e Application -> Storage -> IndexedDB per ispezionare i modelli nella cache. Il pannello Performance può aiutare a profilare l'uso della GPU/CPU.
L'integrazione di LLM locali nel browser tramite WebLLM rappresenta un salto quantico nello sviluppo web. Abbattendo le barriere dell'elaborazione cloud, apre le porte a una nuova generazione di applicazioni intelligenti, private e resilienti. Dalle assistenti personali integrate, agli strumenti di analisi di documenti riservati, fino a giochi con NPC dinamici, le possibilità sono vastissime.
Sebbene la tecnologia sia ancora giovane e il supporto browser non universale, il trend è chiaro: l'IA si sta democratizzando e spostando verso il "edge". WebLLM, insieme a progetti simili, fornisce gli strumenti per essere pionieri in questo spazio. Iniziare oggi a sperimentare con questi strumenti non significa solo costruire applicazioni innovative, ma anche acquisire una competenza che diventerà sempre più cruciale nello sviluppo software dei prossimi anni.
L'articolo ha fornito una base solida, dalla teoria all'implementazione pratica. Il passo successivo è esplorare, personalizzare e costruire qualcosa di unico, sfruttando il potere dell'IA direttamente nelle mani degli utenti, un browser alla volta.
Negli ultimi anni i Large Language Model (LLM) sono passati da curiosi ...
Leggi ->Il Festival della canzone italiana ritorna nella sua tradizionale sede dell’Ariston di ...
Leggi ->Claude è il modello di conversazionale sviluppato da Anthropic, sempre ...
Leggi ->L’estate 2025 è alle porte: dove andremo in vacanza?Con l’ar ...
Leggi ->Le batterie a flusso redox rappresentano una soluzione innovativa per l’accumulo ...
Leggi ->Profinet è un sistema di comunicazione aperto ...
Leggi ->Con l'avvento del 5G, la tecnologia delle telecomunicazioni ha subito una si ...
Leggi ->Nel panorama attuale dell'AI, la capacità di un agente di interagire con il mondo ester ...
Leggi ->Come evitare truffe su Vinted.it: c ...
Leggi ->Ciao e bentornati! In questo articolo, voglio parlare di uno dei temi più discuss ...
Leggi ->