昇思+昇腾开发板:DeepSeek-R1-Distill-Qwen-1.5B 模型推理部署与 JIT 优化实践

目录

引言

模型推理部署

环境准备

安装 MindSpore

 查看当前 mindspore 版本

安装 MindNLP

模型与分词器加载

导入必要的库

加载分词器

加载模型

对话功能实现

设置系统提示词

构建对话历史输入

推理函数实现

交互界面实现

推理JIT优化

        基础环境安装

JIT 优化配置

核心优化组件实现

Top-p 采样函数

模型加载与 JIT 化

JIT 加速的推理函数

自回归生成与优化效果验证

静态缓存与生成流程

优化效果测试


引言


        本文将详细介绍如何对 DeepSeek-R1-Distill-Qwen-1.5B 模型进行推理部署,构建可交互的对话机器人,并利用 MindSpore 的 JIT(Just-In-Time)编译技术进行推理优化,以提升模型的响应速度和用户体验。本教程适用于昇思大模型平台的单卡环境,相关操作在昇腾开发板上的实际应用可参考示例代码。

模型推理部署


环境准备

        在进行模型部署前,需要先配置合适的运行环境,主要包括安装指定版本的 MindSpore 深度学习框架和 MindNLP 自然语言处理工具库。

安装 MindSpore

        MindSpore 是华为推出的开源深度学习框架,本教程使用 2.6.0 版本,安装命令如下:

%%capture captured_output
# 实验环境已经预装了mindspore==2.6.0,如需更换mindspore版本,可更改下面 MINDSPORE_VERSION 变量
!pip uninstall mindspore -y
%env MINDSPORE_VERSION=2.6.0
!pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/${MINDSPORE_VERSION}/MindSpore/unified/aarch64/mindspore-${MINDSPORE_VERSION}-cp39-cp39-linux_aarch64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple

 查看当前 mindspore 版本

# 查看当前 mindspore 版本
!pip show mindspore

运行结果:

Name: mindspore
Version: 2.6.0
Summary: MindSpore is a new open source deep learning training/inference framework that could be used for mobile, edge and cloud scenarios.
Home-page: https://www.mindspore.cn
Author: The MindSpore Authors
Author-email: contact@mindspore.cn
License: Apache 2.0
Location: /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages
Requires: asttokens, astunparse, dill, numpy, packaging, pillow, protobuf, psutil, safetensors, scipy
Required-by: mindnlp

安装 MindNLP

        MindNLP 是基于 MindSpore 的自然语言处理库,提供了丰富的预训练模型和处理工具,本教程使用 0.4.1 版本:

%%capture captured_output
# 安装mindnlp 0.4.1 版本
!pip uninstall mindnlp -y
!pip install https://xihe.mindspore.cn/coderepo/web/v1/file/MindSpore/mindnlp/main/media/mindnlp-0.4.1-py3-none-any.whl

模型与分词器加载

        环境配置完成后,需要加载 DeepSeek-R1-Distill-Qwen-1.5B 模型及其对应的分词器。

导入必要的库

from mindnlp.transformers import AutoModelForCausalLM, AutoTokenizer
from mindnlp.transformers import TextIteratorStreamer
from mindnlp.peft import PeftModel
from threading import Thread

运行结果:

加载分词器

        分词器的作用是将自然语言文本转换为模型可理解的 token 序列:


# 开启同步,在出现报错,定位问题时开启
# mindspore.set_context(pynative_synchronize=True)# Loading the tokenizer and model from Modelers's model hub.
tokenizer = AutoTokenizer.from_pretrained("MindSpore-Lab/DeepSeek-R1-Distill-Qwen-1.5B-FP16", mirror="modelers")
# 设置pad_token为eos_token
if tokenizer.pad_token is None:tokenizer.pad_token = tokenizer.eos_token

  运行结果:

加载模型

        使用 AutoModelForCausalLM 加载预训练的因果语言模型:

model = AutoModelForCausalLM.from_pretrained("MindSpore-Lab/DeepSeek-R1-Distill-Qwen-1.5B-FP16", mirror="modelers")
# adapter_model path
# model = PeftModel.from_pretrained(model, "./output/DeepSeek-R1-Distill-Qwen-1.5B/adapter_model_for_demo/")

        加载过程中可能会出现一些警告信息,如关于模型未继承 GenerationMixin 类和滑动窗口注意力机制的提示,这些通常不影响基本功能的使用。

运行结果:

对话功能实现

        为了实现与用户的交互,需要构建处理对话历史、生成模型响应的相关函数。

设置系统提示词

        系统提示词用于定义模型的行为和角色:

system_prompt = "你是一个智能聊天机器人,以最简单的方式回答用户问题"

构建对话历史输入

        该函数将历史对话和当前用户输入整理成模型所需的格式:

def build_input_from_chat_history(chat_history, msg: str):messages = [{'role': 'system', 'content': system_prompt}]for info in chat_history:role, content = info['role'], info['content']messages.append({'role': role, 'content': content})messages.append({'role': 'user', 'content': msg})return messages

推理函数实现

        推理函数负责将用户输入转换为模型输入,调用模型生成响应,并处理流式输出:

def inference(message, history):messages = build_input_from_chat_history(history, message)input_ids = tokenizer.apply_chat_template(messages,add_generation_prompt=True,return_tensors="ms",tokenize=True)streamer = TextIteratorStreamer(tokenizer, timeout=300, skip_prompt=True, skip_special_tokens=True)generate_kwargs = dict(input_ids=input_ids,streamer=streamer,max_new_tokens=1024,use_cache=True,)t = Thread(target=model.generate, kwargs=generate_kwargs)t.start()  # Starting the generation in a separate thread.partial_message = ""for new_token in streamer:partial_message += new_tokenprint(new_token, end="", flush=True)messages.append({'role': 'assistant', 'content': partial_message})return messages[1:]

交互界面实现

        为了方便用户使用,构建一个简单的命令行交互界面:

import os
import platformos_name = platform.system()
clear_command = 'cls' if os_name == 'Windows' else 'clear'
welcome_prompt = '欢迎使用 DeepSeek-R1-Distill-Qwen-1.5B 模型,输入内容即可进行对话,clear 清空对话历史,stop 终止程序'
print(welcome_prompt)
history = []
while True:query = input("\n用户:")if query.strip() == "stop":breakif query.strip() == "clear":os.system(clear_command)print(welcome_prompt)continueprint("\nDeepSeek-R1-Distill-Qwen-1.5B:", end="")history = inference(query, history)print("")

运行结果:

输入框中输入:qianduanjidi回车

推理JIT优化


        在大语言模型的实际应用中,推理速度直接影响用户体验。本文将详细介绍如何基于 MindSpore 框架的 JIT(Just-In-Time)编译技术,对 DeepSeek-R1-Distill-Qwen-1.5B 模型进行推理优化,通过降低单次推理耗时提升对话响应速度。

        基础环境安装

        JIT 优化依赖特定版本的 MindSpore 和 MindNLP,需先完成环境配置:

# 卸载现有MindSpore版本
!pip uninstall mindspore -y
# 指定MindSpore版本为2.6.0并安装
%env MINDSPORE_VERSION=2.6.0
!pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/${MINDSPORE_VERSION}/MindSpore/unified/aarch64/mindspore-${MINDSPORE_VERSION}-cp39-cp39-linux_aarch64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple# 安装适配的MindNLP 0.4.1版本
!pip uninstall mindnlp -y
!pip install https://xihe.mindspore.cn/coderepo/web/v1/file/MindSpore/mindnlp/main/media/mindnlp-0.4.1-py3-none-any.whl

        安装完成后,可通过pip show mindspore确认版本为 2.6.0,确保环境一致性。

JIT 优化配置

        MindSpore 的 JIT 编译需要通过set_context进行参数配置,开启图算融合和指定优化级别:

import mindspore
from mindnlp.transformers import AutoTokenizer, AutoModelForCausalLM, StaticCache
from mindnlp.core import ops
from mindnlp.configs import set_pyboost
import time
import numpy as np# 开启O2级别的jit优化,开启图算融合
mindspore.set_context(enable_graph_kernel=True,mode=mindspore.GRAPH_MODE,jit_config={"jit_level": "O2",},
)

运行结果:

核心优化组件实现

Top-p 采样函数

        采样环节是生成式模型的关键步骤,为提升效率,采用基于 NumPy 的实现(在边缘设备如香橙派上表现更优):

def sample_top_p(probs, p=0.9):"""Top-p采样函数,用于生成文本时选择下一个token。此处优先采用基于numpy而不是原生MindSpore的实现方式,因为在香橙派上运行效率更高"""probs_np = probs.asnumpy()# 按概率降序排序sorted_indices = np.argsort(-probs_np, axis=-1)sorted_probs = np.take_along_axis(probs_np, sorted_indices, axis=-1)# 计算累积概率并创建掩码cumulative_probs = np.cumsum(sorted_probs, axis=-1)mask = cumulative_probs - sorted_probs > psorted_probs[mask] = 0.0sorted_probs = sorted_probs / np.sum(sorted_probs, axis=-1, keepdims=True)# 转换回MindSpore Tensorsorted_probs_tensor = mindspore.Tensor(sorted_probs, dtype=mindspore.float32)sorted_indices_tensor = mindspore.Tensor(sorted_indices, dtype=mindspore.int32)next_token_idx = ops.multinomial(sorted_probs_tensor, 1)batch_size = probs.shape[0]batch_indices = ops.arange(0, batch_size, dtype=mindspore.int32).reshape(-1, 1)# 此处采用基于mindspore.ops的实现方式,在香橙派上兼容性最好# next_token = sorted_indices_tensor[batch_indices, next_token_idx]next_token = mindspore.ops.gather(sorted_indices_tensor, next_token_idx, axis=1, batch_dims=1)# next_token = mindspore.mint.gather(sorted_indices_tensor, dim=1, index=next_token_idx)return next_token

模型加载与 JIT 化

        加载模型并通过model.jit()实现全图静态化,为编译优化奠定基础:

# 该任务将使用DeepSeek-R1-Distill-Qwen-1.5B模型,对给定的prompt进行补齐
prompts = ["请介绍一下自己。<think>","My favorite all time favorite condiment is ketchup.",
]# 生成参数配置
NUM_TOKENS_TO_GENERATE = 40  # 每个输入要生成的token数量
TEMPERATURE = 0.8            # 温度参数(控制生成多样性)
TOP_P = 0.8                  # Top-p采样阈值model_id = "MindSpore-Lab/DeepSeek-R1-Distill-Qwen-1.5B-FP16"
tokenizer = AutoTokenizer.from_pretrained(model_id, mirror="modelers")
model = AutoModelForCausalLM.from_pretrained(model_id, low_cpu_mem_usage=True, mirror="modelers")# 使用model.jit()将全图静态图化
model.jit()inputs = tokenizer(prompts, return_tensors="ms", padding=True)
set_pyboost(False)

运行结果:

JIT 加速的推理函数

        通过@mindspore.jit装饰器对核心推理函数进行编译优化,减少重复计算开销:

# 使用@mindspore.jit装饰器封装模型推理函数
@mindspore.jit(jit_config=mindspore.JitConfig(jit_syntax_level='STRICT'))
def get_decode_one_tokens_logits(model, cur_token, input_pos, cache_position, past_key_values, temperature=TEMPERATURE, top_p=TOP_P):"""单个token的解码函数,返回logits,可以使用jit进行优化"""logits = model(cur_token,position_ids=input_pos,cache_position=cache_position,past_key_values=past_key_values,return_dict=False,use_cache=True)[0]return logits
def decode_one_tokens(model, cur_token, input_pos, cache_position, past_key_values, temperature=TEMPERATURE, top_p=TOP_P):"""单个token的解码函数,由logits、温度和Top_p选择合适的token"""logits = get_decode_one_tokens_logits(model, cur_token, input_pos, cache_position, past_key_values, temperature, top_p)if temperature > 0:probs = mindspore.mint.softmax(logits[:, -1] / temperature, dim=-1)new_token = sample_top_p(probs, top_p)else:new_token = mindspore.mint.argmax(logits[:, -1], dim=-1)[:, None]return new_token

自回归生成与优化效果验证

静态缓存与生成流程

        使用StaticCache缓存注意力计算结果,减少自回归生成中的重复计算:

batch_size, seq_length = inputs["input_ids"].shape# 创建静态缓存(用于加速自回归生成)
past_key_values = StaticCache(config=model.config, max_batch_size=2, max_cache_len=512, dtype=model.dtype
)
cache_position = ops.arange(seq_length)
generated_ids = ops.zeros(batch_size, seq_length + NUM_TOKENS_TO_GENERATE + 1, dtype=mindspore.int32
)
generated_ids[:, cache_position] = inputs["input_ids"].to(mindspore.int32)# 初始前向传播获取首个logits
logits = model(**inputs, cache_position=cache_position, past_key_values=past_key_values,return_dict=False, use_cache=True
)[0]

优化效果测试

        通过循环生成并记录单步耗时,验证 JIT 优化效果:

# 生成第一个新token
if TEMPERATURE > 0:probs = mindspore.mint.softmax(logits[:, -1] / TEMPERATURE, dim=-1)next_token = sample_top_p(probs, TOP_P)
else:next_token = mindspore.mint.argmax(logits[:, -1], dim=-1)[:, None]generated_ids[:, seq_length] = next_token[:, 0]# 自回归生成循环
cache_position = mindspore.tensor([seq_length + 1])
for i in range(1, NUM_TOKENS_TO_GENERATE):s = time.time()next_token = decode_one_tokens(model, next_token, None, cache_position, past_key_values)generated_ids[:, cache_position] = next_token.int()cache_position += 1t = time.time()# 打印单步生成耗时print("[%d]:" % i, t - s)text = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)
print(text)

打印时间:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917870.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用phpstudy安装php8.2后报错:意思是找不到php_redis.dll拓展时

1.地址&#xff1a;https://pecl.php.net/package/redis/6.2.0/windows 2.下载3.解压后复制php_redis.dll到phpstudy_pro\Extensions\php\php8.2.9nts\ext目录 4.打开php.ini&#xff0c;加上 extension_dir “D:\software\phpstudy_pro\Extensions\php\php8.2.9nts\ext”

开源列式分布式数据库clickhouse

这里写自定义目录标题开源列式OLAP数据库clickhouseclickhouse使用 ClickHouse 的场景如何理解行式存储和列式存储clickhouse-go开源列式OLAP数据库clickhouse OLAP (分析型)&#xff1a;专为快速扫描、聚合、分析海量数据设计。OLTP (事务型)&#xff1a;专为处理大量短事务&…

Java Stream API 详解(Java 8+)

1. Stream 操作分类Stream 操作分为两类&#xff1a;中间操作&#xff08;Intermediate Operations&#xff09;返回新的 Stream&#xff0c;可以链式调用&#xff08;如 filter, map, sorted, distinct&#xff09;。惰性求值&#xff1a;只有遇到终止操作时才会执行。终止操作…

「源力觉醒 创作者计划」_文心大模型4.5系列开源模型, 从一行代码到一个生态:聊聊开源战略那些事儿,顺便扯扯文心大模型 4.5 的使用心得

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录从一行…

算法专题(二)回文链表

1、源代码class Solution {public boolean isPalindrome(ListNode head) {ListNode fasthead,slowhead; //快慢指针都在头结点//快指针走2步&#xff0c;慢指针走一步。//双数快指针最后是null&#xff0c;单数快指针下一位是nullwhile(fast!null && fast.next!null){f…

2025《艾诺提亚失落之歌》逆向工程解包尝试

前言 想开发一下光明之魂&#xff0c;看能不能解包《艾诺提亚失落之歌》的模型。 之前写了&#xff08;https://blog.csdn.net/weixin_42875245/article/details/148616547?spm1001.2014.3001.5501&#xff09; 沿用这个思路进行逆向工程解包。 文章目录请添加图片描述前言…

JVM 03 类加载机制

JVM 将字节码二进制流加载到内存称为类加载。 什么时候加载类 new 实例化对象。而对象所属类还没被加载。读取/设置类的静态非常量字段&#xff0c;常量字段在常量池。调用类的静态方法。类初始化&#xff0c;优先初始化父类。虚拟机启动时&#xff0c;先加载用户指定的主类。 …

STM32H7+FreeRTOS+LwIP移植EtherCAT开源主站SOEM

代码下载什么的就不多说了&#xff0c;直接看需要移植修改的代码。 1、osal.c修改 /******************************************************************************* * *** **** *** *** …

VijosOJ:中文信息学竞赛的二十年开源之路

VijosOJ&#xff1a;中文信息学竞赛领域的老牌开源在线判题系统 在中文编程教育与信息学竞赛的发展历程中&#xff0c;在线判题系统&#xff08;OJ&#xff09;扮演了至关重要的角色。它们不仅是选手训练的 “战场”&#xff0c;更是知识传递与社区交流的枢纽。VijosOJ&#x…

QPainter::CompositionMode解析

基本概念目标(Destination)&#xff1a;已经存在的像素。源(Source)&#xff1a;要绘制的新像素。组合模式&#xff1a;决定源和目标如何混合。总结SourceOver&#xff1a;源绘制在目标之上。DestinationOver&#xff1a;目标绘制在源之上。Clear&#xff1a;二者重叠区域被清空…

对接钉钉审批过程记录(C#版本)

钉钉开放平台&#xff1a;API总览 - 钉钉开放平台 按照开放平台操作指引&#xff0c;进入到钉钉开发者后台&#xff1a;开发者后台统一登录 - 钉钉统一身份认证&#xff0c;进行应用创建。 按照开放平台指引下载钉钉SDK&#xff08;新版&#xff09;。 在vs引入钉钉dll文件。 获…

AFSIM入门教程03.03:更新所有依赖库版本

系列索引&#xff1a;AFSIM入门教程索引 上一篇中更新了tiff库版本&#xff0c;本文将更新所有使用到的依赖库版本。 失败了 依赖库 首先获取哪些库被使用了。打开源码目录&#xff0c;搜索# Configure the 3rd_party&#xff0c;可以看到调用第三方库的代码。 官方提供的…

完美解决hive external表中csv字段内容含“,“逗号的问题

为解决hive表中csv字段内容含","逗号的问题&#xff0c;网上几乎都是说要用org.apache.hadoop.hive.serde2.OpenCSVSerde。 使用方法为&#xff1a; 1、mysql导出时&#xff0c;加一个ENCLOSED BY ‘"’&#xff0c; 示例&#xff1a; mysql -h 10.16.0.10 -P …

【Git】修改本地和远程的分支名称

其原理是&#xff1a; 对于本地&#xff1a;可直接修改分支名称&#xff1b;对于远程&#xff1a;不可直接重命名分支&#xff0c;所以应该将修改好名称的分支以新分支的形式推送上远程仓库&#xff0c;之后将新分支与远程新分支关联&#xff0c;之后可选择删除旧分支# 例子&am…

ubuntu24.04安装selenium、chrome、chromedriver

实验环境&#xff1a;kaggle notebook、colab notebook1、安装chrome!wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb!sudo dpkg -i google-chrome-stable_current_amd64.deb!sudo apt-get install -f!export QT_QPA_PLATFORMoffscreen!sudo…

西门子PLC基础指令6:读取时钟指令、设置时钟指令、使能含义与注意

读/写指令 1. 读取时钟 指令 READ_RTCREAD_RTC &#xff08;RTC 全称是 Real - Time Clock&#xff0c;即实时时钟 &#xff09;指令的主要作用是将 CPU 内部实时时钟&#xff08;RTC&#xff09;的当前日期和时间信息读取出来&#xff0c;并存储到以指定字节地址&#xff08;图…

GeoTools 结合 OpenLayers 实现缓冲区分析

前言❝ 缓冲区分析是地理信息系统&#xff08;GIS&#xff09;空间分析的核心功能之一。它通过围绕点、线或面等地理实体&#xff0c;自动生成指定距离&#xff08;或宽度&#xff09;的等距区域&#xff08;缓冲区&#xff09;。该功能为量化空间邻近度、评估影响范围、识别潜…

SpringBoot 接入SSE实现消息实时推送的优点,原理以及实现

SpringBoot 接入SSE实现消息实时推送的优点,原理以及实现 前言 上一篇文章 我写的关于SpringBoot整合t-io是websocket实时通信的文章中我们可以了解到 websocket是双向通信的,而且需要TCP连接的支持,今天在这里我要说的SSE(Server-Sent Events) 是一个单项通信的消息实时推…

创建型设计模式:对象诞生的艺术与智慧

&#x1f3ad; 创建型设计模式&#xff1a;对象诞生的艺术与智慧 &#x1f4a1; 温馨提示&#xff1a;本文将以轻松有趣的方式带你探索设计模式的世界&#xff0c;就像在听一个关于"如何优雅地生孩子"的故事一样&#xff01; &#x1f6aa; 传送门&#xff1a;在开始…

如何解决pip安装报错ModuleNotFoundError: No module named ‘gensim’问题

【Python系列Bug修复PyCharm控制台pip install报错】如何解决pip安装报错ModuleNotFoundError: No module named ‘gensim’问题 摘要 在使用 PyCharm 2025 进行 Python 开发时&#xff0c;常常需要通过 pip install 安装第三方包以丰富项目功能。但在安装 gensim 等包时&…