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

1,521 阅读5分钟

刚开始学习,不对的地方,多多指教呀,老铁们

❤️Onion99/MineGPT: MineGPT 是一个基于Kotlin Multiplatform 开发的本地小型语言模型(SLM)对话应用

❤️Onion99/KMP-MineStableDiffusion: 全网Kotlin Multiplatform 首个LocalStableDiffusion

UI 设计

作为一个成熟的CV工程师,多年潜伏在UI部门群,总算知道怎么切图了,今天我就要导一个模板给兄弟们看看

  • 首先作为一个躺平已久的CV工程师,设计能力肯定一个没有,什么Material Design、Fluent Design呀、都是背了跟设计同事吹牛用的
  • 虽然,但是,多年的CV大法已经让我渐渐变成了一个低级的缝合怪
  • image.png

哒哒哒,让你们见识一下缝合怪的实力😁😁😁

project_cover.webp

功能设计

我们作为一个初学者,步子肯定不能迈的太大,不然就扯着蛋了

我们的目标是搭建一个简单的聊天DEMO,然后加入GPT对话能力,先实现DeskTop平台Demo,这里单纯现在两部分

  • 绘制聊天界面
  • 引入llama.cpp库,来实现模型对话能力

UI这部分不用多说,一个6年的切图仔,扑哧扑哧几下,就搭建好了, 接下来就是重点了,要与大名鼎鼎的ggml-org/llama.cpp: LLM inference in C/C++库进行交互了

image.png

看看者Star,简直让人高山仰止

与 llama.cpp Native进行交互

Kotlin说Java你的特性是我的,我的特性不是你的

KMP的Desktop平台是基于JVM,这让你想起了什么,熟悉的Android人肯定就想起被JNI支配的恐惧了,没错,现在我们的DeskTop平台也是基于JNI去跟llama.cpp打交道

  • 首先实现KMP上的通用实现类声明expect class
expect class LLMReader(){
    fun loadModel(modelPath: String)
    fun getContextSize():Long?
    fun getChatTemplate():String?
}
expect class LLMTalker() {
    fun create(modelPath: String, minP: Float, temperature: Float,
               storeChats: Boolean, contextSize: Long, chatTemplate: String,
               nThreads: Int, useMmap: Boolean, useMlock: Boolean, ): Boolean

    fun addUserMessage(message: String)
    fun addSystemPrompt(prompt: String)
    fun addAssistantMessage(message: String)
    fun getResponseGenerationSpeed():Float
    fun getContextLengthUsed():Int
    fun getResponse(query: String): Flow<String>
    fun close()
}
  • 然后实现我们现在目标平台Desktop的实现声明
actual class LLMReader {
    init {
        System.loadLibrary("libggufreader")
    }

    private var nativeHandle: Long = 0L

    actual fun loadModel(modelPath: String) {
        nativeHandle = getGGUFContextNativeHandle(modelPath)
    }

    actual fun getContextSize(): Long? {
        assert(nativeHandle != 0L) { "Use GGUFReader.load() to initialize the reader" }
        val contextSize = getContextSize(nativeHandle)
        return if (contextSize == -1L) {
            null
        } else {
            contextSize
        }
    }
    ...
}

这里给你们看目录结构更清晰点

image.png

对应JNI声明部分在这里,具体去Github源码Onion99/MineGPT: MineGPT看吧

image.png

编译动态链接库

害,还没学会如何在KMP Gradle中如何直接构建CMake

声明好 C 接口后,就可以在 CLion 中编译出对应的动态链接库了

image.png

这里当然还有许多坑,不过挑一个我很烦的吧,编译生成windows平台的dll问题之后,代码执行加载

屏幕截图 2025-05-01 205558.png

WTF,什么狗吧错误,一点提示都看不懂,考考考

最终似乎是重新下MingGW-64就好了,有点玄学,最终编译成功,在lib目录下生成

image.png

需要注意的是,不同DeskTop系统下Clion生成的动态链接库扩展名是不一样的,听说有交叉编译的说法,不是很懂,懂得老铁可以说下

平台共享库扩展名
Linux/Unix.so
macOS.dylib
Windows.dll

选择GGUF模型

这里笔者选的是最佳小型LLM 模型 DeepSeek-R1-Distill-Qwen-1.5B

关于各种B的,老铁们可以看看

DeepSeek模型版本参数量特点适用场景硬件配置
DeepSeek-R1-1.5B1.5B轻量级模型,参数量少,模型规模小适用于轻量级任务,如短文本生成、基础问答等4核处理器、8G内存,无需显卡
DeepSeek-R1-7B7B平衡型模型,性能较好,硬件需求适中适合中等复杂度任务,如文案撰写、表格处理、统计分析等8核处理器、16G内存,Ryzen7或更高,RTX 3060(12GB)或更高
DeepSeek-R1-8B8B性能略强于7B模型,适合更高精度需求适合需要更高精度的轻量级任务,比如代码生成、逻辑推理等8核处理器、16G内存,Ryzen7或更高,RTX 3060(12GB)或4060
DeepSeek-R1-14B14B高性能模型,擅长复杂的任务,如数学推理、代码生成可处理复杂任务,如长文本生成、数据分析等i9-13900K或更高、32G内存,RTX 4090(24GB)或A5000
DeepSeek-R1-32B32B专业级模型,性能强大,适合高精度任务适合超大规模任务,如语言建模、大规模训练、金融预测等Xeon 8核、128GB内存或更高,2-4张A100(80GB)或更高
DeepSeek-R1-70B70B顶级模型,性能最强,适合大规模计算和高复杂任务适合高精度专业领域任务,比如多模态任务预处理。这些任务对硬件要求非常高,需要高端的 CPU 和显卡,适合预算充足的企业或研究机构使用Xeon 8核、128GB内存或更高,8张A100/H100(80GB)或更高
DeepSeek-R1-671B671B超大规模模型,性能卓越,推理速度快,适合极高精度需求适合国家级 / 超大规模 AI 研究,如气候建模、基因组分析等,以及通用人工智能探索64核、512GB或更高,8张A100

咱们电脑普遍性能都不是不很好,所以一般7b以下就好了,我考,肚子太饿了,有点写不动了,直接上Demo了

屏幕截图 2025-05-02 211337.png

感兴趣的朋友欢迎一键三连,欢迎 Star~ 👉Onion99/MineGPT: MineGPT 是一个基于Kotlin Multiplatform 开发的本地小型语言模型(SLM)对话应用