0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ORinNano离线部署Deepseek R1大模型教程

ljx2016 来源:ljx2016 作者:ljx2016 2025-04-10 15:32 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1. Deepseek简介

DeepSeek-R1,是幻方量化旗下AI公司深度求索(DeepSeek)研发的推理模型。DeepSeek-R1采用强化学习进行后训练,旨在提升推理能力,尤其擅长数学、代码和自然语言推理等复杂任务。作为国产AI大数据模型的代表,凭借其卓越的推理能力和高效的文本生成技术,在全球人工智能领域引发广泛关注。

本文主要说明DeepSeek-R1如何离线运行在EASY-EAI-Orin-Nano(RK3576)硬件上, RK3576 具有优异的端侧AI能效比与极高的性价比,是AI落地的不二之选。

wKgZPGf3dJGANQs8AAKMEq82LEI341.jpgwKgZO2f3dJGAEPrzAA8S8oQ1sJE106.png

2. 开发环境搭建

2.1 RKLLM-Toolkit安装

本节主要说明如何通过 pip 方式来安装 RKLLM-Toolkit,用户可以参考以下的具体流程说明完成 RKLLM-Toolkit 工具链的安装。

工具安装包链接: https://pan.baidu.com/s/1y5ZN5sl4e3HJI5d9Imt4pg?pwd=1234(提取码: 1234)。

wKgZPGf3dJGAJ09mAAEtI4AlA3g058.jpg

2.1.1 安装miniforge3工具

为防止系统对多个不同版本的 Python 环境的需求,建议使用 miniforge3 管理 Python 环境。 检查是否安装 miniforge3 和 conda 版本信息,若已安装则可省略此小节步骤。

下载 miniforge3 安装包:

wget -c https://mirrors.bfsu.edu.cn/github-release/conda-forge/miniforge/LatestRelease/Miniforge3-Linux-x86_64.sh

安装miniforge3:

chmod 777 Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.sh

2.1.2 创建 RKLLM-Toolkit Conda 环境

进入 Conda base 环境:

source ~/miniforge3/bin/activate

创建一个 Python3.8 版本(建议版本)名为 RKLLM-Toolkit 的 Conda 环境:

conda create -n RKLLM-Toolkit python=3.8

进入 RKLLM-Toolkit Conda 环境:

conda activate RKLLM-Toolkit

wKgZO2f3dJGACEiGAACGr3xjCK8314.png

2.1.3 安装RKLLM-Toolkit

在 RKLLM-Toolkit Conda 环境下使用 pip 工具直接安装所提供的工具链 whl 包,在安装过程 中,安装工具会自动下载 RKLLM-Toolkit 工具所需要的相关依赖包。

pip3 install nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl
pip3 install torch-2.1.0-cp38-cp38-manylinux1_x86_64.whl
pip3 install rkllm_toolkit-1.1.4-cp38-cp38-linux_x86_64.whl

若在安装的过程中,某些文件安装很慢,可以登录python官网单独下载:

https://pypi.org/

执行以下命令没有报错,则安装成功。

wKgZPGf3dJKANl-aAACzdH6ZGzg764.png

3. Deepseek-R1模型转换

本章主要说明如何实现Deepseek-R1大语言模型如何转换为RKLLM模型。

wKgZO2f3dJKAF743AACu6FmaZEM101.jpg

3.1 模型与脚本下载

本节提供两种大模型文件,Hugging face的原始模型和转换完成的NPU模型。

wKgZPGf3dJKANJEZAAAspf-Kql4349.png

还有用于模型转换的脚本:

wKgZO2f3dJKAEi9XAAAgeTAakmY644.png

下载链接: https://pan.baidu.com/s/1yLALcGl4jUupU8BZvU9xcA?pwd=1234 (提取码: 1234)。

3.2 模型转换

下载完成后模型和脚本放到同一个目录:

wKgZPGf3dJKAIvzPAACYg6U3Yrg123.png

在RKLLM-Toolkit环境,执行以下指令进行模型转换:

wKgZO2f3dJOASTXqAAEl_b06QpA717.png

至此模型转换成功,生成deepseek_w4a16.rkllm NPU化的大模型文件:

wKgZPGf3dJOAATqqAACmyttkt7o723.png

test.py转换脚本如下所示, 用于转换deepseek-r1模型:

from rkllm.api import RKLLM
from datasets import load_dataset
from transformers import AutoTokenizer
from tqdm import tqdm
import torch
from torch import nn
import os
# os.environ['CUDA_VISIBLE_DEVICES']='1'


modelpath = '/home/developer/RKLLM-Toolkit/DeepSeek-R1-Distill-Qwen-1.5B'
llm = RKLLM()

# Load model
# Use 'export CUDA_VISIBLE_DEVICES=2' to specify GPU device
# options ['cpu', 'cuda']
ret = llm.load_huggingface(model=modelpath, model_lora = None, device='cpu')
# ret = llm.load_gguf(model = modelpath)
if ret != 0:
    print('Load model failed!')
    exit(ret)

# Build model
dataset = "./data_quant.json"
# Json file format, please note to add prompt in the input,like this:
# [{"input":"Human: 你好!nAssistant: ", "target": "你好!我是人工智能助手KK!"},...]

qparams = None
# qparams = 'gdq.qparams' # Use extra_qparams
ret = llm.build(do_quantization=True, optimization_level=1, quantized_dtype='w4a16',
                quantized_algorithm='normal', target_platform='rk3576', num_npu_core=2, extra_qparams=qparams, dataset=None)

if ret != 0:
    print('Build model failed!')
    exit(ret)

# Chat with model
messages = "<|im_start| >system You are a helpful assistant.<|im_end| ><|im_start| >user你好!n<|im_end| ><|im_start| >assistant"
kwargs = {"max_length": 128, "top_k": 1, "top_p": 0.8,
          "temperature": 0.8, "do_sample": True, "repetition_penalty": 1.1}
# print(llm.chat_model(messages, kwargs))


# Export rkllm model
ret = llm.export_rkllm("./deepseek_r1_rk3576_w4a16.rkllm")
if ret != 0:
print('Export model failed!')

4. Deepseek-R1模型部署

本章主要说明RKLLM格式的NPU模型如何运行在EASY-EAI-Orin-Nano硬件上。

wKgZO2f3dJOALp0SAAAnUhf_Byc762.png

下载链接:https://pan.baidu.com/s/1B-DZTI-Q6i__b6Tdsrk_Ow?pwd=1234(提取码: 1234)。

然后把例程【复制粘贴】到nfs挂载目录中。(不清楚目录如何构建的,可以参考《入门指南/开发环境准备/nfs服务搭建与挂载》)。特别注意:源码目录和模型最好cp到板子上,如/userdata,否则在nfs目录执行大模型会导致模型初始化过慢。

wKgZPGf3dJOAHP_UAACltj5zwfg442.png

进入到开发板对应的例程目录执行编译操作,具体命令如下所示:

cd /userdata/deepseek-demo/
./build.sh
wKgZO2f3dJSAU_paAAEmHi_N9ug591.png

4.1 例程运行及效果

进入例程的deepseek-demo/deepseek-demo_release目录,执行下方命令,运行示例程序:

cd deepseek-demo_release/
ulimit -HSn 102400 
./deepseek-demo deepseek_w4a16.rkllm 256 512
wKgZPGf3dJSAemGBAACWWOfr2dg968.png

至此可以进行对话测试了,试着输入“直角三角形两直角边是3和4,斜边是多少?”。回答如下所示:

wKgZO2f3dJSAd0gWAAEciJ_SCGQ389.png

4.2 RKLLM算法例程

例程目录为rkllm-demo/src/main.cpp,操作流程如下。

wKgZPGf3dJSAKuyEAACUr3WjVwc084.jpg

具体代码如下所示:

#include < string.h >
#include < unistd.h >
#include < string >
#include "rkllm.h"
#include < fstream >
#include < iostream >
#include < csignal >
#include < vector >

#define PROMPT_TEXT_PREFIX "<|im_start| >system You are a helpful assistant. <|im_end| > <|im_start| >user"
#define PROMPT_TEXT_POSTFIX "<|im_end| ><|im_start| >assistant"


using namespace std;
LLMHandle llmHandle = nullptr;

void exit_handler(int signal)
{
    if (llmHandle != nullptr)
    {
        {
            cout < < "程序即将退出" < < endl;
            LLMHandle _tmp = llmHandle;
            llmHandle = nullptr;
            rkllm_destroy(_tmp);
        }
    }
    exit(signal);
}

void callback(RKLLMResult *result, void *userdata, LLMCallState state)
{
    if (state == RKLLM_RUN_FINISH)
    {
        printf("n");
    } else if (state == RKLLM_RUN_ERROR) {
        printf("\run errorn");
    } else if (state == RKLLM_RUN_GET_LAST_HIDDEN_LAYER) {
        /* ================================================================================================================
        若使用GET_LAST_HIDDEN_LAYER功能,callback接口会回传内存指针:last_hidden_layer,token数量:num_tokens与隐藏层大小:embd_size
        通过这三个参数可以取得last_hidden_layer中的数据
        注:需要在当前callback中获取,若未及时获取,下一次callback会将该指针释放
        ===============================================================================================================*/
        if (result- >last_hidden_layer.embd_size != 0 && result->last_hidden_layer.num_tokens != 0) {
            int data_size = result->last_hidden_layer.embd_size * result->last_hidden_layer.num_tokens * sizeof(float);
            printf("ndata_size:%d",data_size);
            std::ofstream outFile("last_hidden_layer.bin", std::ios::binary);
            if (outFile.is_open()) {
                outFile.write(reinterpret_cast< const char* >(result->last_hidden_layer.hidden_states), data_size);
                outFile.close();
                std::cout < < "Data saved to output.bin successfully!" < < std::endl;
            } else {
                std::cerr < < "Failed to open the file for writing!" < < std::endl;
            }
        }
    } else if (state == RKLLM_RUN_NORMAL) {
        printf("%s", result- >text);
    }
}

int main(int argc, char **argv)
{
    if (argc < 4) {
        std::cerr < < "Usage: " < < argv[0] < < " model_path max_new_tokens max_context_lenn";
        return 1;
    }

    signal(SIGINT, exit_handler);
    printf("rkllm init startn");

    //设置参数及初始化
    RKLLMParam param = rkllm_createDefaultParam();
    param.model_path = argv[1];

    //设置采样参数
    param.top_k = 1;
    param.top_p = 0.95;
    param.temperature = 0.8;
    param.repeat_penalty = 1.1;
    param.frequency_penalty = 0.0;
    param.presence_penalty = 0.0;

    param.max_new_tokens = std::atoi(argv[2]);
    param.max_context_len = std::atoi(argv[3]);
    param.skip_special_token = true;
    param.extend_param.base_domain_id = 0;

    int ret = rkllm_init(&llmHandle, ¶m, callback);
    if (ret == 0){
        printf("rkllm init successn");
    } else {
        printf("rkllm init failedn");
        exit_handler(-1);
    }

    string text;
    RKLLMInput rkllm_input;

    // 初始化 infer 参数结构体
    RKLLMInferParam rkllm_infer_params;
    memset(&rkllm_infer_params, 0, sizeof(RKLLMInferParam));  // 将所有内容初始化为 0

    // 1. 初始化并设置 LoRA 参数(如果需要使用 LoRA)
    // RKLLMLoraAdapter lora_adapter;
    // memset(&lora_adapter, 0, sizeof(RKLLMLoraAdapter));
    // lora_adapter.lora_adapter_path = "qwen0.5b_fp16_lora.rkllm";
    // lora_adapter.lora_adapter_name = "test";
    // lora_adapter.scale = 1.0;
    // ret = rkllm_load_lora(llmHandle, &lora_adapter);
    // if (ret != 0) {
    //     printf("nload lora failedn");
    // }

    // 加载第二个lora
    // lora_adapter.lora_adapter_path = "Qwen2-0.5B-Instruct-all-rank8-F16-LoRA.gguf";
    // lora_adapter.lora_adapter_name = "knowledge_old";
    // lora_adapter.scale = 1.0;
    // ret = rkllm_load_lora(llmHandle, &lora_adapter);
    // if (ret != 0) {
    //     printf("nload lora failedn");
    // }

    // RKLLMLoraParam lora_params;
    // lora_params.lora_adapter_name = "test";  // 指定用于推理的 lora 名称
    // rkllm_infer_params.lora_params = &lora_params;

    // 2. 初始化并设置 Prompt Cache 参数(如果需要使用 prompt cache)
    // RKLLMPromptCacheParam prompt_cache_params;
    // prompt_cache_params.save_prompt_cache = true;                  // 是否保存 prompt cache
    // prompt_cache_params.prompt_cache_path = "./prompt_cache.bin";  // 若需要保存prompt cache, 指定 cache 文件路径
    // rkllm_infer_params.prompt_cache_params = &prompt_cache_params;
    
    // rkllm_load_prompt_cache(llmHandle, "./prompt_cache.bin"); // 加载缓存的cache

    rkllm_infer_params.mode = RKLLM_INFER_GENERATE;

    while (true)
    {
        std::string input_str;
        printf("n");
        printf("user: ");
        std::getline(std::cin, input_str);
        if (input_str == "exit")
        {
            break;
        }
        for (int i = 0; i < (int)pre_input.size(); i++)
        {
            if (input_str == to_string(i))
            {
                input_str = pre_input[i];
                cout < < input_str < < endl;
            }
        }
        
	//text = PROMPT_TEXT_PREFIX + input_str + PROMPT_TEXT_POSTFIX;
        text = input_str;
        rkllm_input.input_type = RKLLM_INPUT_PROMPT;
        rkllm_input.prompt_input = (char *)text.c_str();
        printf("robot: ");

        // 若要使用普通推理功能,则配置rkllm_infer_mode为RKLLM_INFER_GENERATE或不配置参数
        rkllm_run(llmHandle, &rkllm_input, &rkllm_infer_params, NULL);
    }
    rkllm_destroy(llmHandle);

    return 0;
}

5. 资料获取

完整资料包的下载链接:https://pan.baidu.com/s/1FY7XHwQydqRPuTxdQezhyw?pwd=1234(提取码:1234)。

wKgZO2f3dJWAddihAAARxLht0wE180.png

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 大模型
    +关注

    关注

    2

    文章

    3879

    浏览量

    5303
  • rk3576
    +关注

    关注

    1

    文章

    319

    浏览量

    1732
  • DeepSeek
    +关注

    关注

    2

    文章

    862

    浏览量

    3491
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    百度腾讯抢滩布局!DeepSeek-R1升级和开源背后,国产AI的逆袭之路

    电子发烧友网报道(文/李弯弯)日前,DeepSeek官方宣布DeepSeek-R1模型已完成小版本试升级,当前版本为DeepSeek-R1-0528。次日,
    的头像 发表于 06-03 06:34 6478次阅读

    瑞芯微(EASY EAI)RV1126B AI模型部署

    1.AI模型部署DeepSeek-R1,是幻方量化旗下AI公司深度求索(DeepSeek)研发的推理模型
    的头像 发表于 05-14 17:17 605次阅读
    瑞芯微(EASY EAI)RV1126B AI<b class='flag-5'>模型</b><b class='flag-5'>部署</b>

    DeepSeek爆火一周年的寂静

    ,争先恐后地展示技术进步。而另一边,则是DeepSeek模型缺席春节假期,与一年前R1横空出世、引爆全球关注的高光姿态,形成了鲜明对比。   恰逢R1爆火一周年的时刻,我们回溯了过去
    的头像 发表于 02-26 14:15 1.1w次阅读
    <b class='flag-5'>DeepSeek</b>爆火一周年的寂静

    如何在ZYNQ本地部署DeepSeek模型

    一个将最小号 DeepSeek 模型部署到 AMD Zynq UltraScale+ MPSoC 处理系统的项目。
    的头像 发表于 12-19 15:43 8025次阅读
    如何在ZYNQ本地<b class='flag-5'>部署</b><b class='flag-5'>DeepSeek</b><b class='flag-5'>模型</b>

    DeepSeek模型如何在云服务器上部署

    随着大型语言模型(LLM)的应用日益普及,许多开发者和企业希望将像DeepSeek这样的优秀模型部署到自己的云服务器上,以实现私有化、定制化服务并保障数据安全。本文将详细阐述
    的头像 发表于 10-13 16:52 1254次阅读

    广和通成功部署DeepSeek-R1-0528-Qwen3-8B模型

    近日,广和通在MediaTek MT8893平台上成功部署并运行了DeepSeek-R1-0528-Qwen3-8B模型,显著提升了端侧AI设备的处理效率与智能化水平,特别是在本地化复杂
    的头像 发表于 09-26 13:35 1075次阅读

    本地部署openWebUI + ollama+DeepSeek 打造智能知识库并实现远程访问

    DeepSeek是一款由国内人工智能公司研发的大型语言模型,实现了媲美OpenAI-o1模型的效果,拥有强大的自然语言处理能力,还大幅降低了推理模型
    的头像 发表于 09-10 16:41 5612次阅读
    本地<b class='flag-5'>部署</b>openWebUI + ollama+<b class='flag-5'>DeepSeek</b> 打造智能知识库并实现远程访问

    DeepSeek R1 MTP在TensorRT-LLM中的实现与优化

    。我们在之前的博客[1] 中介绍了 DeepSeek-R1 模型实现超低推理延迟的关键优化措施。本文将深入探讨 TensorRT-LLM 中的 MTP 实现与优化。
    的头像 发表于 08-30 15:47 4834次阅读
    <b class='flag-5'>DeepSeek</b> <b class='flag-5'>R1</b> MTP在TensorRT-LLM中的实现与优化

    如何在NVIDIA Blackwell GPU上优化DeepSeek R1吞吐量

    开源 DeepSeek R1 模型的创新架构包含多头潜在注意力机制 (MLA) 和大型稀疏混合专家模型 (MoE),其显著提升了大语言模型
    的头像 发表于 08-12 15:19 4630次阅读
    如何在NVIDIA Blackwell GPU上优化<b class='flag-5'>DeepSeek</b> <b class='flag-5'>R1</b>吞吐量

    速看!EASY-EAI教你离线部署Deepseek R1模型

    1.Deepseek简介DeepSeek-R1,是幻方量化旗下AI公司深度求索(DeepSeek)研发的推理模型DeepSeek-R1采用
    的头像 发表于 07-25 15:22 1658次阅读
    速看!EASY-EAI教你<b class='flag-5'>离线</b><b class='flag-5'>部署</b><b class='flag-5'>Deepseek</b> <b class='flag-5'>R1</b>大<b class='flag-5'>模型</b>

    【「DeepSeek 核心技术揭秘」阅读体验】--全书概览

    讲解Deepseek的使用方法 第三章 深入剖析Deepseek-V3的模型架构、训练框架、推理阶段优化、后训练优化等关键技术 第四章关于DeepSeek-R1的技术剖析 第五章 从
    发表于 07-21 00:04

    【VisionFive 2单板计算机试用体验】3、开源大语言模型部署

    1、ollama平台搭建 ollama可以快速地部署开源大模型,网址为https://ollama.com, 试用该平台,可以在多平台上部署 Dee
    发表于 07-19 15:45

    【「DeepSeek 核心技术揭秘」阅读体验】书籍介绍+第一章读后心得

    的展望,大模型的训练方法、推理部署,到 GPU 硬件及推理模型的发展趋势,以前瞻性的视角为读者描绘了大模型的发展蓝图。 技惊四座的DeepSee
    发表于 07-17 11:59

    Arm Neoverse N2平台实现DeepSeek-R1满血版部署

    颇具优势。Arm 携手合作伙伴,在 Arm Neoverse N2 平台上使用开源推理框架 llama.cpp 实现 DeepSeek-R1 满血版的部署,目前已可提供线上服务。
    的头像 发表于 07-03 14:37 1504次阅读
    Arm Neoverse N2平台实现<b class='flag-5'>DeepSeek-R1</b>满血版<b class='flag-5'>部署</b>

    【书籍评测活动NO.62】一本书读懂 DeepSeek 全家桶核心技术:DeepSeek 核心技术揭秘

    DeepSeek-V3 的发布几乎没有预热和炒作,仅凭借其出色的效果和超低的成本迅速走红。 DeepSeek-R1 则是在 DeepSeek-V3 的基础上构建的推理模型,它在后训练
    发表于 06-09 14:38