浏览器里跑大模型:2026年WebLLM/Transformers.js/ONNX Web全栈实战指南

技术架构浏览器 AI 与 WebAssembly

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能力

总结

  1. 浏览器端AI已从"玩具"变成"工具" — 4B模型25 tok/s,足够日常使用
  2. 三大框架各有侧重 — WebLLM快、Transformers.js全、ONNX稳
  3. 隐私是最大卖点 — 数据不离开浏览器,零服务端成本
  4. 降级策略是关键 — WebGPU → 小模型 → 云端API,保证可用性

2026年,如果你的AI产品还在把所有请求都发到云端,你不仅浪费了服务器成本,还错失了隐私保护这个最大的差异化优势。

本站提供浏览器本地工具,免注册即可试用 →

#WebLLM#Transformers.js#ONNX#WebGPU#浏览器AI#边缘推理#大模型#本地AI