从 expect/actual 到端侧大模型:KMP Shared Module 调用本地 AI 的握手实录
在 KMP(Kotlin Multiplatform)架构中,shared模块的公共代码(commonMain)本不依赖平台,但要调用本地大模型(如 llama.cpp 或 Gemini Nano),必须通过expect/actual 契约与cinterop/JNI 桥接实现“握手”。本文结合生产实践,梳理从接口声明到隐私敏感功能设计的完整链路。
一、expect/actual:屏蔽平台差异的契约层
在commonMain中声明与平台无关的推理接口,使业务层完全不感知原生引擎:
// commonMain expect class LlmEngine { fun loadModel(path: String, config: ModelConfig): Boolean fun generate(prompt: String, params: GenerationParams): Flow<String> fun currentThermalState(): ThermalState }Android 端通过 JNI 调 llama.cpp,iOS 端通过 Kotlin/Native cinterop 生成绑定,均用actual实现上述契约。同理,对于 Gemini Nano,可定义LocalAgentEngine接口,由androidMain接入 AICore(Private Compute Core 沙箱)。
二、cinterop 桥接 llama.cpp:Kotlin/Native 与 C++ 的握手
- 绑定配置:在
nativeInterop/cinterop/llama.def指定头文件与链接库,构建期生成.klib。 - mmap 安全加载:Q4_K_M 量化的 3B 模型约 1.8–2.0 GB,必须采用内存映射避免堆内分配导致 OOM 杀进程。
- 自适应 thermal 节流:持续推理 60–90s 后 token 速率可降 40–60%,需监听
PowerManager.THERMAL_STATUS_*(Android)并动态限流。
when (currentThermalState()) { ThermalState.NOMINAL -> params.copy(throttleMs = 0) ThermalState.SERIOUS -> params.copy(throttleMs = 50, nPredict = 128) ThermalState.CRITICAL -> suspendGeneration() }三、Gemini Nano 的隐私敏感设计
Gemini Nano 通过 Android AICore 在Private Compute Core隔离执行,输入不联网、权重由 Titan M2 加密。KMP 共享层仅持AgentRequest,androidMain将其映射为 AICore 会话:
// androidMain: AndroidAgentEngine val config = SessionConfig.Builder() .setModelType(SessionConfig.MODEL_TYPE_GEMINI_NANO_2) .setTemperature(request.temperature).build() val session = aiCoreManager!!.createSession(config) // 沙箱内 session.executeGenerateStream(params) // 本地 NPU 推理该设计使敏感数据零出境,契合 GDPR/HIPAA[前文 Gemini Nano 隐私基座]。
四、结构化输出与工程避坑
- GBNF 约束:用 llama.cpp 的 GBNF 语法强制 JSON 输出,在
commonMain用kotlinx.serialization解析,消除重试。 - 量化默认 Q4_K_M:perplexity 增量仅 0.3–0.5,旗舰机可上 Q5_K_S。
- NNAPI 陷阱:中端骁龙开启 NNAPI 可能因驱动开销反降级,需逐设备 benchmark 并保 CPU 回退。
五、落地范例参考
MineGPT 将 llama.cpp 交互、对话管理全置于shared,CMP 驱动 Android/Desktop UI,印证“一套代码多端离线 Agent”。OfflineAI-KMP 则统一 Android/iOS 推理栈,支持 LiteRT-LM 与工具调用。
综上,KMP Shared Module 调用本地 AI 的“握手” =expect/actual 隔离 + cinterop/JNI 桥接 + mmap/thermal/沙箱隐私约束,让同一份 Kotlin 业务逻辑安全驱动端侧大模型。
