浏览器里跑大模型:2026年WebLLM/Transformers.js/ONNX Web全栈实战指南
2026年,大模型不再需要服务器
GPT-4需要云端API?那是2024年的思维。2026年,7B参数的模型已经可以在浏览器里流畅运行,你的数据永远不离开本地。
隐私 + 零成本 + 离线可用 = 浏览器端AI的三大杀手级优势
浏览器端AI进化时间线
2023 Q4 WebLLM首发,Llama 2在浏览器跑出2 tok/s
2024 Q2 Transformers.js发布,Hugging Face生态打通
2024 Q4 WebGPU全面支持,推理速度提升5x
2025 Q2 ONNX Runtime Web支持WebGPU,企业级方案成熟
2025 Q4 量化技术突破,7B模型压缩到3GB
2026 Q2 Gemma 3 4B浏览器端达到25 tok/s,可用性质变
三大框架定位
| 框架 | 定位 | 核心技术 | 适用场景 |
|---|---|---|---|
| WebLLM | 高性能LLM推理 | WebGPU + MLCEngine | 聊天、代码补全 |
| Transformers.js | 全栈ML推理 | ONNX + WASM/WebGPU | NLP、视觉、音频 |
| ONNX Runtime Web | 企业级推理引擎 | ONNX + WebGPU/WASM | 生产级部署 |
WebLLM — 浏览器端LLM的性能之王
核心架构
┌──────────────────────────────────────────────────┐
│ 应用层 │
│ 聊天界面 │ 代码补全 │ 文档摘要 │ 翻译 │
├──────────────────────────────────────────────────┤
│ WebLLM Engine │
│ ChatModule │ Pipeline │ Tokenizer │ Scheduler │
├──────────────────────────────────────────────────┤
│ MLCEngine(编译优化层) │
│ 模型编译 │ Kernel优化 │ 量化 │ 内存管理 │
├──────────────────────────────────────────────────┤
│ WebGPU Runtime │
│ Compute Shader │ GPU Buffer │ Pipeline State │
└──────────────────────────────────────────────────┘
快速上手
import { CreateMLCEngine } from "@mlc-ai/web-llm";
const engine = await CreateMLCEngine("gemma-3-4b-it-q4f16_1-MLC", {
initProgressCallback: (progress) => {
console.log(`模型加载: ${(progress.progress * 100).toFixed(1)}%`);
},
});
const reply = await engine.chat.completions.create({
messages: [
{ role: "system", content: "你是一个有帮助的AI助手。" },
{ role: "user", content: "用TypeScript写一个快速排序" },
],
temperature: 0.7,
max_tokens: 1024,
stream: true,
});
for await (const chunk of reply) {
const delta = chunk.choices[0]?.delta?.content || "";
process.stdout.write(delta);
}
React组件集成
"use client";
import { useState, useRef, useEffect } from "react";
import { CreateMLCEngine, MLCEngine } from "@mlc-ai/web-llm";
export function BrowserChat() {
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [input, setInput] = useState("");
const [loading, setLoading] = useState("");
const [isReady, setIsReady] = useState(false);
const engineRef = useRef<MLCEngine | null>(null);
useEffect(() => {
async function initEngine() {
const engine = await CreateMLCEngine("gemma-3-4b-it-q4f16_1-MLC", {
initProgressCallback: (p) => setLoading(`加载模型 ${Math.round(p.progress * 100)}%`),
});
engineRef.current = engine;
setIsReady(true);
}
initEngine();
}, []);
async function handleSend() {
if (!input.trim() || !engineRef.current) return;
const userMsg = { role: "user" as const, content: input };
setMessages((prev) => [...prev, userMsg]);
setInput("");
const reply = await engineRef.current.chat.completions.create({
messages: [...messages, userMsg].map((m) => ({
role: m.role, content: m.content,
})),
stream: true,
temperature: 0.7,
});
let assistantContent = "";
setMessages((prev) => [...prev, { role: "assistant", content: "" }]);
for await (const chunk of reply) {
const delta = chunk.choices[0]?.delta?.content || "";
assistantContent += delta;
setMessages((prev) => {
const updated = [...prev];
updated[updated.length - 1] = { role: "assistant", content: assistantContent };
return updated;
});
}
}
return (
<div className="flex flex-col h-full max-w-2xl mx-auto p-4">
{!isReady && <div className="text-center py-8">{loading}</div>}
{isReady && (
<>
<div className="flex-1 overflow-y-auto space-y-4 mb-4">
{messages.map((msg, i) => (
<div key={i} className={`${msg.role === "user" ? "text-right" : "text-left"}`}>
<span className={`inline-block px-4 py-2 rounded-lg ${
msg.role === "user" ? "bg-blue-500 text-white" : "bg-gray-100 dark:bg-gray-800"
}`}>{msg.content}</span>
</div>
))}
</div>
<div className="flex gap-2">
<input value={input} onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && handleSend()}
className="flex-1 px-4 py-2 border rounded-lg" placeholder="输入消息..." />
<button onClick={handleSend} className="px-6 py-2 bg-blue-500 text-white rounded-lg">发送</button>
</div>
</>
)}
</div>
);
}
支持模型与性能(2026年6月)
| 模型 | 参数量 | 量化后大小 | 推理速度(tok/s) | 首次加载 |
|---|---|---|---|---|
| Gemma 3 4B IT | 4B | 2.3GB | 25 | 8s |
| Phi-4 Mini | 3.8B | 2.1GB | 28 | 7s |
| Qwen2.5 3B | 3B | 1.8GB | 32 | 6s |
| Llama 3.2 3B | 3B | 1.7GB | 30 | 6s |
| SmolLM2 1.7B | 1.7B | 1.0GB | 45 | 4s |
| Qwen2.5 0.5B | 0.5B | 0.4GB | 85 | 2s |
测试环境:M3 MacBook Pro / Chrome 126 / WebGPU
Transformers.js — Hugging Face生态的浏览器延伸
核心优势:模型生态最丰富
import { pipeline, env } from "@xenova/transformers";
env.allowLocalModels = false;
const classifier = await pipeline("text-classification", "Xenova/distilbert-base-uncased-finetuned-sst-2-english");
const result = await classifier("This browser AI is amazing!");
// [{ label: "POSITIVE", score: 0.9998 }]
支持的Pipeline类型
| Pipeline | 用途 | 示例模型 |
|---|---|---|
| text-classification | 情感分析 | distilbert-sst2 |
| token-classification | NER命名实体识别 | bert-base-NER |
| question-answering | 问答系统 | distilbert-qa |
| text-generation | 文本生成 | phi-2, smollm |
| summarization | 摘要生成 | distilbart-cnn |
| translation | 翻译 | opus-mt-en-zh |
| image-classification | 图像分类 | vit-base-patch16 |
| object-detection | 目标检测 | detr-resnet-50 |
| image-to-text | OCR/图像描述 | trocr-small |
| automatic-speech-recognition | 语音识别 | whisper-tiny |
| text-to-speech | 语音合成 | speecht5 |
实战:浏览器端智能文档助手
"use client";
import { useState } from "react";
import { pipeline, Pipeline } from "@xenova/transformers";
export function SmartDocAssistant() {
const [doc, setDoc] = useState("");
const [question, setQuestion] = useState("");
const [answer, setAnswer] = useState("");
const [loading, setLoading] = useState(false);
async function askQuestion() {
setLoading(true);
try {
const qa = await pipeline("question-answering", "Xenova/distilbert-base-cased-distilled-squad");
const result = await qa(question, { context: doc });
setAnswer(result.answer);
} finally {
setLoading(false);
}
}
async function summarize() {
setLoading(true);
try {
const summarizer = await pipeline("summarization", "Xenova/distilbart-cnn-6-6");
const result = await summarizer(doc, { max_new_tokens: 100 });
setAnswer(result[0].summary_text);
} finally {
setLoading(false);
}
}
async function extractEntities() {
setLoading(true);
try {
const ner = await pipeline("token-classification", "Xenova/bert-base-NER");
const entities = await ner(doc);
const grouped = entities.reduce((acc: Record<string, string[]>, e: any) => {
(acc[e.entity_group] = acc[e.entity_group] || []).push(e.word);
return acc;
}, {});
setAnswer(JSON.stringify(grouped, null, 2));
} finally {
setLoading(false);
}
}
return (
<div className="max-w-3xl mx-auto p-6 space-y-4">
<textarea value={doc} onChange={(e) => setDoc(e.target.value)}
className="w-full h-48 p-4 border rounded-lg" placeholder="粘贴文档内容..." />
<div className="flex gap-2">
<input value={question} onChange={(e) => setQuestion(e.target.value)}
className="flex-1 px-4 py-2 border rounded-lg" placeholder="输入问题..." />
<button onClick={askQuestion} className="px-4 py-2 bg-blue-500 text-white rounded-lg">问答</button>
<button onClick={summarize} className="px-4 py-2 bg-green-500 text-white rounded-lg">摘要</button>
<button onClick={extractEntities} className="px-4 py-2 bg-purple-500 text-white rounded-lg">NER</button>
</div>
{loading && <p>处理中...</p>}
{answer && <div className="p-4 bg-gray-50 rounded-lg whitespace-pre-wrap">{answer}</div>}
</div>
);
}
ONNX Runtime Web — 企业级推理引擎
核心架构
┌──────────────────────────────────────────────────┐
│ ONNX Runtime Web │
├──────────────────────────────────────────────────┤
│ 推理Session │
│ SessionOptions │ Provider选择 │ 线程配置 │
├──────────────────────────────────────────────────┤
│ 执行Provider │
│ WebGPU(首选) │ WebGL │ WASM(兜底) │
├──────────────────────────────────────────────────┤
│ ONNX模型格式 │
│ 优化图 │ 量化节点 │ 自定义算子 │
└──────────────────────────────────────────────────┘
基础使用
import ort from "onnxruntime-web";
ort.env.wasm.numThreads = navigator.hardwareConcurrency || 4;
ort.env.wasm.simd = true;
async function runInference(modelPath: string, input: Float32Array) {
const session = await ort.InferenceSession.create(modelPath, {
executionProviders: ["webgpu", "wasm"],
graphOptimizationLevel: "all",
});
const inputTensor = new ort.Tensor("float32", input, [1, input.length]);
const feeds = { input: inputTensor };
const results = await session.run(feeds);
return results.output.data;
}
Provider选择策略
function getBestProvider(): string {
if (navigator.gpu) return "webgpu";
if (document.createElement("canvas").getContext("webgl2")) return "webgl";
return "wasm";
}
const session = await ort.InferenceSession.create(modelPath, {
executionProviders: [getBestProvider()],
});
性能基准:三大框架全面对比
LLM推理性能(Gemma 3 4B,4bit量化)
| 指标 | WebLLM | Transformers.js | ONNX Runtime Web |
|---|---|---|---|
| 推理速度(tok/s) | 25 | 18 | 22 |
| 首次加载时间 | 8s | 12s | 10s |
| 内存占用 | 3.2GB | 3.8GB | 3.5GB |
| 流式输出 | ✅ | ✅ | ❌(需手动实现) |
| OpenAI API兼容 | ✅ | ❌ | ❌ |
| 多模态 | ❌ | ✅ | ✅ |
非LLM任务性能(情感分析)
| 指标 | Transformers.js | ONNX Runtime Web |
|---|---|---|
| 推理延迟 | 45ms | 28ms |
| 内存占用 | 180MB | 120MB |
| 模型生态 | 10,000+ | 5,000+ |
生产级部署策略
模型缓存与渐进加载
const CACHE_NAME = "web-llm-models";
async function loadModelWithCache(modelId: string) {
const cache = await caches.open(CACHE_NAME);
const cached = await cache.match(modelId);
if (cached) {
console.log("从缓存加载模型");
return cached;
}
console.log("首次下载模型,缓存到本地");
const response = await fetch(modelUrl);
await cache.put(modelId, response.clone());
return response;
}
降级策略
async function createEngineWithFallback() {
// 1. 尝试WebGPU(最快)
if (navigator.gpu) {
try {
return await CreateMLCEngine("gemma-3-4b-it-q4f16_1-MLC");
} catch (e) {
console.warn("WebGPU加载失败,降级到小模型");
}
}
// 2. 降级到小模型
try {
return await CreateMLCEngine("SmolLM2-1.7B-q4f16_1-MLC");
} catch (e) {
console.warn("小模型也失败,降级到API");
}
// 3. 最终降级:云端API
return new APIFallbackEngine({ endpoint: "/api/chat" });
}
Service Worker离线支持
// sw.ts
const MODEL_CACHE = "ai-models-v1";
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(MODEL_CACHE).then((cache) =>
cache.addAll([
"/models/smolm2-1.7b-q4.onnx",
"/models/tokenizer.json",
])
)
);
});
self.addEventListener("fetch", (event) => {
if (event.request.url.includes("/models/")) {
event.respondWith(
caches.match(event.request).then((cached) => cached || fetch(event.request))
);
}
});
适用场景决策矩阵
你的需求?
│
├─ 聊天/对话式AI
│ └─ ✅ WebLLM(OpenAI API兼容 + 流式 + 最快推理)
│
├─ 多模态AI(文本+图像+语音)
│ └─ ✅ Transformers.js(Pipeline最全 + HF生态)
│
├─ 企业级生产部署
│ └─ ✅ ONNX Runtime Web(最稳定 + 多Provider降级)
│
├─ 离线优先应用
│ └─ ✅ WebLLM + Service Worker缓存
│
└─ 快速原型验证
└─ ✅ Transformers.js(3行代码跑起来)
2026下半年趋势
| 趋势 | 说明 |
|---|---|
| WebGPU全面普及 | Safari 18+支持,浏览器AI不再有兼容性问题 |
| MoE模型浏览器化 | Mixtral等稀疏模型可在浏览器运行(只激活部分专家) |
| 端侧微调 | LoRA权重在浏览器下载,个性化模型无需服务器 |
| 多模态融合 | 文本+图像+语音统一模型在浏览器运行 |
| AI SDK标准化 | W3C Web AI API提案,浏览器原生AI能力 |
总结
- 浏览器端AI已从"玩具"变成"工具" — 4B模型25 tok/s,足够日常使用
- 三大框架各有侧重 — WebLLM快、Transformers.js全、ONNX稳
- 隐私是最大卖点 — 数据不离开浏览器,零服务端成本
- 降级策略是关键 — WebGPU → 小模型 → 云端API,保证可用性
2026年,如果你的AI产品还在把所有请求都发到云端,你不仅浪费了服务器成本,还错失了隐私保护这个最大的差异化优势。
本站提供浏览器本地工具,免注册即可试用 →
#WebLLM#Transformers.js#ONNX#WebGPU#浏览器AI#边缘推理#大模型#本地AI