On-device AI:端侧推理的性能与隐私权衡
- Published on
On-device AI:端侧推理的性能与隐私权衡
我第一次把模型放到手机上跑时,最先感受到的不是“AI 下沉了”,而是进度条。模型加载很慢,第一次回答要等很久,连续问几次以后手机开始发热,电量也掉得明显。服务器上的模型只要看 QPS 和显卡利用率,到了设备端,问题突然多了起来:内存够不够,芯片有没有 NPU,应用包会不会太大,后台会不会被系统杀掉,用户能不能接受这几秒钟的等待。
端侧 AI 的价值也正是在这些限制里显现出来:不必把每一句输入都发到服务器,离线时仍然能工作,交互延迟更低,服务端成本也能下降。但“数据不出设备”只是一个优点,不是完整的安全结论。设备本身可能被备份、调试、恶意软件或越权应用读取,模型也可能被反编译和滥用。
所以,端侧推理不是简单地把一个大模型文件塞进 App,而是在质量、速度、功耗、隐私和可维护性之间做一次很现实的取舍。
一、先决定哪些任务值得放到设备端
不是所有任务都适合端侧。可以先按四个问题判断:
- 是否需要低延迟?例如键盘补全、实时字幕和拍照后的即时识别。
- 是否经常离线?例如旅行翻译、设备诊断和本地笔记搜索。
- 输入是否敏感?例如私人照片、健康记录和未同步的会议内容。
- 任务是否边界清楚?例如分类、抽取、改写和固定格式生成。
如果任务需要最新的外部知识、复杂的长上下文或大规模工具调用,端侧模型可能只能做前置工作,最终仍需云端模型。比较实用的架构不是端云二选一,而是分层:
设备端小模型
├─ 低风险、短输入、离线任务 → 本地完成
├─ 问题改写、敏感信息识别 → 本地预处理
└─ 复杂推理、最新知识、高质量生成 → 脱敏后请求云端
端侧模型可以先判断问题类型和置信度。置信度低、内容太长或需要在线知识时,再把任务升级。这样既不会为了追求“全部本地”而牺牲质量,也不会把本来可以本地完成的简单请求全部发送出去。
二、先做内存预算,再谈模型大小
模型参数量只是内存的一部分。粗略估算时,权重内存可以这样算:
权重内存 ≈ 参数量 × 每个参数的字节数
例如一个 3B 参数模型使用 FP16,每个参数 2 字节,仅权重就大约需要 6GB;换成 INT4 后理论上约为 1.5GB,但实际还要加上量化元数据、运行时缓冲区、Tokenizer、KV Cache 和系统开销。
生成式模型的 KV Cache 也很容易被低估。上下文越长,Cache 越大;并发越高,占用也越多。端侧通常只有一个或少量并发,但用户长时间对话仍会推高内存。应用应该设置上下文上限,并在达到阈值时做摘要、截断或重新开始,而不是无限把历史对话拼进去。
const MAX_CONTEXT_TOKENS = 4096
const MAX_MEMORY_MB = 1800
function fitContext(messages: Message[]) {
const selected = takeLatest(messages, MAX_CONTEXT_TOKENS)
return summarizeIfNeeded(selected, MAX_MEMORY_MB)
}
在低内存设备上,模型加载失败不应该直接让整个功能崩溃。可以根据设备能力选择模型档位:高端设备使用更大模型,普通设备使用量化小模型,内存不足时退回云端或关闭本地生成。
三、量化不是免费午餐
端侧部署通常离不开量化。FP16 质量较好,但占用大;INT8 更容易保持效果;INT4 节省内存明显,但对某些任务的影响会更大。选择时要在目标设备上比较,而不是只看模型仓库里的文件大小。
量化前后至少要评测:
- 任务准确率和结构化输出成功率;
- 长文本和中文输入质量;
- 首 Token 延迟和每秒生成 Token;
- 峰值内存和模型加载时间;
- 连续运行时的温度和耗电;
- 不同芯片、不同系统版本的稳定性。
尤其要注意“平均质量没变,但边界样本坏了”。一个文本分类模型量化后总体准确率只下降 0.5%,并不代表它安全;如果少数的高风险类别从 95% 掉到 80%,用户依然会遇到明显问题。
量化策略也要结合硬件。某些芯片对 INT8 有专门加速,另一些设备对 FP16 更友好。模型转换为 Core ML、TensorFlow Lite、ONNX Runtime、ExecuTorch 或其他格式后,还可能发生算子不支持、回退 CPU 和精度变化。最终结果要以真实设备上的端到端测试为准。
四、推理优化的第一目标是减少等待
用户感受到的不是总耗时,而是“什么时候开始有反馈”。因此可以拆开三个指标:
启动耗时:打开模型到可以接受请求
首 Token 延迟:提交问题到出现第一个结果
生成速度:后续每秒生成多少 Token
模型可以在应用启动后延迟加载,避免每次打开页面都阻塞;也可以在用户进入相关功能时预热。对于流式输出,先返回可解释的状态和首批 Token,用户会比盯着空白屏幕更有耐心。
不过,流式输出不能掩盖总耗时和质量问题。如果模型第一个词很快出现,后面每个词都要等很久,体验依然糟糕。端侧应该记录启动、首 Token、完成时间和取消率,分别优化。
另外,别忘了系统的热设计功耗。连续生成会让 CPU/GPU/NPU 长时间工作,设备降频以后,前几次很快,后几次变慢。性能测试至少要包含连续十次或更长时间的任务,而不是只跑一次“冷启动”样本。
五、端侧隐私强,但不是天然安全
把数据留在本地可以减少传输和云端留存,但仍然要考虑:
- 应用日志是否记录了原始问题和模型输出?
- 崩溃报告是否把 Prompt 或本地文档上传了?
- 本地数据库和缓存是否加密?
- 应用备份是否包含模型上下文?
- 其他 App 或调试工具能否读取临时文件?
- 用户删除对话后,索引和缓存是否真的清理?
隐私设计要覆盖“本地数据的生命周期”。比如本地笔记搜索可以使用向量索引,但索引文件同样属于用户数据;模型回答暂存在内存里,也不能随意写入普通日志。
如果端云协同,上传前要明确数据策略:本地先做实体识别和脱敏,云端只接收完成任务所需的最小内容;网络恢复后同步也要经过用户授权,不能因为“之前同意过 AI 功能”就默认上传所有离线数据。
六、模型文件也需要保护
端侧模型通常会随着应用分发到用户设备,这意味着模型权重可能被提取。对于通用能力,这也许是可以接受的;对于包含企业私有知识或专有能力的模型,就要谨慎。不要把密钥、内部 Prompt 或高价值业务规则硬编码进客户端,以为做一次混淆就安全了。
模型签名和完整性校验比“隐藏文件名”更有意义:
async function loadModel(packageFile: File) {
const manifest = await readManifest(packageFile)
if (!verifySignature(manifest, trustedPublicKey)) {
throw new Error('模型签名校验失败')
}
if (manifest.minAppVersion > currentAppVersion) {
throw new Error('模型与当前应用版本不兼容')
}
return runtime.load(packageFile)
}
模型更新也要支持分批、断点续传、版本回滚和空间检查。用户可能在网络很差、存储空间不足或电量很低时收到更新任务,不能假设设备永远在线且资源充足。
七、端云路由需要可解释
当系统决定把请求发到云端时,最好能知道为什么:本地模型置信度低、上下文过长、任务需要在线知识,还是设备资源不足。路由原因既帮助调试,也让产品能向用户解释数据边界。
type RouteDecision = {
target: 'device' | 'cloud' | 'human'
reason:
| 'high_confidence'
| 'needs_online_knowledge'
| 'device_resource_limit'
| 'high_risk'
}
高风险任务不能只看模型置信度。涉及支付、账户权限、医疗建议和公开发布的操作,即使端侧模型很有把握,也应该增加确认或人工审核。端侧只是部署位置,不会自动改变任务风险。
八、我建议用一张设备矩阵收尾
上线前建立设备矩阵,把真实目标写出来:
| 设备档位 | 可用内存 | 模型 | 目标首 Token | 降级策略 |
|---|---|---|---|---|
| 高端设备 | 8GB 以上 | 4B INT4 | 1 秒内 | 失败时云端 |
| 主流设备 | 4GB 左右 | 1B INT8 | 2 秒内 | 切换更小模型 |
| 低端设备 | 2GB 左右 | 分类/抽取模型 | 500ms 内 | 仅保留规则能力 |
这张表不需要一开始就很精确,但它迫使团队面对真实问题:支持哪些用户,最差体验是什么,什么时候放弃端侧,云端成本会增加多少。没有设备矩阵,所谓“支持移动端”通常只是开发机上的一句话。
总结:端侧 AI 的价值来自克制
端侧推理给了我们一条很有吸引力的路:更快的反馈、更少的数据传输、离线也能工作,还能降低一部分云端成本。但它要求我们克制,不要把一个并不适合设备的巨型模型硬塞进去,也不要把“本地运行”误认为“绝对安全”。
真正成熟的方案通常是分层的:简单任务在设备端完成,复杂任务升级到云端;模型根据设备能力选择档位;量化和蒸馏用真实数据验证;上下文、缓存、日志和备份都纳入隐私生命周期;模型更新可以失败、恢复和回滚。
我最后留下的判断标准很简单:用户关掉网络以后,功能是否仍然有价值;设备发热和耗电时,体验是否还能接受;用户问“我的数据去哪了”时,团队能不能用一句明白的话回答。端侧 AI 不是把服务器搬进手机,而是重新学习怎样在有限资源里,把一件事情做得足够好、足够快,也足够尊重用户。