一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

移植Mediapipe LLM Demo到Kotlin Multiplatform

谷歌開(kāi)發(fā)者 ? 來(lái)源:Android高效開(kāi)發(fā) ? 2024-12-05 16:29 ? 次閱讀

以下文章來(lái)源于Android高效開(kāi)發(fā),作者2BAB

作者 / Android 谷歌開(kāi)發(fā)者專家 El Zhang (2BAB)

在今年的廈門和廣州 Google I/O Extended 上,我分享了《On-Device Model 集成 (KMP) 與用例》。本文是當(dāng)時(shí) Demo 的深入細(xì)節(jié)分析,同時(shí)也是后面幾篇同類型文章的開(kāi)頭。通過(guò)本文你將了解到:

移植 Mediapipe 的 LLM Inference Android 官方 Demo 到 KMP,支持在 iOS 上運(yùn)行。

KMP 兩種常見(jiàn)的調(diào)用 iOS SDK 的方式:

Kotlin 直接調(diào)用 Cocoapods 引入的第三方庫(kù)。

Kotlin 通過(guò) iOS 工程調(diào)用第三方庫(kù)。

KMP 與多平臺(tái)依賴注入時(shí)的小技巧 (基于 Koin)。

On-Device Model 與 LLM 模型 Gemma 1.1 2B 的簡(jiǎn)單背景。

On-Device Model 本地模型

大語(yǔ)言模型 (LLM) 持續(xù)火熱了很長(zhǎng)一段時(shí)間,而今年開(kāi)始這股風(fēng)正式吹到了移動(dòng)端,包括 Google 在內(nèi)的最新手機(jī)與系統(tǒng)均深度集成了此類 On-Device Model 的相關(guān)功能。對(duì)于 Google 目前的公開(kāi)戰(zhàn)略中,On-Device Model 這塊的大語(yǔ)言模型主要分為兩個(gè):

Gemini Nano: 非開(kāi)源,支持機(jī)型較少 (某些機(jī)型支持特定芯片加速如 Tensor G4),具有強(qiáng)勁的表現(xiàn)。目前可以在桌面平臺(tái) (Chrome) 和部分 Android 手機(jī)上使用 (Pixel 8/9 Samsung 和小米部分機(jī)型)。據(jù)報(bào)道晚些時(shí)候會(huì)公開(kāi)給更多的開(kāi)發(fā)者進(jìn)行使用和測(cè)試。

Gemma: 開(kāi)源,支持所有滿足最低要求的機(jī)型,同樣有不俗的性能表現(xiàn),與 Nano 使用類似的技術(shù)路線進(jìn)行訓(xùn)練。目前可以在多平臺(tái)上體驗(yàn) (Android/iOS/Desktop)。

目前多數(shù)移動(dòng)端開(kāi)發(fā)者尚無(wú)法直接基于 Gemini Nano 開(kāi)發(fā),所以今天的主角便是 Gemma 1 的 2B 版本。想在移動(dòng)平臺(tái)上直接使用 Gemma,Google 已給我們提供一個(gè)開(kāi)箱即用的工具: Mediapipe。MediaPipe 是一個(gè)跨平臺(tái)的框架,它封裝了一系列預(yù)構(gòu)建的 On-Device 機(jī)器學(xué)習(xí)模型和工具,支持實(shí)時(shí)的手勢(shì)識(shí)別、面部檢測(cè)、姿態(tài)估計(jì)等任務(wù),還可應(yīng)用于生成圖片、聊天機(jī)器人等各種應(yīng)用場(chǎng)景。感興趣的朋友可以試玩它的 Web 版 Demo,以及相關(guān)文檔。

82cea7ea-b223-11ef-93f3-92fbcf53809c.jpg

而其中的 LLM Inference API (上表第一行),用于運(yùn)行大語(yǔ)言模型推理的組件,支持 Gemma 2B/7B,Phi-2,F(xiàn)alcon-RW-1B,StableLM-3B 等模型。針對(duì) Gemma 的預(yù)轉(zhuǎn)換模型 (基于 TensorFlow Lite) 可在 Kaggle 下載,并在稍后直接放入 Mediapipe 中加載。

82e4ad24-b223-11ef-93f3-92fbcf53809c.png

LLM Inference

Android Sample

Mediapipe 官方的 LLM Inference Demo 包含了 Android/iOS/Web 前端等平臺(tái)。

82f6f0f6-b223-11ef-93f3-92fbcf53809c.png

打開(kāi) Android 倉(cāng)庫(kù)會(huì)發(fā)現(xiàn)幾個(gè)特點(diǎn):

純 Kotlin 實(shí)現(xiàn)。

UI 是純 Jetpack Compose 實(shí)現(xiàn)。

依賴的 LLM Task SDK 已經(jīng)高度封裝,暴露出來(lái)的方法僅 3 個(gè)。

再查看 iOS 的版本:

UI 是 SwiftUI 實(shí)現(xiàn),做的事情和 Compose 一模一樣,稍微再簡(jiǎn)化掉一些元素 (例如 Topbar 和發(fā)送按鈕)。

依賴的 LLM Task SDK 已經(jīng)高度封裝,暴露出來(lái)的方法一樣為 3 個(gè)。

所以,一個(gè)好玩的想法出現(xiàn)了:Android 版本的這個(gè) Demo 具備移植到 iOS 上的基礎(chǔ);移植可使兩邊的代碼高度高度一致,大幅縮減維護(hù)成本,而核心要實(shí)現(xiàn)的僅僅是橋接下 iOS 上的 LLM Inference SDK。

Kotlin Multiplatform

移植工程所使用的技術(shù)叫做 Kotlin Multiplatform (縮寫為 KMP),它是 Kotlin 團(tuán)隊(duì)開(kāi)發(fā)的一種支持跨平臺(tái)開(kāi)發(fā)的技術(shù),允許開(kāi)發(fā)者使用相同的代碼庫(kù)來(lái)構(gòu)建 Android、iOS、Web 等多個(gè)平臺(tái)的應(yīng)用程序。通過(guò)共享業(yè)務(wù)邏輯代碼,KMP 能顯著減少開(kāi)發(fā)時(shí)間和維護(hù)成本,同時(shí)盡量保留每個(gè)平臺(tái)的原生性能和體驗(yàn)。Google 在今年的 I/O 大會(huì)上也宣布對(duì) KMP 提供一等的支持,把一些 Android 平臺(tái)上的庫(kù)和工具遷移到了多平臺(tái),KMP 的開(kāi)發(fā)者可以方便的使用它到 iOS 等其他平臺(tái)。

盡管 Mediapipe 也支持多個(gè)平臺(tái),但我們這次主要聚焦在 Android 和 iOS。一方面更貼近現(xiàn)實(shí),各行各業(yè)使用 KMP 的公司的用例更多在移動(dòng)端上;另外一方面也更方便對(duì)標(biāo)其他移動(dòng)端開(kāi)發(fā)技術(shù)棧。

移植流程

初始化

使用 IDEA 或 Android Studio 創(chuàng)建一個(gè) KMP 的基礎(chǔ)工程,你可以借助 KMP Wizard 或者第三方 KMP App 的模版。如果你沒(méi)有 KMP 的相關(guān)經(jīng)驗(yàn),可以看到它其實(shí)就是一個(gè)非常類似 Android 工程的結(jié)構(gòu),只不過(guò)這一次我們把 iOS 的殼工程也放到根目錄,并且在 app 模塊的 build.gradle.kts 內(nèi)同時(shí)配置了 iOS 的相關(guān)依賴。

8344db68-b223-11ef-93f3-92fbcf53809c.jpg

封裝和調(diào)用 LLM Inference

我們?cè)?commonMain 中,根據(jù) Mediapipe LLM Task SDK 的特征抽象一個(gè)簡(jiǎn)單的接口,使用 Kotlin 編寫,用以滿足 Android 和 iOS 兩端的需要。該接口取代了原有倉(cāng)庫(kù)里的 InferenceModel.kt 類。

// app/src/commonMain/.../llm/LLMOperator
interface LLMOperator {


    /**
     * To load the model into current context.
     * @return 1. null if it went well 2. an error message in string
     */
    suspend fun initModel(): String?


    fun sizeInTokens(text: String): Int


    suspend fun generateResponse(inputText: String): String


    suspend fun generateResponseAsync(inputText: String): Flow>


}
在 Android 上面,因?yàn)?LLM Task SDK 原先就是 Kotlin 實(shí)現(xiàn)的,所以除了初始化加載模型文件,其余的部分基本就是代理原有的 SDK 功能。
class LLMInferenceAndroidImpl(private val ctx: Context): LLMOperator {


    private lateinit var llmInference: LlmInference
    private val initialized = AtomicBoolean(false)
    private val partialResultsFlow = MutableSharedFlow>(...)


    override suspend fun initModel(): String? {
        if (initialized.get()) {
            return null
        }
        return try {
            val modelPath = ...
            if (File(modelPath).exists().not()) {
                return "Model not found at path: $modelPath"
            }
            loadModel(modelPath)
            initialized.set(true)
            null
        } catch (e: Exception) {
            e.message
        }
    }
    private fun loadModel(modelPath: String) {
        val options = LlmInference.LlmInferenceOptions.builder()
            .setModelPath(modelPath)
            .setMaxTokens(1024)
            .setResultListener { partialResult, done ->
                // Transforming the listener to flow,
                // making it easy on UI integration.
                partialResultsFlow.tryEmit(partialResult to done)
            }
            .build()


        llmInference = LlmInference.createFromOptions(ctx, options)
    }


    override fun sizeInTokens(text: String): Int = llmInference.sizeInTokens(text)


    override suspend fun generateResponse(inputText: String): String {
        ...
        return llmInference.generateResponse(inputText)
    }


    override suspend fun generateResponseAsync(inputText: String): Flow> {
        ...
        llmInference.generateResponseAsync(inputText)
        return partialResultsFlow.asSharedFlow()
    }


}

而針對(duì) iOS,我們先嘗試第一種調(diào)用方式:直接調(diào)用 Cocoapods 引入的庫(kù)。在 app 模塊引入 cocoapods 的插件,同時(shí)添加 Mediapipe 的 LLM Task 庫(kù):

// app/build.gradle.kts
plugins {
    ...
    alias(libs.plugins.cocoapods)
}
cocoapods {
    ...
    ios.deploymentTarget = "15"


    pod("MediaPipeTasksGenAIC") {
        version = "0.10.14"
        extraOpts += listOf("-compiler-option", "-fmodules")
    }
    pod("MediaPipeTasksGenAI") {
        version = "0.10.14"
        extraOpts += listOf("-compiler-option", "-fmodules")
    }
}

注意上面的引入配置中要添加一個(gè)編譯參數(shù)為 -fmodules 才可正常生成 Kotlin 的引用 (參考鏈接)。

一些 Objective-C 庫(kù),尤其是那些作為 Swift 庫(kù)包裝器的庫(kù),在它們的頭文件中使用了 @import 指令。默認(rèn)情況下,cinterop 不支持這些指令。要啟用對(duì) @import 指令的支持,可以在 pod() 函數(shù)的配置塊中指定 -fmodules 選項(xiàng)。

之后,我們?cè)?iosMain 中便可直接 import 相關(guān)的庫(kù)代碼,如法炮制 Android 端的代理思路:

// 注意這些 import 是 cocoapods 開(kāi)頭的
import cocoapods.MediaPipeTasksGenAI.MPPLLMInference
import cocoapods.MediaPipeTasksGenAI.MPPLLMInferenceOptions
import platform.Foundation.NSBundle
...
class LLMOperatorIOSImpl: LLMOperator {


    private val inference: MPPLLMInference


        init {
        val modelPath = NSBundle.mainBundle.pathForResource(..., "bin")


        val options = MPPLLMInferenceOptions(modelPath!!)
        options.setModelPath(modelPath!!)
        options.setMaxTokens(2048)
        options.setTopk(40)
        options.setTemperature(0.8f)
        options.setRandomSeed(102)


        // NPE was thrown here right after it printed the success initialization message internally.
        inference = MPPLLMInference(options, null) 
    }


    override fun generateResponse(inputText: String): String {...}
    override fun generateResponseAsync(inputText: String, ...) :... {
        ...
    }
    ...
}

但這回我們沒(méi)那么幸運(yùn),MPPLLMInference 初始化結(jié)束的一瞬間有 NPE 拋出。最可能的問(wèn)題是因?yàn)?Kotlin 現(xiàn)在 interop 的目標(biāo)是 Objective-C,MPPLLMInference 的構(gòu)造器比 Swift 版本多一個(gè) error 參數(shù),而我們傳入的是 null。

constructor(
  options: cocoapods.MediaPipeTasksGenAI.MPPLLMInferenceOptions, 
error:CPointer>?)

但幾番測(cè)試各種指針傳入,也并未解決這個(gè)問(wèn)題:

// 其中一種嘗試
memScoped {
    val pp: CPointerVar> = allocPointerTo()
    val inference = MPPLLMInference(options, pp.value)
    Napier.i(pp.value.toString())
}

于是只能另辟蹊徑采用第二種方案: 通過(guò) iOS 工程調(diào)用第三方庫(kù)。

// 1. 聲明一個(gè)類似 LLMOperator 的接口但更簡(jiǎn)單,方便適配 iOS 的 SDK。
// app/src/iosMain/.../llm/LLMOperator.kt
interface LLMOperatorSwift {
    suspend fun loadModel(modelName: String)
    fun sizeInTokens(text: String): Int
    suspend fun generateResponse(inputText: String): String
    suspend fun generateResponseAsync(
        inputText: String,
        progress: (partialResponse: String) -> Unit,
        completion: (completeResponse: String) -> Unit
    )
}


// 2. 在 iOS 工程里實(shí)現(xiàn)這個(gè)接口
// iosApp/iosApp/LLMInferenceDelegate.swift
class LLMOperatorSwiftImpl: LLMOperatorSwift {
    ...
    var llmInference: LlmInference?


    func loadModel(modelName: String) async throws {
        let path = Bundle.main.path(forResource: modelName, ofType: "bin")!
        let llmOptions =  LlmInference.Options(modelPath: path)
        llmOptions.maxTokens = 4096
        llmOptions.temperature = 0.9


        llmInference = try LlmInference(options: llmOptions)
    }


    func generateResponse(inputText: String) async throws -> String {
        return try llmInference!.generateResponse(inputText: inputText)
    }


    func generateResponseAsync(inputText: String, progress: @escaping (String) -> Void, completion: @escaping (String) -> Void) async throws {
        try llmInference!.generateResponseAsync(inputText: inputText) { partialResponse, error in
            // progress
            if let e = error {
                print("(self.errorTag) (e)")
                completion(e.localizedDescription)
                return
            }
            if let partial = partialResponse {
                progress(partial)
            }
        } completion: {
            completion("")
        }
    }
    ...    
}


// 3. iOS 再把代理好的(重點(diǎn)是初始化)類傳回給 Kotlin
// iosApp/iosApp/iosApp.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(){
        ...
        let delegate = try LLMOperatorSwiftImpl()
        MainKt.onStartup(llmInferenceDelegate: delegate)        
    }
}


// 4. 最初 iOS 在 KMP 上的實(shí)現(xiàn)細(xì)節(jié)直接代理給該對(duì)象(通過(guò)構(gòu)造器注入)
class LLMOperatorIOSImpl(
   private val delegate: LLMOperatorSwift) : LLMOperator {   
   ...
}
細(xì)心的朋友可能已經(jīng)發(fā)現(xiàn),兩端的 Impl 實(shí)例需要不同的構(gòu)造器參數(shù),這個(gè)需求一般使用 KMP 的 expect 與 actual 關(guān)鍵字解決。下面的代碼中:

利用了 expect class 不需要構(gòu)造器參數(shù)聲明的特點(diǎn)加了層封裝 (類似接口)。

利用了 Koin 實(shí)現(xiàn)各自平臺(tái)所需參數(shù)的注入,再統(tǒng)一把創(chuàng)建的接口實(shí)例注入到 Common 層所需的地方。

// Common
expect class LLMOperatorFactory {
    fun create(): LLMOperator
}
val sharedModule = module {
   // 從不同的 LLMOperatorFactory 創(chuàng)建出 Common 層所需的 LLMOperator
  single { get().create() }
}


// Android
actual class LLMOperatorFactory(private val context: Context){
    actual fun create(): LLMOperator = LLMInferenceAndroidImpl(context)
}
val androidModule = module {
    // Android 注入 App 的 Context
    single { LLMOperatorFactory(androidContext()) }
}


// iOS
actual class LLMOperatorFactory(private val llmInferenceDelegate: LLMOperatorSwift) {
    actual fun create(): LLMOperator = LLMOperatorIOSImpl(llmInferenceDelegate)
}


module {
    // iOS 注入 onStartup 函數(shù)傳入的 delegate
    single { LLMOperatorFactory(llmInferenceDelegate) }
}
小結(jié): 我們通過(guò)一個(gè)小小的案例,領(lǐng)略到了 KotlinSwift深度交互。還借助 expect/actual 關(guān)鍵字與 Koin 的依賴注入,讓整體方案更流暢和自動(dòng)化,達(dá)到了在 KMP 的 Common 模塊調(diào)用 Android 和 iOS Native SDK 的目標(biāo)。

移植 UI 和 ViewModel

原項(xiàng)目里的 InferenceMode 已經(jīng)被上一節(jié)的 LLMOperator 所取代,因此我們拷貝除 Activity 的剩下 5 個(gè)類:

835b8264-b223-11ef-93f3-92fbcf53809c.png

下面我們修改幾處代碼使 Jetpack Compose 的代碼可以方便的遷移到 Compose Multiplatform。

首先是外圍的 ViewModel,KMP 版本我在這里使用了 Voyage,因此替換為 ScreenModel。不過(guò)官方 ViewModel 的方案也在實(shí)驗(yàn)中了,請(qǐng)參考這個(gè)文檔。

// Android 版本
class ChatViewModel(
    private val inferenceModel: InferenceModel
) : ViewModel() {...}


// KMP 版本,轉(zhuǎn)換 ViewModel 為 ScreenModel,并修改傳入對(duì)象
class ChatViewModel(
    private val llmOperator: LLMOperator
):ScreenModel{...}

Voyage https://github.com/adrielcafe/voyager

文檔 https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-viewmodel.html

相應(yīng)的 ViewModel 初始化方式也更改成 ScreenModel 的方法:

// Android 版本
@Composable
internal fun ChatRoute(
    chatViewModel: ChatViewModel = viewModel(
        factory = ChatViewModel.getFactory(LocalContext.current.applicationContext)
    )
) {
    ...
    ChatScreen(...) {...}
}


// KMP 版本,改成外部初始化后傳入
@Composable
internal fun ChatRoute(
    chatViewModel: ChatViewModel
) {


// 此處采用了默認(rèn)參數(shù)注入的方案,便于解耦。
// koinInject() 是 Koin 官方提供的針對(duì) Compose 
// 的 @Composable 函數(shù)注入的一個(gè)方法。
@Composable
fun AiScreen(llmOperator:LLMOperator = koinInject()) {
    // 使用 ScreenModel 的 remember 方法
    val chatViewModel = rememberScreenModel { ChatViewModel(llmOperator) }
    ...
    Column {
        ...
        Box(...) {
            if (showLoading) {
                ...
            } else {
                ChatRoute(chatViewModel)
            }
        }
    }
}
對(duì)應(yīng)的 ViewModel 內(nèi)部的 LLM 功能調(diào)用接口也要進(jìn)行替換:
// Android 版本
inferenceModel.generateResponseAsync(fullPrompt)
inferenceModel.partialResults
    .collectIndexed { index, (partialResult, done) ->
        ...
    }


// KMP 版本,把 Flow 的返回前置了,兼容了兩個(gè)平臺(tái)的 SDK 設(shè)計(jì)
llmOperator.generateResponseAsync(fullPrompt)
    .collectIndexed { index, (partialResult, done) ->
        ...
    }

然后是 Compose Multiplatform 特定的資源加載方式,把 R 文件替換為 Res:

// Android 版本
Text(stringResource(R.string.chat_label))


// KMP 版本,該引用是使用插件從 xml 映射而來(lái)
// (commonMain/composeResources/values/strings.xml)
import mediapiper.app.generated.resources.chat_label
...
Text(stringResource(Res.string.chat_label))

至此我們已經(jīng)完成了 ChatScreen ChatViewModel 的主頁(yè)面功能遷移。

最后是其他的幾個(gè)輕微改動(dòng):

LoadingScreen 我們?nèi)绶ㄅ谥苽魅?LLMOperator 進(jìn)行初始化 (替換原有 InferenceModel)。

ChatMessage 只需修改了 UUID 調(diào)用的一行 API 到原生實(shí)現(xiàn) (Kotlin 2.0.20 后就不需要了)。

ChatUiState 則完全不用動(dòng)。

剩下的就只有整體修改下 Log 庫(kù)的引用等小細(xì)節(jié)。

小結(jié): 倘若略去 Log、R 文件的引用替換以及 import 替換等,核心的修改其實(shí)僅十幾行,便能把整個(gè) UI 部分也跑起來(lái)了

簡(jiǎn)單測(cè)試

那 Gemma 2B 的性能如何,我們看幾個(gè)簡(jiǎn)單的例子。此處主要使用三個(gè)版本的模型進(jìn)行測(cè)試,模型的定義在 me.xx2bab.mediapiper.llm.LLMOperator (模型在兩端部署請(qǐng)參考項(xiàng)目 README)。

gemma-2b-it-gpu-int4

gemma-2b-it-cpu-int4

gemma-2b-it-cpu-int8

其中:

it 指代一種變體,即 Instruction Tuned 模型,更適合聊天用途,因?yàn)樗鼈兘?jīng)過(guò)微調(diào)能更好地理解指令,并生成更準(zhǔn)確的回答。

int4/8 指代模型量化,即將模型中的浮點(diǎn)數(shù)轉(zhuǎn)換為低精度整數(shù),從而減小模型的大小和計(jì)算量以適配小型的本地設(shè)備例如手機(jī)。當(dāng)然,模型的精度和回答準(zhǔn)確度也會(huì)有一些下降。

CPU 和 GPU指針對(duì)的硬件平臺(tái),這方便了設(shè)備 GPU 較弱甚至沒(méi)有時(shí)可選擇 CPU 執(zhí)行。從下面的測(cè)試結(jié)果你會(huì)發(fā)現(xiàn)當(dāng)前移動(dòng)設(shè)備上 CPU 版本也常常會(huì)占優(yōu),因?yàn)槟P鸵?guī)模小、簡(jiǎn)單對(duì)話計(jì)算操作也不大,并且 Int 量化也有利于 CPU 的指令執(zhí)行。

首先我們測(cè)試一個(gè)簡(jiǎn)單的邏輯: "蘆筍是不是一種動(dòng)物"?可以看到下圖的 CPU 版本答案比兩個(gè) GPU (iOS 和 Android) 更合理。而下一個(gè)測(cè)試是翻譯答案為中文,則是三個(gè)嘗試都不太行。

837b13d6-b223-11ef-93f3-92fbcf53809c.jpg

接著我們提高了測(cè)試問(wèn)題的難度,讓它執(zhí)行區(qū)分動(dòng)植物的單詞分類: 不管是 GPU 或者 CPU 的版本都不錯(cuò)。

839ab6f0-b223-11ef-93f3-92fbcf53809c.png

再次升級(jí)上個(gè)問(wèn)題,讓它用 JSON 的方式輸出答案,就出現(xiàn)明顯的問(wèn)題:

圖 1 沒(méi)有輸出完整的代碼片段,缺少了結(jié)尾的三個(gè)點(diǎn) ```。

圖二分類錯(cuò)誤,把山竹放到動(dòng)物,植物出現(xiàn)了兩次向日葵。

圖三同二的錯(cuò)誤,但這三次都沒(méi)有純輸出一個(gè) JSON,實(shí)際上還是不夠嚴(yán)格執(zhí)行作為 JSON Responder 的角色。

83addb68-b223-11ef-93f3-92fbcf53809c.jpg

最后,這其實(shí)不是極限,如果我們使用 cpu-int8 的版本,則可以高準(zhǔn)確率地解答上面問(wèn)題。以及,如果把本 Demo 的 iOS 入口代碼發(fā)送給它分析,也能答的不錯(cuò)。

83c400aa-b223-11ef-93f3-92fbcf53809c.jpg

Gemma 1 的 2B 版本測(cè)試至此,我們發(fā)覺(jué)其推理效果還有不少進(jìn)步空間,勝在回復(fù)速度不錯(cuò)。而事實(shí)上 Gemma 2 的 2B 版本前不久已推出,并且據(jù)官方測(cè)試其綜合水平已超過(guò) GPT 3.5。這意味著在一臺(tái)小小的手機(jī)里,本地的推理已經(jīng)可以達(dá)到一年半前的主流模型效果??偨Y(jié)實(shí)現(xiàn)這個(gè)本地聊天 Demo 的遷移和測(cè)試,給了我們些一手的經(jīng)驗(yàn):

LLM 的 On-Device Model 發(fā)展非常迅速,而借助 Google 的一系列基礎(chǔ)設(shè)施可以讓第三方 Mobile App 開(kāi)發(fā)者也迅速地集成相關(guān)的功能,并跨越 Android 與 iOS 雙平臺(tái)。

觀望目前情況綜合判斷,LLM 的 On-Device Model 有望在今年達(dá)到初步可用狀態(tài),推理速度已經(jīng)不錯(cuò),準(zhǔn)確度還有待進(jìn)一步測(cè)試 (例如 Gemma 2 的 2B 版本 + Mediapipe)。

遵循 Android 團(tuán)隊(duì)目前的策略 "Kotlin First"并大膽使用 Compose,是頗具前景的——在基礎(chǔ)設(shè)施完備的情況下,一個(gè)聊天的小模塊僅寥寥數(shù)行修改即可遷移到 iOS。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Google
    +關(guān)注

    關(guān)注

    5

    文章

    1782

    瀏覽量

    58496
  • 移植
    +關(guān)注

    關(guān)注

    1

    文章

    392

    瀏覽量

    28509
  • 開(kāi)源
    +關(guān)注

    關(guān)注

    3

    文章

    3533

    瀏覽量

    43292
  • iOS
    iOS
    +關(guān)注

    關(guān)注

    8

    文章

    3399

    瀏覽量

    152262
  • LLM
    LLM
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    640

原文標(biāo)題:【GDE 分享】移植 Mediapipe LLM Demo 到 Kotlin Multiplatform

文章出處:【微信號(hào):Google_Developers,微信公眾號(hào):谷歌開(kāi)發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    無(wú)法在OVMS上運(yùn)行來(lái)自Meta的大型語(yǔ)言模型 (LLM),為什么?

    無(wú)法在 OVMS 上運(yùn)行來(lái)自 Meta 的大型語(yǔ)言模型 (LLM),例如 LLaMa2。 從 OVMS GitHub* 存儲(chǔ)庫(kù)運(yùn)行 llama_chat Python* Demo 時(shí)遇到錯(cuò)誤。
    發(fā)表于 03-05 08:07

    怎樣去使用MediaPipe的helloworld example呢

    Mediapipe有何功能?怎樣去使用MediaPipe的helloworld example呢?
    發(fā)表于 02-11 07:35

    求助,鴻蒙移植kotlin代碼,需要將其轉(zhuǎn)換成java實(shí)現(xiàn)嗎?

    鴻蒙移植kotlin代碼,需要將其轉(zhuǎn)換成java實(shí)現(xiàn)嗎?
    發(fā)表于 06-08 11:33

    求助,官方出的MESH DEMO怎么改成了Kotlin和JAVA混和了?

    對(duì)于我們大多數(shù)搞偏硬件的,一般都是用C的,對(duì)于C++,JAVA有天生的熟悉感,稍微學(xué)習(xí)一下,在官方的基礎(chǔ)上搞個(gè)東西難度不大,但是現(xiàn)在這個(gè)Kotlin是個(gè)什么鬼?語(yǔ)法規(guī)則完全不同了,連分號(hào)都不
    發(fā)表于 09-21 07:31

    分析Kotlin和Java EE的關(guān)系

    java老標(biāo)準(zhǔn)設(shè)置的所有障礙。在此過(guò)程中,新時(shí)代語(yǔ)言Kotlin特定的構(gòu)造,使的代碼更簡(jiǎn)潔而安全。 如果您沒(méi)有閱讀本系列的前兩部分,可以在這里找到: Kotlin和Java EE:第一部分 - 從Java
    發(fā)表于 09-28 17:12 ?0次下載
    分析<b class='flag-5'>Kotlin</b>和Java EE的關(guān)系

    Kotlin的概述

    相信很多開(kāi)發(fā)人員,尤其是Android開(kāi)發(fā)者都會(huì)或多或少聽(tīng)說(shuō)過(guò)Kotlin,當(dāng)然如果沒(méi)有聽(tīng)過(guò)或者不熟悉也沒(méi)有關(guān)系。因?yàn)楸酒恼乱约安┛秃笃诘膬?nèi)容會(huì)涉及很多關(guān)于Kotlin的知識(shí)分享。 在寫
    發(fā)表于 09-28 19:48 ?0次下載
    <b class='flag-5'>Kotlin</b>的概述

    使用Kotlin替代Java重構(gòu)AOSP應(yīng)用

    兩年前,Android 開(kāi)源項(xiàng)目 (AOSP) 應(yīng)用團(tuán)隊(duì)開(kāi)始使用 Kotlin 替代 Java 重構(gòu) AOSP 應(yīng)用。之所以重構(gòu)主要有兩個(gè)原因: 一是確保 AOSP 應(yīng)用能夠遵循 Android
    的頭像 發(fā)表于 09-16 09:26 ?2067次閱讀
    使用<b class='flag-5'>Kotlin</b>替代Java重構(gòu)AOSP應(yīng)用

    bilisoleil-kotlin Kotlin版仿B站項(xiàng)目

    ./oschina_soft/bilisoleil-kotlin.zip
    發(fā)表于 06-10 14:12 ?0次下載
    bilisoleil-<b class='flag-5'>kotlin</b> <b class='flag-5'>Kotlin</b>版仿B站項(xiàng)目

    將其Android應(yīng)用的Java代碼遷移到Kotlin

    J2K,即 IntelliJ/Android Studio 中的 Java Kotlin 轉(zhuǎn)換器。但 J2K 不是萬(wàn)能的,遷移中的有些情況仍然很復(fù)雜。
    的頭像 發(fā)表于 10-28 15:15 ?870次閱讀

    使用Mediapipe控制Gripper

    電子發(fā)燒友網(wǎng)站提供《使用Mediapipe控制Gripper.zip》資料免費(fèi)下載
    發(fā)表于 02-06 10:50 ?0次下載
    使用<b class='flag-5'>Mediapipe</b>控制Gripper

    Kotlin發(fā)布2023年路線圖:K2編譯器、完善教程文檔等

    Kotlin Multiplatform Mobile:通過(guò)提高工具鏈穩(wěn)定性和文檔,確保兼容性保證,將 Kotlin 移動(dòng)端技術(shù)推向穩(wěn)定。完善相關(guān)生態(tài):借助 Kotklin 庫(kù)作者的經(jīng)驗(yàn),整合一批有助于設(shè)置、開(kāi)發(fā)和發(fā)布
    的頭像 發(fā)表于 02-06 10:25 ?839次閱讀

    Kotlin的語(yǔ)法糖解析

    最近又開(kāi)始要寫一些客戶端代碼,現(xiàn)在項(xiàng)目都是使用Kotlin,但是之前沒(méi)有系統(tǒng)的學(xué)習(xí)過(guò)Kotlin,對(duì)于Kotlin的一些語(yǔ)法糖還不熟悉,所以寫篇文章總結(jié)下。
    的頭像 發(fā)表于 04-19 10:21 ?1323次閱讀

    Kotlin聲明式UI框架Compose Multiplatform支持iOS

    JetBrains 在?KotlinConf’23 大會(huì)上宣布,Compose Multiplatform 已支持 iOS,目前處于 alpha 階段。至此,Compose
    的頭像 發(fā)表于 04-24 09:12 ?1514次閱讀
    <b class='flag-5'>Kotlin</b>聲明式UI框架Compose <b class='flag-5'>Multiplatform</b>支持iOS

    由Java改為 Kotlin過(guò)程中遇到的坑

    最近了解了下 Kotlin ,其中的很多語(yǔ)法糖很有意思,并且可以與 Java 無(wú)縫兼容。故嘗試在一個(gè) SpringBoot 工程上將部分類修改為 Kotlin ,下面記錄了由 Java 改為
    的頭像 發(fā)表于 09-30 16:51 ?1021次閱讀
    由Java改為 <b class='flag-5'>Kotlin</b>過(guò)程中遇到的坑

    詳解Object Detection Demo移植

    繼上一篇移植MediapipeLLM Inference 后,這篇文章我們將繼續(xù)探索 Object Detection Demo移植
    的頭像 發(fā)表于 02-05 13:42 ?325次閱讀
    詳解Object Detection <b class='flag-5'>Demo</b>的<b class='flag-5'>移植</b>