最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android端部署DeepSeek的詳細(xì)教程

 更新時(shí)間:2025年03月25日 09:04:17   作者:技術(shù)野俠客  
DeepSeek最近幾個(gè)月很火熱,很多產(chǎn)品以及企業(yè)都在接入DeepSeek,比如微信搜索接入,可以搜索公眾號(hào)信息并總結(jié),這個(gè)對(duì)于查一些資料還挺好用,畢竟手機(jī)才是用戶(hù)用的最多的,既然談到了手機(jī),那么DeepSeek能否部署于手機(jī)之上呢,本文給大家介紹了android端部署的DeepSeek方法

DeepSeek最近幾個(gè)月很火熱,很多產(chǎn)品以及企業(yè)都在接入DeepSeek,比如微信搜索接入,可以搜索公眾號(hào)信息并總結(jié),這個(gè)對(duì)于查一些資料還挺好用,因?yàn)楝F(xiàn)在很多都會(huì)在公眾號(hào)上寫(xiě)一些東西,進(jìn)行宣傳,畢竟手機(jī)才是用戶(hù)用的最多的。

既然談到了手機(jī),那么DeepSeek能否部署于手機(jī)之上呢,在不聯(lián)網(wǎng)的情況下就能使用?基于這個(gè)問(wèn)題,查詢(xún)了相關(guān)資料,發(fā)現(xiàn)android端部署DeepSeek兩種方法:

第一種是使用Termux。Termux 是一款終端模擬器應(yīng)用程序,專(zhuān)為 Android 系統(tǒng)設(shè)計(jì),提供完整的 Linux 環(huán)境,允許用戶(hù)在 Android 設(shè)備上運(yùn)行 Linux 命令和工具,無(wú)需 root 權(quán)限。然后使用ollama相關(guān)命令下載部署模型即可。目前網(wǎng)上基本上都是這種方式,這種方式其實(shí)跟在服務(wù)端部署差不多,所以為啥不直接用服務(wù)端部署的模型呢。

第二種就是直接將模型文件下載到手機(jī)中,應(yīng)用內(nèi)直接加載模型文件并運(yùn)行,這種方式好處在于,可結(jié)合自身業(yè)務(wù)做一些基于大模型的離線本地私有化應(yīng)用,耗費(fèi)基本為0。

本文主要采用第二種方法,基于阿里MNN庫(kù)進(jìn)行部署。

MNN代碼倉(cāng)庫(kù)

1 準(zhǔn)備環(huán)境

1.1 MNN轉(zhuǎn)換工具

cd MNN
mkdir build && cd build
cmake .. -DMNN_BUILD_CONVERTER=ON
make -j8

這個(gè)主要是得到MNNConvert轉(zhuǎn)換工具,可用來(lái)轉(zhuǎn)換onnx格式為mnn格式

1.2 大模型轉(zhuǎn)換工具

安裝大模型轉(zhuǎn)換工具需要的一些依賴(lài),可用conda來(lái)進(jìn)行環(huán)境管理

cd path/MNN/transformers/llm/export
pip install -r requirements.txt

如果只是想試試大模型android端部署,把這些依賴(lài)下載下來(lái),然后使用如下方式一轉(zhuǎn)換模型就行了

1.3 模型下載

git lfs install
git clone https://www.modelscope.cn/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B.

1.4 模型轉(zhuǎn)換

方式一:直接使用llmexport.py直接轉(zhuǎn)換得到mnn格式的模型文件

python llmexport.py --path path/model/DeepSeek-R1-Distill-Qwen-1.5B --export mnn

方式二:可先轉(zhuǎn)換為onnx,然后再使用MNNConvert轉(zhuǎn)換為mnn格式模型

python llmexport.py --path path/model/DeepSeek-R1-Distill-Qwen-1.5B --export onnx ./MNNConvert -f ONNX --modelFile llm.onnx --MNNModel llm.mnn --bizCode biz

兩種方式都嘗試過(guò),轉(zhuǎn)換出來(lái)的模型都沒(méi)啥問(wèn)題,方式二主要可以進(jìn)行其他bits數(shù)的量化

成功:

產(chǎn)物解釋?zhuān)?/p>

1.5 編譯android依賴(lài)庫(kù)

cd project/android
mkdir build_64 && cd build_64
../build_64.sh "-DMNN_LOW_MEMORY=true -DMNN_CPU_WEIGHT_DEQUANT_GEMM=true -DMNN_BUILD_LLM=true -DMNN_SUPPORT_TRANSFORMER_FUSE=true -DMNN_ARM82=true -DMNN_OPENCL=true -DMNN_USE_LOGCAT=true"
mkdir build_32 && cd build_32
../build_32.sh "-DMNN_LOW_MEMORY=true -DMNN_CPU_WEIGHT_DEQUANT_GEMM=true -DMNN_BUILD_LLM=true -DMNN_SUPPORT_TRANSFORMER_FUSE=true -DMNN_ARM82=true -DMNN_OPENCL=true -DMNN_USE_LOGCAT=true"

這個(gè)主要是用于編譯android需要用的mnn庫(kù),編譯完成后將*.so文件將其放在android工程中

提示:如果需要調(diào)試mnn庫(kù),需要將build_64/32.sh文件中的如下參數(shù)設(shè)置為true

2 android工程

主要介紹一下其中一些關(guān)鍵的點(diǎn):CMakeList文件的編寫(xiě)、JNI文件的編寫(xiě),以及簡(jiǎn)要說(shuō)一下android native的實(shí)現(xiàn)

2.1 頭文件導(dǎo)入

將MNN庫(kù)中的頭文件(要包含llm.hpp頭文件),以及1.5編譯的android依賴(lài)庫(kù)放入android工程中,目錄如下:

2.2 CMakeList

cmake_minimum_required(VERSION 3.10.2)

project("my_deep_seek")

aux_source_directory(./ SRC_LIST)

add_library(my_deep_seek SHARED ${SRC_LIST})

find_library(log-lib log)
find_library(android-lib android)

include_directories(${CMAKE_SOURCE_DIR}/mnn/include)
include_directories(${CMAKE_SOURCE_DIR}/mnn/include/expr/)
add_library(libMNN STATIC IMPORTED)
add_library(libMNN_CL STATIC IMPORTED)
add_library(libMNN_Express STATIC IMPORTED)
add_library(libllm STATIC IMPORTED)
set_target_properties(
        libMNN PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/mnn/${CMAKE_ANDROID_ARCH_ABI}/libMNN.so
)
set_target_properties(
        libMNN_CL PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/mnn/${CMAKE_ANDROID_ARCH_ABI}/libMNN_CL.so
)
set_target_properties(
        libMNN_Express PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/mnn/${CMAKE_ANDROID_ARCH_ABI}/libMNN_Express.so
)
set_target_properties(
        libllm PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/mnn/${CMAKE_ANDROID_ARCH_ABI}/libllm.so
)

message("===>>>> abi is : ${CMAKE_ANDROID_ARCH_ABI} <<<<===")

target_link_libraries(
        my_deep_seek

        ${log-lib}
        ${android-lib}
        libMNN
        libMNN_CL
        libMNN_Express
        libllm
)

2.3 JNI

class Chat : Serializable {
    companion object {
        init {
            System.loadLibrary("my_deep_seek")
        }
    }

    external fun Init(modelDir: String): Boolean // 加載模型
    external fun Submit(input: String): String // 輸入請(qǐng)求
    external fun Respose(): ByteArray // 模型輸出
    external fun Done()
    external fun Reset()
}
#include <android/asset_manager_jni.h>
#include <android/bitmap.h>
#include <android/log.h>

#include <jni.h>
#include <string>
#include <vector>
#include <sstream>
#include <thread>

#include "MNN/llm.hpp"

#ifndef LOG_TAG
#define LOG_TAG "MyDeepSeek"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG ,__VA_ARGS__) // 定義LOGD類(lèi)型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG ,__VA_ARGS__) // 定義LOGI類(lèi)型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG ,__VA_ARGS__) // 定義LOGW類(lèi)型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG ,__VA_ARGS__) // 定義LOGE類(lèi)型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG ,__VA_ARGS__) // 定義LOGF類(lèi)型
#endif

static std::unique_ptr<MNN::Transformer::Llm> llm(nullptr);
static std::stringstream response_buffer;

extern "C" {

// 模型加載
JNIEXPORT jboolean JNICALL
Java_com_example_mydeepseek_Chat_Init(JNIEnv *env, jobject thiz, jstring modelDir) {
    const char* model_dir = env->GetStringUTFChars(modelDir, 0);
    if (!llm.get()) {
        llm.reset(MNN::Transformer::Llm::createLLM(model_dir));
        try {
            llm->load();
        } catch (const std::exception& e) {
            LOGI("=== 異常:%s ====", e.what());
            return JNI_FALSE;
        }
    }
    return JNI_TRUE;
}

// 將問(wèn)題輸入模型
JNIEXPORT jstring JNICALL
Java_com_example_mydeepseek_Chat_Submit(JNIEnv *env, jobject thiz, jstring inputStr) {
    if (!llm.get()) {
        return env->NewStringUTF("Failed, Chat is not ready!");
    }
    const char* input_str = env->GetStringUTFChars(inputStr, 0);
    auto chat = [&](std::string str) {
        llm->response(str, &response_buffer, "<eop>");
    };
    std::thread chat_thread(chat, input_str); //子線程運(yùn)行
    chat_thread.detach();
    jstring result = env->NewStringUTF("Submit success!");
    return result;
}

// 取出模型輸出
JNIEXPORT jbyteArray JNICALL
Java_com_example_mydeepseek_Chat_Respose(JNIEnv *env, jobject thiz) {
    auto len = response_buffer.str().size();
    jbyteArray res = env->NewByteArray(len);
    env->SetByteArrayRegion(res, 0, len, (const jbyte*)response_buffer.str().c_str());
    return res;
}

JNIEXPORT void JNICALL
Java_com_example_mydeepseek_Chat_Done(JNIEnv *env, jobject thiz) {
    response_buffer.str("");
}

JNIEXPORT void JNICALL
Java_com_example_mydeepseek_Chat_Reset(JNIEnv *env, jobject thiz) {
    llm->reset();
}

} // extern "C"

2.4 android native

app實(shí)現(xiàn)方面比較簡(jiǎn)單,使用recycleview來(lái)顯示與模型的對(duì)話,其他就調(diào)用jni接口即可

(1)加載模型

將1.4節(jié)模型轉(zhuǎn)換得到的那些文件將其放到手機(jī)的/data/local/tmp/DeepSeek-R1-Distill-Qwen-1.5B目錄下,然后mModelDir就為/data/local/tmp/DeepSeek-R1-Distill-Qwen-1.5B/llm.mnn

Thread {
    mChat = Chat()
    if (mChat?.Init(mModelDir) == true) {
        runOnUiThread {
            mIntent?.putExtra("chat", mChat)
            startActivityForResult(mIntent, 100)
        }
    } else {
        Toast.makeText(this,"加載模型失敗", Toast.LENGTH_SHORT).show()
    }
}.start()

(2)向模型輸入

mChat?.Submit(input)

(3)得到模型輸出

Thread {
    mChat?.Submit(input) // 輸入
    var lastResponse = ""
    while (!lastResponse.contains("<eop>")) { // 模型輸出結(jié)束標(biāo)志"<eop>"
        try {
            Thread.sleep(50) // 等模型輸出一點(diǎn)信息
            val response: String = String(mChat?.Respose() ?: ByteArray(0))
            if (response != lastResponse) {
                lastResponse = response
                lifecycleScope.launch {
                    updateBotResponse(
                        response.replaceFirst(
                            "<eop>".toRegex(),
                            ""
                        )
                    )
                }
            }
        } catch (e: InterruptedException) {
            Thread.currentThread().interrupt()
        }
    }
    mChat?.Done()
}

3 總結(jié)

1.5B模型,運(yùn)行內(nèi)存最高1.5G,推理時(shí)1G,占用內(nèi)存還挺多,且模型性能相比云端模型還是差很多。但需向前看,最近阿里的QwQ-32B模型不是達(dá)到了DeepSeek 671B模型的性能了嗎,甚至某些方面還超越DeepSeek,發(fā)展還是很快的。說(shuō)不定后面不到1B參數(shù)的模型,性能可比肩671B模型,狠狠期待一下。

以上就是Android端部署DeepSeek的詳細(xì)教程的詳細(xì)內(nèi)容,更多關(guān)于Android端部署DeepSeek的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android編程實(shí)現(xiàn)攔截短信并屏蔽系統(tǒng)Notification的方法

    Android編程實(shí)現(xiàn)攔截短信并屏蔽系統(tǒng)Notification的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)攔截短信并屏蔽系統(tǒng)Notification的方法,較為詳細(xì)的分析了Android短信與Notification的原理及對(duì)應(yīng)的設(shè)置取消技巧,需要的朋友可以參考下
    2015-12-12
  • Android繪圖之Paint的使用方法詳解

    Android繪圖之Paint的使用方法詳解

    這篇文章主要給大家介紹了關(guān)于Android繪圖之Paint使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),并給大家介紹了DrawText 基線確定的方法,需要的朋友可以參考借鑒,下面隨著小編來(lái)一些學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • Android Jetpack組件庫(kù)LiveData源碼深入探究

    Android Jetpack組件庫(kù)LiveData源碼深入探究

    LiveData是Jetpack組件的一部分,更多的時(shí)候是搭配ViewModel來(lái)使用,相對(duì)于Observable,LiveData的最大優(yōu)勢(shì)是其具有生命感知的,換句話說(shuō),LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動(dòng)生命周期狀態(tài)的時(shí)候才會(huì)更新數(shù)據(jù)
    2022-09-09
  • android中關(guān)于call撥號(hào)功能的實(shí)現(xiàn)方法

    android中關(guān)于call撥號(hào)功能的實(shí)現(xiàn)方法

    這篇文章主要介紹了android中關(guān)于call撥號(hào)功能實(shí)現(xiàn)的記錄,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • android手機(jī)獲取唯一標(biāo)識(shí)的方法

    android手機(jī)獲取唯一標(biāo)識(shí)的方法

    這篇文章主要 為大家詳細(xì)介紹了android手機(jī)獲取唯一標(biāo)識(shí)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Android 手勢(shì) 正則匹配圖片實(shí)例代碼

    Android 手勢(shì) 正則匹配圖片實(shí)例代碼

    這篇文章主要介紹了Android 手勢(shì) 正則匹配圖片實(shí)例代碼,需要的朋友可以參考下
    2017-07-07
  • Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間

    Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間

    這篇文章主要介紹了Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • Android相機(jī)、圖冊(cè)demo

    Android相機(jī)、圖冊(cè)demo

    這篇文章主要為大家詳細(xì)介紹了Android相機(jī)、圖冊(cè)的基本常見(jiàn)使用方法,幾乎涵蓋了Android相機(jī)、圖冊(cè)操作方法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Android控件動(dòng)態(tài)用法實(shí)例分析

    Android控件動(dòng)態(tài)用法實(shí)例分析

    這篇文章主要介紹了Android控件動(dòng)態(tài)用法,以實(shí)例形式較為詳細(xì)的分析了Android控件動(dòng)態(tài)的具體編程實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Android NavigationBar問(wèn)題處理的方法

    Android NavigationBar問(wèn)題處理的方法

    本篇文章主要介紹了Android NavigationBar問(wèn)題處理的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10

最新評(píng)論

鸡西市| 中超| 武清区| 军事| 沙洋县| 介休市| 洛浦县| 辽中县| 台南县| 建阳市| 苏州市| 循化| 阿拉善左旗| 珲春市| 商丘市| 潢川县| 罗源县| 岱山县| 舞钢市| 朝阳市| 屏东县| 桂平市| 民丰县| 鸡泽县| 霍山县| 滨海县| 巍山| 德惠市| 晋中市| 安图县| 贵南县| 天祝| 宁国市| 四平市| 兰州市| 兴隆县| 都兰县| 荣成市| 平阴县| 库伦旗| 巫溪县|