大模型端侧推理的前端落地:WebGPU 与 ONNX Runtime 的浏览器部署 大模型端侧推理的前端落地WebGPU 与 ONNX Runtime 的浏览器部署一、为什么把大模型塞进浏览器云端那套账算不平了去年底一个面向律师的合同审查工具上线首日就挂掉了。问题不在模型是云端推理的 P99 延迟从 800 毫秒飙到 6 秒弱网下甚至超时。客服接到的投诉是一句「点完按钮我以为死机了」。这事我见过太多团队栽进去——首字体验比模型准确率更影响留存。更麻烦的是成本账单。把大模型 API 直接暴露给前端单次会话消耗的 token 折算下来单用户月度成本比会员费还高。某 SaaS 团队复盘过一次仅一周的免费试用就吃掉两个月预算。于是端侧推理被推到台前。WebGPU 让浏览器首次拥有了接近原生的并行计算能力配合 ONNX Runtime Web 这类推理引擎量化到 INT8 的小模型完全可以在笔记本甚至手机上实时跑通。把延迟、成本、隐私这三块同时压下去收益是看得见的。但这没这么简单。端侧受限于设备内存、算力与电量。把 70B 模型塞进浏览器既不现实也无必要。适用的只是参数小、对延迟敏感、数据不宜出端的轻量任务本地翻译、文本分类、语音唤醒、轻量对话。其余的仍要留给云端。二、从模型文件到张量计算端侧推理的完整链路端侧推理的完整链路是把训练框架导出的模型转成开放格式ONNX再由浏览器推理引擎加载、用 WebGPU 后端执行。前端的核心职责是获取模型、准备输入张量、调度推理、回收资源并在不支持 WebGPU 时降级到 WASM。sequenceDiagram participant B as 浏览器前端 participant C as 模型 CDN/缓存 participant O as ORT 引擎 participant G as WebGPU 设备 B-C: 拉取 .onnx 模型(带 Range 断点续传) C--B: 返回模型权重 B-O: 初始化 Session(backend:webgpu) alt 设备支持 WebGPU O-G: 创建 GPU 计算管线 G--O: 分配显存缓冲区 else 不支持则降级 O-O: 切换 wasm 后端 end B-O: run(inputs Tensor) O-G: 提交计算着色器 G--O: 输出张量 O--B: 解析为业务结果WebGPU 之所以关键是它提供了GPUComputePass与显存缓冲区让矩阵乘法这类张量运算跑在 GPU 上吞吐远超 CPU。但浏览器里的 GPU 显存有限通常数百 MB 到数 GB模型权重与中间激活值必须精打细算。量化能把模型体积与显存占用砍掉三到四倍是端侧可行的前提。另一个常被忽略的是「预热」。WebGPU 首次创建管线涉及着色器编译可能耗数百毫秒。应在应用空闲时预先session.run一次空输入做 warmup避免用户首次使用时被卡顿吓退。三、生产级端侧推理封装缓存、超时与后端降级下面给出一个基于 ONNX Runtime Web 的端侧推理封装。它处理了生产环境三大隐患模型大文件断点续传与缓存、WebGPU 不可用时的 WASM 降级、以及推理超时保护避免低端设备上的「假死」。import * as ort from onnxruntime-web; // 带缓存与超时的模型加载大模型权重动辄数十 MB必须复用 async function loadSession(modelUrl: string): Promiseort.InferenceSession { // 优先用 Cache Storage 缓存模型避免重复下载浪费流量与等待 const cache await caches.open(ort-models); let resp await cache.match(modelUrl); if (!resp) { // 用 fetch 自带 Range 支持弱网中断可借 service worker 续传 resp await fetch(modelUrl); if (!resp.ok) throw new Error(模型下载失败: ${resp.status}); await cache.put(modelUrl, resp.clone()); } const buf await resp.arrayBuffer(); // 后端优先级WebGPU 优先失败回退 wasm保证可用性是第一原则 try { return await ort.InferenceSession.create(buf, { executionProviders: [webgpu] }); } catch { return await ort.InferenceSession.create(buf, { executionProviders: [wasm] }); } } // 带超时与取消的推理调用低端设备推理可能极慢必须设上限 async function infer( session: ort.InferenceSession, input: ort.Tensor, timeoutMs 5000 ): Promiseort.Tensor { const ctrl new AbortController(); const timer setTimeout(() ctrl.abort(), timeoutMs); try { // 用 Promise.race 包裹超时即抛错让上层降级到云端或提示 const result await Promise.race([ session.run({ input }), new Promisenever((_, rej) ctrl.signal.addEventListener(abort, () rej(new Error(端侧推理超时))) ), ]); return result.output as ort.Tensor; } finally { clearTimeout(timer); } }这段实现的三处关键第一caches把大模型缓到本地二次加载近乎瞬时第二WebGPU 初始化包在try/catch里失败自动退到 WASM把「可用性」置于「性能」之前第三Promise.raceAbortController给推理设硬超时防止低端设备无限阻塞主线程超时后上层可平滑切回云端 API。四、端侧架构的边界何时不该上浏览器端侧推理有清晰的适用边界越界反而带来灾难。第一是模型规模。通常 5 亿参数以内、INT8 量化后 200MB 的模型才适合端侧更大的模型显存放不下加载也慢得不可用。这类任务应留在云端端侧只做轻量预处理。第二是设备差异。同一套 WebGPU 代码在集显笔记本与旗舰手机上性能可能差十倍。必须做运行时能力探测与分级探测到算力不足就主动降级到 WASM 或直接云推理而不是让用户盯着转圈。某电商客户端曾因此被投诉——导购助手在中端安卓机上要等 12 秒比人工还慢。第三是更新与一致性。端侧模型缓存在用户设备模型升级后旧版本会长期滞留。需要版本号校验发现缓存模型版本不匹配就强制刷新否则会出现「同输入不同结果」的诡异问题。第四是电量与发热。持续 GPU 推理会显著耗电发热移动端长时间使用会触发降频反而变慢。应对策略是把推理做成「按需触发」而非「常驻」并在后台标签页暂停。最后是安全边界。端侧模型权重完全暴露在浏览器容易被提取逆向。若模型本身是核心资产端侧化等于公开权重这类场景必须留在服务端。五、总结端侧大模型推理用 WebGPU 与 ONNX Runtime 把部分 AI 能力下沉到浏览器换取低延迟、低成本与数据不出端。落地要点有三第一仅对小规模、低延迟、高隐私要求的任务端侧化大模型仍留云端第二生产封装必须包含模型缓存、WebGPU→WASM 降级、推理超时三道保险把可用性放在性能前面第三警惕设备差异、模型版本滞留、电量发热与权重泄露四道边界越界场景应回退云端。端云协同、按能力分级才是可持续的浏览器 AI 架构。这条路在千万级调用下能跑通回报是值得的。