书生·浦语大模型实战训练营第二期第五节--LMDeploy 量化部署 LLM&VLM实战--homework

一.LMDeploy环境部署

这次的demo比较简单一些,比较LMDeploy已经开发的比较完善了,代码量比较少一些,纯纯导库就行。

1.老样子,先创建一个conda虚拟环境:lmdeploy

conda create -n lmdeply python=3.10.8

2.vscode终端打开lmdeploy

conda activate lmdeploy

3.安装下面的库,包含pytorch和安装0.3.0版本的lmdeploy(all,啥都装,整个下下来)

#需要下载的库:
pip install torch==2.1.2
pip install lmdeploy[all]==0.3.0
pip install modelscope==1.9.5
pip install einops==0.7.0

OK了,此次的demo要用的环境就这样了,是不是so easy!

二.LMDeploy模型对话(chat)

这里就是要利用LMDeply来部署(绑定)模型啦(模型是模型,LMDeploy类似一个将模型部署下来的一个拓展?可以有很多的玩意可以操作,总之可以解决模型部署的很多问题啦!)

1.下载模型(modelscope下载--魔塔社区)

本demo用到的只有两个模型:internlm2-chat-1_8b和llava-v1.6-vicuna-7b

from modelscope.hub.snapshot_download import snapshot_download

# save_dir是模型保存到本地的目录
save_dir="/root/autodl-tmp/LMDeploy/model"


# 1.下载internlm2-chat-1_8b和llava-v1.6-vicuna-7b
snapshot_download("Shanghai_AI_Laboratory/internlm2-chat-1_8b", 
                  cache_dir=save_dir, 
                  revision='v1.1.0')

snapshot_download("AI-ModelScope/llava-v1.6-vicuna-7b", 
                  cache_dir=save_dir, 
                  )

其实以后下模型,都可以直接先搜索一下名字然后去看看在哪里有,整好路径和版本啥的直接用代码下就好咯ww 

2.使用Transformer库运行模型(也就是普通正常一般的模型部署咯)

先在code目录下创建一个pipeline_transformer.py文件,写入下面代码

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("/root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b", trust_remote_code=True)

# Set `torch_dtype=torch.float16` to load model in float16, otherwise it will be loaded as float32 and cause OOM Error.
model = AutoModelForCausalLM.from_pretrained("/root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b", torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()

inp = "hello"
print("[INPUT]", inp)
response, history = model.chat(tokenizer, inp, history=[])
print("[OUTPUT]", response)

inp = "please provide three suggestions about time management"
print("[INPUT]", inp)
response, history = model.chat(tokenizer, inp, history=history)
print("[OUTPUT]", response)

直接运行改代码,先大概有个模型应答速度的感觉吧

3.使用LMDeploy运行模型

使用LMDeploy与模型进行对话的通用命令格式为:

#使用LMDeploy与模型进行对话的通用命令格式为:
lmdeploy chat [HF格式模型路径/TurboMind格式模型路径]
#例如与internlm2-chat-1_8b对话:
lmdeploy chat /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b

在终端命令行运行之后我们就可以使用LMDeploy与InternLM2-Chat-1.8B大模型对话了

其实有感觉是速度比transformer库的快很多;退出对话的化,输入“exit”并按两下Enter即可。

拓展内容:有关LMDeploy的chat功能的更多参数可通过-h命令查看。

lmdeploy chat -h

三.LMDeploy模型量化(减小显存占用空间)

正式介绍 LMDeploy 量化方案前,需要先介绍两个概念:

  • 计算密集(compute-bound): 指推理过程中,绝大部分时间消耗在数值计算上;针对计算密集型场景,可以通过使用更快的硬件计算单元来提升计算速度。
  • 访存密集(memory-bound): 指推理过程中,绝大部分时间消耗在数据读取上;针对访存密集型场景,一般通过减少访存次数、提高计算访存比或降低访存量来优化。

常见的 LLM 模型由于 Decoder Only 架构的特性,实际推理时大多数的时间都消耗在了逐 Token 生成阶段(Decoding 阶段),是典型的访存密集型场景。所以,如何减少访存占用的显存空间,对充分利用GPU的计算能力是非常重要的!

解释一下量化的目的哈,其实在上一篇博客已经提过了这个量化的功能其实就是为了减小数据交换(访存)所占用的显存空间,有两种方法:

1.KV8量化是指将逐 Token(Decoding)生成过程中的上下文 K 和 V 中间结果进行 INT8 量化(计算时再反量化),以降低生成过程中的显存占用。

2.W4A16 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本。Weight Only 是指仅量化权重,数值计算依然采用 FP16(需要将 INT4 权重反量化)。

下面就针对这两种量化方式来实践操作一下:

1.设置最大KV Cache缓存大小

这个KV Cache其实就是一种缓存技术,通过存储键值对的形式来复用计算结果,以达到提高性能和降低内存消耗的目的。在大规模训练和推理中,KV Cache可以显著减少重复计算量,从而提升模型的推理速度。理想情况下,KV Cache全部存储于显存,以加快访存速度。当显存空间不足时,也可以将KV Cache放在内存,通过缓存管理器控制将当前需要使用的数据放入显存。(因为访存速度必然是变的慢了,但是模型推理速度还是要看你KV占内存调的有多低吧, 就是这个KV cache如果调低了占用显存的比例,显存可用空间确实大了,但是访存速度肯定会慢的,那模型推理不是更慢了吗,还是说这其实就是一个权衡的问题,毕竟LLM是访存密集型任务,本身访存就耗大头的时间,这个就相当于牺牲一部分访存速度,换来的GPU显存全给了LLM的计算,一边变慢,一边变快,但是计算那边减少的时间肯定大于访存这边增加的时间,只要KV占用显存比例别小到离谱就行)

模型在运行时,占用的显存可大致分为三部分:1.模型参数本身占用的显存;2.KV Cache占用的显存;3.以及中间运算结果占用的显存。LMDeploy的KV Cache管理器可以通过设置--cache-max-entry-count参数,控制KV缓存占用剩余显存的最大比例。默认的比例为0.8。

下面就来实验一下吧

1.1 KV Cache占用的最大显存比例:默认0.8
#通过--cache-max-entry-count参数的大小控制KV缓存占用剩余显存的最大比例,默认为0.8
lmdeploy chat /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b

显存使用率:85.26%

1.2 KV Cache占用的最大显存比例:0.4
#通过--cache-max-entry-count参数的大小控制KV缓存占用剩余显存的最大比例,默认为0.8
lmdeploy chat /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b --cache-max-entry-count 0.4

显存使用率:52.04%

1.3 KV Cache占用的最大显存比例:0.01

这个就太极限了哈,搞的这么低给缓存,访存速度不得慢成乌龟,你计算那边提的再快也没屌用啊哈哈哈,总体的模型推理速度必然是下降的。

#通过--cache-max-entry-count参数的大小控制KV缓存占用剩余显存的最大比例,默认为0.8
lmdeploy chat /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b --cache-max-entry-count 0.01

显存使用率:19.21%

显然结果已经很显然了哈哈哈 

2.使用W4A16量化

LMDeploy使用AWQ算法,实现模型4bit权重量化。也就是将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本

--model-format awq

使用一下命令完成模型的量化工作

#使用W4A16量化
lmdeploy lite auto_awq \
   /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b \ #需要量化的模型的路径
  --calib-dataset 'ptb' \
  --calib-samples 128 \
  --calib-seqlen 1024 \
  --w-bits 4 \ #这是一个选项,指定权重(weights)使用的位数。在这种情况下,权重使用 4 位。
  --w-group-size 128 \
  --work-dir /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b-4bit #权重量化为4bit后的模型保存路径

模型量化中ing

量化结束之后,接下来就可以直接调用它了 ,为了更明显对比,再把KV Cache比例调成0.01

#下面使用Chat功能运行W4A16量化后的模型(为了更明显对比,再把KV Cache比例调成0.01
lmdeploy chat /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b-4bit --model-format awq --cache-max-entry-count 0.01

显存使用率:10.7%

简直就是无敌小了已经哈哈哈,从最开始的默认LMDeploy运行模型的85%一路到现在10.7%!

四.LMDeploy服务(serve)

下面我们就来通过不同的方式将大模型封装起来,方便进行各种拓展调用使用

我们把从架构上把整个服务流程分成下面几个模块。

  • 模型推理/服务。主要提供模型本身的推理,一般来说可以和具体业务解耦,专注模型推理本身性能的优化。可以以模块、API等多种方式提供。(后端)
  • API Server。中间协议层,把后端推理/服务通过HTTP,gRPC或其他形式的接口,供前端调用。(中介)
  • Client。可以理解为前端,与用户交互的地方。通过通过网页端/命令行去调用API接口,获取模型推理/服务。(前端)

值得说明的是,以上的划分是一个相对完整的模型,但在实际中这并不是绝对的。比如可以把“模型推理”和“API Server”合并,有的甚至是三个流程打包在一起提供服务。

下面我们试三种不同的封装调用方式:

1.API+命令行

启动API服务器(以后想这么玩也是可以的噢),运行之后打开下面的链接就行。

#启动API服务器(使用W4A16量化和KV Cache调为0.4)
lmdeploy serve api_server \
    /root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b-4bit \
    --model-format awq  \ #使用AWQ算法对模型进行W4A16量化
    --cache-max-entry-count 0.4 \ #KV Cache设置为0.01
    --server-name 0.0.0.0 \ #指定服务器的名称或地址,在这种情况下,服务器名称为 0.0.0.0,表示服务器将监听所有可用的网络接口。
    --server-port 23333 \ #指定服务器的端口号。在这种情况下,服务器将在端口号 23333 上监听请求。
    --tp 1 #指定线程池的大小

运行命令行客户端(已连接API,不要关掉那个API的终端就行)

#运行命令行客户端:(不要关API的那个终端!)
#lmdeploy serve api_client:lmdeploy工具启动一个API服务
lmdeploy serve api_client http://localhost:23333

OK,以上就是实现了该功能;具体的运行架构如下图:

1.首先是有一个已经训练好的大模型,然后模型推理(TurMind就是LMDeploy下面的一个字产品)来运行部署这个大模型,

2.其次LMDeploy通过API接口调用后面的TurboMind模型服务,再通过23333这个端口暴露给客户端也就是命令行这里,

3.咱只需要在命令行访问这个23333端口就能将自己的问题通过端口输入到模型推理里面,模型推理完解答就通过端口又送回来命令行客户端;

所以,命令行就是个显示器前端,服务器在模型推理后端里面。

2.API+web端

其实原理跟前面的命令行差不多,不就是也是通过API这个中介接起来模型推理,然后暴露一个端口,然后开发一个web网页,接收这个端口,就可以实现web端的模型推理咯。

不要关掉那个API服务端!

继续!

#使用Gradio作为前端,启动网页客户端。(不要关API的那个终端!)
#lmdeploy serve gradio:lmdeploy工具启动gradio服务

lmdeploy serve gradio http://localhost:23333 \ #接受那个API暴露出来的端口
       --server-name 0.0.0.0 \ #指定服务器的名称或地址,在这种情况下,服务器名称为 0.0.0.0,表示服务器将监听所有可用的网络接口。
       --server-port 6006 \ #指定服务器的端口号。在这种情况下,服务器将在端口号 23333 上监听请求。

为啥这里不需要Gradio的代码就能打开一个gradio创建的网页呢?有没有一种可能是你刚刚运行的是“lmdeploy serve gradio",人家LMDeploy早就集成了你这gardio了好吗,代码可能都早封进lmdeploy里面了。(嘻嘻嘻)

整个的运行架构如下,自己看看吧~

五.python代码集成

在开发项目时,有时我们需要将大模型推理集成到Python代码里面。放心,LMDeploy已经给你封装好代码了,直接调用就行(还可以调参数喔!)

#引入lmdeploy的pipeline等模块
from lmdeploy import pipeline, TurbomindEngineConfig

# 调低 k/v cache内存占比调整为总显存的40%
backend_config = TurbomindEngineConfig(cache_max_entry_count=0.4)

#从目录“./internlm2-chat-1_8b”加载HF模型
pipe = pipeline('/root/autodl-tmp/LMDeploy/model/Shanghai_AI_Laboratory/internlm2-chat-1_8b-4bit',
                backend_config = backend_config)

#运行pipeline,这里采用了批处理的方式,用一个列表包含两个输入(BS=2)
#lmdeploy同时推理两个输入,产生两个输出结果,结果返回给response 
response = pipe(['Hi, pls intro yourself', '上海是'])

#输出response
print(response)

运行结果,挺好的,这样就可以直接代码调用模型之间干了!就是不太方便交互式回答,不过这可能主要功能就是利用LMDeploy调用这个模型可以向TurboMind后端传递一下参数嘛(量化推理!)

六.拓展部分

1.使用LMDeploy运行视觉多模态大模型llava

安装llava依赖库

pip install git+https://github.com/haotian-liu/LLaVA.git@4e2277a060da264c4f21b364c867cc622c945874

新建一个python文件,比如pipeline_llava.py,并填入以下代码:

#lmdeploy的pipeline模块,第2行引入用于载入图片的load_image函数 \
from lmdeploy.vl import load_image
from lmdeploy import pipeline, TurbomindEngineConfig

#创建了pipeline实例
backend_config = TurbomindEngineConfig(session_len=8192) # 图片分辨率较高时请调高session_len
# pipe = pipeline('liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config) 非开发机运行此命令
pipe = pipeline('/root/autodl-tmp/LMDeploy/model/liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config)

#从github下载了一张关于老虎的图片
image = load_image('https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/tests/data/tiger.jpeg')

#运行pipeline,输入提示词“describe this image”,和图片,结果返回至response
response = pipe(('describe this image', image))

#输出
print(response)

运行一下,完美的小老虎图片分析嘿嘿嘿

1.使用LMDeploy+gradio在web端运行视觉多模态大模型llava

新建python文件gradio_llava.py,填入以下代码:嘿嘿嘿,这里就要自己用给gradio写一个网页咯。

import gradio as gr
from lmdeploy import pipeline, TurbomindEngineConfig


backend_config = TurbomindEngineConfig(session_len=8192) # 图片分辨率较高时请调高session_len
# pipe = pipeline('liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config) 非开发机运行此命令
pipe = pipeline('/root/autodl-tmp/LMDeploy/model/liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config)

def model(image, text):
    if image is None:
        return [(text, "请上传一张图片。")]
    else:
        response = pipe((text, image)).text
        return [(text, response)]

demo = gr.Interface(fn=model, inputs=[gr.Image(type="pil"), gr.Textbox()], outputs=gr.Chatbot())
demo.launch()   

直接运行,打开链接,小小完美。

好!那这次的笔记+作业就是这些啦,下次再见啦! 

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值