【书生大模型实战营】LMDeploy 量化部署进阶实践

news2024/9/20 14:41:44

LMDeploy 量化部署进阶实践

  • 【书生大模型实战营】LMDeploy 量化部署进阶实践
    • 任务
    • 环境
    • 将大模型封装为API接口服务
      • 以命令行形式连接API服务器
      • 以Gradio网页形式连接API服务器
    • LMDeploy Lite和InternLM
      • kv cache
      • W4A16 模型量化和部署
      • W4A16 量化+ KV cache+KV cache 量化
    • LMDeploy与InternVL2
    • LMDeploy之FastAPI与Function call
      • API开发
      • Function call
    • 任务记录

【书生大模型实战营】LMDeploy 量化部署进阶实践

任务

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

环境

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

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

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

使用上一节创建好的agent环境,然后安装一些依赖:

conda activate agent_camp3
pip install timm==1.0.8 openai==1.40.3 lmdeploy[all]==0.5.3

然后设置要用到模型文件的软链接:

ln -s /root/share/new_models//Shanghai_AI_Laboratory/internlm2_5-7b-chat /root/model
ln -s /root/share/new_models/OpenGVLab/InternVL2-26B /root/model

然后对InternLM2_5-7b-chat进行部署验证:

lmdeploy chat /root/model/internlm2_5-7b-chat

结果如下:
在这里插入图片描述
此时显存占用是接近23G:
在这里插入图片描述

将大模型封装为API接口服务

以InternLM2.5为例,在vscode命令行运行如下命令:

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

其中:

  • quant-policy:这个参数指定了量化策略。
  • tp:这个参数表示并行数量(GPU数量)。
  • model-format:这个参数指定了模型的格式。hf代表“Hugging Face”格式。

得到如下界面,是一个FastAPI请求格式的命令说明:
在这里插入图片描述

以命令行形式连接API服务器

新建一个命令行窗口,运行:

lmdeploy serve api_client http://localhost:23333

得到如下结果:
在这里插入图片描述
上面API界面回应如下:
在这里插入图片描述
此时调用了/v1/chat/interactive这个接口。

以Gradio网页形式连接API服务器

退出上面创建的命令行终端,输入以下命令,使用Gradio作为前端,启动网页:

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

结果如下:
在这里插入图片描述

LMDeploy Lite和InternLM

kv cache

在使用lmdeploy chat /root/models/internlm2_5-7b-chat,引入cache-max-entry-count变量设置,控制kv缓存占用剩余显存的最大比例,默认值为0.8,如:

lmdeploy chat /root/model/internlm2_5-7b-chat --cache-max-entry-count 0.4

这个命令是在命令行和模型进行交互的,此时显存占用只有19G,跟0.8相比减少了4G。
在这里插入图片描述

在线 kv cache int4/int8 量化:创建API服务时使用KV cache nt4/int8 量化,就是将kv cache的存储类型用int4或者int8代替。通过设定 quant_policy cache-max-entry-count参数:

  • quant_policy :qant_policy=4 表示 kv int4 量化,quant_policy=8 表示 kv int8 量化
  • cache-max-entry-count:kv cache比例
lmdeploy serve api_server \
    /root/model/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

这个命令是通过接口的方式和大模型进行交互的。相比使用BF16精度的kv cache,int4的Cache可以在相同4GB的显存下只需要4位来存储一个数值,而BF16需要16位。这意味着int4的Cache可以存储的元素数量是BF16的四倍。

此时占用的显存为:
在这里插入图片描述

W4A16 模型量化和部署

模型量化是一种优化技术,旨在减少机器学习模型的大小并提高其推理速度。量化通过将模型的权重和激活从高精度(如16位浮点数)转换为低精度(如8位整数、4位整数、甚至二值网络)来实现。

W4A16的量化配置意味着:

  • 权重被量化为4位整数。
  • 激活保持为16位浮点数。

使用如下命令执行量化:

lmdeploy lite auto_awq \
   /root/model/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 /root/model/internlm2_5-7b-chat-w4a16-4bit

相关参数解释如下:

  • lmdeploy lite auto_awq:启动量化,auto_awq代表自动权重量化(auto-weight-quantization)
  • calib-dataset 'ptb': 这个参数指定了一个校准数据集
  • w-bits 4: 这表示权重(weights)的位数将被量化为4位。
  • work-dir: 这是工作目录的路径,用于存储量化后的模型和中间结果。

如果出现错误The repository for ptb_text_only contains custom code which must be executed to correctly load the dataset.,添加如下指令:

export HF_ENDPOINT=https://hf-mirror.com 

W4A16 量化+ KV cache+KV cache 量化

使用如下命令,将这些方案全部使用(时间比较长,大概5个多小时):

lmdeploy serve api_server \
    /root/model/internlm2_5-7b-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

注意这里使用的模型是W4A16量化后的模型,同时model-format参数也变成了awq,不是hf了。

最终得到的模型大小为:
在这里插入图片描述
只有4.9G了,而原始模型的大小有15G。
然后使用如下命令运行模型:

lmdeploy chat /root/model/internlm2_5-7b-chat-w4a16-4bit/ --model-format awq

LMDeploy与InternVL2

进行InternVL2的W4A16量化(大概10个小时),代码为:

lmdeploy lite auto_awq \
   /root/model/InternVL2-26B \
  --calib-dataset 'ptb' \
  --calib-samples 128 \
  --calib-seqlen 2048 \
  --w-bits 4 \
  --w-group-size 128 \
  --batch-size 1 \
  --search-scale False \
  --work-dir /root/model/InternVL2-26B-w4a16-4bit

然后使用如下命令启用API服务:

lmdeploy serve api_server \
    /root/model/InternVL2-26B-w4a16-4bit \
    --model-format awq \
    --quant-policy 0 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

不过这个30%的跑不起来,显存会爆,需要使用50%的。

LMDeploy之FastAPI与Function call

API开发

先启动API服务:

lmdeploy serve api_server \
    /root/model/internlm2_5-7b-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 internlm2_5.py,得到如下结果:
在这里插入图片描述
API服务开启界面的反应:
在这里插入图片描述

Function call

启动没有量化的模型(使用量化的后面调用函数会报错 'NoneType' object is not subscriptable):

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

抱持API服务的窗口不变,继续创建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)

得到的结果如下:
在这里插入图片描述
这种工具感觉会根据函数自动对指令进行分析,将(3+5)2分成了(3+5)和82。

任务记录

使用如下命令开启量化后模型的API服务:

lmdeploy serve api_server \
    /root/model/internlm2_5-7b-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

然后在命令行指定接口和大模型进行交流:

lmdeploy serve api_client http://localhost:23333

此时大模型的回复和显存占用为:
在这里插入图片描述
然后我们尝试在文件里面和量化后的模型进行交流,创建internlm2_5_awq.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)

然后运行,得到的结果如下:
在这里插入图片描述
最后实现function call功能。直接套用之前的代码会报错,应该是量化过后模型的理解能力下降了,查看输出的response可以出现了解析错误:
在这里插入图片描述
这个时候我们尝试更改temperaturetop_p,这两个参数的意义为:

  • temperature:这个值越大生成内容越随机,多样性更好,但可能会牺牲一些准确性或连贯性。具体地,temperature 会调整概率输出的softmax概率分布,如果 temperature 的值为1,则没有任何调整;如果其值比1大,则会生成更加随机的文本;如果其值比1小,则生成的文本更加保守。
  • top_p:单步累计采用阈值,越大越多token会被考虑。如果累计概率已经超过0.95,剩下的token不会被考虑例如有下面的token及其概率,a:0.9,b:0.03,c:0.03,d:0.015,e… 。则只会采用用abc,因为已经是0.96超过了0.95

修改temperature=1.9,top_p=0.9,得到的结果为(尝试了多次,因为结果随机):
在这里插入图片描述
但它没有使用tool_calls,调整参数也不行。

不知道咋解决了,暂时放在这里吧,感觉还是它理解能力下降了,导致模型无法解析。

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

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

相关文章

【JavaEE】MyBatis 实战指南:从 JDBC 到高效数据库操作的进阶教程

目录 MyBatis 操作数据库JDBC 操作⽰例回顾什么是MyBatis?MyBatis⼊⻔1. 准备⼯作2. 配置数据库连接字符串3. 写持久层代码4. 单元测试使用MyBatis可能遇到的问题 MyBatis的基础操作打印⽇志参数传递增(Insert)返回主键 删(Delete)改(Update)查(Select)起别名结果映射开启驼峰…

vue使用高德获取当前地区天气

1、收件箱 | 高德控制台 (amap.com) 首先打开高德开放平台注册一下 2、创建一个应用获取到key后面获取天气的时候 请求接口的时候会用到key 2.1.1 创建应用的时候注意类型选成天气 2.1.2 创建完成之后就点添加key 然后选择web服务就行 3、可以调取天气接口 天气查询-基础 API…

https握手过程详解

https握手过程详解 上一篇《HTTPS通讯全过程》中https握手过程实际上还有更多的细节,为什么会这样设计呢?是因为一开始将握手过程时,吧步骤说的太详细会导致更难理解惹。所以我就先在上一篇把部分细节忽略,把原来几步的过程先简化…

洛杉物理服务器怎么样?

洛杉矶作为美国科技和互联网的重要中心,物理服务器的质量通常非常高,可以提供卓越的性能、强大的安全性、多样的配置选项和专业的服务支持。以下是对洛杉物理服务器的详细介绍。 1. 优质的性能 稳定的网络连接:洛杉矶物理服务器位于先进的数据…

CASS11时空版 全新升级支持多版本CAD软件下载License使用

南方数码地形地籍成图软件CASS,经过二十余年的发展,市场和技术积累丰厚,用户遍及国内外测绘地理信息相关行业。软件销量和市场占有率持续领先,是业内应用广,服务优的软件品牌。 南方数码深刻理解信息化测绘的内…

合宙LuatOS生成毫秒级时间戳

合宙Luatos - os操作 os.time()生成时间戳的精度只能达到秒级,在很多联网应用中需要毫秒级的时间戳。 经查看LuatOS-SOC接口文档,发现了解决办法。 socket - 网络接口文档 通过文档,我们只要获取当前数,然后把毫秒数与os.time(…

【C语言】:字符和字符串中的字符比较

1.入门 当我们想要一个字符和字符串中的某个字符进行比较时,可以直接用“”进行比较。 为什么可以用“”? 因为字符是存放在常量区,字符变量的值是固定的,字符之间的比较,本质上是对字符的ASCII比较。ASCII_百度百科…

FinalData-绿色便携免安装数据恢复软件 下载

下载地址(资源制作整理不易,使用需付费,不能接受请勿浪费时间下载): 链接:https://pan.baidu.com/s/17CH5tkSc2qAj-6FuGvfb9Q?pwdvyze 提取码:vyze

基于Java语言的能源管理系统-水电气热油数据采集系统

基于Java语言的能源管理系统-水电气热油数据采集系统 介绍 适用于高能耗企业、建筑、工厂、园区的水、电、气、热、油、空压机等能源数据采集、分析、报表; 基于SpringCloud的能源管理系统-能源管理平台源码-能源在线监测平台-双碳平台源码-SpringCloud全家桶-能管…

string模拟

本章准备对string模拟进行讲解,以下是string的学习网址: string - C Reference (cplusplus.com) string本质可以理解为储存char类型的顺序表,其中string的迭代器用一个char*就可以解决。所以string类成员变量如下: 这里用了一个命…

PumpkinRaising靶机

端口扫描 目录扫描 访问80端口, 在页面上面发现提到了一个Jack,可能是一个用户名 f12查看源码 找到一个页面 拼接访问 查看源码 发现一个注释 解密 是一个目录 /scripts/spy.pcap 访问,自动下载了一个文件 wireshark打开流量包 找到第一个s…

Element plus部分组件样式覆盖记录

文章目录 一、el-button 样式二、Popconfirm 气泡确认框三、Popover 气泡卡片四、Checkbox 多选框五、Pagination 分页六、Form 表单七、Table 表格 一、el-button 样式 html&#xff1a; <el-button class"com_btn_style">button</el-button>样式覆盖…

端口隔离 Port isolation 华为交换机配置端口隔离

Port isolation 什么是端口隔离 如果用户想进行二层隔离&#xff0c;用户可以将不同的端口加入不同的VLAN&#xff0c;但这样会浪费有限的VLAN资源。采用端口隔离功能&#xff0c;可以实现同一VLAN内端口之间的隔离。用户只需要将端口加入到隔离组中&#xff0c;就可以实现隔离…

hyper-v连接显卡,hyper-v使用显卡能力、Hyper-V显卡虚拟化VMGpu设置

hyper-v连接显卡&#xff0c;hyper-v使用显卡能力、Hyper-V显卡虚拟化VMGpu设置 现在越来越多的软件在使用时&#xff0c;都会调用GPU获得更好的使用效果。如&#xff1a;浏览器的硬件加速模式。由于Nvidia和AMD都屏蔽了家用显卡虚拟化技术&#xff0c;常用的虚拟机也无法对显卡…

交互式散点图,快速提升你的PPT观赏性|每日科研绘图·24-08-17

一、散点图基础概念 散点图是一种非常直观且功能强大的图表&#xff0c;用于探索和展示两个数值变量之间的相关性。这种图表通过在二维平面上绘制数据点&#xff0c;使得观察者能够一眼看出变量间的潜在联系。 1-1&#xff1a;散点图的构成 X轴&#xff08;横轴&#xff09;&…

电话语音机器人优势很多

智能语音机器人近年来备受关注&#xff0c;受到很多个人或是企业的青睐&#xff0c;其广泛受到欢迎归因于智能语音机器人对电话销售提供了极大的帮助&#xff0c;其可以完美替代人工进行电销外呼服务&#xff0c;不间断的工作&#xff0c;不带有任何情绪色彩&#xff0c;且能实…

Hive:大数据时代的SQL魔法师

时间&#xff1a;2024年08月17日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频地址&#xff1a;https://xima.tv/1_ZRh54d?_sonic0 希望大家帮个忙&#xff01;如果大家有工作机会&#xff0c;希望帮小蒋内推一下&#x…

半岛体存储器常见类型简介

前言 个人邮箱&#xff1a;zhangyixu02gmail.com在学习 ESP32 的存储器结构时&#xff0c;发现 DRAM 是 Data RAM 而非 Dynamic RAM&#xff0c;IRAM 是 Instruction RAM 而非 Internal RAM 。突然发现自己对于这一块的知识还比较混乱&#xff0c;因此查阅相关资料进行学习整理…

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(一)---UnrealCV获取深度+分割图像

前言 本系列教程旨在使用UE5配置一个具备激光雷达深度摄像机的仿真小车&#xff0c;并使用通过跨平台的方式进行ROS2和UE5仿真的通讯&#xff0c;达到小车自主导航的目的。本教程使用的环境&#xff1a; ubuntu 22.04 ros2 humblewindows11 UE5.4.3python8 本系列教程将涉及以…

04-正弦波,衰减正弦波,正弦波脉冲冲串的产生

1.设置波形线宽 点击Waveforms a 2.添加Comment 3.添加正弦波 3.1先添加一个电压源 3.2增加波形窗口 3.3右键选择Advanced 3.31原始正弦波 名称含义①DC offset直流偏置②Amplitude幅值③Freq频率④Tdelay延迟⑤Theta衰减⑥Phi相位⑦Ncycles产生正弦波的个数 设置完成后&am…