0%

大模型应用系列(七) LLama Factory和OpenWebui的安装和使用

详细介绍了LLamaFactory和OpenWebui的安装和使用, 以及如何在LLamaFactory上进行推理,微调。以及如何通过脚本对模型进行Lora微调。最后解释量化原理。

一. LLama Factory的安装

我的服务器配置为:

RTX 4090, cuda 12.4 python=3.10 pytorch=2.5.1

本文涉及的所有模型,数据集下载方法参考:

Huggingface的安装和使用 | CodeRQ

参考官网资料即可:

LLaMA-Factory/README_zh.md at main · hiyouga/LLaMA-Factory · GitHub

安装命令,首先拉去llamaFactory代码仓,然后进入代码仓目录,即LLamA-Factory, 接着执行安装指令。

1
2
3
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e . # 官网要装其他包,但建议先装基础就行,其他的运行时缺啥补啥就行。

可能网络问题连不上git,可以在本地拉取后上传到服务器。

官网给出了使用的三种基本操作:LoRA微调,推理,合并

1
2
3
llamafactory-cli train examples/train_lora/llama3_lora_sft.yaml
llamafactory-cli chat examples/inference/llama3_lora_sft.yaml
llamafactory-cli export examples/merge_lora/llama3_lora_sft.yaml

但建议直接用可视化界面,监控方便一些。启动界面的时候路径一定要在 LLaMA-Factory

1
llamafactory-cli webui

但是这个界面是在服务器上启动的,本地理论上是访问不到的,如果用vscode,它自带端口转发,会将服务器上的端口转发到本地,可以直接访问。

image-20250322085717610

启动后界面如下:

image-20250322085822264

二. 使用LLamaFacory进行LoRA微调

模型 数据集
Qwen2.5-0.5B-Instruct LLamaFactory自带数据集identity.json
2.1 准备数据集

LLamaFactory在文件夹./LLamA-Factory/data/下给出了一些实例数据集,选择其中的identity.json作为微调示例。示例数据如下,将其中的{{name}},{{author}}替换成对应的数据即可。

image-20250322090324378

我修改为如下内容:

image-20250322090639811

如果是自己准备的数据集,也要放大data目录下,同时在其中的dataset_info.json文件中配置自己数据集的信息,这里使用的是示例数据集,因此已经配置好,配置完在UI界面才可以找到该数据集。

image-20250322091121652

2.2 准备模型

从huggingface上下载qwen2.5-0.5B-Instruct,具体方法见前文。

2.3 在UI界面上配置模型和数据,开始LoRA微调

配置如下:

image-20250322094406107

点击开始按钮,开始训练,同时开启新的终端监测GPU使用情况,检测方法前文说过,

image-20250322094557848

这里显存利用率较低,可以增加batch-size,一般怎加到利用率为90%为最佳,我改为50.

如果点击中断后重新开始,会报错(报错要看后台):

image-20250322095440471

这是因为训练结果的保存目录已经创建,它默认不会覆盖,这个目录在LLamaFactory下的saves文件加中,将它里面的东西删除即可。(删到只剩saves)也可以改一下输出目录的名称:

image-20250322101243548

但是发现个问题,AutoDL上训练如果batch-size开太大有问题,显存在动但训练进度不动。我发现设置为10就可以,但显存也没满。AutoDL的毛病,其他服务器应该就不会。

重新点击开始。后台看到训练在进行:

image-20250322100441051

界面中会给出损失曲线:

image-20250322100524476

浅蓝色的是实际的loss曲线,深蓝色是loss曲线平滑后的结果,便于观察趋势,当loss曲线趋于平滑,即变化不大,就可以终止训练了。

训练的权重会保存在saves文件夹下,默认每100个epoch保存一次。

如果中断后想从上次训练的checkpoints继续训练,则加载模型时加载对应的LoRA参数,同时修改输出目录,点击开始即可。

image-20250322101553974

image-20250322101623058

可以看到,一开始loss就很小,说明是从上次的检查点开始的

image-20250322101913757

三. 测试训练效果

使用LLamaFactory的chat功能

3.1首先加载原模型:

image-20250322102441651

可以直接在下面对话款对话,结果如下:

image-20250322102507513

3.2 加载训练后的模型

先卸载刚才的模型,

在检查点路径中选择对应的检查点,绝对路径

点击加载模型

image-20250322102635341

结果如下:

image-20250322102736647

输出和训练数据风格一致,说明训练起效果了。

四. 在自己创建的数据集上微调

4.1 制作训练集

首先从官网上观察数据集格式,数据集是json文件, 其中数据是json object 列表,分为单轮对话和多轮对话。

单轮对话格式如下: 其中instruction才是输入,input 是对instruction的补充,可以为空。

1
2
3
4
5
6
7
8
9
10
11
12
[
{
"instruction": "识别并解释给定列表中的两个科学理论:细胞理论和日心说。",
"input": "",
"output": "细胞理论是生物科学的一个理论,它认为所有生命体都是由微小的基本单元——细胞所构成。这是生物学的一个基础理论,认为细胞是所有生物的基本结构和功能单位,所有的生物都是由一个或多个细胞组成,细胞只能通过细胞分裂产生新的细胞。这一理论由薛定谔、施瓦内和雪莱于1839年首次提出。\n\n日心说是指太阳是太阳系的中心,也就是说,行星围绕太阳旋转的理论。这个理论打破了传统的地心说观点,认为地球并不是宇宙的中心。日心说的提出者是尼古拉·哥白尼,他在16世纪初发表了他的著作《天体运行论》,阐述了太阳系行星围绕太阳运行的模型,为天文学的发展做出了巨大贡献。"
},
{
"instruction": "输入三支篮球队的名称并生成一个适当的口号。",
"input": "输入:俄克拉荷马城雷霆队,芝加哥公牛队,布鲁克林网队。",
"output": "输出: \"雷霆,公牛和网队:各显神通,角逐群雄!\""
}
]

多轮对话格式如下: 注意,instruction 是本轮对话,即第三轮,并且多轮之间要有逻辑关系,不然微调出来的模型是混乱的。

1
2
3
4
5
6
7
8
9
10
11
12
[
{
"instruction": "人类指令(必填)",
"input": "人类输入(选填)",
"output": "模型回答(必填)",
"system": "系统提示词(选填)",
"history": [
["第一轮指令(选填)", "第一轮回答(选填)"],
["第二轮指令(选填)", "第二轮回答(选填)"]
]
}
]

我选择弱智吧的问答作为训练集,可以从HF-mirror下载(下载方法见前文(插入链接)LooksJuicy/ruozhiba 内容如下:

1
2
3
4
5
6
7
8
9
10
[
{
"instruction": "只剩一个心脏了还能活吗?",
"output": "能,人本来就只有一个心脏。"
},
{
"instruction": "爸爸再婚,我是不是就有了个新娘?",
"output": "不是的,你有了一个继母。\"新娘\"是指新婚的女方,而你爸爸再婚,他的新婚妻子对你来说是继母。"
},
]

要把它转为LLamaFactory可以识别的格式,转化脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import json
# 要修改文件路径
with open('./data/ruozhiba/ruozhiba_qa.json', 'r', encoding='utf-8') as file:
data_list = json.load(file)

result_list = []
for each in data_list:
result_list.append({"instruction":each['instruction'],
"input": "",
"output": each['output']})
print(len(result_list))
with open("./data/ruozhiba/duozhiba_qa_llamaFactory.json", 'w', encoding='utf-8') as file:
json.dump(result_list, file, ensure_ascii=False, indent=4)

修改后格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
[
{
"instruction": "只剩一个心脏了还能活吗?",
"input": "",
"output": "能,人本来就只有一个心脏。"
},
{
"instruction": "爸爸再婚,我是不是就有了个新娘?",
"input": "",
"output": "不是的,你有了一个继母。\"新娘\"是指新婚的女方,而你爸爸再婚,他的新婚妻子对你来说是继母。"
}
]
4.2 模型微调

注意配置数据集时先将处理好的数据集放到data目录下,然后在dataset_info.json 中配置文件信息。插入:

1
2
3
"duozhiba_qa_llamaFactory": {
"file_name": "duozhiba_qa_llamaFactory.json"
},

参考3.3的配置方法,微调Qwen2.5-0.5B-Instruct, 另外,可以选择多个数据集,会混合起来训练。

image-20250322110317630

训练到损失趋于平缓即可停止。

image-20250322122711208

五. 测试训练效果

LLama-Factory给出了三种微调后的处理方式:Evaluation&Predict(测试), Chat(对话),Export(模型合并,量化)

5.1 Evaluation & Predict

选择模型,最后保存的checkpoint,测试集(如果没有特别划分,可以直接用训练集,这里直接用训练集),截断长度和训练时一致,batch_size可以改变,具体配置如下:

image-20250322124104289

image-20250322124026735

点击开始,后台会报错,因为一些依赖没有安装,缺啥补啥就行。

image-20250322124217867

只会进行一个epoch。测试结果如下:

1
2
3
4
5
6
7
8
9
10
{
"predict_bleu-4": 88.64074418449198,
"predict_model_preparation_time": 0.0065,
"predict_rouge-1": 92.81370474598931,
"predict_rouge-2": 90.33300949197861,
"predict_rouge-l": 91.9221340909091,
"predict_runtime": 329.3329,
"predict_samples_per_second": 4.543,
"predict_steps_per_second": 0.455
}

各个指标的含义在8.1中解释。

5.2 chat

同 四,加载基座模型,设置LoRA配置即可。

效果如下:

image-20250322125150092

image-20250322125228457

和训练数据类似,说明微调起效果了。

注意:每次输入一次对话产生输出后,要清空历史,chat对话框默认是上下文对话,如果不清空历史,上文会影响本轮输出,结果会出错。比如

image-20250322125529070

5.3 合并模型Export

设置好基座模型,LoRA路径,导出目录即可。

其中最大分块大小一般选4G,因为一些机器超过4会有问题。

image-20250322125931429

点击开始。导出后会在目标路径生成一个和base模型格式一样的文件

image-20250322130116083

直接运行该模型就能得到微调后的效果。

5.4 量化

量化主要时用int8甚至更少的比特数表示参数,是为了降低对硬件的依赖,但同样的会造成模型效果的变差,这里量化微调后的模型,LLama-Factory只支持量化合并后的模型,所以只能合并后再量化.

这里量化到int8,量化过程中需要校准,校准数据集都可以,具体校准方法在补充中说明。

image-20250322132401286

需要安装一些包,缺啥补啥就行

注意:auto-gptq包和pytorch版本,cuda版本,python版本有关,我的版本可以直接安装,有时不可以,就先创建一个新的虚拟环境(按照我的配置,特别是python,cuda,pytorch) 然后先安装auto-gtpq,再安装llamafactory,就不容易出错。

另外,量化过程需要从huggingface上下载文件,如果服务器没有梯子,可以配置huggingface国内源,方法之前的文章有写,直接用命令

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

量化完成后出现量化后的模型:

image-20250322135645030

测试该模型效果:

image-20250322135940845

结果混乱了,并不是量化过程出错。但说明这次量化失败了,主要这个模型本来就很小,量化后精度损失太大了,按理来说,模型越大,量化后精度损失越小。

六. 使用OpenWebui

6.1 open webui 下载

注意:openwebui要在python=3.11下安装,所以要新开一个虚拟环境,新开后直接安装就行

1
2
3
conda create -n openwebui python==3.11 -y
conda activate openwebui
pip install open-webui
6.2 启动

首先启动vllm,启动教程前面文章讲过了: ollama,vllm,LMDeploy 部署大模型 | CodeRQ

也可以用其他工具部署,只要记住接口就行了。

接着启动open-webui

启动前要配置几个东西:

1
2
3
export HF_ENDPOINT=https://hf-mirror.com # 要从huggingface下载东西,配置国内huggingface镜像源
export ENABLE_OLLAMA_API=False # open-webui默认用ollama部署,如果用的vllm或者其他,则关闭,如果用ollama就不用
export OPENAI_API_BASE_URL=http://127.0.0.1:8000/v1 # 服务对应的端口,vllm端口在8000

配置完了直接启动

1
open-webui serve

就会启动了,但第一次启动会比较慢,要安装东西,要等一等。

image-20250322142754073

image-20250322143824215

我这里服务器卡住了,按理到这里就是成功了,会弹窗出来。

6.3 解决弹不出窗口的问题

一开始我以为是服务器问题,没有深究,后来通过查阅资料,发现是新版Ollama的问题,我们之前启动LLama-Factory的时候其实服务是启动在服务器上的,之所以我们本地能通过浏览器访问,是因为vscode帮我们做了端口转发,而open-webui启动的时候不会自动做端口转发,所以我们需要自己做端口转发。

在vscode中配置端口转发,把服务器的8080端口转发到本地,即可在本地打开

image-20250328003144480

首次登录需要设置邮箱密码。

image-20250328003251767

设置完密码还需要等很久,之后会出现对话界面

image-20250328005035684

七. 通过脚本直接Lora微调Qwen

参考连接 self-llm/examples/Chat-嬛嬛/readme.md at master · datawhalechina/self-llm

主要LoRA微调 Qwen2.5-0.5B-Instruct,使其输出分格类似甄嬛。直接通过脚本微调。

7.1 获取数据集

通过以下链接获取,然后上传到服务器。 self-llm/dataset/huanhuan.json at master · datawhalechina/self-llm

7.2 配置环境

我的配置为: PyTorch 2.5.1; Python 3.12(ubuntu22.04); CUDA 12.4

1
2
3
conda create -n myenv python==3.12 -y
conda activate myenv
pip install transformers accelerate peft datasets
7.3 模型微调

可以参考 3.3和5.2 的方法使用LLama-Factory进行微调,这里展示直接通过脚本微调的方式。训练代码如下:

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
from datasets import Dataset
import pandas as pd
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer, GenerationConfig
from peft import LoraConfig, TaskType, get_peft_model

# 基座模型路径
model_path = ""
# 训练集路径
train_path = ""
# 微调的lora参数输出路径
output_path = ""

# 处理训练集
def process_func(example):
MAX_LENGTH = 384 # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
input_ids, attention_mask, labels = [], [], []
instruction = tokenizer(f"<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\n现在你要扮演皇帝身边的女人--甄嬛<|eot_id|><|start_header_id|>user<|end_header_id|>\n\n{example['instruction'] + example['input']}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n", add_special_tokens=False) # add_special_tokens 不在开头加 special_tokens
response = tokenizer(f"{example['output']}<|eot_id|>", add_special_tokens=False)
input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1] # 因为eos token咱们也是要关注的所以 补充为1
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
# 尽量不要截断
# if len(input_ids) > MAX_LENGTH: # 做一个截断
# input_ids = input_ids[:MAX_LENGTH]
# attention_mask = attention_mask[:MAX_LENGTH]
# labels = labels[:MAX_LENGTH]
return {
"input_ids": input_ids,
"attention_mask": attention_mask,
"labels": labels
}

if __name__ == "__main__":
# 加载模型
model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16)
model.enable_input_require_grads() # 开启梯度检查点时,要执行该方法
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token

# 将JSON文件转换为CSV文件
# 加载训练集
df = pd.read_json(train_path)
ds = Dataset.from_pandas(df)
tokenized_id = ds.map(process_func, remove_columns=ds.column_names)

config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
inference_mode=False, # 训练模式
r=8, # Lora 秩
lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
lora_dropout=0.1# Dropout 比例
)
model = get_peft_model(model, config)
model.print_trainable_parameters() # 打印总训练参数

args = TrainingArguments(
output_dir=output_path,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
logging_steps=10,
num_train_epochs=3,
save_steps=100, # 为了快速演示,这里设置10,建议你设置成100,每100个steps保存一次
learning_rate=1e-4,
save_on_each_node=True,
gradient_checkpointing=True
)
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenized_id,
data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)
trainer.train() # 开始训练
# 在训练参数中设置了自动保存策略此处并不需要手动保存。

运行train.py ,开始训练:

image-20250323221203024

8.4 模型合并

训练是输出是lora参数,并不是整个模型,如果想用vllm或者其他工具部署,可以将lora参数合并到基座模型,导出微调后的整个模型。合并和导出代码如下:

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
import torch
from peft import PeftModel
from transformers import AutoTokenizer, AutoModelForCausalLM, LlamaTokenizer
from transformers.generation.utils import GenerationConfig


def apply_lora(model_name_or_path, output_path, lora_path):
print(f"Loading the base model from {model_name_or_path}")
base_tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=False, trust_remote_code=True)
base = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map="cuda:0", torch_dtype=torch.bfloat16, trust_remote_code=True)
# base.generation_config = GenerationConfig.from_pretrained(model_name_or_path)

print(f"Loading the LoRA adapter from {lora_path}")

lora_model = PeftModel.from_pretrained(
base,
lora_path,
torch_dtype=torch.float16,
)

print("Applying the LoRA")
model = lora_model.merge_and_unload()

print(f"Saving the target model to {output_path}")
model.save_pretrained(output_path)
base_tokenizer.save_pretrained(output_path)


if __name__ == "__main__":
# 更换为自己对应的路径
lora_path = "/root/autodl-tmp/output/huanhuan-lora/checkpoint-699"
model_path = "/root/autodl-tmp/Qwen2.5-0.5B-Instruct"
output = "/root/autodl-tmp/Qwen2.5-0.5B-Instruct-huanhuan"

apply_lora(model_path,output,lora_path)
8.5 测试模型

合并后的模型和基座模型结构一样,可以用上面的工具部署,这里仅为了测试效果,所以直接通过脚本测试。代码如下:

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
from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = "/root/autodl-tmp/Qwen2.5-0.5B-Instruct-huanhuan"

model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)

prompt = "你是谁?"
messages = [
{"role": "system", "content": "现在你要扮演皇帝身边的女人--甄嬛"},
{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)

generated_ids = model.generate(
**model_inputs,
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]
print(response)

运行后输出如下:

image-20250323221548136

符合预期效果,说明微调起效。

八. 补充

8.1 LLamaFactory evaluation中各个指标的含义

在 5.1 中通过LLama-Factory进行测试,结果如下:

1
2
3
4
5
6
7
8
9
10
{
"predict_bleu-4": 88.64074418449198,
"predict_model_preparation_time": 0.0065,
"predict_rouge-1": 92.81370474598931,
"predict_rouge-2": 90.33300949197861,
"predict_rouge-l": 91.9221340909091,
"predict_runtime": 329.3329,
"predict_samples_per_second": 4.543,
"predict_steps_per_second": 0.455
}

这几个结果的含义如下:

  1. predict_bleu-4
8.2 量化校准的原理
8.2.1 为什么需要量化

量化的主要目的是节约显存,提升计算效率以及加快通信。如下表,deepseek-r1-7b模型以不同类ing加载和随不同数据类型所占用的显存也不一样

FP32 FP16 Int8 Int3
显存占用 28G 14G 7G 3.5G

总的来说,量化就是把Float类型(FP32,FP16)的模型参数和激活值,用整数(Int8. Int4)来代替,同时尽可能减少量化后模型推理的误差。

8.2.2 对称量化vs非对称量化

(1)对称量化:如下图,对称量化的原理就是找到, xf 中绝对值的最大值,然后对其进行缩放得到量化后的值,然后进行反量化得到原来的值,可以看出量化是存在一定误差的,具体原理如下图:

img

这样量化的缺点就是,坐标轴上有一段数值空间被浪费了,对应图中-127那一部分。基于这个缺点,为了让量化后的坐标轴上的数值被充分利用,引入非对称量化。

(2)非对称量化:非对称量化有一个额外的参数Z调整零点的映射,这个参数通常称为零点。非对称量化表示的范围没有严格的限制,可以根据浮点值的范围,选取任意的想要表示的范围。因此非对称量化的效果通常比对称量化好,但是需要额外存储以及推理时计算零点相关的内容。

img

因此,对称量化具有计算简单,精度低等特点,非对称量化的计算有一个额外的参数Z调整零点的映射,因此计算复杂,但精度相对较高。

(3)在矩阵乘法中的应用:下图为对称量化在居中乘法当中的应用示意图(非对称量化也类似),通过量化,可以把浮点矩阵的乘法,转化为整数矩阵的乘法,虽然存在一定误差,但误差不大。在矩阵乘法中采用量化可以降低计算复杂度,提升矩阵乘法效率。

img

8.2.3 如何对神经网络进行量化

为什么量化对神经网络精度影响不大?

  1. 因为一般权重和输入都经过Normalization, 基本数值范围都不大。
  2. 因为激活函数,数值影响会被平滑。
  3. 绝大部分神经网络都是分类问题,最后都是概率值,只要最后某种类别的概率高于其他类别就可以,不需要绝对数值。
8.2.4 动态量化vs静态量化

量化在神经网络中的是对每一层而言,每一层进行量化计算,每一层输出时进行反量化。具体而言,量化在神经网络当中的应用又可分为动态量化(Post Training Quantization Dynamic, PTQ Dynamic)与静态量化(Post Training Quantization Static), PTQ Static

(1) 动态量化流程

  1. 将训练好的模型权重量化为Int8,并保存量化参数。
  2. 在模型推理时,对每一层输入的FP32激活值,动态进行量化为Int8。
  3. 在每一层对量化后的Int8权重和Int8激活值进行计算。
  4. 在每一层输出时将结果反量化为FP32。
  5. 将FP32激活值传入到下一层。

可用下图表示:

img

动态量化存在的问题:

  1. 每一次推理每一层都要对输入统计量化参数,耗时。
  2. 每一层计算完都转化为FP32,存入显存,占用显存带宽。

(2)静态量化流程

针对动态量化的问题1,通过用有代表性的输入数据跑一遍整个网络,通过统计得到每层大概的量化参数来解决;问题2,这一层的输出是下一层的输入。下一层还是要量化,通过在这一层直接量化好再传给下一层方法来解决。这就是静态量化。

  1. 将训练好的模型权重量化为Int8, 并保存量化参数。
  2. 校准:利用一些数据进行模型推理,用这些数据在神经网络每一层产生的激活估算除激活值的量化参数。这样就不用推理时每次根据实际激活值计算量化参数。
  3. 在每一层对量化后的Int8权重和Int8激活值进行计算。
  4. 在每一层输出时将结果反量化为FP32,同时根据校准产生的激活值量化参数,把激活值量化为Int8,把量化参数放入量化后的激活值中。
  5. 将Int8的激活值和它的量化参数传入到下一层。

可用下图表示:

img

8.3 提醒

整个项目东西有点多,有几点容易出错:

  • 时刻注意,你要在虚拟环境中,开启webui的命令行路径在LLama-Factory文件夹中。
  • 有时下载包后仍显示没有该包,要重启终端。
  • 尽量用python3.10,兼容性好一些。
  • openwebui要用python3.11
如果您读文章后有收获,可以打赏我喝咖啡哦~