LLaMA-Factory
LLaMA-Factory
项目特色
- 多种模型 :LLaMA、Mistral、Mixtral-MoE、Qwen、Yi、Gemma、Baichuan、ChatGLM、Phi 等等。
- 集成方法 :(增量)预训练、指令监督微调、奖励模型训练、PPO 训练、DPO 训练 和 ORPO 训练。
- 多种精度 :32 比特全参数微调、16 比特冻结微调、16 比特 LoRA 微调 和 基于 AQLM/AWQ/GPTQ/LLM.int8 的 2/4/8 比特 QLoRA 微调。
- 先进算法 :GaLore、DoRA、LongLoRA、LLaMA Pro、LoRA+、LoftQ 和 Agent 微调。
- 实用技巧 :FlashAttention-2、Unsloth、RoPE scaling、NEFTune 和 rsLoRA。
- 实验监控 :LlamaBoard、TensorBoard、Wandb、MLflow 等等。
- 极速推理 :基于 vLLM 的 OpenAI 风格 API、浏览器界面 和 命令行接口。
数据集
预训练数据集指令微调数据集偏好数据集
部分数据集的使用需要确认,使用下述命令登录您的 Hugging Face 账户。
1 | pip install --upgrade huggingface_hub |
软硬件依赖
必需项 | 至少 | 推荐 |
---|---|---|
python | 3.8 | 3.10 |
torch | 1.13.1 | 2.2.0 |
transformers | 4.37.2 | 4.39.3 |
datasets | 2.14.3 | 2.18.0 |
accelerate | 0.27.2 | 0.28.0 |
peft | 0.9.0 | 0.10.0 |
trl | 0.8.1 | 0.8.1 |
可选项 | 至少 | 推荐 |
---|---|---|
CUDA | 11.6 | 12.2 |
deepspeed | 0.10.0 | 0.14.0 |
bitsandbytes | 0.39.0 | 0.43.0 |
flash-attn | 2.3.0 | 2.5.6 |
硬件依赖
* 估算值
训练方法 | 精度 | 7B | 13B | 30B | 70B | 8x7B |
---|---|---|---|---|---|---|
全参数 | AMP | 120GB | 240GB | 600GB | 1200GB | 900GB |
全参数 | 16 | 60GB | 120GB | 300GB | 600GB | 400GB |
GaLore | 16 | 16GB | 32GB | 64GB | 160GB | 120GB |
部分参数 | 16 | 20GB | 40GB | 80GB | 200GB | 160GB |
LoRA | 16 | 16GB | 32GB | 64GB | 160GB | 120GB |
QLoRA | 8 | 10GB | 20GB | 40GB | 80GB | 60GB |
QLoRA | 4 | 6GB | 12GB | 24GB | 48GB | 30GB |
QLoRA | 2 | 4GB | 8GB | 16GB | 24GB | 18GB |
安装过程
1.UV安装
1 | git clone https://github.com/hiyouga/LLaMA-Factory.git |
LLaMA Board 可视化界面
1 | uv run llamafactory-cli webui |
2.普通安装
按照GitHub上介绍的过程安装即可,为了加快速度,增加了国内的pip 源。
1 | git clone https://github.com/hiyouga/LLaMA-Factory.git |
可选的额外依赖项:deepspeed、metrics、unsloth、galore、vllm、bitsandbytes、gptq、awq、aqlm、qwen、quality
LLaMA Board 可视化界面
使用本地环境:
1 | export CUDA_VISIBLE_DEVICES=0 # Windows 使用 `set CUDA_VISIBLE_DEVICES=0` |
数据准备
可以使用 HuggingFace / ModelScope 上的数据集或加载本地数据集。使用自定义数据集时,请更新 data/dataset_info.json 文件。
原始模型直接推理
CUDA_VISIBLE_DEVICES=0 是指定了当前程序使用第0张卡,是指定全局变量的作用, 也可以不使用
1 | uv run llamafactory-cli webchat \ |
需要注意的是,本次及后续所有的程序的入口都是 llamafactory-cli, 通过不同的参数控制现在是实现什么功能,比如现在是想使用网页版本直接推理,所以第一个参数设置为webchat, 所有的可选项包括
动作参数枚举 | 参数说明 |
---|---|
version | 显示版本信息 |
train | 命令行版本训练 |
chat | 命令行版本推理chat |
export | 模型合并和导出 |
api | 启动API server,供接口调用 |
eval | 使用mmlu等标准数据集做评测 |
webchat | 前端版本纯推理的chat页面 |
webui | 启动LlamaBoard前端页面,包含可视化训练,预测,chat,模型合并多个子页面 |
另外两个关键参数解释如下,后续的基本所有环节都会继续使用这两个参数
参数名称 | 参数说明 |
---|---|
model_name_or_path | 参数的名称(huggingface或者modelscope上的标准定义,如“meta-llama/Meta-Llama-3-8B-Instruct”), 或者是本地下载的绝对路径,如/media/codingma/LLM/llama3/Meta-Llama-3-8B-Instruct |
template | 模型问答时所使用的prompt模板,不同模型不同,请参考 https://github.com/hiyouga/LLaMA-Factory?tab=readme-ov-file#supported-models 获取不同模型的模板定义,否则会回答结果会很奇怪或导致重复生成等现象的出现。chat 版本的模型基本都需要指定,比如Meta-Llama-3-8B-Instruct的template 就是 llama3 |
当然你也可以提前把相关的参数存在yaml文件里,比如LLaMA-Factory/examples/inference/llama3.yaml at main · hiyouga/LLaMA-Factory, 本地位置是 examples/inference/llama3.yaml ,内容如下
1 | model_name_or_path: E:\Datasets\LLM\Llama-3.2-3B-Instruct |
这样就可以通过如下命令启动,其效果跟上面是一样的,但是更方便管理
1 | uv run llamafactory-cli webchat examples/inference/llama3.yaml |
自定义数据集构建
数据集的格式要求在不同的阶段是不同的,本教程以sft阶段的数据集需求,将以系统自带的identity数据集和将自定义的一个商品文案生成数据集为例,介绍数据集的使用。更多详情可以在 https://github.com/hiyouga/LLaMA-Factory/blob/main/data/README_zh.md 中找到相关解释。
系统目前支持 alpaca 和sharegpt两种数据格式,以alpaca为例,整个数据集是一个json对象的list,具体数据格式为
1 | [ |
例子比如单轮(alpaca_data_zh_51k.json 中的例子, 数据集在data/dataset_info.json中注册为alpaca_zh)
1 | { |
和多轮 (oaast_sft_zh.json 中的例子, 数据集在data/dataset_info.json中注册为oaast_sft_zh)
1 | { |
所以我们训练的数据最好也转换成这种格式,然后在 data/dataset_info.json中进行注册(如果不做字段名称转换,则需要在注册的时候在 columns字段中做两个数据的映射配置)
使用两个具体的例子来说明数据集的使用
1.你是谁:
第一个是系统自带的identity.json数据集(已默认在data/dataset_info.json 注册为identity),对应文件已经在data目录下,我们通过操作系统的文本编辑器的替换功能,可以替换其中的NAME 和 AUTHOR ,换成我们需要的内容。如果是linux系统,可以使用sed 完成快速替换。比如助手的名称修改为PonyBot, 由 LLaMA Factory 开发
1 | sed -i 's/{{name}}/PonyBot/g' data/identity.json |
替换前
1 | { |
替换后
1 | { |
2.微调:
第二个是一个商品文案生成数据集,原始链接为 https://cloud.tsinghua.edu.cn/f/b3f119a008264b1cabd1/?dl=1
原始格式如下,很明显,训练目标是输入content (也就是prompt), 输出 summary (对应response)
1 | { |
想将该自定义数据集放到我们的系统中使用,则需要进行如下两步操作
- 复制该数据集到 data目录下
- 修改 data/dataset_info.json 新加内容完成注册, 该注册同时完成了3件事
- 自定义数据集的名称为adgen_local,后续训练的时候就使用这个名称来找到该数据集
- 指定了数据集具体文件位置
- 定义了原数据集的输入输出和我们所需要的格式之间的映射关系
基于LoRA的sft指令微调
在准备好数据集之后,我们就可以开始准备训练了,我们的目标就是让原来的LLaMA3模型能够学会我们定义的“你是谁”,同时学会我们希望的商品文案的一些生成。
这里我们先使用命令行版本来做训练,从命令行更容易学习相关的原理。
本脚本参数改编自 LLaMA-Factory/examples/train_lora/llama3_lora_sft.yaml at main · hiyouga/LLaMA-Factory
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli train \ |
windows uv对应脚本 :
1 | uv run llamafactory-cli train ` |
--evaluation_strategy steps \
--load_best_model_at_end \
这两行参数在windows下报错,修改epochs和steps参数并不能正常通过命令行传入
(1)Some specified arguments are not used by the HfArgumentParser
(2)--load_best_model_at_end requires the save and eval strategy to match, but found
- Evaluation strategy: no
- Save strategy: steps
删除后正常
关于参数的完整列表和解释可以通过如下命令来获取
1 | llamafactory-cli train -h |
这里对部分关键的参数做一下解释,model_name_or_path 和template 上文已解释
参数名称 | 参数说明 |
---|---|
stage | 当前训练的阶段,枚举值,有“sft”,”pt”,”rm”,”ppo”等,代表了训练的不同阶段,这里我们是有监督指令微调,所以是sft |
do_train | 是否是训练模式 |
dataset | 使用的数据集列表,所有字段都需要按上文在data_info.json里注册,多个数据集用”,”分隔 |
dataset_dir | 数据集所在目录,这里是 data,也就是项目自带的data目录 |
finetuning_type | 微调训练的类型,枚举值,有”lora”,”full”,”freeze”等,这里使用lora |
output_dir | 训练结果保存的位置 |
cutoff_len | 训练数据集的长度截断 |
per_device_train_batch_size | 每个设备上的batch size,最小是1,如果GPU 显存够大,可以适当增加 |
fp16 | 使用半精度混合精度训练 |
max_samples | 每个数据集采样多少数据 |
val_size | 随机从数据集中抽取多少比例的数据作为验证集 |
pt
(Pre-training / 预训练)- 目标: 让模型学习语言的基本规律、语法结构、世界知识和上下文理解能力。这是构建强大 LLM 的基础。
- 数据: 通常使用海量的、无标注的文本数据,例如来自互联网的书籍、文章、网站内容等。
- 任务: 最常见的预训练任务是语言建模 (Language Modeling)。
- Causal Language Modeling (CLM) / 因果语言建模: 模型学习根据前面的文本预测下一个词 (token)。例如,给定 “今天天气很”,模型应该能预测出 “好”、”晴朗” 等。GPT 系列模型主要采用这种方式。
- Masked Language Modeling (MLM) / 掩码语言建模: 模型学习预测文本中被随机遮盖 (mask) 掉的词。例如,给定 “今天[MASK]很好”,模型应该能预测出 “[MASK]” 是 “天气”。BERT 系列模型主要采用这种方式。
- 产出: 一个基础模型 (base model)。这个模型拥有广泛的知识和语言理解能力,但可能不擅长直接回答问题或遵循特定指令。它更像是一个知识库,而不是一个对话助手。
- 特点: 计算量巨大,需要大量的计算资源和时间。
sft
(Supervised Fine-Tuning / 指令微调 / 有监督微调)- 目标: 教会预训练好的模型如何遵循人类的指令,并以期望的格式生成回答。这是让模型从一个“知识库”转变为一个“助手”的关键一步。
- 数据: 使用高质量的、成对的“指令-回答”(instruction-response) 数据集。这些数据通常由人工编写或筛选,或者由更强大的模型生成后再经人工校验。Alpaca 格式的数据就是典型的 SFT 数据。
- 例如:
- 指令: “写一首关于春天的诗”
- 回答: (一首关于春天的诗)
- 指令: “解释什么是黑洞”
- 回答: (关于黑洞的解释)
- 例如:
- 任务: 模型学习在给定一个指令 (可能还有额外的输入上下文) 的情况下,生成一个符合该指令的、高质量的回答。这仍然是一个监督学习任务,模型试图最小化其生成的回答与数据集中标准回答之间的差异。
- 产出: 一个经过指令微调的模型。这个模型能够更好地理解并执行用户的指令,生成的回答也更有针对性。
- 特点: 相比预训练,SFT 需要的数据量较少,计算成本也低得多。但数据质量对 SFT 的效果至关重要。
rm
(Reward Modeling / 奖励模型训练)- 目标: 训练一个模型,使其能够评估给定指令下,模型生成的不同回答的质量好坏,并给出一个标量分数 (奖励值) 来表示其质量。这个奖励模型是后续强化学习阶段 (PPO) 的核心。
- 数据: 需要人类对模型生成的多个回答进行排序或打分的数据。
- 通常的做法是:给定一个相同的用户指令,让 SFT 阶段的模型生成多个不同的回答 (或者从不同模型收集回答)。然后,让人类标注员对这些回答进行排序,指出哪个更好,哪个次之,哪个最差。
- 例如:
- 指令: “推荐一部科幻电影”
- 回答 A: “《星际穿越》”
- 回答 B: “《流浪地球》”
- 回答 C: “《银翼杀手2049》”
- 人类标注: B > A > C (表示 B 最好,C 最差)
- 任务: 奖励模型学习预测人类对回答的偏好。它输入一个指令和模型的一个回答,输出一个标量奖励分数。目标是让奖励模型给出的分数与人类的排序偏好尽可能一致(例如,人类认为更好的回答,奖励模型也应该给出更高的分数)。
- 产出: 一个奖励模型 (Reward Model, RM)。这个模型本身不直接与用户交互,而是作为后续 PPO 阶段的“裁判”。
- 特点: 需要大量的人类标注数据,标注成本较高。奖励模型的质量直接影响 PPO 阶段的效果。
ppo
(Proximal Policy Optimization / 近端策略优化 / 强化学习微调)- 目标: 使用强化学习的方法,根据奖励模型提供的反馈信号,进一步微调 SFT 阶段的模型,使其生成的回答能够获得更高的奖励分数,从而更符合人类的偏好,变得更有用、更诚实、更无害。
- 过程:
- 采样: SFT 模型 (也称为策略模型或 actor 模型) 接收一个指令 (prompt)。
- 生成: SFT 模型生成一个回答。
- 评估: 训练好的奖励模型 (RM) 评估这个“指令-回答”对,并给出一个奖励分数。
- 更新: 使用 PPO 算法(一种强化学习算法)根据这个奖励分数来更新 SFT 模型的参数。PPO 的目标是最大化期望奖励,同时还会加入一个与原始 SFT 模型行为差异的惩罚项,以防止模型在追求高奖励时偏离太远,导致语言能力下降或生成不连贯的内容。
- 数据: 通常从一个指令数据集中采样指令。不需要人工标注的“正确答案”,而是依赖奖励模型的实时反馈。
- 产出: 一个经过强化学习微调的、与人类偏好更对齐的最终模型。这个模型通常在对话能力、遵循复杂指令、避免有害输出等方面表现更好。
- 特点: 计算上比 SFT 更复杂,需要同时运行 SFT 模型和奖励模型,并执行强化学习的优化步骤。对超参数比较敏感。
这些阶段之间的关系:
通常的流程是:
PT
(基础模型) → SFT
(指令遵循能力) → RM
(学习人类偏好) → PPO
(根据偏好进一步优化)
- PT 是基础,提供了语言的底层能力。
- SFT 是第一步对齐,让模型学会如何“做任务”和“回答问题”。
- RM 和 PPO 共同构成了从人类反馈中学习强化学习 (Reinforcement Learning from Human Feedback, RLHF) 的核心部分。RM 学习什么是“好”的,PPO 利用 RM 的判断来引导 SFT 模型变得“更好”。
注意:精度相关的参数还有bf16 和pure_bf16,但是要注意有的老显卡,比如V100就无法支持bf16,会导致程序报错或者其他错误
训练过程中,系统会按照logging_steps的参数设置,定时输出训练日志,包含当前loss,训练进度等
1 | [INFO|tokenization_utils_base.py:2519] 2025-05-21 10:58:59,586 >> Special tokens file saved in ./saves/LLaMA3.2-3B/lora/sft\checkpoint-300\special_tokens_map.json |
训练完后就可以在设置的output_dir下看到如下内容,主要包含3部分
adapter开头的就是 LoRA保存的结果了,后续用于模型推理融合
adapter_config.json
文件是使用 PEFT (Parameter-Efficient Fine-Tuning) 库(特别是 LoRA - Low-Rank Adaptation)进行模型微调后,保存下来的适配器 (adapter) 的配置文件。它记录了训练这个 LoRA 适配器时所使用的所有关键配置参数。adapter_config.json
的整体作用:- 记录 LoRA 配置: 最主要的作用是详细记录了用于训练这个特定 LoRA 适配器的所有超参数和设置。这使得训练过程可以被复现,也方便其他人理解这个适配器是如何被训练的。
- 加载适配器: 当你需要在后续进行模型推理或进一步微调时,PEFT 库会读取这个
adapter_config.json
文件,以了解如何正确地将 LoRA 权重加载并应用到基础模型上。没有这个配置文件,PEFT 库就不知道 LoRA 模块应该应用于哪些层、秩 (rank) 是多少、alpha 是多少等关键信息。 - 模型融合与部署: 在将 LoRA 适配器与基础模型融合(merge)以创建一个完整的、可以直接部署的模型时,这个配置文件提供了必要的信息来确保融合过程的正确性。
- 可移植性与共享: 当你分享你的 LoRA 适配器时,这个配置文件与适配器权重 (
adapter_model.bin
或类似文件) 一起,使得其他人可以方便地在兼容的基础模型上使用你的适配器。
各项参数的作用 (基于你提供的
adapter_config.json
):alpha_pattern
:{}
- 用于更细致地控制不同 LoRA 模块的
lora_alpha
值。空字典表示所有模块使用全局的lora_alpha
。
- 用于更细致地控制不同 LoRA 模块的
auto_mapping
:null
- 用于自动映射任务类型到模型头部,通常在某些特定任务中需要。
null
表示不使用自动映射。
- 用于自动映射任务类型到模型头部,通常在某些特定任务中需要。
base_model_name_or_path
:"E:/Datasets/LLM/Llama-3.2-3B-Instruct"
- 非常重要: 指定了训练这个 LoRA 适配器时所使用的基础模型的名称或本地路径。当加载这个适配器时,PEFT 会确保它被应用到正确的基础模型上。
bias
:"none"
- 指定 LoRA 层中偏置 (bias) 参数的处理方式。
"none"
: 不训练偏置参数。"all"
: 训练所有偏置参数。"lora_only"
: 只训练 LoRA 层引入的偏置参数。
- 你这里设置为
"none"
,表示 LoRA 层没有可训练的偏置。
- 指定 LoRA 层中偏置 (bias) 参数的处理方式。
corda_config
:null
,eva_config
:null
- 这些是其他特定类型的 PEFT 方法(如 CoRDA, EVA)的配置,对于 LoRA 适配器,它们是
null
。
- 这些是其他特定类型的 PEFT 方法(如 CoRDA, EVA)的配置,对于 LoRA 适配器,它们是
exclude_modules
:null
- 如果设置了,会从
target_modules
中排除某些特定的模块,不应用 LoRA。null
表示不排除任何模块。
- 如果设置了,会从
fan_in_fan_out
:false
- 一个布尔值,指示 LoRA 权重初始化时是否考虑权重矩阵的扇入扇出 (fan-in/fan-out)。当为
true
时,LoRA 矩阵 B 会根据 fan-in 初始化,A 会初始化为零,这有时能帮助稳定训练。false
表示使用标准的初始化方法。
- 一个布尔值,指示 LoRA 权重初始化时是否考虑权重矩阵的扇入扇出 (fan-in/fan-out)。当为
inference_mode
:true
- 指示这个适配器当前是否处于推理模式。当为
true
时,一些与训练相关的操作(如 dropout)会被禁用。在加载适配器用于推理时,这个值通常会被 PEFT 库自动处理或设置。
- 指示这个适配器当前是否处于推理模式。当为
init_lora_weights
:true
- 指定是否以及如何初始化 LoRA 权重。
true
: (默认) LoRA 矩阵 A 使用 Kaiming uniform 初始化,LoRA 矩阵 B 初始化为零。这确保了在训练开始时,LoRA 模块对模型的输出没有影响,使得训练更稳定。false
: 不进行特殊的 LoRA 初始化。"gaussian"
: 使用高斯分布初始化。"loftq"
: 与 LoftQ 量化方法相关的初始化。
- 指定是否以及如何初始化 LoRA 权重。
layer_replication
:null
- 用于在模型中复制层并对复制的层应用 LoRA,一种高级技术。
null
表示不使用。
- 用于在模型中复制层并对复制的层应用 LoRA,一种高级技术。
layers_pattern
:null
- 允许使用正则表达式模式来选择要应用 LoRA 的层,是对
target_modules
和layers_to_transform
的补充或替代。null
表示不使用。
- 允许使用正则表达式模式来选择要应用 LoRA 的层,是对
layers_to_transform
:null
- 可以直接指定要转换的层的索引或名称列表。如果
target_modules
已经足够,这个可以是null
。
- 可以直接指定要转换的层的索引或名称列表。如果
loftq_config
:{}
- 与 LoftQ(一种量化感知的 LoRA 技术)相关的配置。空字典表示不使用 LoftQ。
lora_alpha
:16
- LoRA 的核心参数之一。Alpha 是一个缩放因子,用于调整 LoRA 输出的幅度。LoRA 的输出会乘以
alpha / r
。通常alpha
会被设置为与r
相近或两倍的值。这里alpha
是 16。
- LoRA 的核心参数之一。Alpha 是一个缩放因子,用于调整 LoRA 输出的幅度。LoRA 的输出会乘以
lora_bias
:false
- 这个参数似乎与
bias
参数有重叠,但通常bias
参数更为通用。lora_bias
可能特指是否在 LoRA 结构中添加可训练的偏置项(独立于原始层的偏置)。这里是false
。
- 这个参数似乎与
lora_dropout
:0.0
- 应用于 LoRA 层的 dropout 比率。在 LoRA A 矩阵的输出之后和与 B 矩阵相乘之前应用。
0.0
表示不使用 dropout。
- 应用于 LoRA 层的 dropout 比率。在 LoRA A 矩阵的输出之后和与 B 矩阵相乘之前应用。
megatron_config
:null
,megatron_core
:"megatron.core"
- 与 Megatron-LM(一种用于训练超大规模模型的框架)集成相关的配置。如果你的基础模型是基于 Megatron-LM 训练的,这些配置可能很重要。
modules_to_save
:null
- 除了 LoRA 模块外,还额外指定模型中需要保存的其他模块(例如,如果你微调了模型的某些特定头部或层)。
null
表示只保存由 PEFT 修改的 LoRA 模块。
- 除了 LoRA 模块外,还额外指定模型中需要保存的其他模块(例如,如果你微调了模型的某些特定头部或层)。
peft_type
:"LORA"
- 非常重要: 指明了所使用的 PEFT 方法的类型。这里是
"LORA"
,明确了这个适配器是 LoRA 类型的。
- 非常重要: 指明了所使用的 PEFT 方法的类型。这里是
r
:8
- LoRA 的核心参数之一,代表秩 (rank)。LoRA 将原始权重矩阵的更新分解为两个较小的低秩矩阵 (A 和 B),其中 A 的维度是
(original_output_dim, r)
,B 的维度是(r, original_input_dim)
。r
的值越小,引入的可训练参数越少,但可能限制了适配器的表达能力。r
的值越大,参数越多,表达能力可能更强,但训练和存储成本也更高。这里r
是 8。
- LoRA 的核心参数之一,代表秩 (rank)。LoRA 将原始权重矩阵的更新分解为两个较小的低秩矩阵 (A 和 B),其中 A 的维度是
rank_pattern
:{}
- 用于更细致地控制不同 LoRA 模块的秩
r
。空字典表示所有模块使用全局的r
。
- 用于更细致地控制不同 LoRA 模块的秩
revision
:null
- 当从 Hugging Face Hub 加载模型时,可以指定模型的特定版本 (revision/commit hash)。
null
表示使用默认或最新版本。
- 当从 Hugging Face Hub 加载模型时,可以指定模型的特定版本 (revision/commit hash)。
target_modules
:["o_proj", "gate_proj", "k_proj", "q_proj", "down_proj", "v_proj", "up_proj"]
- 非常重要: 这是一个模块名称的列表,指定了在基础模型中哪些类型的线性层或卷积层应该被 LoRA 适配器替换/适配。
- 这些名称通常对应于 Transformer 模型中常见的层,例如:
q_proj
,k_proj
,v_proj
: 注意力机制中的查询 (Query)、键 (Key)、值 (Value) 投影层。o_proj
: 注意力机制的输出投影层。gate_proj
,up_proj
,down_proj
: 前馈网络 (FFN) 中的门控层、上投影层和下投影层。
- PEFT 库会遍历基础模型,找到所有名称在
target_modules
列表中的层,并在这些层上应用 LoRA。
- 这些名称通常对应于 Transformer 模型中常见的层,例如:
- 非常重要: 这是一个模块名称的列表,指定了在基础模型中哪些类型的线性层或卷积层应该被 LoRA 适配器替换/适配。
task_type
:"CAUSAL_LM"
- 指定了模型微调的任务类型。这里是
"CAUSAL_LM"
(因果语言模型),例如 GPT 类型的模型,用于文本生成。这个信息有助于 PEFT 正确配置模型,例如,如果需要修改模型的头部。
- 指定了模型微调的任务类型。这里是
trainable_token_indices
:null
- 用于某些特定技术(如 P-tuning 的变体),指定哪些 token embedding 是可训练的。对于标准的 LoRA,这通常是
null
。
- 用于某些特定技术(如 P-tuning 的变体),指定哪些 token embedding 是可训练的。对于标准的 LoRA,这通常是
use_dora
:false
- 指示是否使用了 DoRA (Weight-Decomposed Low-Rank Adaptation),一种 LoRA 的变体,声称可以提高性能。
false
表示未使用。
- 指示是否使用了 DoRA (Weight-Decomposed Low-Rank Adaptation),一种 LoRA 的变体,声称可以提高性能。
use_rslora
:false
- 指示是否使用了 RSLoRA (Rank-Stabilized LoRA),另一种 LoRA 的变体,通过调整
alpha
来稳定不同r
值下的训练。false
表示未使用。
- 指示是否使用了 RSLoRA (Rank-Stabilized LoRA),另一种 LoRA 的变体,通过调整
training_loss 和trainer_log等记录了训练的过程指标
其他是训练当时各种参数的备份
1 | {"current_steps": 50, "total_steps": 585, "loss": 2.307, "lr": 4.9675684557832825e-05, "epoch": 0.4250797024442083, "percentage": 8.55, "elapsed_time": "0:02:22", "remaining_time": "0:25:26"} |
关于loss是什么等,这块不在本教程讨论内容范围之内,只需要记住loss在 正常情况下会随着训练的时间慢慢变小,最后需要下降到1以下的位置才会有一个比较好的效果,可以作为训练效果的一个中间指标。
7. 动态合并LoRA的推理
本脚本参数改编自 LLaMA-Factory/examples/inference/llama3_lora_sft.yaml at main · hiyouga/LLaMA-Factory
当基于LoRA的训练进程结束后,我们如果想做一下动态验证,在网页端里与新模型对话,与步骤4的原始模型直接推理相比,唯一的区别是需要通过finetuning_type参数告诉系统,我们使用了LoRA训练,然后将LoRA的模型位置通过 adapter_name_or_path参数即可。
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli webchat \ |
win uv对应脚本:
1 | uv run llamafactory-cli webchat --model_name_or_path E:/Datasets/LLM/Llama-3.2-3B-Instruct --adapter_name_or_path ./saves/LLaMA3.2-3B/lora/sft --template llama3 --finetuning_type lora |
效果如下,可以看到,模型整个已经在学习了新的数据知识,学习了新的身份认知和商品文案生成的格式。
1 | input: |
如果不方便使用webui来做交互,使用命令行来做交互,同样也是可以的。
本脚本改编自 LLaMA-Factory/examples/inference/llama3_lora_sft.yaml at main · hiyouga/LLaMA-Factory
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli chat \ |
1 | uv run llamafactory-cli chat --model_name_or_path E:/Datasets/LLM/Llama-3.2-3B-Instruct --adapter_name_or_path ./saves/LLaMA3.2-3B/lora/sft --template llama3 --finetuning_type lora |
效果如下
1 | User: 类型# 上衣风格#清新风格#潮风格#性感 字领衣门襟#系带*衣款式#不对称 |
8. 批量预测和训练效果评估
当然上文中的人工交互测试,会偏感性,那有没有办法批量地预测一批数据,然后使用自动化的bleu和 rouge等常用的文本生成指标来做评估。指标计算会使用如下3个库,请先做一下pip安装
1 | uv pip install jieba |
本脚本参数改编自 https://github.com/hiyouga/LLaMA-Factory/blob/main/examples/train_lora/llama3_lora_predict.yaml
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli train \ |
uv 对应
1 | uv run llamafactory-cli train ` |
与训练脚本主要的参数区别如下两个
参数名称 | 参数说明 |
---|---|
do_predict | 现在是预测模式 |
predict_with_generate | 现在用于生成文本 |
max_samples | 每个数据集采样多少用于预测对比 |
最后会在output_dir下看到如下内容
1 | {"prompt": "<|begin_of_text|><|start_header_id|>user<|end_header_id|>\n\n保持健康的三个提示。<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n", "predict": "1. 运动:进行适量的运动有助于保持健康。适当的运动有助于提高心脏健康,降低疾病风险,增强肌肉力量,提高精神健康,减轻压力和焦虑。\n\n2. 进食健康饮食:健康饮食是保持健康的基础。饮食中应包含足够的水果,蔬菜,蛋白质食物,健康面料,健康脂肪和碳水化合物。避免过多食用高糖、高盐、高脂肪和高热量食物。\n\n3. 睡眠:睡眠对于身体健康非常重要。每晚应睡足7-8小时,睡眠质量也非常重要。避免晚上使用电子设备,避免晚上进食,保持良好的睡眠环境,避免刺激性物质,保持安静和舒适。", "label": "以下是保持健康的三个提示:\n\n1. 保持身体活动。每天做适当的身体运动,如散步、跑步或游泳,能促进心血管健康,增强肌肉力量,并有助于减少体重。\n\n2. 均衡饮食。每天食用新鲜的蔬菜、水果、全谷物和脂肪含量低的蛋白质食物,避免高糖、高脂肪和加工食品,以保持健康的饮食习惯。\n\n3. 睡眠充足。睡眠对人体健康至关重要,成年人每天应保证 7-8 小时的睡眠。良好的睡眠有助于减轻压力,促进身体恢复,并提高注意力和记忆力。"} |
generated_predictions.jsonl 文件 输出了要预测的数据集的原始label和模型predict的结果
predict_results.json给出了原始label和模型predict的指标数据
这里给相关的指标做一下进一步的解释
指标 | 含义 |
---|---|
BLEU-4 | BLEU(Bilingual Evaluation Understudy)是一种常用的用于评估机器翻译质量的指标。BLEU-4 表示四元语法 BLEU 分数,它衡量模型生成文本与参考文本之间的 n-gram 匹配程度,其中 n=4。值越高表示生成的文本与参考文本越相似,最大值为 100。 |
predict_rouge-1 和 predict_rouge-2 | ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一种用于评估自动摘要和文本生成模型性能的指标。ROUGE-1 表示一元 ROUGE 分数,ROUGE-2 表示二元 ROUGE 分数,分别衡量模型生成文本与参考文本之间的单个词和双词序列的匹配程度。值越高表示生成的文本与参考文本越相似,最大值为 100。 |
predict_rouge-l | ROUGE-L 衡量模型生成文本与参考文本之间最长公共子序列(Longest Common Subsequence)的匹配程度。值越高表示生成的文本与参考文本越相似,最大值为 100。 |
predict_runtime | 预测运行时间,表示模型生成一批样本所花费的总时间。单位通常为秒。 |
predict_samples_per_second | 每秒生成的样本数量,表示模型每秒钟能够生成的样本数量。通常用于评估模型的推理速度。 |
predict_steps_per_second | 每秒执行的步骤数量,表示模型每秒钟能够执行的步骤数量。对于生成模型,一般指的是每秒钟执行生成操作的次数。 |
9. LoRA模型合并导出
如果想把训练的LoRA和原始的大模型进行融合,输出一个完整的模型文件的话,可以使用如下命令。合并后的模型可以自由地像使用原始的模型一样应用到其他下游环节,当然也可以递归地继续用于训练。
本脚本参数改编自 LLaMA-Factory/examples/merge_lora/llama3_lora_sft.yaml at main · hiyouga/LLaMA-Factory
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli export \ |
win uv:
1 | uv run llamafactory-cli export ` |
10. webui board的使用
一个好的产品离不开好的交互,Stable Diffusion的大放异彩的重要原因除了强大的内容输出效果,就是它有一个好的WebUI。这个board将训练大模型主要的链路和操作都在一个页面中进行了整合,所有参数都可以可视化地编辑和操作。
通过以下命令启动
注意:目前webui版本只支持单机单卡和单机多卡,如果是多机多卡请使用命令行版本
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli webui |
1 | uv run llamafactory-cli webui |
如果要开启 gradio的share功能,或者修改端口号
1 | CUDA_VISIBLE_DEVICES=0 GRADIO_SHARE=1 GRADIO_SERVER_PORT=7860 llamafactory-cli webui |
上述的多个不同的大功能模块都通过不同的tab进行了整合,提供了一站式的操作体验。
当各种参数配置好后,在train页面,可以通过预览命令功能,将训练脚本导出,用于支持多gpu训练
点击开始按钮, 即可开始训练,网页端和服务器端会同步输出相关的日志结果
训练完毕后, 点击“刷新适配器”,即可找到该模型历史上使用webui训练的LoRA模型文件,后续再训练或者执行chat的时候,即会将此LoRA一起加载。
11. API Server的启动与调用
训练好后,可能部分同学会想将模型的能力形成一个可访问的网络接口,通过API 来调用,接入到langchian或者其他下游业务中,项目也自带了这部分能力。
API 实现的标准是参考了OpenAI的相关接口协议,基于uvicorn服务框架进行开发, 使用如下的方式启动
本脚本改编自 https://github.com/hiyouga/LLaMA-Factory/blob/main/examples/inference/llama3_lora_sft.yaml
1 | CUDA_VISIBLE_DEVICES=0 API_PORT=8000 llamafactory-cli api \ |
项目也支持了基于vllm 的推理后端,但是这里由于一些限制,需要提前将LoRA 模型进行merge,使用merge后的完整版模型目录或者训练前的模型原始目录都可。
1 | CUDA_VISIBLE_DEVICES=0 API_PORT=8000 llamafactory-cli api \ |
vLLM 只支持 linux 或 wsl
服务启动后,即可按照openai 的API 进行远程访问,主要的区别就是替换 其中的base_url,指向所部署的机器url和端口号即可。
1 | import os |
12. 进阶-大模型主流评测 benchmark
虽然大部分同学的主流需求是定制一个下游的垂直模型,但是在部分场景下,也可能有同学会使用本项目来做更高要求的模型训练,用于大模型刷榜单等,比如用于评测mmlu等任务。当然这类评测同样可以用于评估大模型二次微调之后,对于原来的通用知识的泛化能力是否有所下降。(因为一个好的微调,尽量是在具备垂直领域知识的同时,也保留了原始的通用能力)
本项目提供了mmlu,cmmlu, ceval三个常见数据集的自动评测脚本,按如下方式进行调用即可。
说明:task 目前支持 mmlu_test, ceval_validation, cmmlu_test
本脚本改编自 https://github.com/hiyouga/LLaMA-Factory/blob/main/examples/train_lora/llama3_lora_eval.yaml
如果是chat版本的模型
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli eval \ |
直接运行报错:Loading mmlu requires you to execute the dataset script in that repo on your local machine. Make sure you have read the code there to avoid malicious use, then set the option trust_remote_code=True
to remove this error.
找到LLaMA-Factory\src\llamafactory\hparams\model_args.py
1 | trust_remote_code: bool = field( |
命令行加入--trust_remote_code true
1 | Generating test split: 163 examples [00:00, 26106.29 examples/s] | 36/57 [10:45<05:30, 15.72s/it, jurisprudence] |
附:该模型使用HfArgumentParser是Transformer中的命令行解析工具,它是ArgumentParser的子类。用于从类对象中创建解析对象。所以,我们可以直接使用llamafactory-cli eval -h
获取参数帮助。
输出如下, 具体任务的指标定义请参考mmlu,cmmlu, ceval等任务原始的相关资料, 和llama3的官方报告基本一致
1 | Processing subjects: 100%|████████████████████████████████████████████| 57/57 [23:49<00:00, 25.09s/it, world religions] |
如果是base版本的模型,template改为fewshot即可
1 | CUDA_VISIBLE_DEVICES=0 llamafactory-cli eval \ |
13. 进阶-导出GGUF,部署Ollama
GGUF 是 lllama.cpp 设计的大模型存储格式,可以对模型进行高效的压缩,减少模型的大小与内存占用,从而提升模型的推理速度和效率。Ollama框架可以帮助用户快速使用本地的大型语言模型,那如何将LLaMA-Factory项目的训练结果 导出到Ollama中部署呢?需要经过如下几个步骤
- 将lora模型合并
- 安装gguf库
- 使用llama.cpp的转换脚本将训练后的完整模型转换为gguf格式
- 安装Ollama软件
- 注册要部署的模型文件
- 启动Ollama
1-3 步是准备好 gguf格式的文件,这也是Ollama所需要的标准格式。
4-6 步就是如何在Ollama环境中启动训练后的模型。
1.lora模型合并
参考上文lora微调后合并
注意:合并后可以在该目录下获取 转换好ollama需要的 Modelfile 文件
2. 安装gguf库
gguf · PyPI还没有do
1 | uv pip install gguf |
1 | GGUF Release history |
1 | TODO |
发现没有支持脚本运行
1 | git clone https://github.com/ggerganov/llama.cpp.git |
3. 格式转换
返回 llama.cpp 项目根目录,会有一个官方提供的 convert-hf-to-gguf.py 脚本,用于完成huggingface格式到gguf格式的转换.
1 | uv run .\llama.cpp\convert_hf_to_gguf.py E:/Datasets/LLM/Llama-3.2-3B-Instruct |
转换成功下得到如下的Llama-3.2-3B-Instruct-F16.gguf文件
1 | INFO:gguf.gguf_writer:Writing the following files: |
1 | Directory: E:\Datasets\LLM\Llama-3.2-3B-Instruct |
4. Ollama安装
5. 注册要部署的模型文件
6. 启动Ollama
4、5、6在Ollama部署已成功