用 ONNX Runtime 在浏览器里跑 AI 模型
用 ONNX Runtime 在浏览器里跑 AI 模型
多年来"浏览器里的 AI"听起来像玩具 demo:MNIST 上的一个微型分类器、或一段把笔记本熔化的风格迁移。直到 ONNX Runtime Web 成熟、WebGPU/WebGL 路径对真实图像负载足够可靠,这件事才变了样。在 Ai2Done,我们用 ONNX 驱动的模型做增强、分割这类端侧功能——因为把用户照片发到远程 GPU 与我们所代表的一切相悖。
为什么偏偏选 ONNX
ONNX 格式把模型作者与部署解耦。研究者用 PyTorch 或其它框架训练、导出为 ONNX,我们只消费一份制品,ONNX Runtime 就能为不同执行后端做优化。在浏览器里,这意味着我们能在可用时瞄准 WebGPU,不可用时优雅回退。
概念上,推理循环长这样:
// 伪代码:加载会话、喂张量、读输出张量
const session = await ort.InferenceSession.create("/models/segmentation.onnx");
const feeds = { input: inputTensor };
const results = await session.run(feeds);
const mask = results.output; // 交给 canvas / WASM 胶水
我们栈中的 Go 与 WASM 层 保持纤薄:搬运字节、暴露进度、把业务规则留在 internal/apps/ai2done/tool 中——而不是塞进模型运行时。
内存、张量与诚实
神经网络很吃资源。一个错误假设——在五年前的笔记本上加载"全分辨率一切"的模型——会造成标签页崩溃和愤怒的用户。我们的应对:
- 模型量化(画质允许时)
- 渐进加载(让 UI 保持响应)
- 明确上限(带用户可见的提示)
这与我们对 PDF 和视频 WASM 的哲学一致:尊重浏览器限制,而不是假装 Web 是个数据中心。
隐私作为技术保证
推理在本地跑时,隐私故事自己就成立。你的图像不会为了增强而落到我们的硬盘——不是因为我们在 banner 里温柔承诺,而是该操作在架构上根本不存在上传路径。这种差别对受监管环境和"不愿把度假照交给陌生人 GPU"的人都重要。
Go 在哪里发挥作用
我们仍喜欢用 Go 做编排、静态托管、嵌入 WASM 包。心智模型很干净:Go 发应用、JS 桥接 ONNX、WASM 承担确定性变换——当与服务端共享代码有价值时尤甚。DDD 边界让每一层都诚实:领域逻辑放 tool/,服务协调请求,模板里不"耍小聪明"。
调试真实世界的漂移
模型在不同设备上表现不同:色彩配置、WebGPU 可用性、浮点小怪都会让输出微妙偏移。我们在代表性输入上投入金标准文件测试,并采用零埋点的用户反馈(字面意义上:"报告问题"按钮,不外送像素)来捕获边角情况。
展望
随着浏览器暴露更多性能、模型变得更小,端侧 ML 会持续进步。Ai2Done 会不把你的媒体变成别人训练数据的前提下继续乘风而行。如果你是在评估浏览器 ONNX 的工程师,我们的建议很简单:把内存与回退作为一等需求,你的用户会感到不同。