公司动态

从 expect/actual 到端侧大模型:KMP Shared Module 调用本地 AI 的握手实录

📅 2026/7/18 16:38:04
从 expect/actual 到端侧大模型:KMP Shared Module 调用本地 AI 的握手实录
在 KMPKotlin 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): FlowString fun currentThermalState(): ThermalState }Android 端通过 JNI 调 llama.cppiOS 端通过 Kotlin/Native cinterop 生成绑定均用actual实现上述契约。同理对于 Gemini Nano可定义LocalAgentEngine接口由androidMain接入 AICorePrivate Compute Core 沙箱。二、cinterop 桥接 llama.cppKotlin/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 共享层仅持AgentRequestandroidMain将其映射为 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_Mperplexity 增量仅 0.3–0.5旗舰机可上 Q5_K_S。NNAPI 陷阱中端骁龙开启 NNAPI 可能因驱动开销反降级需逐设备 benchmark 并保 CPU 回退。五、落地范例参考MineGPT 将 llama.cpp 交互、对话管理全置于sharedCMP 驱动 Android/Desktop UI印证“一套代码多端离线 Agent”。OfflineAI-KMP 则统一 Android/iOS 推理栈支持 LiteRT-LM 与工具调用。综上KMP Shared Module 调用本地 AI 的“握手” expect/actual 隔离 cinterop/JNI 桥接 mmap/thermal/沙箱隐私约束让同一份 Kotlin 业务逻辑安全驱动端侧大模型。