# 從微調到瀏覽器:JavaScript + WebGPU 加速 LLM 在瀏覽器運行實戰 - Wei
{%hackmd @JSDC-tw/B1loEcwJZl %}
###### tags: `JSDC2025`
:::warning
本議程不提供錄影
:::
Slido:https://app.sli.do/event/48M22gQP21J2kVv2peyASA
Slide:
https://drive.google.com/file/d/1eHKnykorI9vkdSGtFydNc4_KZYqNbuAA/view?usp=sharing
> 開始做筆記
從 RAG 開始可以先了解 https://docs.unsloth.ai/
Phi 3 開始研究視覺辨識
---
## 前言(GenAI Era)
### 主流需求 → 個人化需求(Extreme personal experience)

在上一波 AI 技術,推薦系統的革命後,小眾需求的創造者跟需求端能夠更有效率媒合,因此開始越來越多的娛樂內容、SaaS 服務,滿足那些比較個人化、比較特殊的需求(癖好)。
原本生產力工具上一直難以做到個人化,因為像客製化影片或專屬工具,都需要高昂製作成本。直到 2023 年 ChatGPT 出現後這個問題被解決,像是 Cursor、NotionAI、Custom GPTs 等工具,讓個人即使需求再小眾,也能獲得客製化的效率提升。(這次的簡報跟圖片都是 Gemini 生出來的)
這些原本規模很小的需求,因為都能被 AI 滿足,最終集合成一個非常大的群體。
### How might we build UI/UX that was impossible before?
在這一波 GenAI 的情況下,我們終於有能力可以打造 **超級獨特** 的個人體驗,而 JavaScript 是打造互動或前端界面(打造人的體驗)最好的工具。當我們有了這樣的技術之後,下一步是:要怎麼把這個技術放到我們現有的工具中,讓 **之前做不到的UI/UX** 變得可能。
---
## **現狀(**The Status Quo**)**
### 第三方 API 依賴(Rely heavily on 3rd-party APIs)
如果要在現有產品中整合 AI,基本上主要有兩種做法:
1. 直接發送 HTTP 請求(fetch)

2. 使用 OpenAI Node.js SDK

> 這些方法都高度依賴第三方的 AI 模型,也因此存在多項缺點。
>
### 痛點(Pain Points)
1. **Token 成本問題(Token Cost Issue)**
使用者付費還是開發者付費?在傳統 SaaS 中,通常是開發者付費再用訂閱方案收回成本,但在 LLM 時代,LLM 每次運作都需要 Token 費用,成本難以下降,到底 **誰要付這個帳單** 變成一個很大的問題。(前陣子有一位 vibe coding 的 KOL 讓大家使用他做的東西,結果他付帳單)
2. **延遲(Latency)**
呼叫外部 API 的延遲(Network round-trips)會讓有些互動變得不太可能。如果我按一個按鈕希望一秒內回復,呼叫 API 很多時候做不到,或是他很要求網路環境到一定的程度。
3. **網絡依賴(Network Dependency)**
在網路爆掉的情況下,你就沒辦法再用到 AI 的能力。(前陣子的 Cloudflare 🤯 )
4. **單點故障(Single Point of Failure)**
即使一切都好,公司可能因為太多請求或自身問題,導致產品無法服務。例如,有時會出現 **status code 429** 代表無法回應。
5. **糟糕的開發體驗(Bad DX)**
在開發階段,模擬 AI 的互動是很困難的。如果呼叫固定的 API、定好 Schema 和 Use Case 即可進行模擬,但 AI 互動則難以實現良好的 Mock。
---
## **WebLLM 介紹**
**WebLLM** 是一個新的技術框架,它允許我們在 **瀏覽器內部運行大型模型**。
### **WebLLM 效能**
在其原始論文中提到 WebLLM 的效能比直接在電腦本地運行的效能大約有 **20% 的折損**。但在小模型的應用上,這種折損基本上可以忽略不計。
### **運作方式:混合引擎 (The Hybrid Engine)**
WebLLM 結合了兩種核心技術:
- **WebGPU (Inference Engine)**:
- 允許 Chrome 瀏覽器透過瀏覽器本身與裝置 GPU 互動,直接操作 GPU。
- 負責較複雜的矩陣運算,特別是 **Transformer** 模型中使用的 **注意力機制**。
- **WebAssembly (WASM)**:
- 使用靜態類型語言取代動態語言中運算較慢的部分,加速關鍵過程。
- 負責處理輸入輸出、將模型參數塞入計算、以及將模型計算結果轉換成最終輸出。
在這兩個技術的優化與革新下,**在瀏覽器上跑LLM** 變成一件可行的事情。
---
## MBTI 性格測驗(LIVE DEMO)
[https://github.com/Joshua0128/smarter-form/](https://github.com/Joshua0128/smarter-form/)
WebLLM 被用來協助使用者回答 MBTI 性格測驗中那些含糊不清的問題(例如:「少數」是幾個人)。使用者可以在填寫測驗時直接問 LLM。
### 分支
- 分支 step 0 → 純介面的應用
- 分支 step 1 → 設定 WebLLM
- (+) script.js → `useLLM`
- (+) webllm-init.js → `initWebLLM`
- 分支 step 2 → 整合成聊天助手的方式互動
- (+) chat-assistant.js
### **初始化 LLM** `initWebLLM` [[代碼](https://github.com/Joshua0128/smarter-form/blob/step/1-setup-webllm/webllm-init.js)]
1. 選用模型
- [http://github.com/mlc-ai/web-llm](http://github.com/mlc-ai/web-llm)
> Here are the primary families of models currently supported:
>
> - **Llama**: Llama 3, Llama 2, Hermes-2-Pro-Llama-3
> - **Phi**: Phi 3, Phi 2, Phi 1.5
> - **Gemma**: Gemma-2B
> - **Mistral**: Mistral-7B-v0.3, Hermes-2-Pro-Mistral-7B, NeuralHermes-2.5-Mistral-7B, OpenHermes-2.5-Mistral-7B
> - **Qwen (通义千问)**: Qwen2 0.5B, 1.5B, 7B
```vbnet
Qwen2.5-1.5B-Instruct-q4f16_1-MLC
--- -------- --------------------
模型 大小 參數
```
2. 呼叫 `webllm.CreateMLCEngine`
3. 設定加載時候的 hook `initProgressCallback`
4. 丟到 `window.llmEngine`
### **WebLLM** 的優勢與實現
- WebLLM **遵循 OpenAI 的 API 格式**,支援像是 Streaming(串流式輸出)、Structured JSON Output(結構化輸出)、以及 Tool Calling(功能調用)等技術。
- [http://github.com/mlc-ai/web-llm](http://github.com/mlc-ai/web-llm)
> **Full OpenAI Compatibility**
>
>
> WebLLM is designed to be fully compatible with [OpenAI API](https://platform.openai.com/docs/api-reference/chat). Thus, besides building a simple chatbot, you can also have the following functionalities with WebLLM:
>
> - [streaming](https://github.com/mlc-ai/web-llm/blob/main/examples/streaming): return output as chunks in real-time in the form of an AsyncGenerator
> - [json-mode](https://github.com/mlc-ai/web-llm/blob/main/examples/json-mode): efficiently ensure output is in JSON format, see [OpenAI Reference](https://platform.openai.com/docs/guides/text-generation/chat-completions-api) for more.
> - [seed-to-reproduce](https://github.com/mlc-ai/web-llm/blob/main/examples/seed-to-reproduce): use seeding to ensure a reproducible output with fields `seed`.
> - [function-calling](https://github.com/mlc-ai/web-llm/blob/main/examples/function-calling) (WIP): function calling with fields `tools` and `tool_choice` (with preliminary support); or manual function calling without `tools` or `tool_choice` (keeps the most flexibility).
- WebLLM 呼叫格式(例如 `chat completion create`)與 OpenAI 幾乎一模一樣,參數(如 `temperature`, `max token`)也相同。但唯一有差別的是 **不能在呼叫時指定模型**。你初始化什麼模型,它就回答什麼模型。
- 演示中,WebLLM 讓 LLM 能夠在瀏覽器上以 **1GB 以內** 的記憶體用量下運行。
- 初次運行時,WebLLM 的模型會被下載並存放在瀏覽器的 **Cache Storage** 中。但基於資安考量,它只在**同一個 Origin** 下緩存模型。如果跳轉到不同的網域 (Origin),就需要重新下載模型。
- 模型由三個主要檔案組成:
1. **Model:** 被寫成很多碎片檔的大模型,之後會組起來。
2. **WebAssembly:** 負責 CPU 加速及參數組裝的邏輯。
3. **Config:** 存放 LLM 相關的設定。
- 在演示的過程中,**沒有花費任何Token**。
- 沒有呼叫任何外部API,因此可以直接把網路調到 **離線模式** (Offline) 也能執行。
- 這種應用是本來做不到的,因為無法收斂表單的互動。現在,透過 LLM 與設定好的系統提示(System Prompt),可以讓填表單的人體驗更好,而且基本上**不用花費你的算力**,可以盡情的「浪費」。
---
## AI 小鎮物語(LIVE DEMO)
另一個盡情浪費的案例:
[https://minitown.zeabur.app/](https://minitown.zeabur.app/)
此案例是 **muti-agent 架構** 的 Demo。這些 LLM Agent 有不同的設定,會在虛擬世界中觀察周圍的人和事件,並開始行動和做判斷。如果用外部 API 運行三個小時,將會是一筆昂貴的費用。但既然模型放在瀏覽器中,就可以進行「**浪費**」(例如上班時掛在旁邊看)。
> 使用範例:現在中央公園起火了,快去幫忙!
>
---
## 部署自訂模型(Customizing with your model)
如果你想要把自己的模型丟到瀏覽器上,你需要經過以下步驟:
### 1. 微調 (Fine-Tuning)
- 起手可以使用 **LoRA (Low-Rank Adaptation)** 技術進行微調。
最建議的工具是使用 **unsloth(樹懶)**。
- **LoRA 原理:** 與其直接去修改整個大模型(像一本字典),LoRA 是透過建立許多 **便利貼(補丁)** 來修改關鍵的東西。這樣可以用較少的成本,將新的領域知識或風格灌注到模型中。
- **訓練**:可以在 Google Colab 上完成,Colab 提供免費的 GPU 資源,可以運行從 1.7B 到 32B 的模型,大概可以免費使用 24 小時,之後就要付費。
### 2. 量化 (Quantization)
- 一般模型參數使用 32位(32-bit)長度的浮點數表示,但有時候參數不需要那麼高的精度。
- 量化是透過將參數精度降低(例如從 32-bit 浮點數轉換為 16-bit 或 8-bit 的近似整數),來**縮小模型大小**。
- 需要使用 **MLC-LLM** 進行量化。
### 3. 部署 (Deploy)
部署時需要定義設定檔。

- **model:** 定義你量化完的模型檔案存放的網址。
- **model_id:** 模型的名稱。
- **model_lib:** 做模型有分兩種,第一種拿別人的架構去改參數來做模型;第二種則是使用了別人沒有用過的架構(例如自己設計的新架構),你需要自己將這個架構 **compile 成 WebAssembly**,並替換這裡的 model library,才能把自己客製化的東西放上來。
---
## MLC-LLM
將運行在 LLM 上的程式碼轉化為 **適合各種硬體的機械碼**,扮演著「翻譯者」的角色,不論模型是用 Python 或 JavaScript 編寫,經過 MLC 轉換後,它都能在 NVIDIA、Android、iOS、**Web 瀏覽器**等不同平台上運行,從而降低成本與效能。
---
## WebLLM 與 Transformers.js 的比較
| 特性 | Transformers.js | WebLLM (MLC AI) |
| --- | --- | --- |
| **底層優化** | 在瀏覽器環境上執行一個 ONNX Runtime。 | 使用 MLC LLM 將程式碼直接轉換成 **硬體最適化** 的機械碼。 |
| **效能** | 效能較弱,因為多了一層虛擬層在上面運行。 | 效能更高,因為直接優化底層硬體。 |
| **API 支援** | 不支援 OpenAI API 的能力。 | 支援 OpenAI API 的能力。 |
| **適用性** | 任何 Transformer 模型都可運行(包括圖像、聲音、影片)。 | 適用於聊天模型 (Chat Model)。 |
---
## 裝置相容性檢查
使用者可以透過 [**WebGPU Report**](https://webgpureport.org/) 網站檢查自己的電腦是否適合運行 LLM。如果手機是 Android 系統,可能會顯示效能如何;如果是 iOS 系統,則會直接顯示不支援。
---
## 結語
WebLLM 為什麼越來越重要,是因為 **小模型** 正變得越來越強大。在某些應用與分數上,小模型甚至可以 **超越大型模型**(例如超過 GPT-5),小模型也更容易進行微調。
在 GenAI 時代,WebLLM 使得我們能夠以非常小的成本下打造 **超個人化的 UX**,可以用小模型在瀏覽器上做超酷的東西,大家快去玩!
---
> 聊天區
---
{%hackmd @JSDC-tw/jsdc2025_sponsor %}