自学内容网 自学内容网

Camp4-L2:LMDeploy 量化部署进阶实践

书生浦语大模型实战营第四期:LMDeploy 量化部署进阶实践

  • 教程链接:https://github.com/InternLM/Tutorial/tree/camp4/docs/L2/LMDeploy
  • 视频链接:https://www.bilibili.com/video/BV18aUHY3EEG/?vd_source=b96c7e6e6d1a48e73edafa36a36f1697
  • 任务链接:https://github.com/InternLM/Tutorial/blob/camp4/docs/L2/LMDeploy/task.md
  • 提交链接:https://aicarrier.feishu.cn/share/base/form/shrcnUqshYPt7MdtYRTRpkiOFJd

任务说明

基础任务(完成此任务即完成闯关)

  • 使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat模型封装本地API并与大模型进行一次对话,作业截图需包括显存占用情况与大模型回复,参考4.1 API开发(优秀学员必做),请注意2.2.3节与4.1节应使用作业版本命令。
  • 使用Function call功能让大模型完成一次简单的"加"与"乘"函数调用,作业截图需包括大模型回复的工具调用情况,参考4.2 Function call(选做)

视频教程

在这里插入图片描述

LMDeploy部署模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

大模型缓存推理技术

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

大模型量化技术

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

大模型外推技术

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Function Calling

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

环境配置

conda create -n lmdeploy  python=3.10 -y
conda activate lmdeploy
pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu121
pip install timm==1.0.8 openai==1.40.3 lmdeploy[all]==0.5.3
pip install datasets==2.19.2

下载internlm2_5-7b-chatinternlm2_5-1_8b-chat两个模型至models文件夹,具体参考之前入门岛的内容即可,然后测试下环境:

lmdeploy chat models/internlm2_5-7b-chat

在这里插入图片描述
这样环境基本上就搭建好了,看下显存占用,后面对比下:
在这里插入图片描述
显存占用分析

对于一个7B(70亿)参数的模型,每个参数使用16位浮点数(等于 2个 Byte)表示,则模型的权重大小约为:

7×10^9 parameters×2 Bytes/parameter=14GB

70亿个参数×每个参数占用2个字节=14GB

因此,对于internLM2.5 7B模型为bf16,LMDpeloy推理精度为bf16的7B模型权重需要占用14GB显存

然后lmdeploy默认设置cache-max-entry-count为0.8,即kv cache占用剩余显存的80%;

所以,对于24GB的A10显卡,权重占用14GB显存,剩余显存24-14=10GB,因此kv cache占用10GB*0.8=8GB,加上原来的权重14GB,总共占用14+8=22GB。

启动API服务器

conda activate lmdeploy
lmdeploy serve api_server \
    models/Shanghai_AI_Laboratory/internlm2_5-7b-chat \
    --model-format hf \
    --quant-policy 0 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

参数解释:

  • lmdeploy serve api_server:这个命令用于启动API服务器。
  • models/Shanghai_AI_Laboratory/internlm2_5-7b-chat :这是模型的路径。
  • –model-format hf:这个参数指定了模型的格式。hf代表“Hugging Face”格式。
  • –quant-policy 0:这个参数指定了量化策略。
    –server-name 0.0.0.0:这个参数指定了服务器的名称。在这里,0.0.0.0是一个特殊的IP地址,它表示所有网络接口。
  • –server-port 23333:这个参数指定了服务器的端口号。在这里,23333是服务器将监听的端口号。
  • –tp 1:这个参数表示并行数量(GPU数量)

示例:
在这里插入图片描述
在这里插入图片描述
然后可以通过如下方式调用上面的API服务:

conda activate lmdeploy
lmdeploy serve api_client http://localhost:23333

这个跟上面一样,是在终端的对话,也可以通过网页形式:

lmdeploy serve gradio http://localhost:23333 \
    --server-name 0.0.0.0 \
    --server-port 6006

在这里插入图片描述
环境和基本使用就是这样,后面就是各种量化了~

任务1

使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat模型封装本地API并与大模型进行一次对话,作业截图需包括显存占用情况与大模型回复,参考4.1 API开发(优秀学员必做),请注意2.2.3节与4.1节应使用作业版本命令。

首先使用下述命令进行W4A16量化:

lmdeploy lite auto_awq \
  models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat \
  --calib-dataset 'ptb' \
  --calib-samples 128 \
  --calib-seqlen 2048 \
  --w-bits 4 \
  --w-group-size 128 \
  --batch-size 1 \
  --search-scale False \
  --work-dir models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit
  • lmdeploy lite auto_awq: lite这是LMDeploy的命令,用于启动量化过程,而auto_awq代表自动权重量化(auto-weight-quantization)。
  • models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat: 模型文件的路径。
  • –calib-dataset ‘ptb’: 这个参数指定了一个校准数据集,这里使用的是’ptb’(Penn Treebank,一个常用的语言模型数据集)。
  • –calib-samples 128: 这指定了用于校准的样本数量—128个样本
  • –calib-seqlen 2048: 这指定了校准过程中使用的序列长度—2048
  • –w-bits 4: 这表示权重(weights)的位数将被量化为4位。
  • –work-dir models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit: 这是工作目录的路径,用于存储量化后的模型和中间结果。

在这里插入图片描述
由于服务器链接huggingface有问题,所以需要手动下载ptb_text_only.py,然后改一下lmdeploy/lite/utils/calib_dataloader.py中的get_ptb函数,具体改动如下:
在这里插入图片描述
输入以下指令启动量化后的模型:

lmdeploy chat models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit --model-format awq

在这里插入图片描述
显存占用情况如下:
在这里插入图片描述

同时启用W4A16量化后的模型、设定kv cache占用和kv cache int4量化,命令如下:

lmdeploy serve api_server \
    models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit \
    --model-format awq \
    --quant-policy 4 \
    --cache-max-entry-count 0.4\
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

看下显存占用情况:

在这里插入图片描述

计算一下此刻的显存占用情况(11GB):

  • 在 int4 精度下,1.8B模型权重占用0.9GB:3.6/4=0.9GB
  • kv cache占用16.4GB:剩余显存24-0.9=23.1GB,kv cache占用40%,即23.1*0.4=9.24GB
  • 其他项0.9GB
    因此,11GB ∼ \sim 权重占用0.9GB+kv cache占用9.2GB+其它项0.9GB

使用下述命令访问上述API服务

lmdeploy serve gradio http://localhost:23333 \
    --server-name 0.0.0.0 \
    --server-port 6006

开始愉快地对话吧:
在这里插入图片描述
感觉1.8B的模型预留9.2GB的KV cache缓存应该有点浪费,继续将比例从0.4往下调,看下模型是否能正常对话:

lmdeploy serve api_server \
    models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit \
    --model-format awq \
    --quant-policy 4 \
    --cache-max-entry-count 0.1\
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1
lmdeploy serve gradio http://localhost:23333 \
    --server-name 0.0.0.0 \
    --server-port 6006

然后就会发现只占用了4GB的显存:
在这里插入图片描述
模型也依然可以正常对话:
在这里插入图片描述
感觉这个量化还是蛮不错的,马上就开个screen,把7B的模型量化一波儿:

lmdeploy lite auto_awq \
  models/Shanghai_AI_Laboratory/internlm2_5-7b-chat \
  --calib-dataset 'ptb' \
  --calib-samples 128 \
  --calib-seqlen 2048 \
  --w-bits 4 \
  --w-group-size 128 \
  --batch-size 1 \
  --search-scale False \
  --work-dir models/Shanghai_AI_Laboratory/internlm2_5-7b-chat-w4a16-4bit

同样把cache-max-entry-coun设置为0.1测试一下模型占用显存情况,并看看是否能正常对话:

lmdeploy serve api_server \
    models/Shanghai_AI_Laboratory/internlm2_5-7b-chat-w4a16-4bit \
    --model-format awq \
    --quant-policy 4 \
    --cache-max-entry-count 0.1\
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1
lmdeploy serve gradio http://localhost:23333 \
    --server-name 0.0.0.0 \
    --server-port 6006

可以看到基本上只用了7.5GB左右的显存,相当可以了~
在这里插入图片描述
对话目前也是正常的,速度还可以:
在这里插入图片描述
作业基本上就这样了,后续可以再试试比较大的模型,比如70B的模型,大约本身是需要140GB的显存,int4量化后需要35GB,或许两个A10能跑起来,做个实验试试,嘿嘿~

任务2

使用Function call功能让大模型完成一次简单的"加"与"乘"函数调用,作业截图需包括大模型回复的工具调用情况,参考4.2 Function call(选做)

先启动API服务器:

lmdeploy serve api_server \
     models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat-w4a16-4bit \
    --model-format awq \
    --cache-max-entry-count 0.4 \
    --quant-policy 4 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

新建脚本internlm2_5.py,贴入下述内容:

# 导入openai模块中的OpenAI类,这个类用于与OpenAI API进行交互
from openai import OpenAI


# 创建一个OpenAI的客户端实例,需要传入API密钥和API的基础URL
client = OpenAI(
    api_key='YOUR_API_KEY',  
    # 替换为你的OpenAI API密钥,由于我们使用的本地API,无需密钥,任意填写即可
    base_url="http://0.0.0.0:23333/v1"  
    # 指定API的基础URL,这里使用了本地地址和端口
)

# 调用client.models.list()方法获取所有可用的模型,并选择第一个模型的ID
# models.list()返回一个模型列表,每个模型都有一个id属性
model_name = client.models.list().data[0].id

# 使用client.chat.completions.create()方法创建一个聊天补全请求
# 这个方法需要传入多个参数来指定请求的细节
response = client.chat.completions.create(
  model=model_name,  
  # 指定要使用的模型ID
  messages=[  
  # 定义消息列表,列表中的每个字典代表一个消息
    {"role": "system", "content": "你是一个友好的小助手,负责解决问题."},  
    # 系统消息,定义助手的行为
    {"role": "user", "content": "帮我讲述一个关于狐狸和西瓜的小故事"},  
    # 用户消息,询问时间管理的建议
  ],
    temperature=0.8,  
    # 控制生成文本的随机性,值越高生成的文本越随机
    top_p=0.8  
    # 控制生成文本的多样性,值越高生成的文本越多样
)

# 打印出API的响应结果
print(response.choices[0].message.content)  

python运行一下:

在这里插入图片描述
我们成功地使用本地API与大模型进行了一次对话,服务器终端反馈也是正常的:
在这里插入图片描述

关于Function call,即函数调用功能,它允许开发者在调用模型时,详细说明函数的作用,并使模型能够智能地根据用户的提问来输入参数并执行函数。完成调用后,模型会将函数的输出结果作为回答用户问题的依据。

启动API服务器:

lmdeploy serve api_server \
    models/Shanghai_AI_Laboratory/internlm2_5-7b-chat \
    --model-format hf \
    --quant-policy 4 \
    --cache-max-entry-count 0.4 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

新建脚本internlm2_5_func.py,贴入下述内容:

from openai import OpenAI


def add(a: int, b: int):
   return a + b


def mul(a: int, b: int):
   return a * b


tools = [{
   'type': 'function',
   'function': {
       'name': 'add',
       'description': 'Compute the sum of two numbers',
       'parameters': {
           'type': 'object',
           'properties': {
               'a': {
                   'type': 'int',
                   'description': 'A number',
               },
               'b': {
                   'type': 'int',
                   'description': 'A number',
               },
           },
           'required': ['a', 'b'],
       },
   }
}, {
   'type': 'function',
   'function': {
       'name': 'mul',
       'description': 'Calculate the product of two numbers',
       'parameters': {
           'type': 'object',
           'properties': {
               'a': {
                   'type': 'int',
                   'description': 'A number',
               },
               'b': {
                   'type': 'int',
                   'description': 'A number',
               },
           },
           'required': ['a', 'b'],
       },
   }
}]
messages = [{'role': 'user', 'content': 'Compute (3+5)*2'}]

client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
model_name = client.models.list().data[0].id
response = client.chat.completions.create(
   model=model_name,
   messages=messages,
   temperature=0.8,
   top_p=0.8,
   stream=False,
   tools=tools)
print(response)
func1_name = response.choices[0].message.tool_calls[0].function.name
func1_args = response.choices[0].message.tool_calls[0].function.arguments
func1_out = eval(f'{func1_name}(**{func1_args})')
print(func1_out)

messages.append({
   'role': 'assistant',
   'content': response.choices[0].message.content
})
messages.append({
   'role': 'environment',
   'content': f'3+5={func1_out}',
   'name': 'plugin'
})
response = client.chat.completions.create(
   model=model_name,
   messages=messages,
   temperature=0.8,
   top_p=0.8,
   stream=False,
   tools=tools)
print(response)
func2_name = response.choices[0].message.tool_calls[0].function.name
func2_args = response.choices[0].message.tool_calls[0].function.arguments
func2_out = eval(f'{func2_name}(**{func2_args})')
print(func2_out)

python运行一下:

在这里插入图片描述
可以看到InternLM2.5将输入’Compute (3+5)*2’根据提供的function拆分成了"加"和"乘"两步,第一步调用function add实现加,再于第二步调用function mul实现乘,再最终输出结果16.
到这里基本上就完成了任务,不过测试的时候发现一个bug,即将输入换成Compute (4+6)*2时,再执行上述脚本:
在这里插入图片描述
根据输出可以发现模型并没有智能的调用function,这应该是因为模型本身就可以解决这个问题,不需要调用function工具,后面可以再测试一下,嘿嘿~


原文地址:https://blog.csdn.net/fangsfdavid/article/details/143931350

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!