Modèle / jeu de données
ngxson/wllama avatar
ngxson/wllama

wllama : faire tourner un LLM dans le navigateur sans serveur d'inférence

WebAssembly binding for llama.cpp - Enabling on-browser LLM inference

1 201 étoiles121 forksTypeScriptMIT

En bref

De quoi s’agit-il ?
wllama est une liaison WebAssembly vers llama.cpp, publiée sous licence MIT. Elle vise les développeurs qui veulent exécuter un modèle GGUF directement dans une page web, avec WebGPU en option, sans backend dédié.
À qui s’adresse-t-il ?
Adoptez wllama si vous voulez une inférence GGUF locale dans une page web, avec une API compatible OpenAI et un mode worker, et si vous acceptez de servir des en-têtes COOP/COEP et de découper vos modèles. Passez votre chemin si votre cible inclut des navigateurs sans WebAssembly SIMD ou si vous comptez charger des modèles de plus de 2 Go en un seul fichier.
Puis-je l’utiliser commercialement ?
Oui. MIT est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
Est-il encore maintenu ?
Oui. Les derniers commits datent d’il y a 2 jours.
En quel langage est-il écrit ?
Principalement TypeScript, d’après les statistiques de langage de GitHub.

Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.

ANALYSE OPEN SOURCE APPROFONDIE

Le problème : un modèle local sans colonne serveur

Faire tourner un LLM dans une page web oblige normalement à choisir entre deux mauvais compromis. Soit on appelle une API distante, et chaque token généré coûte un aller-retour réseau plus une facture d'inférence. Soit on demande à l'utilisateur d'installer un binaire, ce qui élimine la plupart des visiteurs. wllama propose une troisième voie : compiler llama.cpp en WebAssembly et l'exécuter dans le navigateur, sur la machine du visiteur. Le README annonce l'absence de backend et de GPU requis, en s'appuyant sur WebAssembly SIMD.

Le public visé est précis. Il s'agit de développeurs TypeScript qui construisent des applications web et veulent une inférence locale : démonstrations, outils hors ligne, traitement de texte sensible qui ne doit pas quitter le poste, ou prototypes où l'on refuse de provisionner une instance GPU. Le paquet s'installe via npm sous le nom @wllama/wllama et se présente comme une dépendance d'exécution nulle, ce que le README appuie sur le contenu de package.json. Pour un projet de cette nature, c'est un argument sérieux : moins de dépendances signifie moins de surface de rupture lors des mises à jour.

Architecture : wasm, worker et API compatible OpenAI

Le mécanisme visible dans la documentation tient en trois couches. En bas, un binaire WebAssembly issu de llama.cpp, compilé avec SIMD. Au milieu, une classe Wllama instanciée avec une table de chemins de configuration, par exemple { default: './esm/wasm/wllama.wasm' }. En haut, une surface d'appel qui imite OpenAI : le README montre createChatCompletion avec messages, max_tokens, temperature, top_k et top_p, et la réponse se lit dans response.choices[0].message.content. Cette ressemblance n'est pas cosmétique : elle permet de réutiliser du code écrit pour une API distante en changeant l'objet appelé.

Deux détails d'architecture méritent l'attention. D'abord, l'inférence s'exécute dans un worker, ce qui évite de bloquer le rendu de l'interface. Ensuite, le chargement bascule automatiquement entre une version mono-thread et une version multi-thread selon ce que le navigateur supporte. Le README indique qu'on peut forcer le mono-thread en passant n_threads: 1 dans LoadModelConfig. La version V3 ajoute WebGPU, le multimodal (image et audio) et l'appel d'outils. Selon le README, WebGPU est activé automatiquement depuis la V3.1 et toutes les couches sont déportées sur GPU par défaut, avec n_gpu_layers pour ajuster.

Mise en route : installation et chargement d'un GGUF

L'installation tient en une commande : npm i @wllama/wllama. Le README précise que les binaires wasm ne sont pas précompilés dans le dépôt. Si vous clonez la source plutôt que d'utiliser le paquet npm, il faut Docker et enchaîner npm ci puis npm run build:wasm && npm run build. C'est une contrainte de contribution, pas d'utilisation.

Le chargement d'un modèle passe par loadModelFromHF, qui accepte un objet { repo, file } pointant vers le hub Hugging Face, et un progressCallback qui reçoit loaded et total. Le README donne l'exemple de ggml-org/models avec tinyllamas/stories260K.gguf. Une variante loadModelFromUrl existe pour les modèles hors hub. Pour le WebGPU, l'exemple documenté appelle wllama.setCompat('default', 'firefox_safari') avant loadModel, en signalant que les performances chutent nettement dans ce mode de compatibilité. Le paramètre n_gpu_layers: 4 déporte quatre couches sur GPU, et la valeur 0 désactive l'inférence GPU. Sur le choix des fichiers, le README recommande des quantifications Q4, Q5 ou Q6, et déconseille explicitement les variantes IQ avec imatrix, jugées lentes et de qualité faible.

La limite des 2 Go et le découpage en morceaux de 512 Mo

La contrainte la plus dure est documentée sans détour : la taille maximale d'un fichier est de 2 Go, à cause de la limite de longueur d'un ArrayBuffer. Aucun modèle plus gros ne se chargera tel quel. La parade consiste à découper le GGUF avec llama-gguf-split, dont le README donne la commande : ./llama-gguf-split --split-max-size 512M ./my_model.gguf ./my_model. Le binaire précompilé se récupère sur la page de releases de llama.cpp.

Le découpage n'est pas qu'un contournement. Le README note que des morceaux multiples se téléchargent en parallèle, ce qui accélère légèrement le chargement, et que cela évite certains problèmes de mémoire insuffisante. La recommandation de taille est de 512 Mo par morceau au maximum. Cela signifie que l'utilisateur final paie le coût en bande passante : un modèle de 4 Go représente 4 Go téléchargés chez chaque visiteur, à chaque première visite, puisque rien n'indique de mise en cache persistante dans le matériel fourni. C'est le point où l'approche par navigateur coûte le plus cher, et la documentation ne l'aborde pas.

COOP, COEP et le cas où wllama est le mauvais outil

Le multi-thread exige d'ajouter les en-têtes Cross-Origin-Embedder-Policy et Cross-Origin-Opener-Policy. Le README renvoie à une discussion du projet ffmpeg.wasm pour le détail. Ces deux en-têtes isolent la page et cassent souvent des ressources tierces : images, scripts ou iframes servis sans les bons en-têtes. Un site existant qui ne peut pas les adopter se rabat sur le mono-thread, avec la perte de performance correspondante. C'est un choix d'architecture qui se décide au niveau du serveur, pas dans le code JavaScript.

Deuxième cas défavorable : les navigateurs sans WebAssembly SIMD. Le README présente SIMD comme le socle de l'inférence, et l'activation du multi-thread dépend du support du navigateur. La documentation ne fournit pas de tableau de compatibilité, et le paquet @wllama/wllama-compat est mentionné pour les problèmes de compatibilité sans que le README détaille son périmètre. Si votre audience inclut des navigateurs anciens ou des environnements restreints, ce point doit être vérifié avant tout engagement. Troisième cas : si votre modèle dépasse largement 2 Go et que vous ne pouvez pas le découper, wllama n'est pas l'outil adapté.

Face à Transformers.js : deux philosophies de chargement

L'alternative la plus directe dans l'écosystème JavaScript est Transformers.js, qui exécute des modèles via ONNX Runtime Web. La différence de conception est nette. Transformers.js s'appuie sur des modèles convertis au format ONNX et sur une bibliothèque de pipelines haut niveau, avec un catalogue de modèles préparés pour cette conversion. wllama reste sur le format GGUF de llama.cpp et sur les quantifications Q4 à Q6, ce qui donne accès à l'écosystème GGUF existant sans étape de conversion. Le revers est que les modèles doivent être au format GGUF, et que le découpage manuel via llama-gguf-split devient votre responsabilité.

Sur l'API, wllama expose une surface compatible OpenAI (createChatCompletion, embeddings), ce qui n'est pas la forme d'une bibliothèque de pipelines Python portée en JavaScript. Le README cite également le support multimodal et l'appel d'outils en V3, deux fonctions que l'on n'attend pas d'une simple liaison bas niveau. Le choix se joue donc sur le format de modèle que vous avez déjà et sur le degré de contrôle que vous voulez garder sur le chargement.

Maintenance, licence et coût de mise à jour

Le dépôt n'est pas archivé et la dernière poussée listée date du 6 septembre 2026. Les versions récentes s'enchaînent : 3.6.1 le 27 août 2026, 3.6.0 le 16 août 2026, 3.5.1 le 15 juin 2026. Le rythme est soutenu, ce qui est cohérent avec un projet qui suit llama.cpp de près. Ce suivi a un coût : chaque mise à jour de llama.cpp peut modifier le comportement de chargement ou les paramètres acceptés, et les notes de version sont l'endroit où ces changements sont consignés. Le README renvoie d'ailleurs à la page releases pour le changelog.

La licence est MIT, ce qui autorise l'usage commercial et la modification. Le README signale aussi que @wllama/wllama-compat existe pour les questions de compatibilité, ce qui suggère qu'un chemin de repli est maintenu en parallèle. Aucune information sur le support payant ou les engagements de maintenance n'apparaît dans le matériel fourni. Pour une équipe, cela signifie que la mise à niveau est une tâche récurrente à budgéter, pas un événement isolé.

Conclusion éditoriale

Adoptez wllama si vous voulez une inférence GGUF locale dans une page web, avec une API compatible OpenAI et un mode worker, et si vous acceptez de servir des en-têtes COOP/COEP et de découper vos modèles. Passez votre chemin si votre cible inclut des navigateurs sans WebAssembly SIMD ou si vous comptez charger des modèles de plus de 2 Go en un seul fichier. Avant d'intégrer, vérifiez trois choses concrètes : la présence de Cross-Origin-Embedder-Policy et Cross-Origin-Opener-Policy sur votre serveur, la valeur de n_gpu_layers adaptée à votre VRAM, et le comportement du paquet @wllama/wllama-compat sur les navigateurs que vous devez couvrir.

Sources officielles

  1. License: MIT
  2. ngxson/wllama on GitHub
  3. Project website
  4. README
  5. Releases
Notes de la communauté

Notes de la communauté