如何在 Android 中实现智能回复(Smart Reply)功能?

解读

面试官问“如何实现智能回复”,并不是想听“调个 MLKit 接口就行”。他要的是:

  1. 你对端侧 AI 推理链路(数据→模型→推理→缓存→UI)在 Android 上的落地有完整认知;
  2. 你清楚国内“GMS 不可用”的现实,能给出可上线的国产化方案;
  3. 你知道在主线程 16 ms、隐私合规、后台耗电、多语言分词、敏感词过滤等约束下,如何保障体验与合规。
    因此,回答必须体现“模型选型-推理框架-工程化-业务封装-性能优化-合规兜底”六层闭环。

知识点

  1. 场景定义:即时通讯、通知、输入法三类入口,触发时机为“新消息到达”与“用户拉起面板”。
  2. 模型侧:
    • 通用英文模型:TensorFlow Lite 官方 SmartReply 平均 0.7 MB,top-3 召回 90%+;
    • 中文模型需自训练:采用 ALBERT-tiny + 字级 Tokenizer,用 300 万条社交语料蒸馏,量化后 1.1 MB,推理 20 ms(Pixel 6 CPU)。
  3. 推理框架:
    • GMS 可用:MLKit SmartReply 一键调用;
    • GMS 不可用:TensorFlow Lite + Google Play Service-less Task API,或华为 HMS ML Kit 智能回复;
    • 自研:TFLite + NNAPI Delegate,GPU/Hexagon/NPU 自动 fallback。
  4. 工程化:
    • 数据管道:NotificationListenerService 抓取消息→脱敏→分句→正则清洗→敏感词树过滤;
    • 缓存策略:LRU 缓存最近 20 条会话,Hash 去重,避免重复推理;
    • 线程模型:WorkManager 触发后台任务→Coroutine(Default) 推理→withContext(Main) 刷新 RecyclerView;
    • 内存:模型 mmap 加载,Interpreter 单例,输入 Tensor 复用 DirectBuffer,防止 GC 抖动。
  5. 业务封装:
    • Repository 层暴露 Flow<List<SmartReply>>,UI 层纯观察;
    • 支持“不感兴趣”负反馈,点击后写入 DataStore,用于联邦学习增量训练。
  6. 性能与合规:
    • 耗时:CPU 推理 ≤25 ms,端到端 ≤120 ms(含 I/O);
    • 耗电:后台每日 ≤30 mAh(通过 Battery Historian 验证);
    • 隐私:模型与字典本地部署,不上云;敏感词实时替换“***”;提供开关供用户关闭,满足《个人信息保护法》第 13 条最小必要原则。

答案

“国内项目落地时,我采用‘端侧轻量模型 + TFLite + 自研缓存’的三段式方案。
第一步,数据层:在 NotificationListenerService 中监听新消息,先通过正则与敏感词 DFA 树做脱敏,再把最近 5 轮对话拼成 64 字以内字符串,作为模型输入。
第二步,推理层:把自蒸馏的 ALBERT-tiny 中文模型(1.1 MB,INT8)放在 assets/ml/,首次启动时拷贝到私有目录并 mmap 加载;Interpreter 采用单例 + NNAPI Delegate,输入 Tensor 复用 1×128 的 Int32 DirectBuffer,避免频繁 new。推理放在 Dispatchers.Default,通过 suspendCancellableCoroutine 把结果回调到主线程,单次耗时 18 ms。
第三步,业务层:用 Room 缓存最近 20 条历史,Hash 去重;Repository 暴露 Flow<List<SmartReply>>,UI 层用 Jetpack Compose LazyRow 展示 3 个候选;点击后通过 EventBus 把回复文本写回输入框,同时记录负反馈到 DataStore,供后续联邦学习。
性能方面,在 Pixel 6 上连续 100 次推理,CPU 占用 ≤8%,内存抖动 0 次,后台 24 h 耗电 22 mAh;合规方面,模型本地运行,不上传任何明文,提供‘智能回复’开关,默认关闭,符合国内隐私合规要求。上线后,用户点击率 34%,人均输入减少 1.7 次,五星评论提升 2.3%。”

拓展思考

  1. 折叠屏/多窗口场景:如何根据屏幕宽度动态调整候选条数,避免 LazyRow 占用过多垂直空间?
  2. 多语言混输:中文+Emoji+英文缩写,需自定义 SentencePiece 词表,如何保持模型体积不膨胀?
  3. 端云协同:当本地置信度 <0.6 时,是否走云端大模型?如何在弱网、高延迟、用户关闭网络等情况下优雅降级?
  4. 联邦学习:如何基于 Android 的 Privacy Sandbox / Federated Compute 框架,做到“数据不出端、模型能更新”?
  5. A/B 实验:针对国内各大厂商 ROM(小米、华为、OPPO)后台杀进程策略差异,如何确保推理任务在 Doze 与 App Standby 下依旧完成?