当前位置: 首页 > news >正文

MiniCPM-V 多模态模型 Android APP 集成指南

MiniCPM-V 多模态模型 Android APP 集成指南本教程主要讲述的是如何将 MiniCPM-V 系列多模态模型图文/视频理解集成到你自己的 Android App原始项目地址https://github.com/OpenBMB/MiniCPM-V-Apps1. 前置条件为了避免出现其他兼容性问题建议与原始项目MiniCPM-V-demo-Android中的版本保持一致项目要求Android Studio2024.1支持 AGP 8.9AGP8.9.1Gradle8.11.1NDK27.0.12077973CMake3.22.1Kotlin2.0.21minSdk24目标 ABIarm64-v8a仅支持 64 位 ARM磁盘空间≥ 10GBllama.cpp 编译 模型文件Java112. 文件清单必须复制Kotlin层LlamaEngine.kt引擎单例封装全部 JNI 调用ModelInfo.kt模型元数据下载源、文件名、MD5校验等ModelDownloadService.kt模型下载服务CpuFeatures.ktCPU 特性检测选优化的 .soJNI层CMakeLists.txtCMake 配置llama_jni.cppJNI 桥接logging.h日志可选文件MarkdownEscape.ktV4.6 输出的\n转真换行显示优化VideoFrameExtractor.kt视频理解功能只有MiniCPM-V 4.6模型支持3. 步骤一搭建 Native 层3.1 添加 llama.cpp 子模块在项目根目录cd/path/to/your/projectgitsubmoduleadd-bSupport-iOS-Demo https://github.com/tc-mb/llama.cpp.git llama.cppcdllama.cpp⚠️重要必须使用Support-iOS-Demo分支它包含 MiniCPM-V 的 clip.cpp 兼容代码主线分支的 mmproj 转换格式不兼容。3.2 复制 C 文件把llama_jni.cpp、logging.h、CMakeLists.txt复制到你项目的app/src/main/cpp/下。3.3 修改 CMakeLists.txt 中的 llama.cpp 路径打开CMakeLists.txt修改第 38-39 行的LLAMA_SRC路径# 默认在项目4级目录上找 llama.cpp if(NOT DEFINED LLAMA_SRC) set(LLAMA_SRC ${CMAKE_CURRENT_LIST_DIR}/../../../../../llama.cpp) endif() # 如果你的llama.cpp 在项目根目录下改成 if(NOT DEFINED LLAMA_SRC) set(LLAMA_SRC ${CMAKE_CURRENT_LIST_DIR}/../../../../llama.cpp) endif()路径关系app/src/main/cpp/→ 上 4 级到项目根 →llama.cpp/3.4 修改 JNI 函数名llama_jni.cpp中的 JNI 函数名基于包名com.example.minicpm_v_demo格式为Java_包名_类名_方法名. → __ → _1当前函数名示例Java_com_example_minicpm_1v_1demo_LlamaEngine_load如果你的包名是com.yourapp.ai需要把所有 JNI 函数前缀改为Java_com_yourapp_ai_LlamaEngine_load完整替换列表在llama_jni.cpp中搜索替换原始前缀新前缀Java_com_example_minicpm_1v_1demo_LlamaEngine_Java_com_yourapp_ai_LlamaEngine_4. 步骤二配置 Gradle 构建4.1gradle/libs.versions.toml[versions] agp 8.9.0 kotlin 2.0.21 coreKtx 1.10.1 appcompat 1.6.1 material 1.10.0 constraintlayout 2.1.4 lifecycleRuntimeKtx 2.6.2 activityKtx 1.8.0 [libraries] androidx-core-ktx { group androidx.core, name core-ktx, version.ref coreKtx } androidx-appcompat { group androidx.appcompat, name appcompat, version.ref appcompat } material { group com.google.android.material, name material, version.ref material } androidx-constraintlayout { group androidx.constraintlayout, name constraintlayout, version.ref constraintlayout } androidx-lifecycle-runtime-ktx { group androidx.lifecycle, name lifecycle-runtime-ktx, version.ref lifecycleRuntimeKtx } androidx-activity-ktx { group androidx.activity, name activity-ktx, version.ref activityKtx } [plugins] android-application { id com.android.application, version.ref agp } kotlin-android { id org.jetbrains.kotlin.android, version.ref kotlin }4.2gradle/wrapper/gradle-wrapper.propertiesdistributionUrlhttps\://services.gradle.org/distributions/gradle-8.11.1-bin.zip4.3app/build.gradle.ktsplugins{alias(libs.plugins.android.application)alias(libs.plugins.kotlin.android)alias(libs.plugins.kotlin.compose)}android{namespacecom.xxx.xxx//改为自己的项目包路径compileSdk36ndkVersion27.0.12077973defaultConfig{applicationIdcom.xxx.xxxminSdk24targetSdk36versionCode1versionName1.0testInstrumentationRunnerandroidx.test.runner.AndroidJUnitRunnerndk{abiFilters.add(arm64-v8a)// 只构建 ARM64}//cmake相关的配置externalNativeBuild{cmake{arguments-DCMAKE_BUILD_TYPEReleasearguments-DBUILD_SHARED_LIBSONarguments-DLLAMA_BUILD_COMMONONarguments-DLLAMA_OPENSSLOFFarguments-DGGML_NATIVEOFFarguments-DGGML_LLAMAFILEONarguments-DGGML_CPU_ARM_ARCHarmv8.2-adotprodfp16}}}buildTypes{release{isMinifyEnabledfalseproguardFiles(getDefaultProguardFile(proguard-android-optimize.txt),proguard-rules.pro)}}compileOptions{sourceCompatibilityJavaVersion.VERSION_11 targetCompatibilityJavaVersion.VERSION_11}kotlinOptions{jvmTarget11}externalNativeBuild{cmake{pathfile(src/main/cpp/CMakeLists.txt)version3.22.1}}buildFeatures{composetrue}}dependencies{implementation(libs.androidx.core.ktx)implementation(libs.androidx.lifecycle.runtime.ktx)implementation(libs.androidx.activity.compose)implementation(platform(libs.androidx.compose.bom))implementation(libs.androidx.ui)implementation(libs.androidx.ui.graphics)implementation(libs.androidx.ui.tooling.preview)implementation(libs.androidx.material3)implementation(libs.androidx.material.icons.extended)testImplementation(libs.junit)androidTestImplementation(libs.androidx.junit)androidTestImplementation(libs.androidx.espresso.core)androidTestImplementation(platform(libs.androidx.compose.bom))androidTestImplementation(libs.androidx.ui.test.junit4)debugImplementation(libs.androidx.ui.tooling)debugImplementation(libs.androidx.ui.test.manifest)}5. 步骤三复制 Kotlin 核心文件5.1 必须文件把以上提到的必须复制文件复制到你的包名目录下并修改package声明。5.2 LlamaEngine.kt 的 JNI 声明如果你的包名改变了需要同步修改LlamaEngine.kt中的external函数声明。Kotlin 的external函数名必须和 C 端一致不改 Kotlin 声明改 C 端的函数名来匹配。6. 步骤四配置 AndroidManifestmanifest...!-- 网络权限下载模型必须 --uses-permissionandroid:nameandroid.permission.INTERNET/uses-permissionandroid:nameandroid.permission.ACCESS_NETWORK_STATE/!-- 以下权限仅在集成 ModelDownloadService 时需要 --uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE/uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE_DATA_SYNC/uses-permissionandroid:nameandroid.permission.WAKE_LOCK/uses-permissionandroid:nameandroid.permission.POST_NOTIFICATIONS/applicationandroid:networkSecurityConfigxml/network_security_config...!-- 如果使用 ModelDownloadService --serviceandroid:name.ModelDownloadServiceandroid:exportedfalseandroid:foregroundServiceTypedataSync//application/manifestnetwork_security_config.xml?xml version1.0 encodingutf-8?network-security-configbase-configcleartextTrafficPermittedtrue//network-security-config7. 步骤五模型文件管理7.1 模型存储结构/data/data/com.yourapp.ai/files/models/ ├── minicpm-v-4/ # ModelInfo.id │ ├── ggml-model-Q4_K_M.gguf # LLM 主模型 │ └── mmproj-model-f16.gguf # 视觉投影模型 └── minicpm-v-4_6-instruct/ # 另一个模型 ├── MiniCPM-V-4_6-Q4_K_M.gguf └── mmproj-model-merger-f16.gguf7.2 下载源模型大小下载策略MiniCPM-V-4 (Q4_K_M)~4.1BHuggingFace → ModelScope 回退MiniCPM-V-4.6 (Q4_K_M)~1.2B华为云 OBS 直链7.3 下载方式方式 AApp 内下载推荐集成ModelDownloadService.kt用户点击下载按钮即可支持断点续传和 MD5 校验。//启动下载ModelDownloadService.start(context)//下载状态lifecycleScope.launch{ModelDownloadController.status.collect{status-when(status){isModelDownloadController.Status.Running-showProgress(status.message)isModelDownloadController.Status.Completed-onDownloadComplete()isModelDownloadController.Status.Failed-showError(status.message)else-{}}}}方式 Badb 侧载#推送模型文件到设备 测试时可以这样adb push ggml-model-Q4_K_M.gguf /data/data/com.yourapp.ai/files/models/minicpm-v-4/ adb push mmproj-model-f16.gguf /data/data/com.yourapp.ai/files/models/minicpm-v-4/8. 步骤六在 App 中使用// 初始化引擎 条件加载模型 这里建议放到MainActivity的onCreate中 在启动的时候自动加载模型valengineLlamaEngine.getInstance(this)if(LlamaEngine.modelsExist(this)){lifecycleScope.launch{engine.state.collect{state-if(stateisLlamaState.Initialized){Log.i(ModelLoad,模型文件已就绪开始加载...)try{engine.loadModel(LlamaEngine.modelPath(thisMainActivity),LlamaEngine.mmprojPath(thisMainActivity))Log.i(ModelLoad,模型加载成功)}catch(e:Exception){Log.e(ModelLoad,模型加载失败,e)}returncollect// 只触发一次}}}}9. API 表LlamaEngine 公开 API方法简要说明getInstance(context)获取单例loadModel(path, mmprojPath?)加载模型视觉模型setSystemPrompt(prompt)设置系统提示词sendUserPrompt(msg, predictLen)发送用户消息prefillImage(imageData)预填充图片prefillVideoFrames(frames, onProgress)预填充视频帧clearContext()清空上下文unloadModel()卸载模型cancelGeneration()取消当前生成destroy()销毁引擎setImageMaxSliceNums(n)设置图片切片数state引擎状态流isVisionSupported是否支持图片isVideoUnderstandingSupported是否支持视频LlamaEngine 静态 API方法简要说明getSelectedModel(context)获取当前选择的模型setSelectedModel(context, id)选择模型modelPath(context)GGUF 文件路径mmprojPath(context)mmproj 文件路径modelsExist(context)模型文件是否都在modelDir(context)模型根目录modelDirFor(context, model)某模型目录getImageMaxSliceNums(context)图片切片数setImageMaxSliceNumsPref(context, n)持久化切片数downloadModels(context, onProgress)下载模型文件migrateLegacyLayoutIfNeeded(context)迁移旧文件布局9.1 自定义推理参数在llama_jni.cpp中修改constexprintN_THREADS4;// 推理 线程数影响推理速度 亲测 这里可以稍微调大constexprintDEFAULT_CONTEXT_SIZE4096;// KV cache 大小constexprintV46_CONTEXT_SIZE8192;// V4.6 的 KV cacheconstexprintBATCH_SIZE2048;// 批处理大小 这里也可以稍微调大一些constexprfloatDEFAULT_SAMPLER_TEMP0.7f;// 温度
http://www.zskr.cn/news/1377880.html

相关文章:

  • 为什么学了那么多,企业还是一点没变?
  • 从原子堆叠到芯片性能:一张图看懂碳化硅C面/Si面为啥这么重要
  • 佛山黄金回收实测,福正美口碑登顶 - 上门黄金回收
  • ANSYS 2020R1 Linux版安装避坑指南:ISO挂载、路径权限与License替换的那些细节
  • 激光雷达数据处理与典型案例分析实践技术应用
  • OpenCore Legacy Patcher深度探索:为旧款Mac注入新生的实战指南
  • 洛雪音乐桌面版:一站式跨平台音乐聚合播放器终极指南
  • 基于ZYNQ MPSoC 在多轴伺服电机驱动器中的架构设计与工程实践
  • 如何用WaveTools终极优化鸣潮游戏体验:从帧率解锁到抽卡分析的完整指南
  • 2026年北京搬家公司横评:从居民搬家到企业搬迁的解决方案 - 企业名录优选推荐
  • 5月兰州金价回落不少朋友想趁低点入手金饰 优选长悦 - 专业黄金回收
  • 智慧树自动刷课神器:3步快速安装,彻底告别手动操作烦恼
  • 3分钟解决方案:让Windows资源管理器原生支持iPhone HEIC照片预览
  • 从数据到洞察:BioAge生物年龄计算工具包的科研应用实践
  • Joy-Con Toolkit:终极开源手柄控制工具完整指南
  • 如何通过窗口强制置顶技术彻底解决macOS多任务处理的遮挡难题
  • 小红书数据采集实战指南:3个核心技巧破解反爬机制
  • 工业控制、车载信息娱乐、医疗设备:K4F8E304HB-MGCJ的LPDDR4应用版图
  • NT5CB512M8EQ-FL:南亚4Gb DDR3-2133内存颗粒,x8组织,0°C~95°C,FBGA-78封装
  • 深入浅出:图解高通Sensor SEE与SSC架构差异,以及如何影响你的调试效率
  • KMS_VL_ALL_AIO智能激活脚本:告别Windows和Office激活烦恼的完整解决方案
  • 保姆级教程:用Robotics Toolbox的SerialLink.plot让你的机器人动起来(附完整配置清单)
  • 想让ChatGLM2-6B只聊技术?一个自定义LogitsProcessor搞定内容定向生成
  • 上海高复择校核心维度对标:未来路vs苏洵 师资、提分、口碑及管理全解析 - 资讯焦点
  • BetterJoy:在Windows上使用Switch控制器的终极完整指南
  • BepInEx插件框架终极指南:5个常见问题深度解析与高效解决方案
  • 风格化手绘风 3D 渲染出图参数调校技巧
  • [开源] 医嘱最小合规改动路径枚举系统:面向临床开方与医保质控的反事实推理工具
  • 沃尔玛购物卡回收避坑指南 !新手速看! - 可可收公众号
  • 2026年北京搬家公司深度横评:居民搬迁到企业运营的全链条对标指南 - 企业名录优选推荐