LLM量化文档.md 13 KB
Newer Older
wanglch's avatar
wanglch committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# LLM量化文档
swift支持使用awq、gptq、bnb、hqq、eetq技术对模型进行量化。其中awq、gptq量化技术支持vllm进行推理加速,需要使用校准数据集,量化性能更好,但量化速度较慢。而bnb、hqq、eetq无需校准数据,量化速度较快。这五种量化方法都支持qlora微调。

awq、gptq需要使用`swift export`进行量化。而bnb、hqq、eetq可以直接在sft和infer时进行快速量化。


从vllm推理加速支持的角度来看,更推荐使用awq和gptq进行量化。从量化效果的角度来看,更推荐使用awq、hqq和gptq进行量化。而从量化速度的角度来看,更推荐使用hqq进行量化。


## 目录
- [环境准备](#环境准备)
- [原始模型](#原始模型)
- [微调后模型](#微调后模型)
- [QLoRA微调](#QLoRA微调)
- [推送模型](#推送模型)

## 环境准备
GPU设备: A10, 3090, V100, A100均可.
```bash
# 设置pip全局镜像 (加速下载)
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
# 安装ms-swift
git clone https://github.com/modelscope/swift.git
cd swift
pip install -e '.[llm]'

# 使用awq量化:
# autoawq和cuda版本有对应关系,请按照`https://github.com/casper-hansen/AutoAWQ`选择版本
pip install autoawq -U

# 使用gptq量化:
# auto_gptq和cuda版本有对应关系,请按照`https://github.com/PanQiWei/AutoGPTQ#quick-installation`选择版本
pip install auto_gptq -U

# 使用bnb量化:
pip install bitsandbytes -U

# 使用hqq量化:
# pip install transformers>=4.41
pip install hqq

# 使用eetq量化:
# pip install transformers>=4.41

# 参考https://github.com/NetEase-FuXi/EETQ
git clone https://github.com/NetEase-FuXi/EETQ.git
cd EETQ/
git submodule update --init --recursive
pip install .

# 环境对齐 (通常不需要运行. 如果你运行错误, 可以跑下面的代码, 仓库使用最新环境测试)
pip install -r requirements/framework.txt  -U
pip install -r requirements/llm.txt  -U
```

## 原始模型

### awq、gptq

这里展示对qwen1half-7b-chat进行awq, gptq量化.
```bash
# awq-int4量化 (使用A100大约需要18分钟, 显存占用: 13GB)
# 如果出现量化的时候OOM, 可以适度降低`--quant_n_samples`(默认256)和`--quant_seqlen`(默认2048).
# gptq-int4量化 (使用A100大约需要20分钟, 显存占用: 7GB)

# awq: 使用`alpaca-zh alpaca-en sharegpt-gpt4:default`作为量化数据集
CUDA_VISIBLE_DEVICES=0 swift export \
    --model_type qwen1half-7b-chat --quant_bits 4 \
    --dataset alpaca-zh alpaca-en sharegpt-gpt4:default --quant_method awq

# gptq: 使用`alpaca-zh alpaca-en sharegpt-gpt4:default`作为量化数据集
# gptq量化请先查看此issue: https://github.com/AutoGPTQ/AutoGPTQ/issues/439
OMP_NUM_THREADS=14 CUDA_VISIBLE_DEVICES=0 swift export \
    --model_type qwen1half-7b-chat --quant_bits 4 \
    --dataset alpaca-zh alpaca-en sharegpt-gpt4:default --quant_method gptq

# awq: 使用自定义量化数据集
# gptq同理
CUDA_VISIBLE_DEVICES=0 swift export \
    --model_type qwen1half-7b-chat --quant_bits 4 \
    --dataset xxx.jsonl \
    --quant_method awq

# 推理 swift量化产生的模型
# awq
CUDA_VISIBLE_DEVICES=0 swift infer \
    --model_type qwen1half-7b-chat \
    --model_id_or_path qwen1half-7b-chat-awq-int4
# gptq
CUDA_VISIBLE_DEVICES=0 swift infer \
    --model_type qwen1half-7b-chat \
    --model_id_or_path qwen1half-7b-chat-gptq-int4

# 推理 原始模型
CUDA_VISIBLE_DEVICES=0 swift infer --model_type qwen1half-7b-chat
```

**量化效果对比**:

```python
# swift量化产生的awq-int4模型
"""
<<< 你好
你好!有什么问题我可以帮助你吗?
--------------------------------------------------
<<< 2000年是闰年嘛?
是的,2000年是闰年。闰年规则是:普通年份能被4整除但不能被100整除,或者能被400整除的年份就是闰年。2000年满足后者,所以按照公历是闰年。
--------------------------------------------------
<<< 15869+587=?
15869 + 587 = 16456
--------------------------------------------------
<<< 浙江的省会在哪
浙江省的省会是杭州市。
--------------------------------------------------
<<< 这有什么好吃的
浙江美食非常丰富,以下列举一些具有代表性的:

1. **杭州菜**:如西湖醋鱼、东坡肉、龙井虾仁、叫化童鸡等,清淡而精致。
2. **宁波菜**:如红烧肉、汤圆、水磨年糕、宁波汤包等,口味鲜美。
3. **温州菜**:温州海鲜如蝤蛑、蝤蛑炒年糕、瓯菜,口味偏咸鲜。
4. **绍兴菜**:如东坡肉、霉干菜扣肉、绍兴黄酒等,酒香浓郁。
5. **嘉兴粽子**:如嘉兴肉粽,特别是五芳斋的粽子,口感软糯。
6. **金华火腿**:浙江特产,以金华地区最为著名,口感醇厚。
7. **浙东土菜**:如农家小炒、野菜、腌菜等,原汁原味。

各地还有许多特色小吃,如杭州的知味观、宋城的宋嫂鱼羹,以及各种小吃街如河坊街、西湖醋鱼一条街等,都值得一尝。如果你有具体地方或口味偏好,可以告诉我,我可以给出更具体的建议。
"""

# swift量化产生的gptq-int4模型
"""
<<< 你好
你好!很高兴为你提供帮助。有什么问题或需要咨询的吗?
--------------------------------------------------
<<< 2000年是闰年嘛?
是的,2000年是闰年。根据格里高利历(公历),闰年的规则是:普通年份能被4整除但不能被100整除,或者能被400整除的年份就是闰年。2000年满足后两个条件,所以是闰年。
--------------------------------------------------
<<< 15869+587=?
15869 + 587 = 16456
--------------------------------------------------
<<< 浙江的省会在哪
浙江省的省会是杭州市。
--------------------------------------------------
<<< 这有什么好吃的
浙江美食丰富多样,以下是一些具有代表性的:

1. **杭州菜**:如东坡肉、西湖醋鱼、龙井虾仁、叫化鸡等,注重原汁原味,讲究刀工和火候。
2. **宁波的海鲜**:如宁波汤圆、海鲜大餐,宁波炒肉丝也很有名。
3. **嘉兴粽子**:以嘉兴五芳斋的粽子最为人知,有各种口味如肉粽、豆沙粽等。
4. **绍兴黄酒**:搭配当地特色菜肴,如醉鸡、糟溜鱼片等。
5. **金华火腿**:浙江特产,口感醇厚,常作为节日礼品。
6. **温州瓯菜**:口味偏酸辣,如温州鱼生、白斩鸡等。
7. **浙东佛跳墙**:类似福建的佛跳墙,用多种海鲜和山珍炖制。

如果你对某种具体的食物感兴趣,可以告诉我,我可以提供更详细的推荐。
"""

# 原始模型
"""
<<< 你好
你好!有什么问题我可以帮助你吗?
--------------------------------------------------
<<< 2000年是闰年嘛?
是的,2000年是闰年。根据格里高利历(公历),闰年的规则是:普通年份能被4整除但不能被100整除,或者能被400整除的年份都是闰年。2000年满足后者,所以是闰年。
--------------------------------------------------
<<< 15869+587=?
15869 + 587 = 16456
--------------------------------------------------
<<< 浙江的省会在哪
浙江省的省会是杭州市。
--------------------------------------------------
<<< 这有什么好吃的
浙江的美食非常丰富,以下列举一些具有代表性的:

1. **杭州菜**:如西湖醋鱼、东坡肉、龙井虾仁、叫化童鸡等,清淡鲜美,注重原汁原味。
2. **宁波菜**:如宁波汤圆、红烧肉、海鲜类,如宁波海鲜面、清蒸河鳗等。
3. **绍兴菜**:如霉干菜扣肉、茴香豆、醉排骨,特色是酱香浓郁。
4. **温州菜**:如温州鱼丸、白斩鸡、楠溪江三鲜,口味偏咸鲜。
5. **嘉兴粽子**:特别是嘉兴五芳斋的粽子,闻名全国,甜咸皆有。
6. **金华火腿**:浙江名特产,口感鲜美,营养丰富。
7. **浙东土菜**:如东阳火腿、嵊州菜、台州海鲜等,地方特色鲜明。

当然,浙江各地还有许多特色小吃,如衢州的鸭头、湖州的粽子、舟山的海鲜等,你可以根据自己的口味选择。如果你需要更具体的推荐,可以告诉我你对哪种类型或者哪个地方的美食感兴趣。
"""
```


### bnb、hqq、eetq
对于bnb、hqq、eetq,我们只需要使用swift infer来进行快速量化并推理。
```bash
CUDA_VISIBLE_DEVICES=0 swift infer \
    --model_type qwen1half-7b-chat \
    --quant_method bnb \
    --quantization_bit 4

CUDA_VISIBLE_DEVICES=0 swift infer \
    --model_type qwen1half-7b-chat \
    --quant_method hqq \
    --quantization_bit 4

CUDA_VISIBLE_DEVICES=0 swift infer \
    --model_type qwen1half-7b-chat \
    --quant_method eetq \
    --dtype fp16
```

## 微调后模型

假设你使用lora微调了qwen1half-4b-chat, 模型权重目录为: `output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx`.

这里只介绍使用awq技术对微调后模型进行量化, 如果要使用gptq技术量化, 同理.

**Merge-LoRA & 量化**
```shell
# 使用`alpaca-zh alpaca-en sharegpt-gpt4:default`作为量化数据集
CUDA_VISIBLE_DEVICES=0 swift export \
    --ckpt_dir 'output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx' \
    --merge_lora true --quant_bits 4 \
    --dataset alpaca-zh alpaca-en sharegpt-gpt4:default --quant_method awq

# 使用微调时使用的数据集作为量化数据集
CUDA_VISIBLE_DEVICES=0 swift export \
    --ckpt_dir 'output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx' \
    --merge_lora true --quant_bits 4 \
    --load_dataset_config true --quant_method awq
```

**推理量化后模型**
```shell
# awq/gptq量化模型支持vllm推理加速. 也支持模型部署.
CUDA_VISIBLE_DEVICES=0 swift infer --ckpt_dir 'output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx-merged-awq-int4'
```

**部署量化后模型**

服务端:

```shell
CUDA_VISIBLE_DEVICES=0 swift deploy --ckpt_dir 'output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx-merged-awq-int4'
```

测试:
```shell
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen1half-4b-chat",
"messages": [{"role": "user", "content": "晚上睡不着觉怎么办?"}],
"max_tokens": 256,
"temperature": 0
}'
```

## QLoRA微调

### awq、gptq
如果想要对awq、gptq量化的模型进行qlora微调,你需要进行提前量化。例如可以对原始模型使用`swift export`进行量化。然后使用以下命令进行微调,你需要指定`--quant_method`来指定对应量化的方式:

```bash
# awq
CUDA_VISIBLE_DEVICES=0 swift sft \
    --model_type qwen1half-7b-chat \
    --model_id_or_path qwen1half-7b-chat-awq-int4 \
    --quant_method awq \
    --sft_type lora \
    --dataset alpaca-zh#5000 \

# gptq
CUDA_VISIBLE_DEVICES=0 swift sft \
    --model_type qwen1half-7b-chat \
    --model_id_or_path qwen1half-7b-chat-gptq-int4 \
    --quant_method gptq \
    --sft_type lora \
    --dataset alpaca-zh#5000 \
```


### bnb、hqq、eetq
如果想要使用bnb、hqq、eetq进行qlora微调,你需要在训练中指定`--quant_method``--quantization_bit`

```bash
# bnb
CUDA_VISIBLE_DEVICES=0 swift sft \
    --model_type qwen1half-7b-chat \
    --sft_type lora \
    --dataset alpaca-zh#5000 \
    --quant_method bnb \
    --quantization_bit 4 \
    --dtype fp16 \

# hqq
CUDA_VISIBLE_DEVICES=0 swift sft \
    --model_type qwen1half-7b-chat \
    --sft_type lora \
    --dataset alpaca-zh#5000 \
    --quant_method hqq \
    --quantization_bit 4 \

# eetq
CUDA_VISIBLE_DEVICES=0 swift sft \
    --model_type qwen1half-7b-chat \
    --sft_type lora \
    --dataset alpaca-zh#5000 \
    --quant_method eetq \
    --dtype fp16 \
```

**注意**
- hqq支持更多自定义参数,比如为不同网络层指定不同量化配置,具体请见[命令行参数](https://github.com/modelscope/swift/blob/main/docs/source/LLM/命令行参数.md)
- eetq量化为8bit量化,无需指定quantization_bit。目前不支持bf16,需要指定dtype为fp16
- eetq目前qlora速度比较慢,推荐使用hqq。参考[issue](https://github.com/NetEase-FuXi/EETQ/issues/17)


## 推送模型
假设你使用lora微调了qwen1half-4b-chat, 模型权重目录为: `output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx`.

```shell
# 推送原始量化模型
CUDA_VISIBLE_DEVICES=0 swift export \
    --model_type qwen1half-7b-chat \
    --model_id_or_path qwen1half-7b-chat-gptq-int4 \
    --push_to_hub true \
    --hub_model_id qwen1half-7b-chat-gptq-int4 \
    --hub_token '<your-sdk-token>'

# 推送lora增量模型
CUDA_VISIBLE_DEVICES=0 swift export \
    --ckpt_dir output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx \
    --push_to_hub true \
    --hub_model_id qwen1half-4b-chat-lora \
    --hub_token '<your-sdk-token>'

# 推送merged模型
CUDA_VISIBLE_DEVICES=0 swift export \
    --ckpt_dir output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx \
    --push_to_hub true \
    --hub_model_id qwen1half-4b-chat-lora \
    --hub_token '<your-sdk-token>' \
    --merge_lora true

# 推送量化后模型
CUDA_VISIBLE_DEVICES=0 swift export \
    --ckpt_dir output/qwen1half-4b-chat/vx-xxx/checkpoint-xxx \
    --push_to_hub true \
    --hub_model_id qwen1half-4b-chat-lora \
    --hub_token '<your-sdk-token>' \
    --merge_lora true \
    --quant_bits 4
```