当浏览器具备可用的 GPU、成熟的 JavaScript 推理库和本地分析能力后,AI 应用不必把每一次推理都发送到云端。James Hall 在演讲中讨论了将 AI 工作负载从云服务商迁移到本地边缘设备的技术原因与产品价值,并分享了 WebGPU、Transformers.js 和 DuckDB 的组合实践。
这不是简单地把一个模型文件塞进前端。真正可用的方案还要同时处理隐私、首次加载、设备差异、推理延迟和结果评估。
为什么把推理放到浏览器
云端推理容易接入,也便于统一升级,但所有输入都要离开用户设备。对于文档、代码、客服记录、医疗资料或企业内部数据,这会带来数据合规、网络传输和供应商依赖等问题。
本地推理的价值主要体现在三个方面:
- 数据留在设备上:原始文本、图片或音频可以只在浏览器内处理。
- 交互延迟更稳定:推理不再依赖往返网络,断网场景也可能继续工作。
- 云端成本更可控:高频、低复杂度的分类、检索前处理和摘要任务可以由客户端承担。
代价同样明确:模型需要下载和缓存,低端设备可能缺少足够的内存或 GPU 能力,浏览器之间的 WebGPU 支持也存在差异。因此,边缘 AI 更适合从明确、可度量的工作负载开始,而不是一开始就尝试把大型通用模型完整搬到客户端。
WebGPU 与 Transformers.js 的浏览器推理
WebGPU 为 JavaScript 提供了访问 GPU 计算能力的标准接口。Transformers.js 则把常见 Transformer 模型的加载和推理流程封装成前端可调用的 API。两者结合后,可以在浏览器中运行文本分类、嵌入生成和其他适合端侧的模型任务。
下面是一个可直接改造的最小示例。它使用浏览器原生 WebGPU,并通过 Transformers.js 在本地执行情感分类。第一次运行会下载模型,之后通常可以利用浏览器缓存。示例假设使用支持 WebGPU 的现代浏览器,并通过本地 HTTP 服务打开页面。
先创建一个空目录,安装依赖并启动静态服务器:
mkdir browser-ai-demo
cd browser-ai-demo
npm init -y
npm install @huggingface/transformers
npx serve .
将下面内容保存为 index.html,然后访问终端显示的本地地址:
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8" />
<title>Browser AI Demo</title>
<body>
<textarea id="input" rows="5" cols="60">The local inference result is fast and private.</textarea>
<button id="run">运行推理</button>
<pre id="output">等待输入...</pre>
<script type="module">
import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1/+esm";
// 浏览器端使用缓存,避免每次刷新都重新下载模型。
env.allowLocalModels = false;
const output = document.querySelector("#output");
const input = document.querySelector("#input");
const run = document.querySelector("#run");
let classifier;
async function getClassifier() {
if (!classifier) {
const device = "gpu" in navigator ? "webgpu" : "wasm";
output.textContent = `正在初始化 ${device} 推理...`;
classifier = await pipeline(
"text-classification",
"Xenova/distilbert-base-uncased-finetuned-sst-2-english",
{ device }
);
}
return classifier;
}
run.addEventListener("click", async () => {
run.disabled = true;
try {
const model = await getClassifier();
const result = await model(input.value);
output.textContent = JSON.stringify(result, null, 2);
} catch (error) {
output.textContent = `推理失败:${error.message}`;
} finally {
run.disabled = false;
}
});
</script>
</body>
</html>
生产环境需要进一步处理模型版本固定、下载进度、缓存策略和失败回退。对于隐私敏感的场景,还应检查日志、错误上报和浏览器存储,避免模型输入意外被发送到第三方服务。
DuckDB 让本地评估变得可操作
端侧推理的难点不只是“能不能跑”,还包括“在什么设备上跑得足够好”。开发者需要记录模型版本、输入长度、设备类型、推理耗时、结果置信度和错误案例。DuckDB 适合在本地对这些结构化记录进行分析,尤其适合直接查询 Parquet、CSV 或内存数据。
可以把每次推理记录成类似下面的结构:
CREATE TABLE inference_runs (
model VARCHAR,
device VARCHAR,
input_tokens INTEGER,
latency_ms DOUBLE,
label VARCHAR,
score DOUBLE,
expected_label VARCHAR
);
SELECT
device,
COUNT(*) AS samples,
ROUND(AVG(latency_ms), 2) AS avg_latency_ms,
ROUND(quantile_cont(latency_ms, 0.95), 2) AS p95_latency_ms,
AVG(CASE WHEN label = expected_label THEN 1 ELSE 0 END) AS accuracy
FROM inference_runs
GROUP BY device
ORDER BY p95_latency_ms;
在浏览器中,可以将这类 SQL 交给 DuckDB-WASM 执行;如果评估数据不应离开设备,测试集也可以只存放在本地。这样得到的不是一条脱离环境的平均延迟,而是按设备、输入规模和模型版本拆开的结果。
评估套件至少应覆盖以下维度:
- 质量:准确率、召回率、拒答率或人工标注一致性。
- 性能:首次加载时间、热启动时间、平均延迟和 P95 延迟。
- 资源:模型大小、峰值内存、GPU 使用情况和电量影响。
- 可靠性:WebGPU 不可用、模型下载失败、上下文过长和低内存时的行为。
- 隐私:确认原始输入、调试日志和遥测数据没有越过浏览器边界。
一条务实的落地路径
可以按下面的顺序推进:
- 选择一个输入边界清晰的任务,例如文本分类、嵌入生成、敏感信息预筛选或离线搜索排序。
- 先测量云端基线,包括准确率、响应时间、成本和数据流向。
- 用较小的模型实现 WASM 回退,再用 WebGPU 优化支持设备上的热路径。
- 将模型、输入长度和设备信息写入本地评估表,用 DuckDB 查询分布,而不是只看单次演示。
- 为浏览器不支持 WebGPU、模型初始化失败和设备资源不足设计明确的降级策略。
- 经过真实设备测试后,再决定哪些请求保留在本地,哪些任务仍然交给云端。
浏览器边缘 AI 的边界也需要提前写清楚:大型模型的下载体积和内存占用可能不可接受;不同 GPU 驱动会造成结果和性能差异;客户端模型容易被观察和提取,因此不能把机密规则或高价值模型权重当作绝对安全的资产。
结语
WebGPU 提供计算通道,Transformers.js 降低模型接入成本,DuckDB 则帮助团队把本地推理变成可测量、可比较的工程系统。最可靠的采用方式不是追求“所有 AI 都在浏览器运行”,而是挑选对隐私和交互延迟最敏感、对模型规模要求相对可控的工作负载,建立基准、回退和评估机制,再逐步扩大本地执行范围。