跳到主要内容

端侧 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 二进制文件捆绑,变体就是随包发布的那个,发布状态是“所有安装此版本的人”,而回退机制则是“功能崩溃”。每一个默认选择都会在以后造成伤害。

OTA 模型交付是与应用二进制文件交付分离的独立通道

将模型与应用二进制文件耦合是当今端侧 AI 领域中最大的非受迫性失误。模型的更新频率与 UI 代码不同。它们具有不同的尺寸特征(通常为数百 MB,有时甚至超过 1 GB)。它们需要与应用回滚截然不同的回滚语义——通过推送旧的应用二进制文件来修复一个糟糕的模型,意味着要降级在此期间发布的所有其他改进。

正确的形态是一个类似于 CDN 且具备模型感知语义的交付通道。应用启动后,向清单服务(manifest service)查询其设备类别应运行哪个变体,下载(或验证已拥有)该产物并运行。模型是基于内容寻址的,因此指向相同变体的两个应用版本会共享同一个下载文件。发布可以独立于应用发布阶段性进行——你可以将 5% 的旗舰机用户迁移到变体 N+1,而应用版本保持完全不变。回滚也是即时的:修改清单,设备在下次启动时就会获取前一个产物的哈希值。

无论是 Android 的 A/B 分区系统,还是各种商业 OTA 工具(如 Flutter 的 Shorebird、React Native 生态的热更新工具、Capgo 等),都已经证明了平台支持解耦二进制交付的“机制”。应用商店的政策也越来越宽松:只要模型产物不以需要审核的方式改变应用行为,通过 OTA 发送通常是没有问题的。阻碍因素很少来自平台,更多是因为团队还没有在底层之上构建清单基础设施。

大多数团队都会忽略的一个实用硬化细节:OTA 通道需要由健康信号触发的“自动”回滚,而不仅仅是手动回滚。如果在一个小时的发布过程中,一个新变体将 P95 推理延迟从 800 毫秒推高到了 4 秒,那么清单应该在无需人工干预的情况下自动回退。用于应用代码的生产级 OTA 系统已经吸取了这一教训;而用于“模型”的生产级 OTA 系统通常还没有,因为那些将模型视为静态资产的团队从一开始就没有构建自动回退机制。

分组遥测是那不可见的 80%

运行端侧模型机群所需的遥测数据并非你现有的那些。服务端 AI 为你提供完整的请求日志、完整的提示词和响应、延迟、成本、错误代码——所有这些都集中在一个地方。端侧 AI 几乎不会免费提供这些。你需要为此进行设计。

最有用的最小集合包括:

  • 推理延迟,并与设备类别关联。 不仅仅是全局的 P50/P95——而是“每个设备类别”的 P95。因为旗舰机分组的性能退化与长尾设备的分组退化是完全不同的 Bug,全局 P95 会将其中一个掩盖在另一个之下。这意味着事件需要携带设备类别标识符(或至少是芯片组和内存层级),并且分析后端必须愿意基于这些维度进行切片。
  • 推理质量信号。 这是最难的一点。端侧模型无法通过你在 CI 中运行的相同评估准则进行观察;你必须将质量观察带到推理发生的地方。隐性信号(用户重述率、放弃率、后续编辑)通常是唯一可以大规模获取的数据,但它们需要被收集并关联到模型变体和设备类别。显性信号(点赞/点踩)只有在频率足够高、能在用户流失前检测到性能退化时才有用。
  • 资源影响。 归因于推理的电池损耗、触发的热事件、由于模型加载导致的 OOM(内存溢出)中止。操作系统会提供大部分此类信息,但你必须主动去请求。旗舰机分组比中端机分组快两倍是可以接受的;但如果旗舰机分组快两倍的同时还多消耗了三分之一的电量,这就是你需要了解的问题。
  • 变体归因。 每个事件都必须携带产生它的变体哈希值,因为拥有多个变体的全部意义在于检测哪些变体是有效的。如果不标记变体,无论事件流多么丰富,都无法用于变体对比。

如果你已经构建好了这些遥测数据,你就能回答这个区分“运营机群”与“发布模型”的核心问题:“与变体 N 相比,变体 N+1 在各个设备类别上的表现是变好、变差还是保持不变?”如果你无法快速回答这个问题,那么你拥有的不是一个机群——你只是拥有一个产物和一份运气。

组织失效模式:模型是别人的问题

这种失败模式在各家公司中都表现得极其稳定。移动团队将模型视为捆绑资产——他们发布一次,不负责其质量,并假设模型团队会告诉他们何时更新。模型团队将设备群视为部署基座——他们训练了模型,在几个参考设备上验证了它,并假设移动团队负责处理长尾设备。由于双方都不认为清单是自己的问题,因此没有团队负责维护机群清单。

六个月后,一次客户支持升级揭示了端侧 AI 功能在 Pixel 6a 上的表现明显差于 Pixel 8 Pro。没有人能说清这是量化问题、内存压力问题还是发热问题,因为没有人收集过能够区分这些问题的遥测数据。管理层提议的修复方案——“发布一个更好的模型”——无济于事,因为失败不在于模型产物本身,而在于缺乏那种能将正确的产物路由到正确设备类别的规范。

必须达成的组织认知重构是:交付端侧 AI 是一项“机群运营(fleet operations)”职责,而不是建模职责或移动工程职责。它需要一个明确的负责人、一个版本控制下的清单、一个按层级产出证据的变体流水线、一个与应用二进制解耦的 OTA 通道,以及分组遥测。为此配备人员的团队看起来更像基础设施团队而非 ML 团队;而不为此配备人员的团队,往往会在陷入需要该角色的值班轮换(on-call rotation)时,才发现这个角色的存在。

端侧 AI 是一个挂载了模型的 CDN 问题

这种闭环的架构认知在于:端侧 AI 的难点不在于模型本身 —— 而在于分设备的交付、分群组的可观测性,以及证明系统运行正常的流转回退通道。前沿模型团队多年来致力于建立一套将 Checkpoints 转化为产品的工程规范。端侧 AI 几乎没有继承这些规范,因为其部署基座(庞大的长尾手机机群)并不是那些前沿模型工具所针对的设计目标。

到 2027 年,做对这件事的团队看起来将不再像 ML 组织,而更像那种面向数十亿设备进行交付的平台工程组织:拥有配置清单服务(manifest service)、变体流水线(variant pipeline)、CDN 式的交付通道、全机群遥测系统,以及一小群以分析群组性能回退为生的工程师。而那些没做对的团队将继续只是交付模型,并寄希望于真实机群的表现能和测试手机一样。

模型是产物。机群才是产品。请你区别对待它们。

References:Let's stay in touch and Follow me for more thoughts and updates