Data di pubblicazione: 13 gennaio 2024
Questo è il secondo di una serie in tre parti su LLM e chatbot. L'articolo precedente ha discusso i vantaggi e gli svantaggi degli LLM on-device e in-browser.
Ora che conosci meglio l'AI lato client, puoi aggiungere WebLLM a un'applicazione web di liste di cose da fare. Puoi trovare il codice nel web-llm
branch del repository GitHub.
WebLLM è un runtime basato sul web per i modelli linguistici di grandi dimensioni fornito da Machine Learning Compilation. Puoi provare WebLLM come applicazione autonoma. L'applicazione è ispirata ad applicazioni di chat basate su cloud, come Gemini, ma l'inferenza LLM viene eseguita sul dispositivo anziché sul cloud. I prompt e i dati non vengono mai trasferiti dal dispositivo e puoi stare certo che non vengono utilizzati per addestrare i modelli.
Per eseguire l'inferenza del modello sul dispositivo, WebLLM combina WebAssembly e WebGPU. Sebbene WebAssembly consenta calcoli efficienti sulla unità di elaborazione centrale (CPU), WebGPU offre agli sviluppatori accesso a basso livello all'unità di elaborazione grafica (GPU) del dispositivo.
Installare WebLLM
WebLLM è disponibile come pacchetto npm.
Puoi aggiungere questo pacchetto all'applicazione della lista di cose da fare eseguendo
npm install @mlc-ai/web-llm
.
Seleziona un modello
Successivamente, devi decidere su un modello LLM da eseguire localmente. Sono disponibili diversi modelli.
Per decidere, devi conoscere i seguenti termini e dati chiave:
- Token:l'unità di testo più piccola che un LLM può elaborare.
- Finestra contestuale:il numero massimo di token che il modello può elaborare.
- Parametri o ponderazioni:le variabili interne apprese durante l'addestramento, contate in miliardi.
- Quantizzazione:il numero di bit che rappresentano i pesi. Più bit significano maggiore precisione, ma anche maggiore utilizzo della memoria.
- Formati di numeri in virgola mobile: i numeri in virgola mobile a 32 bit (a precisione completa, F32) offrono una maggiore precisione, mentre i numeri in virgola mobile a 16 bit (a metà precisione, F16) hanno velocità più elevate e un utilizzo della memoria inferiore, ma richiedono hardware compatibile.
Questi termini chiave tendono a far parte del nome del modello. Ad esempio,
Llama-3.2-3B-Instruct-q4f32_1-MLC
contiene le seguenti informazioni:
- Il modello è LLaMa 3.2.
- Il modello ha 3 miliardi di parametri.
- È ottimizzato per le istruzioni e gli assistenti con prompt (Instruct).
- Utilizza la quantizzazione uniforme (_1) a 4 bit (q4).
- Ha numeri a virgola mobile a 32 bit con precisione completa.
- Si tratta di una versione speciale creata da Machine Learning Compilation.
Potresti dover testare diversi modelli per determinare quale è adatto al tuo caso d'uso.
Al momento della stesura di questo articolo, un modello con 3 miliardi di parametri e 4 bit per parametro può già avere un colonna di dimensioni fino a 1,4 GB, che l'applicazione deve scaricare sul dispositivo dell'utente prima del primo utilizzo. È possibile lavorare con modelli da 3 miliardi di parametri, ma quando si tratta di funzionalità di traduzione o conoscenza di curiosità, i modelli da 7 miliardi di parametri offrono risultati migliori. Con 3,3 GB o più, però, sono molto più grandi.
Per creare il motore WebLLM e avviare il download del modello per il chatbot della lista di cose da fare, aggiungi il seguente codice all'applicazione:
import {CreateMLCEngine} from '@mlc-ai/web-llm';
const engine = await CreateMLCEngine('Llama-3.2-3B-Instruct-q4f32_1-MLC', {
initProgressCallback: ({progress}) => console.log(progress);
});
Il metodo CreateMLCEngine
prende la stringa del modello e un oggetto di configurazione facoltativo. Utilizzando il metodo initProgressCallback
, puoi eseguire query sul progresso del download del modello per presentarlo agli utenti in attesa.
API Cache: fai in modo che il tuo LLM venga eseguito offline
Il modello viene scaricato nello spazio di archiviazione della cache del tuo sito web. L'API Cache è stata introdotta insieme ai service worker per consentire il funzionamento offline del tuo sito web o della tua applicazione web. È il miglior meccanismo di archiviazione per memorizzare nella cache i modelli di IA. A differenza della memorizzazione nella cache HTTP, l'API Cache è una cache programmabile completamente sotto il controllo dello sviluppatore.
Una volta scaricati, WebLLM legge i file del modello dall'API Cache anziché richiederli tramite la rete, il che lo rende completamente offline.
Come per tutto lo spazio di archiviazione del sito web, la cache è isolata per origine. Ciò significa che due origini, example.com e example.net, non possono condividere lo stesso spazio di archiviazione. Se questi due siti web volessero utilizzare lo stesso modello, dovrebbero scaricarlo separatamente.
Puoi ispezionare la cache utilizzando DevTools andando a Applicazione > Spazio di archiviazione e aprendo Spazio di archiviazione della cache.
Configurare la conversazione
Il modello può essere inizializzato con un insieme di prompt iniziali. In genere, esistono tre ruoli dei messaggi:
- Prompt di sistema: questo prompt definisce il comportamento, il ruolo e il carattere del modello. Può essere utilizzato anche per l'aggiornamento, ovvero per fornire al modello dati personalizzati che non fanno parte del set di addestramento (ad esempio i dati specifici del dominio). Puoi specificare un solo prompt di sistema.
- Prompt dell'utente: i prompt inseriti dall'utente.
- Prompt dell'assistente: risposte dell'assistente, facoltative.
I prompt dell'utente e dell'assistente possono essere utilizzati per i prompt N-shot fornendo all'LLM esempi di linguaggio naturale su come deve comportarsi o rispondere.
Ecco un esempio minimo per configurare la conversazione per l'app elenco di cose da fare:
const messages = [
{ role: "system",
content: `You are a helpful assistant. You will answer questions related to
the user's to-do list. Decline all other requests not related to the user's
todos. This is the to-do list in JSON: ${JSON.stringify(todos)}`
},
{role: "user", content: "How many open todos do I have?"}
];
Rispondi alla prima domanda
La funzionalità di completamento della chat è esposta come proprietà nell'engine WebLLM creato in precedenza (engine.chat.completions
). Dopo aver scaricato il modello, puoi eseguire l'inferenza del modello chiamando il metodo create()
in questa proprietà. Per il tuo caso d'uso, vuoi trasmettere le risposte in streaming in modo che l'utente possa iniziare a leggerle mentre vengono generate, riducendo il tempo di attesa percepito:
const chunks = await engine.chat.completions.create({ messages, stream: true, });
Questo metodo restituisce un AsyncGenerator
, una sottoclasse della classe nascosta
AsyncIterator
. Utilizza un ciclo for await...of
per attendere i chunk man mano che arrivano. Tuttavia, la risposta contiene solo i nuovi token (delta
), quindi devi assemblare la risposta completa autonomamente.
let reply = '';
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta.content ?? '';
console.log(reply);
}
A quanto pare, il web ha sempre dovuto gestire le risposte in streaming. Puoi utilizzare API come DOMImplementation per lavorare con queste risposte in streaming e aggiornare in modo efficiente il codice HTML.
I risultati sono puramente basati su stringhe. Devi prima analizzarli se vuoi interpretarli come JSON o come altri formati di file.
Tuttavia, WebLLM presenta alcune limitazioni: l'applicazione deve scaricare un modello enorme prima del primo utilizzo, che non può essere condiviso tra le origini, pertanto un'altra app web potrebbe dover scaricare di nuovo lo stesso modello. Sebbene WebGPU raggiunga un rendimento di inferenza quasi nativo, non raggiunge la velocità nativa completa.
Demo
Questi svantaggi vengono risolti dall'API Prompt, un'API esplorativa proposta da Google che viene eseguita anche lato client, ma utilizza un modello centrale scaricato in Chrome. Ciò significa che più applicazioni possono utilizzare lo stesso modello alla massima velocità di esecuzione.
Scopri di più sull'aggiunta di funzionalità di chatbot tramite l'API Prompt nel prossimo articolo.