全网 Kotlin Multiplatform 首个本地小语言模型(SLM)对话应用开发之旅C

986 阅读2分钟

开发之旅

年末重磅 全网Kotlin Multiplatform首个StableDiffusion本地部署应用开发之旅A

全网 Kotlin Multiplatform 首个本地小语言模型(SLM)对话应用开发之旅C

全网 Kotlin Multiplatform 首个本地小语言模型(SLM)对话应用开发之旅B

不同平台的文件系统处理

从所周知,不同系统平台下文件系统也是有区别,像Web端就没有文件系统的概念

得益于Kotlin Multiplatform 志同道合者越来愈多,生态也开始完善起来,诸君一起来参与伟大的KMP生态建设吧

这里找的是vinceglb/FileKit: Pick and save Files, Medias and Folder for Kotlin Multiplatform / KMP and Compose Multiplatform / CMP,非常简洁好用

image.png

  • JVM平台
actual class LLMReader {

    actual suspend fun getLLMFilePath(): String{
        return FileKit.openFilePicker()?.file?.absolutePath ?: ""
    }
  • Android平台

由于Android系统安全机制的升级,文件访问已经没有以前那么简单了,需要拿到文件Uri,然后读取Stream流复制到可访问地区

actual suspend fun getLLMFilePath(): String{
    val androidFile = FileKit.openFilePicker(type = FileKitType.File(listOf("gguf")))
    FileKit.context.contentResolver.openInputStream((androidFile?.absolutePath() ?: "").toUri()).use { inputStream ->
        FileOutputStream(File(FileKit.context.filesDir, androidFile!!.name)).use { outputStream ->
            inputStream?.copyTo(outputStream)
        }
    }
    return File(FileKit.context.filesDir, androidFile!!.name).absolutePath
}

DLottie动画加载

KMP 为数不多的动画库

alexzhirkevich/compottie: Compose Multiplatform library for rendering Lottie animations with custom pure Kotlin renderer

1.gif

CMake构建 Android NDK与Desktop平台 JDK 构建冲突兼容处理

由于Desktop平台基于JVM的,但JVM的JNI部分类型声明又会与NDK的JNI声明有冲突,会有下面的报错,所以在CMake脚本需要兼容处理

image.png

image.png

# 检查我们是否正在为 Android 构建
if(CMAKE_SYSTEM_NAME STREQUAL "Android" OR ANDROID)
    # 这是 Android NDK 构建
    message(STATUS "Android NDK build detected. NDK JNI headers will be used automatically.")
    # 对于 Android,NDK 的工具链会自动设置正确的 JNI 包含路径。
    # 你通常不需要做任何额外的事情来包含 NDK 的 jni.h。
    # 如果你出于某种原因确实需要显式引用 NDK 的 JNI 包含目录,
    # 你可以使用 find_package(JNI),它在 NDK 构建中会找到 NDK 的 JNI。
    # find_package(JNI QUIET)
    # if(JNI_FOUND)
    #    message(STATUS "NDK JNI include directories: ${JNI_INCLUDE_DIRS}")
    #    # 通常不需要显式调用 include_directories(${JNI_INCLUDE_DIRS})
    #    # 因为 NDK 工具链已经处理了。
    #    # target_include_directories(your_target_name PRIVATE ${JNI_INCLUDE_DIRS})
    # endif()
else()
    # 这是非 Android 构建 (例如桌面 Windows, Linux, macOS)
    message(STATUS "Host JNI build detected (Non-Android). Looking for desktop JDK JNI headers.")

    if(NOT DEFINED ENV{JAVA_HOME})
        message(FATAL_ERROR "Please set JAVA_HOME environment variable for host JNI build.")
    endif()

    set(JAVA_INCLUDE_DIR "$ENV{JAVA_HOME}/include")
    include_directories(${JAVA_INCLUDE_DIR}) # 添加 $JAVA_HOME/include

    # 为不同的桌面平台添加平台特定的 JNI 头文件目录
    if(WIN32) # Windows (MSVC, MinGW)
        set(JAVA_INCLUDE_DIR_PLATFORM "$ENV{JAVA_HOME}/include/win32")
        include_directories(${JAVA_INCLUDE_DIR_PLATFORM})
    elseif(APPLE) # macOS
        set(JAVA_INCLUDE_DIR_PLATFORM "$ENV{JAVA_HOME}/include/darwin")
        include_directories(${JAVA_INCLUDE_DIR_PLATFORM})
    elseif(UNIX) # Linux 和其他 Unix-like (确保不是 APPLE 或 ANDROID)
        set(JAVA_INCLUDE_DIR_PLATFORM "$ENV{JAVA_HOME}/include/linux") # 通常是 'linux'
        include_directories(${JAVA_INCLUDE_DIR_PLATFORM})
    else()
        message(WARNING "Host JNI build: Unknown OS for platform-specific JNI headers. Only $JAVA_HOME/include added.")
    endif()

    message(STATUS "Host JNI: Added include directory: ${JAVA_INCLUDE_DIR}")
    if(JAVA_INCLUDE_DIR_PLATFORM AND EXISTS "${JAVA_INCLUDE_DIR_PLATFORM}")
        message(STATUS "Host JNI: Added platform-specific include directory: ${JAVA_INCLUDE_DIR_PLATFORM}")
    endif()

endif()