Data publikacji: 13 stycznia 2024 r.
To jest druga część z 3 częściowej serii dotyczącej LLM i czatbotów. W poprzednim artykule omawialiśmy zalety i wady LLM na urządzeniu i w przeglądarce.
Teraz, gdy lepiej rozumiesz AI po stronie klienta, możesz dodać WebLLM do aplikacji internetowej listy zadań. Kod znajdziesz na gałęzi web-llm
w repozytorium GitHub.
WebLLM to środowisko wykonawcze w internecie dla LLM udostępniane przez kompilację systemów uczących się. Możesz wypróbować WebLLM jako samodzielną aplikację. Aplikacja została zainspirowana aplikacjami do czatu opartymi na chmurze, takimi jak Gemini, ale wnioskowanie LLM jest wykonywane na urządzeniu, a nie w chmurze. Prompty i dane nigdy nie opuszczają Twojego urządzenia. Możesz mieć pewność, że nie są one używane do trenowania modeli.
Aby przeprowadzić wnioskowanie modelu na urządzeniu, WebLLM łączy WebAssembly i WebGPU. WebAssembly umożliwia wydajne wykonywanie obliczeń na procesorze centralnym (CPU), a WebGPU zapewnia deweloperom dostęp do niskiego poziomu procesora graficznego (GPU) urządzenia.
Instalowanie WebLLM
WebLLM jest dostępny jako pakiet npm.
Możesz dodać ten pakiet do aplikacji listy zadań, uruchamiając npm install @mlc-ai/web-llm
.
Wybierz model
Następnie musisz wybrać LLM do wykonania lokalnie. Dostępne są różne modele.
Aby podjąć decyzję, musisz znać te kluczowe terminy i liczby:
- Token: najmniejsza jednostka tekstu, którą może przetworzyć model LLM.
- Okno kontekstu: maksymalna liczba tokenów, które model może przetworzyć.
- Parametry lub wagi: wewnętrzne zmienne wyuczone podczas trenowania, liczone w miliardach.
- Kwantyzacja: liczba bitów reprezentujących wagi. Więcej bitów oznacza większą precyzję, ale też większe wykorzystanie pamięci.
- Formaty liczb zmiennoprzecinkowych: 32-bitowe liczby zmiennoprzecinkowe (pełna precyzja, F32) zapewniają większą dokładność, a 16-bitowe liczby zmiennoprzecinkowe (półpełna precyzja, F16) mają większą szybkość i mniejszą konsumpcję pamięci, ale wymagają kompatybilnego sprzętu.
Te kluczowe terminy są zwykle częścią nazwy modelu. Na przykład:
Llama-3.2-3B-Instruct-q4f32_1-MLC
zawiera te informacje:
- Model to LLaMa 3.2.
- Model ma 3 mld parametrów.
- Jest ono dostosowane do asystentów, którzy udzielają instrukcji i zachęcają do działania (Instrukcja).
- Używa 4-bitowej (q4) jednolitej (_1) kwantyzacji.
- Zawiera 32-bitowe liczby zmiennoprzecinkowe o pełnej precyzji.
- Jest to specjalna wersja utworzona przez systemy uczące się.
Aby określić, który model jest odpowiedni do Twojego przypadku użycia, konieczne może być przetestowanie różnych modeli.
Model z 3 miliardami parametrów i 4 bitami na parametr może mieć rozmiar do 1, 4 GB w momencie pisania tego tekstu.Aplikacja musi pobrać ten plik na urządzenie użytkownika przed pierwszym użyciem. Można korzystać z modeli 3B, ale jeśli chodzi o umiejętności związane z tłumaczeniem lub wiedzą na tematy ogólne, modele 7B dają lepsze wyniki. Jednak pliki o rozmiarze 3,3 GB i większym są znacznie większe.
Aby utworzyć mechanizm WebLLM i rozpocząć pobieranie modelu do chatbota do zadań, dodaj do aplikacji ten kod:
import {CreateMLCEngine} from '@mlc-ai/web-llm';
const engine = await CreateMLCEngine('Llama-3.2-3B-Instruct-q4f32_1-MLC', {
initProgressCallback: ({progress}) => console.log(progress);
});
Metoda CreateMLCEngine
przyjmuje ciąg znaków modelu i opcjonalny obiekt konfiguracji. Korzystając z metody initProgressCallback
, możesz wysłać zapytanie dotyczące postępu pobierania modelu, aby wyświetlić je użytkownikom podczas oczekiwania.
Cache API: uruchamianie LLM offline
Model jest pobierany do pamięci podręcznej witryny. Interfejs Cache API został wprowadzony wraz ze skryptami service worker, aby umożliwić działanie witryny lub aplikacji internetowej w trybie offline. Jest to najlepszy mechanizm przechowywania danych do buforowania modeli AI. W przeciwieństwie do buforowania HTTP interfejs Cache API to programowalna pamięć podręczna, którą deweloper ma w pełni pod kontrolą.
Po pobraniu WebLLM odczytuje pliki modelu z Cache API zamiast wysyłać żądania przez sieć, dzięki czemu będzie w pełni obsługiwać tryb offline.
Podobnie jak w przypadku wszystkich innych danych witryny, pamięć podręczna jest odizolowana na podstawie źródła. Oznacza to, że 2 źródła, example.com i example.net, nie mogą korzystać z tego samego miejsca na dane. Jeśli te 2 witryny chciałyby używać tego samego modelu, musiałyby go osobno pobrać.
Możesz sprawdzać pamięć podręczną za pomocą DevTools, otwierając Aplikacja > Pamięć i otwierając pamięć podręczną.
Konfigurowanie rozmowy
Model można zainicjować za pomocą zestawu początkowych promptów. Zwykle występują 3 role wiadomości:
- Prompt systemowy: ten prompt określa zachowanie, rolę i postać modelu. Można go też używać do uziemienia, czyli podawania do modelu danych niestandardowych, które nie są częścią jego zbioru danych treningowych (np. danych dotyczących Twojej domeny). Możesz podać tylko 1 prompt systemowy.
- Prośba do użytkownika: prośby wprowadzane przez użytkownika.
- Prośba do Asystenta: opcjonalne odpowiedzi Asystenta.
Prompty użytkownika i asystenta można wykorzystać do promptów N-shot, podając modelowi LLM przykłady naturalnego języka, które pokazują, jak powinien się zachowywać lub odpowiadać.
Oto minimalny przykład konfiguracji konwersacji w aplikacji do zarządzania zadaniami:
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?"}
];
Odpowiedz na pierwsze pytanie
Funkcja dopełniania czatu jest udostępniana jako właściwość w uprzednio utworzonym silniku WebLLM (engine.chat.completions
). Po pobraniu modelu możesz uruchomić wnioskowanie modelu, wywołując metodę create()
w tej usłudze. W przypadku Twojego przypadku użycia chcesz przesyłać strumieniowo odpowiedzi, aby użytkownik mógł zacząć czytać, gdy tylko zostaną wygenerowane. Dzięki temu czas oczekiwania będzie wydawał się krótszy:
const chunks = await engine.chat.completions.create({ messages, stream: true, });
Ta metoda zwraca obiekt AsyncGenerator
, który jest podklasą ukrytej klasy AsyncIterator
. Użyj pętli for await...of
, aby czekać na kawałki w miarę ich pojawiania się. Odpowiedź zawiera jednak tylko nowe tokeny (delta
), więc musisz samodzielnie utworzyć pełną odpowiedź.
let reply = '';
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta.content ?? '';
console.log(reply);
}
Okazuje się, że internet zawsze musiał radzić sobie z odpowiedziami strumieniowymi. Możesz używać interfejsów API, takich jak DOMImplementation, do obsługi tych odpowiedzi strumieniowych i skutecznego aktualizowania kodu HTML.
Wyniki są uzyskiwane wyłącznie na podstawie ciągów znaków. Jeśli chcesz interpretować je jako pliki JSON lub inne formaty plików, musisz je najpierw przeanalizować.
WebLLM ma jednak pewne ograniczenia: przed pierwszym użyciem aplikacja musi pobrać ogromny model, którego nie można udostępniać w różnych źródłach, więc inna aplikacja internetowa może ponownie pobrać ten sam model. Chociaż WebGPU osiąga wydajność wnioskowania zbliżoną do natywnej, nie osiąga pełnej natywnej szybkości.
Prezentacja
Te wady eliminuje Prompt API, czyli proponowany przez Google interfejs API do eksploracji, który działa również po stronie klienta, ale korzysta z centralnego modelu pobranego do Chrome. Oznacza to, że wiele aplikacji może korzystać z tego samego modelu z pełną prędkością.
Więcej informacji o dodawaniu funkcji chatbota za pomocą interfejsu Prompt API znajdziesz w następnym artykule.