如何设计一个混合 AI 架构,在离线时降级、在线时增强?

解读

面试官想确认三件事:

  1. 能否把“AI 能力”拆成可离线、可在线的两段,而不是简单地把模型搬到端侧;
  2. 能否用 Android 原生机制(AAR 体积、ABI 过滤、动态下发、权限、电量、隐私)把“降级-增强”做得对用户无感;
  3. 能否在工程层面给出可落地的灰度、回滚、容灾方案,而不是只谈算法。

国内场景还要额外踩坑:GMS 缺失、厂商 ROM 对后台限制各异、用户常年关自启动、工信部 164 号文对“强行更新”的处罚,以及国内商店对 AAB 的伪支持。回答必须体现“国内合规 + 端智能 + 云增强”三位一体。

知识点

  1. 端侧推理框架:TensorFlow Lite、MNN、NCNN、Paddle Lite、TVM Runtime,量化方式(INT8、FP16、Weight-only),Android NNAPI 与厂商 NPU SDK(HiAI、SNPE、NeuroPilot)。
  2. 模型热更新:Google Play Feature Delivery 在国内不可用,改用自研“插件化 + 差分补丁”或 Tinker/Shadow,把 .tflite 当普通 asset 做 bsdiff,下载后放私有目录,绕过 SplitCompat。
  3. 运行时决策:NetworkCallback + ConnectivityManager 判断“Wi-Fi / 5G / 计费网络”,Settings.Global 读取“低电量模式”,WorkManager 做网络约束任务,防止厂商杀后台。
  4. 降级策略:
    离线模型只做“粗粒度”输出(例如 50 类意图),云端做千级别细分类;
    当模型版本低于阈值或 CPU 占用 >40% 时,直接走规则引擎;
    使用 TFLite 的 fallback 路径:GPU Delegate 失败 → NNAPI → CPU。
  5. 增强策略:
    上传加密特征(非原始数据),云端返回 Logits 或蒸馏后的软标签,端侧再做二次融合;
    对折叠屏/平板,利用大屏缓存多帧,上传 batch 推理,减少 30% 云调用;
    引入联邦学习:每天闲时(0-6 点)上传梯度,云端聚合后次日下发新权重,用户数据不出域。
  6. 隐私合规:
    端侧推理属于“本地加工”,无需额外弹窗;
    上传特征需双重匿名(随机 UID + 差分隐私噪声),并在《隐私政策》中单独章节说明;
    提供“仅本地模式”开关,写入 SharedPreferences,下次启动直接跳过云增强。
  7. 性能与功耗:
    使用 Android 12 新 API ThermalService,温度档≥MODERATE 时关闭 GPU Delegate;
    通过 Battery Historian 验证:离线模型单次推理 <7 ms、内存 <35 MB、云调用日均 ≤12 次;
    APK 体积控制:把 8-bit 量化模型放 assets,首次安装 <80 MB,后续按模块动态下发。
  8. 灰度与回滚:
    云侧采用“配置中心 + 用户分桶”方式,把模型版本号、阈值、开关做成 JSON,通过 MQTT/HTTP 长连接秒级生效;
    端侧记录推理耗时与异常码,回传至 Sentry+Prometheus,P99 耗时上涨 15% 或崩溃率 >0.3% 自动回滚到上一版离线模型。

答案

整体采用“端云协同、三层决策”的混合架构:

  1. 能力分层
    ① 离线最小可用模型:INT8 量化、<30 MB、仅覆盖核心场景(如扫码识物、语音唤醒),放在 assets 随包发布;
    ② 在线增强模型:FP16、>100 MB、覆盖长尾场景,通过“差分补丁 + LZ4 压缩”动态下发到私有目录;
    ③ 规则兜底:当模型加载失败、系统剩余内存 <200 MB、或用户关闭“云增强”开关时,走传统 if-else 规则。

  2. 决策引擎
    在 Application.onCreate 阶段初始化 DecisionEngine,输入三维信号:

    • 网络质量:NetworkCallback 判断是否为“Wi-Fi 且非计费网络”,延迟 <100 ms;
    • 系统状态:ThermalService + BatteryManager 判断温度与电量,低于 15% 直接降级;
    • 业务场景:扫码页面生命周期在前台且摄像头已打开,优先端侧;聊天页面输入框触发 AI 助手,允许走云端。
      输出枚举:LOCAL_ONLY、CLOUD_ONLY、FUSION。
  3. 端侧推理
    使用 TFLite 2.x + GPU Delegate + NNAPI,模型文件以 MappedByteBuffer 方式 mmapped,减少 1 次拷贝;
    推理线程绑定大核,采用 HandlerThread + Looper 模型,防止 UI 线程被抢占;
    结果缓存到 LruCache<String, SoftReference<float[]>>,key 为输入特征 MD5,5 分钟内复用。

  4. 云侧增强
    特征经 TEE 加密后上传,云端返回 Top-K Logits 与置信度;
    端侧再做加权融合:若云端置信度 >0.85 且与端侧差值 >0.2,采纳云端结果,否则保留端侧;
    采用“请求去重”:同一用户 10 分钟内相同特征不再上传,节省 40% 流量。

  5. 更新与回滚
    模型版本号写入 build.gradle 的 resValue,云配置中心同步;
    补丁包通过 MD5 + 签名验证,失败即删除并回退到 assets 内置模型;
    灰度按国内渠道号(华为、应用宝、小米、OPPO)+ 用户尾号 2 位分桶,支持实时关闭。

  6. 合规与体验
    首次弹窗《智能增强功能协议》,提供“仅本地模式”一键关闭;
    上传数据采用国密 SM4 加密,密钥存 Keystore,AES-GCM 随机 IV,每次会话轮换;
    在设置页增加“AI 增强耗电”图表,用 Battery Historian 数据可视化,提升用户信任。

拓展思考

  1. 当折叠屏手机展开后,多窗口同时调用 AI 能力,如何防止 GPU 抢占导致卡顿?
    可引入“分时令牌”机制:系统层维护 GPU token,每个进程按优先级排队,超时 100 ms 强制释放。

  2. 如果未来车载 Android(AAOS)也要复用同一套架构,车规级芯片(如高通 8155)NPU 驱动版本碎片化严重,如何一次编译多处运行?
    采用 TVM + Relay 做统一 IR,后端生成 .so + .cl 混合包,运行时根据 /vendor/lib/egl 库名动态加载对应 codegen,把“离线模型”做成芯片级 HAL 插件,与 Android 版本解耦。

  3. 国内鸿蒙 NEXT 不再兼容 APK,而鸿蒙 AI 框架 MindSpore Lite 的算子集与 TFLite 不完全对齐,如何最小成本迁移?
    在编译期用 ONNX 做中间表达,通过自写“算子映射表”把 TFLite 自定义算子转 MindSpore 算子,无法映射的走 fallback CPU 实现;同时把 DecisionEngine 抽成 Kotlin Multiplatform 模块,鸿蒙侧仅重写网络状态与存储适配层,业务逻辑 0 改动。