wllama: llama.cpp als WebAssembly-Binding im Browser
WebAssembly binding for llama.cpp - Enabling on-browser LLM inference
Auf einen Blick
- Was ist das?
- wllama bringt llama.cpp als WebAssembly-Modul in den Browser, mit WebGPU, Multimodalität und Tool-Calling. Der Nutzen liegt im Betrieb ohne Backend, die Kosten in COOP/COEP-Headern, einer 2-GB-Grenze pro Datei und einem Modell, das der Nutzer erst herunterladen muss.
- Für wen ist es gedacht?
- wllama passt zu Projekten, die Inferenz ohne eigenen Server ausliefern wollen und deren Zielgruppe den Modell-Download akzeptiert: kleine bis mittlere quantisierte GGUF-Modelle, Chat- oder Embedding-Funktionen direkt in der Seite. Wer große Modelle, mehrere gleichzeitige Nutzer pro Maschine oder eine zentrale Modellverwaltung braucht, sollte beim Server-Backend bleiben.
- Darf ich es kommerziell nutzen?
- Ja. MIT ist eine freizügige Lizenz: Sie dürfen darauf aufbauende Software nutzen, verändern und verkaufen, solange Sie die Urheberrechts- und Lizenzhinweise beibehalten.
- Wird es noch gepflegt?
- Ja. Die letzten Commits kamen vor 2 Tagen.
- In welcher Sprache ist es geschrieben?
- Hauptsächlich TypeScript, laut der Sprachstatistik von GitHub.
Die Antworten beruhen auf den GitHub-Daten des Projekts (zuletzt abgeglichen am 15. September 2026) und auf unserer Analyse. Sie sind keine Rechtsberatung.
TIEFGEHENDE OPEN-SOURCE-ANALYSE
Kein Backend, aber ein Download beim Nutzer
Das Problem, das wllama adressiert, ist der Betrieb eines Sprachmodells ohne eigene Inferenz-Infrastruktur. Die Bibliothek ist ein WebAssembly-Binding für llama.cpp und führt die Berechnung laut README direkt im Browser aus, auf Basis von WebAssembly SIMD. Es gibt damit keinen Server, der pro Anfrage GPU-Zeit kostet, und keine API-Keys, die auf dem Client landen. Die Zielgruppe sind Frontend-Entwickler, die Completion-, Embedding- oder Bildverarbeitungsfunktionen in eine bestehende Webanwendung einbauen wollen, ohne eine zweite Laufzeitumgebung zu betreiben.
Der Preis dafür steht im selben Dokument: Das Modell liegt beim Nutzer. Wer eine Seite mit einem 4-GB-Modell ausliefert, verlagert den Download auf jede Person, die sie öffnet. Das ist bei einer internen Anwendung mit wenigen bekannten Nutzern verkraftbar, bei einer öffentlichen Seite mit wechselndem Publikum eine andere Rechnung. Die README empfiehlt deshalb, Modelle in Chunks von maximal 512 MB zu teilen, weil mehrere Splits parallel geladen werden können und bestimmte Out-of-Memory-Fälle vermieden werden. Der zweite Grund ist technisch erzwungen: Ein ArrayBuffer hat eine Größenbeschränkung, weshalb die README die maximale Dateigröße mit 2 GB angibt. Größere Modelle müssen gesplittet werden, sonst laden sie nicht.
WebGPU, Worker und der Fallback auf einen Thread
Die Ausführung läuft in einem Worker, damit das Rendering der Seite nicht blockiert. Beim Laden entscheidet die Bibliothek laut README automatisch, ob der Single-Thread- oder der Multi-Thread-Build verwendet wird, abhängig von der Browser-Unterstützung. Wer den Multi-Thread-Pfad will, muss auf dem Server die Header Cross-Origin-Embedder-Policy und Cross-Origin-Opener-Policy setzen. Fehlen sie, bleibt nur der Single-Thread-Build, und die Inferenz ist entsprechend langsamer. Das ist keine Konfigurationsoption der Bibliothek, sondern eine Vorgabe der Browser-Sicherheitsmodelle, und sie betrifft die gesamte Seite, nicht nur den Wasm-Teil.
Seit Version 3.1 ist WebGPU nach Angaben der README automatisch aktiv, sobald die Version aktualisiert wird. Standardmäßig werden alle Layer auf die GPU ausgelagert. Passt das Modell nicht in den VRAM, lässt sich die Anzahl über den Parameter n_gpu_layers in LoadModelParams begrenzen, wobei der Wert 0 die GPU-Inferenz vollständig abschaltet. Für Firefox und Safari existiert ein Kompatibilitätsmodus über wllama.setCompat mit dem Argument firefox_safari, den die README selbst mit dem Hinweis versieht, dass die Leistung dabei deutlich sinkt. Die Dokumentation nennt hier keine Zahlen, und ohne eigene Messung lässt sich nicht sagen, wie groß der Abstand zwischen GPU- und CPU-Pfad in der Praxis ausfällt.
Installation und der erste Modellaufruf
Der Einstieg erfolgt über npm i @wllama/wllama. Wer aus dem Repository bauen will, braucht Docker, weil die Wasm-Binaries laut README nicht vorab im Repository liegen. Der Ablauf ist dort dokumentiert: das Repository als Submodul hinzufügen, git submodule update --init --recursive ausführen, dann npm ci und anschließend npm run build:wasm && npm run build. Der Docker-Schritt ist der aufwendigste Teil, wenn man eine eigene Wasm-Variante braucht.
Im Code wird eine Instanz mit einem Pfad-Objekt erzeugt: new Wllama(CONFIG_PATHS), wobei CONFIG_PATHS den Schlüssel default auf die Datei ./esm/wasm/wllama.wasm zeigt. Für den Ladefortschritt übergibt man einen progressCallback, der die Felder loaded und total erhält und daraus einen Prozentwert berechnet. Geladen wird entweder über loadModelFromHF mit einem Objekt aus repo und file, im README-Beispiel ggml-org/models und tinyllamas/stories260K.gguf, oder über loadModelFromUrl für Modelle außerhalb des Hugging-Face-Hubs. Danach folgt createChatCompletion mit messages, max_tokens, temperature, top_k und top_p. Die Antwort wird wie bei der OpenAI-API über response.choices[0].message.content gelesen. Alternativ lassen sich die Wasm-Dateien über @wllama/wllama/esm/wasm-from-cdn.js von einem CDN beziehen, wovon die README ausdrücklich abrät und das nur für Fälle empfohlen wird, in denen die Wasm-Dateien nicht ins Projekt eingebettet werden können.
Quantisierung und die Grenze des Machbaren
Die README empfiehlt für das Verhältnis von Leistung, Dateigröße und Qualität die Quantisierungsstufen Q4, Q5 oder Q6. Von IQ-Quantisierungen mit imatrix wird abgeraten, weil sie zu langsamer Inferenz und niedriger Qualität führen können. Diese Empfehlung ist bemerkenswert, weil IQ-Formate in Server-Setups häufig gerade wegen der Qualität bei kleiner Dateigröße gewählt werden. Im Browser verschiebt sich die Abwägung: Der Rechenpfad ist schwächer, und ein Format, das mehr Rechenarbeit pro Token erfordert, schlägt stärker durch.
Die harte Grenze bleibt der Speicher. Ein Modell muss in den verfügbaren Arbeitsspeicher des Tabs passen, und bei WebGPU zusätzlich in den VRAM, wenn Layer ausgelagert werden. Die 2-GB-Grenze pro Datei ist nur die offensichtliche Einschränkung; die tatsächliche Obergrenze hängt vom Gerät ab und lässt sich nicht pauschal angeben. Für Anwendungen, die auf Mobilgeräten oder in eingebetteten Webviews laufen, ist das der kritischste Punkt. Wer ein Modell mit zweistelliger Milliardenzahl an Parametern in guter Qualität braucht, ist hier falsch: Das Splitten umgeht die Dateigrenze, nicht den Speicherbedarf.
V3 mit Multimodalität und Tool-Calling
Die Version 3 erweitert die Bibliothek um WebGPU, multimodale Eingaben und Tool-Calling. Multimodal bedeutet laut README die Verarbeitung von Bild- und Audiodateien als Eingabe, mit einem eigenen Beispiel unter examples/multimodal. Tool-Calling ist ebenfalls als Beispiel verlinkt, zusammen mit einem Beispiel für Embeddings und Kosinus-Distanz. Die API ist als OpenAI-kompatibel beschrieben und vollständig typisiert, was bedeutet, dass die Aufrufe den bekannten Feldern der Chat-Completions-API folgen und sich bestehender Code leichter übertragen lässt.
Für Anwendungen, die bereits gegen die OpenAI-API entwickeln, ist das der praktischste Teil: Der Wechsel zwischen Server und Browser betrifft dann vor allem die Modellverwaltung, nicht die Aufrufform. Die Kompatibilität hat aber Grenzen. Die README verweist für Kompatibilitätsprobleme auf das Paket @wllama/wllama-compat, was darauf hindeutet, dass nicht jede Umgebung den Hauptpfad unterstützt. Wer auf exotische Browser oder ältere Webviews zielt, sollte diesen Hinweis ernst nehmen und früh testen, statt erst nach der Integration.
Abgrenzung zu llama.cpp auf dem Server
Die naheliegende Alternative ist llama.cpp selbst, auf einem Server betrieben und über HTTP angesprochen. Der Unterschied liegt nicht im Modellformat, beide lesen GGUF, sondern im Ort der Rechnung. Beim Server-Backend liegen Modell und Rechenlast zentral, mehrere Nutzer teilen sich eine Maschine, und die Modellgröße ist nur durch die Hardware begrenzt. Bei wllama trägt jedes Gerät seine eigene Rechnung, was die Infrastrukturkosten senkt und die Daten das Gerät nicht verlassen lässt, aber die Modellgröße an das schwächste Gerät im Publikum bindet.
Ein zweiter Unterschied ist die Aktualisierung. Ein Servermodell wird an einer Stelle getauscht. Bei wllama liegt die ausgelieferte Version im Browser-Cache des Nutzers, und ein neues Modell bedeutet einen erneuten Download. Wer häufig Modellvarianten testet, merkt das schnell. Umgekehrt entfällt beim Browser-Pfad die Notwendigkeit, Anfragen zu authentifizieren und zu begrenzen, weil es keine zentrale Ressource gibt, die erschöpft werden könnte.
Wartung, Versionen und Lizenz
Das Projekt wird aktiv gepflegt: Die letzten Releases liegen bei 3.6.1 vom 27. August 2026, 3.6.0 vom 16. August 2026 und 3.5.1 vom 15. Juni 2026, der letzte Push datiert auf den 6. September 2026. Der Versionssprung von 3.5 auf 3.6 innerhalb weniger Wochen deutet auf eine Phase mit laufenden Änderungen hin. Das bedeutet für Integratoren, dass sie die Releases-Seite im Blick behalten sollten, weil die README ausdrücklich auf das Changelog dort verweist statt es zu duplizieren.
Lizenziert ist wllama unter MIT. Das ist eine permissive Lizenz, die kommerzielle Nutzung erlaubt, sofern der Copyright-Hinweis und der Lizenztext beibehalten werden. Zu beachten ist, dass wllama ein Binding für llama.cpp ist und die Lizenz des zugrunde liegenden Projekts separat gilt; die README nennt dazu keine Angaben, das sollte vor dem Ausliefern geprüft werden. Für die Modelle gilt ohnehin die Lizenz des jeweiligen Modell-Repositories, die mit der Lizenz der Bibliothek nichts zu tun hat. Rechtliche Beratung ersetzt das nicht.
Wann wllama die falsche Wahl ist
Es gibt Fälle, in denen der Browser-Pfad strukturell nicht passt. Wenn eine Seite keine COOP- und COEP-Header setzen kann, etwa weil sie in eine fremde Umgebung eingebettet ist oder Drittanbieter-Ressourcen ohne diese Header lädt, bleibt nur der Single-Thread-Build. Das ist kein Konfigurationsproblem, sondern eine Einschränkung der Umgebung, und sie kann eine Integration unmöglich machen.
Ebenso ungeeignet ist wllama, wenn die Antwortzeit planbar sein muss. Die Inferenzgeschwindigkeit hängt vom Gerät des Nutzers ab, und die README nennt keine Zahlen, die sich als Zusage verwenden ließen. Für Anwendungen mit Service-Level-Vorgaben ist ein Server-Backend die passende Wahl. Und wenn das Modell größer ist als der Speicher typischer Zielgeräte, hilft auch das Splitten nicht, weil es nur die Dateigrenze umgeht. In diesen Fällen ist der Aufwand für die Integration verlorene Zeit.
Redaktionelles Fazit
wllama passt zu Projekten, die Inferenz ohne eigenen Server ausliefern wollen und deren Zielgruppe den Modell-Download akzeptiert: kleine bis mittlere quantisierte GGUF-Modelle, Chat- oder Embedding-Funktionen direkt in der Seite. Wer große Modelle, mehrere gleichzeitige Nutzer pro Maschine oder eine zentrale Modellverwaltung braucht, sollte beim Server-Backend bleiben. Vor der Übernahme zuerst prüfen, ob die Seite Cross-Origin-Embedder-Policy und Cross-Origin-Opener-Policy setzen kann, denn ohne diese Header greift der Multi-Thread-Build nicht, und dann ein Modell mit n_gpu_layers: 0 gegen einen kleinen Wert vergleichen, um den VRAM-Bedarf einzuschätzen.
Community-Notizen