我在本地部署通义千问Qwen1.5大模型,并实现简单的对话和RAG

news/2024/11/30 2:32:55/

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学,针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。

汇总合集:《大模型面试宝典》(2024版) 发布!


这篇文章中,我们将开源的大模型部署到本地,并实现简单的对话和RAG

环境准备

本地实验环境:

系统:Win11
显卡:1070(8G显存)

首先更新显卡驱动到最新版本,可以去官网下载或者直接在NVIDIA Geforce Experience中直接更新驱动到最新版本,新版本的驱动向下兼容更多版本的CUDA。

图片

查看显卡驱动支持的CUDA的最高版本,小于等于此版本的CUDA均可以使用。CMD或powershell中执行如下命令:

nvidia-smi

图片

技术交流群

前沿技术资讯、算法交流、求职内推、算法竞赛、面试交流(校招、社招、实习)等、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企开发者互动交流~

我们建了算法岗技术与面试交流群, 想要获取最新面试题、了解最新面试动态的、需要源码&资料、提升技术的同学,可以直接加微信号:mlc2040。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。

方式①、微信搜索公众号:机器学习社区,后台回复:加群
方式②、添加微信号:mlc2040,备注:技术交流

在https://pytorch.org/查看当前最新版PyTorch支持最低Python版本为3.8,支持CUDA的11.8和12.1版本,后面我们选择安装12.1版本。

图片

最终生成的命令可以拷贝出来,下文需要使用。

安装CUDA 12.1(可选)

此步骤可选,不安装的话后面Torch会自动安装

下载地址:

https://developer.nvidia.com/cuda-12-1-1-download-archive

图片

下载完成后直接安装即可,如果已经安装需要先卸载后再装。

安装conda

conda可以用来管理Python环境,后面我们会使用conda创建一个Python3.10的运行环境。

下载地址:

https://www.anaconda.com/download

安装完成后,为了能在命令行中使用,需要将conda的相关目录加入环境变量,例如安装在D:\developer\anaconda,则需要将以下目录添加到PATH中:

D:\developer\anaconda
D:\developer\anaconda\Scripts
D:\developer\anaconda\Library\bin
D:\developer\anaconda\Library\mingw-w64\bin

打开powershell,执行conda init初始化conda的powershell和cmd环境,linux下会初始化bash环境,初始化后方便进入conda创建的Python环境。

使用conda创建PyTorch环境

我们使用conda创建一个Python版本为3.10的Python运行环境,在命令行中执行如下命令:

conda create -n pytorch python=3.10
conda activate pytorch

使用上文中安装PyTorch的命令安装PyTorch

conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

5下载模型

我们可以去模搭社区获取模型,国内的地址,下载速度快,不需要魔法可以直接访问。

模型库地址:https://modelscope.cn/models

这里使用Qwen1.5-0.5B-Chat这个对话模型进行体验,模型较小,占用内存少,生成速度快。

点击模型文件 -> 下载模型,可支持两种下载方式:Sdk和Git

我们通过git的方式将模型文件下载到本地

mkdir Qwen && cd Qwen
git clone https://www.modelscope.cn/qwen/Qwen1.5-0.5B-Chat.git
cd ..

加载模型

1. 模型功能验证

可以使用modelscope Library加载模型,使用方法与transformers相同,使用AutoModelForCausalLM.from_pretrained方法和AutoTokenizer.from_pretrained从本地文件中加载,如果路径不存在,这两个方法会自动到modelscope下载模型文件。

需要先安装modelscope库:

pip install modelscope transformers

使用量化模型的话需要安装以下库:

pip install optimum auto-gptq

创建一个Python文件,放到与上文Qwen文件夹同级的目录中,内容如下:

from threading import Threadfrom modelscope import (AutoModelForCausalLM, AutoTokenizer)
from transformers import TextIteratorStreamerdevice = "cuda"  # 将模型加载到哪个硬件,此处为GPUmodel = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B-Chat", # 模型文件夹路径device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B-Chat")while True:user_input = input("请输入问题(q退出):")if user_input.lower() == "q":print("exit")breaktry:messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": user_input}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=False)inputs = tokenizer([text], return_tensors="pt").to(device)streamer = TextIteratorStreamer(tokenizer)generation_kwargs = dict(inputs, streamer=streamer, max_new_tokens=512)thread = Thread(target=model.generate, kwargs=generation_kwargs)thread.start()generated_text = ""count = 0for new_text in streamer:generated_text += new_textprint(new_text, end="", flush=True)print()except Exception as e:print(f"出错了:{str(e)}")

上面的代码首先从本地模型文件夹中加载了模型和分词器,然后我们在一个循环中接收用户输入,并将输入处理后通过大模型进行内容生成。我们可以通过python运行上面的文件,运行后,就可以测试了,就测试运行效果如下:

图片

2. LangChain加载本地模型

到目前为止,我们已经在本地跑起来了一个千问0.5B大语言模型,接下来需要让langchain能够加载这个本地模型。

如果要用langchain加载模型,我们需要继承langchain.llms.base.LLM 类,并且重写_llm_type, _call方法,因为我们需要支持流式输出,就需要重写_stream方法。可参考langchain的官方文档:Custom LLM | 🦜️🔗 LangChain

下面是这个类的代码:

from abc import ABC
from threading import Thread
from typing import Any, List, Mapping, Optional, Iteratorfrom langchain.callbacks.manager import CallbackManagerForLLMRun
from langchain.llms.base import LLM
from langchain_core.outputs import GenerationChunk
from modelscope import AutoModelForCausalLM, AutoTokenizer
from transformers import TextIteratorStreamerdevice = "cuda"  # the device to load the model ontomodel = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B-Chat",device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B-Chat")class QwenLocalLLM(LLM, ABC):max_token: int = 10000temperature: float = 0.01top_p = 0.9def __init__(self):super().__init__()@propertydef _llm_type(self) -> str:return "Qwen"def _call(self,prompt: str,stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,**kwargs: Any) -> str:messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt").to(device)generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]return response@propertydef _identifying_params(self) -> Mapping[str, Any]:"""Get the identifying parameters."""return {"max_token": self.max_token,"temperature": self.temperature,"top_p": self.top_p,"history_len": self.history_len}def _stream(self,prompt: str,stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,**kwargs: Any,) -> Iterator[GenerationChunk]:try:messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=False)inputs = tokenizer([text], return_tensors="pt").to(device)streamer = TextIteratorStreamer(tokenizer)generation_kwargs = dict(inputs, streamer=streamer, max_new_tokens=512)thread = Thread(target=model.generate, kwargs=generation_kwargs)thread.start()generated_text = ""for new_text in streamer:generated_text += new_textprint(new_text, end="", flush=True)yield GenerationChunk(text=new_text)print()except Exception as e:print(f"出错了:{str(e)}")yield GenerationChunk(text=f"生成失败: {str(e)}")

最后修改上一篇文章中的生成方法,将初始化千问模型的代码替换为上面的实现类:

# 替换前
model = Tongyi()
model.model_name = "qwen-max"# 替换后
model = QwenLocalLLM()

效果展示

更换之前:

图片

图片

生成结果:

离线包更新的原理涉及以下几个方面:

  1. 离线包结构 :离线包通常是一个包含前端资源的.zip包,这些资源可以是HTML、CSS、JavaScript文件或者图片等。这些资源被组织在一起,以便客户端能够下载并离线使用。

  2. 离线包类型:可能有不同类型的离线包,比如全量包和增量包。全量包包含所有更新的资源,而增量包只包含与旧版本相比发生变化的资源。

  3. 渲染过程:当客户端应用启动或用户触发更新时,会通过特定的RPC调用获取最新的离线包信息。然后,客户端会下载这个包,并将其解压缩到本地的沙盒目录。如果配置了验签,客户端还会验证包的完整性。一旦包被成功解压和验证,客户端会使用新的资源来渲染页面。

  4. 更新流程:更新流程包括构建前端.zip包,在线生成.amr包(可能是处理签名和版本信息的打包格式),然后通过发布平台将包推送给客户端。客户端在接收到更新信息后,会下载并应用新的离线包。

  5. 检查和调试:如果客户端无法加载新包,可以通过检查RPC返回结果、确认加载的离线包信息、检查沙盒目录下的解压情况、验证签名以及使用Safari调试H5页面来排查问题。

  6. 客户端范围:在控制台上传新版本离线包时,需要指定支持的客户端版本范围,只有在这个范围内的客户端才能接收并更新离线包。

  7. 用户交互:在应用中,用户触发更新后,会收到提示,更新完成后可以访问使用新离线包的页面。


http://www.ppmy.cn/news/1431258.html

相关文章

STM32自动光控窗帘程序+Proteus仿真图 H桥L298驱动电机

目录 1、前言 2、仿真图 3、源程序 资料下载地址:STM32自动光控窗帘程序Proteus仿真图 H桥L298驱动电机 1、前言 基于STM32F103设计的智能光控窗帘,包含STM32芯片、光敏电阻、LCD1602显示屏、电机驱动控制模块等。 备注:通过ARM内部的…

ESP32与SD卡交互实现:文件读写实战与初始化详解及引脚定义

本代码实现ESP32与SD卡的交互,包括定义SPI引脚、创建自定义SPI类实例、编写WriteFile与ReadFile函数进行文件读写。setup函数初始化串口、SPI、SD卡,向“/test.txt”写入“myfirstmessage”,读取并打印其内容。loop函数留空待扩展。 1. 需要…

小游戏:贪吃蛇

🎁个人主页:我们的五年 🔍系列专栏:贪吃蛇 🌷追光的人,终会万丈光芒 目录 🏝1.头文件: 🏝2.实现文件: 🏝3.测试文件 : 前言&#…

单片机 VS 嵌入式LInux (学习方法)

linux 嵌入式开发岗位需要掌握Linux的主要原因之一是,许多嵌入式系统正在向更复杂、更功能丰富的方向发展,需要更强大的操作系统支持。而Linux作为开源、稳定且灵活的操作系统,已经成为许多嵌入式系统的首选。以下是为什么嵌入式开发岗位通常…

Leetcode - 周赛394

目录 一,3120. 统计特殊字母的数量 I 二,3121. 统计特殊字母的数量 II 三,3122. 使矩阵满足条件的最少操作次数 四,3123. 最短路径中的边 一,3120. 统计特殊字母的数量 I 本题就是统计有多少个字母的大小写同时出现…

(一)Java EE企业级应用开发实战之Servlet教程——JDK安装

首先打开清华大学开源软件镜像站,清华大学开源镜像网站地址为: https://mirrors.tuna.tsinghua.edu.cn/ 打开该地址后的界面显示如下图所示 找到8版本对应的SDK安装包,我现在用的开发机器是Windows,所以我找的是Windows对应的版本…

Spring BeanUtils:灵活高效的JavaBean操作助手

1. 概述 Spring BeanUtils是Spring框架提供的一个实用工具类,它封装了一系列操作Java Bean的方法,旨在简化Java Bean属性的获取、设置、复制等操作。通过使用BeanUtils,开发者可以更加高效地进行Java Bean之间的数据转换和属性操作&#xff…

去哪儿网开源的一个对应用透明,无侵入的Java应用诊断工具

今天 V 哥给大家带来一款开源工具Bistoury,Bistoury 是去哪儿网开源的一个对应用透明,无侵入的java应用诊断工具,用于提升开发人员的诊断效率和能力。 Bistoury 的目标是一站式java应用诊断解决方案,让开发人员无需登录机器或修改…