端侧 AI 的全景图:WASM、WebGPU 和 ONNX 的三角关系的深度剖析
端侧 AI 的全景图WASM、WebGPU 和 ONNX 的三角关系的深度剖析一、为什么 AI 必须走出云端去年我在做一个离线翻译工具的需求调研时发现了一个有意思的数据一款流行浏览器翻译插件的日活有 300 万其中 60% 的网络请求被云端的翻译 API 消耗。这 60% 里有至少 40% 是完全可以本地处理的短文本翻译。三个趋势在推动 AI 从云端走向端侧延迟限制——实时视频会议的字幕翻译往返云端 200ms 根本不可接受数据隐私——企业内部的文档摘要不可能把内容发给第三方 API离线场景——飞机上、地下车库、农村地区——没信号就没 AI。而端侧 AI 的落地依赖于三个技术的协作WASM容器、WebGPU加速器、ONNX模型格式。这篇文章会厘清这个三角关系并给出实际可用的技术选型框架。二、ONNX跨框架的模型交换格式ONNXOpen Neural Network Exchange解决的是模型格式碎片化的问题。PyTorch、TensorFlow、JAX 各有各的模型格式ONNX 提供了一个中间表示层让一个模型可以被多个推理引擎消费。# Python 端导出 ONNX 模型 import torch import torch.onnx # 定义一个简单的分类模型 class TextClassifier(torch.nn.Module): def __init__(self, vocab_size: int, embed_dim: int, num_classes: int): super().__init__() self.embedding torch.nn.Embedding(vocab_size, embed_dim) self.fc torch.nn.Linear(embed_dim, num_classes) def forward(self, input_ids): # 简单的嵌入 线性分类示例用实际用 BERT 更复杂 x self.embedding(input_ids).mean(dim1) # 均值池化 return torch.softmax(self.fc(x), dim-1) model TextClassifier(vocab_size30000, embed_dim128, num_classes10) model.eval() # 导出为 ONNX 格式 dummy_input torch.randint(0, 30000, (1, 32)) # batch1, seq_len32 torch.onnx.export( model, dummy_input, text_classifier.onnx, input_names[input_ids], output_names[probs], dynamic_axes{ input_ids: {0: batch_size, 1: seq_len}, probs: {0: batch_size}, }, opset_version14, ) print(模型已导出为 text_classifier.onnx)ONNX 选型时注意两个关键点opset version 兼容性——不是所有 ONNX Runtime 都支持最新的 opset。端侧一般用 opset 12-14浏览器端 onnxruntime-web 对 opset 的兼容最好量化——FP32 模型在浏览器里跑不动的。导出时必须做 INT8 量化内存占用能减到 1/4推理速度提升 2-3 倍。三、WASM浏览器的通用运行时WASM 解决了浏览器能不能跑原生代码的问题。Rust 通过wasm-pack编译到 WASM再通过 JavaScript 加载调用。但对于 AI 推理WASM 有天然的短板——纯 CPU 计算、SIMD 支持有限、不能直接访问 GPU。// 用 wasm-bindgen 暴露 Rust 函数给 JavaScript 调用 use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; /// 在 Web Worker 中运行推理任务 /// 避免阻塞主线程导致页面卡顿 #[wasm_bindgen] pub async fn run_inference_in_worker( model_url: str, input_data: [f32], ) - ResultJsValue, JsValue { // 创建 Web Worker 实例 let worker web_sys::Worker::new(./inference_worker.js) .map_err(|e| JsValue::from_str(format!(创建 Worker 失败: {:?}, e)))?; // 在 Worker 中执行推理——不阻塞主线程 let promise js_sys::Promise::new(mut |resolve, _reject| { // 向 Worker 发送数据和回调 let _ worker.post_message(JsValue::from_str(start_inference)); resolve.call1(JsValue::null(), JsValue::from_str(inference_done)).unwrap(); }); JsFuture::from(promise).await }WASM 的定位是浏览器里跑逻辑的最低门槛方案。适合轻量级模型 50MB、低频推理用户手动触发而非实时、不要求极致性能的场景。四、WebGPU端侧 GPU 推理的答案WebGPU 是三角关系里最重要的角色——它让浏览器以近原生性能访问 GPU。和 WebGL 不同WebGPU 是为计算而非渲染设计的天然适合矩阵运算。// 使用 burn-rs 的 WASM WebGPU 后端 // burn-rs 抽象了 WASM 和原生 GPU 的差异 use burn::tensor::Tensor; use burn::backend::wgpu::{WgpuDevice, Wgpu}; use burn::nn::{Linear, LinearConfig}; use burn::module::Module; use burn::prelude::Backend; /// 模型定义——burn-rs 的代码在后端切换时无需修改 #[derive(Module, Debug)] pub struct SimpleTextModelB: Backend { /// 线性层在 CPU / WGPU / CUDA 上都能跑 linear: LinearB, } implB: Backend SimpleTextModelB { pub fn new(device: B::Device) - Self { let linear LinearConfig::new(128, 10).init(device); Self { linear } } pub fn forward(self, input: TensorB, 2) - TensorB, 2 { // 前向传播——后端的 GPU 加速自动生效 self.linear.forward(input) } } // 后端选择 // CPU 后端开发测试用 // type MyBackend burn::backend::NdArray; // WASM 后端浏览器 CPU // type MyBackend burn::backend::Wgpuf32, i32; // WebGPU 后端浏览器 GPU——生产推荐 type MyBackend Wgpuf32, i32; // CUDA 后端原生桌面 // type MyBackend burn::backend::Cudaf32, i32;WebGPU 选型的现实判断场景是否用 WebGPU原因文本分类/Sentiment不需要计算量太小启动 GPU 的 overhead 超过收益语音识别 Whisper 小模型推荐需要大量矩阵乘法GPU 优势明显Stable Diffusion 推理必须CPU 下跑一次 30 秒 vs GPU 下 3 秒实时视频处理必须每帧都在毫秒级内处理我们的 Whisper 小模型在 WASM纯 CPU上跑一次推理要 2.1 秒切到 WebGPU 后降到 0.3 秒——快了 7 倍。但代价是 WebGPU 的初始化过程完全黑盒设备创建失败时 Chrome 只返回 validation error没有任何细节。最后靠 Google 搜到一个 GitHub issue 才知道是显存不够给了limits.maxStorageBufferBindingSize一个更小的值才通过。WebGPU 的错误信息比 WASM 差了一个数量级排查时需要大量试错建议先在小模型上跑通流程。五、总结WASM、WebGPU 和 ONNX 的三角关系可以这样理解ONNX 决定跑什么模型——它是模型格式标准解决了跨框架兼容问题WASM 决定在哪里跑——它是浏览器环境的运行时容器给了 Rust 代码进入浏览器的大门WebGPU 决定跑多快——它是端侧 GPU 加速的入口把推理速度从秒级降到十毫秒级。我给开发者的技术选型建议起步用 ONNX Runtime Web (WASM 后端)模型跑通了再评估是否值得切 WebGPU。不要一上来就踩 WebGPU 的坑——GPU buffer 管理、shader 编译错误、不同浏览器的兼容差异这些问题都会让你的开发效率腰斩。而 ONNX Runtime 的 WASM 后端只需要npm install onnxruntime-web就能开始用成本极低。端侧 AI 的真正爆发还需要一年左右——等主流浏览器对 WebGPU 的计算特性支持稳定等 ONNX 生态的工具链再成熟一些。但现在开始投入学习和实验正好能赶上第一波红利。