跳到主要内容

端侧 AI 需要的是机群管理器,而非模型卡片

· 阅读需 13 分钟
Tian Pan
Software Engineer

上一季度发布的端侧 AI 演示在单台测试手机上运行了一个 4-bit Llama 变体,表现出色。六个月后,同样的功能却收到了一连串的一星差评,用户抱怨发热、耗电,或者更糟糕的是——无声的质量下降,用户只觉得“老手机上的 AI 变傻了”。模型没变,但机群(fleet)变了。那些原本以为是在交付模型的团队后来才发现,他们交付的其实是一个机群。

这就是导致大多数端侧 AI 发布失败的鸿沟:策略是围着选择“那个”模型转,而真正的难点在于如何为每类设备交付“合适的模型”,观察其运行情况,并在出问题时回滚。弥合这一鸿沟的学科更像是 CDN 运营,而非 ML 研究——清单驱动(manifest-driven)的交付、按分群的遥测、解耦的发布渠道,以及能从一个训练好的检查点生成 N 个量化分级的模型变体流水线。大多数团队并不具备这些,他们只有一个模型卡(model card)和一个构建产物。

机群不是一台手机,而是一个群体

现代 Android 安装基数涵盖了大约 5 个 SoC 厂商、4 到 5 代 NPU 架构、3 或 4 个受支持的 OS 版本,以及至少两个内存层级——实际应用中分为 4GB、6–8GB 和 12GB+。iOS 的范围较窄但也不容忽视:活跃支持的 iPhone 机群仍涵盖 A14 到 A18,其神经网络引擎(Neural Engine)吞吐量、内存带宽和散热限制都有实质性差异。将这些因素相乘会产生数百个有意义的设备类别,这种乘法并非思想实验——从业者报告的测试矩阵通常包含 5 个 SoC × 5 个 RAM 层级 × 4 个 OS 版本,轻松超过 900 种配置。

针对不同的量化容忍度和散热余量,每种组合都有其各自的“最佳模型”。一台拥有 12GB RAM 和专用低精度计算单元的旗舰机可以轻松运行 INT4 格式的 7B 模型,有时 W4A8 变体的 8B 模型表现比 FP16 的 3B 模型更好。而一台运行旧款 NPU 且不支持低精度的 6GB 中端手机可能会退回到 CPU 执行,导致吞吐量下降 5 倍,这意味着在旗舰机上流畅运行的 4B 模型,在这些机器上读到一半就会卡顿到无法使用。4GB 设备可能根本无法运行实用的生成式模型,应该路由到云端回退或更小的专用模型——但它运行 1B 分类器完全没问题。

为所有设备交付同一模型的团队在不知道帕累托前沿(Pareto frontier)存在的情况下,盲目选择了一个点。要么是旗舰机为了运行一个小模型而浪费了本可以处理的性能,要么是长尾设备在限频、过热,并产生评估集从未捕捉到的劣质输出。

量化容忍度是基于任务的,而非基于模型的

标准的流程——以 16-bit 训练,量化为 4-bit 部署——能让你得到一个产物,但得不到部署策略。机群清单需要更细粒度的变体,因为量化质量损失在不同任务中分布并不均匀。一个对自动补全完全没问题的 INT4 模型,在代码生成任务中可能会一败涂地。一个能容忍 8-bit 权重的摘要任务,在长上下文输入下可能会因为注意力误差在 token 间累积而在 4-bit 时出现明显退化。在拥有合适硬件支持的设备上,利用 NPU 8-bit 激活路径的 W8A8 和 W4A8 方案性能可以超过纯 W4,但在缺乏该支持的设备上则不如 W4。

这对变体流水线意味着:为每种架构生成一个量化产物是不够的。流水线需要从单个训练好的检查点生成一个小型量化分级矩阵——比如 FP16、W8A8、W4A8、W4A16——并在代表性的硬件模拟器或参考设备上针对每个变体运行评估集。流水线的输出不仅是“这里有四个文件”,而是“这里有四个文件,以及一张显示每个变体在代表性设备类别上通过了哪些任务质量评估的表格”。

没有这张矩阵的团队从字面意义上讲是在盲目飞行:如果不进行生产环境实验,他们无法回答“如果我将变体 X 推送到设备类别 Y,质量会下降吗?”这个问题。大多数团队正是这么做的。他们第一次发现 INT4 破坏了工具调用(tool-calling)的可靠性,通常是当一名 Pixel 7 用户提交支持工单,而高级工程师不得不跨模型版本和设备进行二分法排查,才能找出是哪个组合导致了问题。

机群清单是真正的产物,而不是 README 中的注释

清单是将端侧 AI 作为产品交付的团队与仅交付过一次的团队之间的分水岭。它将设备类别——通常是(芯片组系列、NPU 能力层级、RAM 层级、OS 版本范围)的元组——映射到应在该类别上运行的模型变体。它包含版本号、有效日期范围和回退路径。它是独立于 App 二进制文件部署的,无需 App Store 审核周期即可更新。

清单中具体包含的内容:

  • 设备类别定义:不仅是“iPhone 15 Pro”,而是“内存 ≥8GB、NPU ≥30 TOPS、OS 支持 INT8 NPU 加速、近三年发布的设备”。任何不够具体的定义都会导致分类过于粗糙,无法进行有意义的针对性投放。
  • 变体分配:每个类别应该拉取哪个产物(通过内容哈希标识)。使用哈希而不是版本名称——版本名称会漂移,而哈希不会。
  • 发布状态:每个设备类别中当前运行新变体与旧变体的比例。这必须是可查询的,因为故障通常表现为“分群 X 的用户体验下降”,在诊断之前,你需要知道分群 X 运行的是变体 N 还是 N-1。
  • 回退路由:当端侧变体失效时(内存溢出 OOM、反复超时、NPU 不可用),请求去向何处?云端?更小的变体?还是显示优雅的 UI 禁用提示?这属于清单的内容,因为答案因设备类别而异。

令人惊讶的是,许多团队将这四点都视为理所当然。模型与 App 二进制文件捆绑,变体就是随包发布的那个,发布状态是“所有安装此版本的人”,而回退机制则是“功能崩溃”。每一个默认选择都会在以后造成伤害。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates