wllama 評測:把 llama.cpp 編進瀏覽器的 WebAssembly 綁定,V3 加了 WebGPU 之後怎麼用
WebAssembly binding for llama.cpp - Enabling on-browser LLM inference
秒懂
- 它是什麼?
- wllama 是 llama.cpp 的 WebAssembly 綁定,讓模型推論跑在瀏覽器裡,不需要後端。V3 加入 WebGPU、多模態與 tool calling,但也帶來 2GB 檔案上限與 COOP/COEP 標頭這類硬限制。
- 適合誰用?
- 如果你的情境是模型要留在使用者裝置上、不想維運推論後端,而且模型能壓在 2GB 以內,wllama 值得進到原型階段;需要多執行緒時得先確認你的伺服器送得出 Cross-Origin-Embedder-Policy 與 Cross-Origin-Opener-Policy,否則它會退回單執行緒版本。反過來說,模型超過 2GB 卻不想做 split、或團隊沒有 Docker 又不想用預建 npm 套件,這條路會卡在第一步。
- 可以商用嗎?
- 可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
- 還在維護嗎?
- 有在維護。儲存庫最近一次提交在 2 天前。
- 用什麼語言寫的?
- 主要是 TypeScript(依據 GitHub 的語言統計)。
以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。
開源專案深度解析
它要解決的是推論位置,不是模型品質
多數人談瀏覽器端 LLM,第一個想到的是隱私,但 wllama 真正改變的是維運形狀。它把 llama.cpp 編成 WebAssembly,推論在瀏覽器內完成,因此不需要後端服務、不需要 GPU 伺服器,也沒有推論 API 的帳單。README 的講法是「no backend or GPU is needed」,並強調「No runtime dependency」。對照它的 package.json 沒有執行期依賴,這件事在瀏覽器端特別有意義:你不需要為了一個聊天框拉進一整套工具鏈。
目標讀者是誰?前端或全端工程師,手上有一個已經用 JavaScript 或 TypeScript 寫成的應用,想加入本地推論能力,而且能接受模型檔案由使用者端下載。次要讀者是做離線工具、內部知識問答、或需要把資料留在裝置上的產品團隊。這裡有個容易誤判的地方:wllama 不是「免費的雲端 LLM」,它是把成本從伺服器移到使用者的下載流量與 CPU、GPU 上。模型多大,使用者就要下載多大。
推論跑在 worker,多執行緒取決於兩個 HTTP 標頭
從 README 能確認的架構有兩層。第一層是 Wasm 模組本身:wllama 提供單執行緒與多執行緒兩種建置,並且「Auto switch between single-thread and multi-thread build based on browser support」,會依瀏覽器支援度自動切換。第二層是執行位置:README 明講「Inference is done inside a worker, does not block UI render」,推論在 worker 內進行,主執行緒的畫面不會被卡住。這兩層合起來解釋了為什麼它能在瀏覽器裡用:Wasm 提供 SIMD 加速的計算核心,worker 提供不阻塞的執行環境。
多執行緒不是免費的。README 的限制段落寫得很直接:要啟用多執行緒,你必須加上 Cross-Origin-Embedder-Policy 與 Cross-Origin-Opener-Policy 這兩個回應標頭。這是瀏覽器對 SharedArrayBuffer 的隔離要求,不是 wllama 自己的設計選擇,但後果由你承擔:加了這兩個標頭,頁面上其他跨來源資源(嵌入的圖片、iframe、第三方腳本)可能一起受影響。這是我認為採用前最該先驗證的一件事,因為它會往回牽動你的部署設定,而不只是前端程式碼。
WebGPU 是另一條路徑。README 說明 WebGPU 支援由 PR #215 引入,且「Upon updating to V3.1, WebGPU will be enabled automatically」,預設會把所有層卸載到 GPU。模型塞不進 VRAM 時,可以透過 LoadModelParams 的 n_gpu_layers 參數手動調整,範例給的是 n_gpu_layers: 4,設為 0 則關閉 GPU 推論。另外還有一個相容模式:wllama.setCompat('default', 'firefox_safari'),README 對此的註解是效能會顯著下降,只在必要時使用。
安裝與最小可用範例
從 npm 安裝是最短路徑:npm i @wllama/wllama。README 也提供從 git repo 安裝的方式,但這裡有個明確前提:Wasm 二進位檔沒有預先建置在 repo 裡,你必須要有 Docker 才能自己編。指令是 git submodule add 之後 npm ci,再依序跑 npm run build:wasm 與 npm run build。如果你的環境沒有 Docker,又不打算用 npm 上的預建套件,這條路走不通。
載入模型有兩種寫法。從 Hugging Face Hub 載入用 loadModelFromHF,傳入 repo 與 file;非 HF 來源則用 loadModelFromUrl。README 的範例用 ggml-org/models 的 tinyllamas/stories260K.gguf,並搭配 progressCallback 回報下載進度,回呼收到 loaded 與 total 兩個欄位。推論端走的是 OpenAI 相容介面,範例呼叫 createChatCompletion,參數包含 messages、max_tokens、temperature、top_k、top_p,回應從 response.choices[0].message.content 取出。
Wasm 檔案的位置透過建構子的設定物件指定,範例是 { default: './esm/wasm/wllama.wasm' }。README 另外提供從 CDN 載入的方式,import WasmFromCDN from '@wllama/wllama/esm/wasm-from-cdn.js',但註解寫明「this is not recommended」,只在你無法把 wasm 檔嵌進專案時使用。想強制單執行緒,作法是載入設定加上 n_threads: 1。
模型格式方面,README 建議量化用 Q4、Q5 或 Q6,理由是效能、檔案大小與品質之間的平衡;並且明確不建議使用 IQ(搭配 imatrix),說法是有機會導致推論變慢與品質下降。這是一個少見的、直接給出負面建議的段落,值得照著做。
2GB 的 ArrayBuffer 天花板,以及 split 之後的副作用
最硬的限制寫在 README 的限制清單裡:單一檔案上限 2GB,原因是 ArrayBuffer 的長度限制。這不是可以靠調參數繞過的設定,而是執行環境的邊界。超過 2GB 的模型必須拆檔,工具是 llama-gguf-split,指令為 ./llama-gguf-split --split-max-size 512M ./my_model.gguf ./my_model,二進位檔可從 llama.cpp 的 release 頁面取得。
拆檔不是純粹的麻煩,它同時是效能手段。README 建議把模型切成最大 512MB 的區塊,理由是瀏覽器可以平行下載多個分片,下載會稍微快一些,也能避免某些 out-of-memory 狀況。換句話說,即使模型沒到 2GB,拆檔仍有機會讓首次載入體驗變好。但代價是你的部署多了一個前置步驟:模型檔案在上架前要先經過 llama-gguf-split 處理,這件事得進到你的建置或發佈流程裡,否則每次換模型都要手動做一次。
還有一個容易被忽略的失敗模式:模型能不能跑,取決於使用者的裝置,而不是你的伺服器。一份在你的開發機上跑得動的量化模型,在記憶體較小的手機上可能直接失敗。wllama 的自動單/多執行緒切換處理的是瀏覽器能力差異,處理不了裝置記憶體差異。這一塊 README 沒有給出建議的記憶體門檻,你只能自己量。
跟 transformers.js 的差別在哪
同在瀏覽器端跑推論,最常被拿來對比的是 Hugging Face 的 transformers.js。兩者的分歧點在底層引擎與模型格式。transformers.js 走的是 ONNX Runtime Web,模型通常是 ONNX 格式,生態系與 Hugging Face 的 Transformers 綁得比較緊,任務涵蓋面也廣,不限於文字生成。wllama 走的是 llama.cpp 編成的 Wasm,吃的是 GGUF 格式,也就是 llama.cpp 生態系那一整套量化與模型轉換流程。
這個差異會直接反映在你的工作流上。如果你已經在用 llama.cpp 或 Ollama 跑本地模型,手上就是 GGUF 檔,wllama 讓你沿用同一批檔案與同一套量化選擇,不必再轉一次格式。反過來說,如果你的模型來源以 ONNX 為主,或你需要的是分類、語音、視覺等非生成任務,transformers.js 的覆蓋面更合適。
第二個差異是硬體後端。wllama 在 V3 之後有 WebGPU 路徑,也可以退回純 WebAssembly SIMD;transformers.js 同樣支援 WebGPU。真正的分水嶺是模型格式與生態系,而不是「誰比較快」。我沒有實際跑過兩者的對比,README 也沒有提供任何效能數字,任何速度上的斷言在這裡都不該被當成事實。
版本與維護成本:V3 是一次帶斷層的升級
從 release 紀錄看,3.6.1 在 2026-08-27 發布,3.6.0 在 2026-08-16,3.5.1 在 2026-06-15,最近一次推送是 2026-09-06,專案沒有被歸檔。節奏談不上頻繁,但也不是停滯。
真正需要注意的是 README 開頭那段警告:V3 帶來了 WebGPU、多模態與 tool calling,並指向 V3 release guide;同時又寫了「For compatibility issues, please refer to @wllama/wllama-compat」。把相容套件獨立成另一個 npm 套件,等於承認 V3 對既有程式碼不是無痛升級。如果你的專案已經綁在 V2 的 API 上,升級前應該先讀那份 V3 指南與 compat 套件的說明,而不是直接改版號。
授權是 MIT。這對商業使用相對寬鬆,但 Wasm 二進位檔是從 llama.cpp 編出來的,llama.cpp 本身的授權狀態請自行確認,這裡不構成法律意見。另外,模型權重有它自己的授權,跟 wllama 的 MIT 無關,商用前要分別檢查。
維護成本的一個實際面向是版本綁定:wllama 的 Wasm 對應特定版本的 llama.cpp,你想用某個新模型架構時,得等 wllama 跟上。這不是 bug,是綁定式專案的固有節奏。
誰該用,以及先驗證什麼
如果你的產品需要把推論留在使用者裝置上,模型能壓在 2GB 以內,而且你的團隊本來就在 llama.cpp 生態系裡工作,wllama 是少數能直接對接 GGUF 的瀏覽器端選項。OpenAI 相容的 API 形狀也讓前端程式碼比較好寫,之後要換回伺服器端推論時,改動範圍相對可控。
如果模型超過 2GB 而你不想導入 llama-gguf-split 這個前置步驟,或者你的部署環境沒辦法加上 Cross-Origin-Embedder-Policy 與 Cross-Origin-Opener-Policy,那 wllama 會退回單執行緒,效能預期要重新算。若你需要的是非生成式任務,transformers.js 的任務覆蓋面更廣。若你只是想找一個不用自己維運的 LLM 服務,瀏覽器端推論把成本轉嫁給使用者,未必是你想要的取捨。
動手前建議依序確認:部署環境能否送出那兩個標頭;目標瀏覽器是否支援 WebAssembly SIMD;模型是否已切成 512MB 以下的分片;以及量化是否落在 README 建議的 Q4、Q5、Q6 範圍內。這四項任一項不成立,後面的整合都會白做。
編輯結論
如果你的情境是模型要留在使用者裝置上、不想維運推論後端,而且模型能壓在 2GB 以內,wllama 值得進到原型階段;需要多執行緒時得先確認你的伺服器送得出 Cross-Origin-Embedder-Policy 與 Cross-Origin-Opener-Policy,否則它會退回單執行緒版本。反過來說,模型超過 2GB 卻不想做 split、或團隊沒有 Docker 又不想用預建 npm 套件,這條路會卡在第一步。動手前先確認三件事:你的部署環境能不能加上那兩個標頭、目標瀏覽器是否支援 WebAssembly SIMD、以及你要用的量化格式是不是 README 建議的 Q4、Q5、Q6。
社群筆記