基于 LoRA 技术调整大模型身份认知的实操记录
本文展示如何使用 LLaMAFactory 对 Qwen1.5-1.8B-Chat 执行 LoRA 微调,目标是改变模型对自身身份的认知。
微调前,当询问"你是谁?"时,Qwen1.5-1.8B-Chat 会回答"我是阿里云自主研发的超大规模语言模型,我叫通义千问"。
微调后,我们希望模型能够回答"我是 Archer,由 意琦行 研发"。
1. 关键概念回顾
大模型的构建一般经历三个阶段:
- 预训练 (Pre Training, PT):使用海量无监督数据训练得到基座模型,使其具备预测下一个 token 的能力,但尚未具备对话功能。
- 指令微调 (Supervised Fine-Tuning, SFT):在基座模型上使用标注的问答数据训练,使其学会针对问题给出答案,而非生成另一个问题。
- 强化学习 (Reinforcement Learning from Human Feedback, RLHF):根据人类反馈优化模型输出质量,使其更符合用户期望和价值观。通常借助奖励模型简化流程。
由于预训练对算力和数据要求极高,普通开发者通常基于开源的基座模型(如 Llama、Qwen、ChatGLM 等)进行微调和强化学习。
微调方法
微调根据更新的参数量分为两类:
- 全量微调 (Full Fine-Tuning, FFT):更新所有参数,训练慢、资源消耗大。
- 参数高效微调 (Parameter-Efficient Fine-Tuning, PEFT):只更新少量参数,训练快、资源占用少。
常见的 PEFT 方法包括:Prompt Tuning、Prefix Tuning、LoRA、QLoRA。
微调工具
- LLaMA-Factory:支持海量模型和主流微调方法,提供命令行和 Web 端操作,内置训练数据集。
- Transformers:基础库,适用于快速实验和生产部署。
- PEFT:Hugging Face 开源的微调基础工具。
- ms-swift:ModelScope 开源,以中文模型为主。
- Megatron-LM:NVIDIA 出品,适合超大规模训练。
本文选用 LLaMAFactory 进行演示。
2. 安装 LLaMAFactory
准备 GPU 环境(如 NVIDIA A40),使用镜像 pytorch/pytorch:2.0.1-cuda11.7-cudnn8-runtime 启动容器。
git clone -b v0.8.1 https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e .[torch,metrics]
若安装缓慢,可配置国内镜像源:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
3. 准备模型与数据集
下载模型
使用 Qwen1.5-1.8B-Chat 进行微调,通过 git lfs 下载:
apt install git-lfs -y
git lfs install
git lfs clone https://www.modelscope.cn/qwen/Qwen1.5-1.8B-Chat.git
下载完成后包含 model.safetensors(3.5G)、tokenizer 等文件。
准备数据集
LLaMA-Factory 内置了 identity 数据集,用于修改模型自我认知。数据格式如下:
[
{
"instruction": "hi",
"input": "",
"output": "Hello! I am {{name}}, an AI assistant developed by {{author}}. How can I assist you today?"
},
{
"instruction": "你是谁?",
"input": "",
"output": "您好,我叫 {{name}},是一个由 {{author}} 训练和开发的人工智能助手。"
}
]
使用 sed 替换变量:
sed -i 's/{{name}}/Archer/g; s/{{author}}/意琦行/g' data/identity.json
注册数据集
将数据集文件放入 data 目录,并在 data/dataset_info.json 中注册:
{
"identity": {
"file_name": "identity.json"
}
}
4. 执行微调
微调命令
modelPath=models/Qwen1.5-1.8B-Chat
llamafactory-cli train \
--model_name_or_path $modelPath \
--stage sft \
--do_train \
--finetuning_type lora \
--template qwen \
--dataset identity \
--output_dir ./saves/lora/sft \
--learning_rate 0.0005 \
--num_train_epochs 8 \
--cutoff_len 4096 \
--logging_steps 1 \
--warmup_ratio 0.1 \
--weight_decay 0.1 \
--gradient_accumulation_steps 8 \
--save_total_limit 1 \
--save_steps 256 \
--seed 42 \
--data_seed 42 \
--lr_scheduler_type cosine \
--overwrite_cache \
--preprocessing_num_workers 16 \
--plot_loss \
--overwrite_output_dir \
--per_device_train_batch_size 1 \
--fp16
训练输出
[INFO|trainer.py:2087] 2024-07-23 15:50:04,741 >> Number of trainable parameters = 7,495,680
...
{'loss': 0.4613, 'grad_norm': 1.1036, 'learning_rate': 8.18e-06, 'epoch': 4.48}
...
{'loss': 0.2622, 'grad_norm': 1.1825, 'learning_rate': 0.0, 'epoch': 4.84}
Training completed.
Saving model checkpoint to ./saves/lora/sft
训练结果分析
训练过程中 loss 逐渐下降并收敛,表明训练效果良好。保存的 LoRA 权重文件仅 29M。
预测评估
计算模型输出与数据集的 ROUGE、BLEU 指标:
llamafactory-cli train \
--stage sft \
--do_predict \
--finetuning_type lora \
--model_name_or_path $modelPath \
--adapter_name_or_path ./saves/lora/sft \
--template qwen \
--dataset identity \
--cutoff_len 4096 \
--max_samples 20 \
--overwrite_cache \
--overwrite_output_dir \
--per_device_eval_batch_size 1 \
--preprocessing_num_workers 16 \
--predict_with_generate
输出:
predict_bleu-4 = 86.09
predict_rouge-1 = 91.55
predict_rouge-2 = 86.11
predict_rouge-l = 89.65
各项指标较高,说明模型输出与目标数据相似度很高。
权重合并
将 LoRA 权重与原始模型合并:
modelPath=models/Qwen1.5-1.8B-Chat
adapterModelPath=./saves/lora/sft/
llamafactory-cli export \
--model_name_or_path $modelPath \
--adapter_name_or_path $adapterModelPath \
--template qwen \
--finetuning_type lora \
--export_dir ./saves/lora/export/ \
--export_size 2 \
--export_device cpu \
--export_legacy_format False
合并后得到完整模型文件(约 3.5G)。
5. 测试微调效果
使用 vLLM 启动推理服务进行测试。
原始模型
python3 -m vllm.entrypoints.openai.api_server \
--model /models/Qwen1.5-1.8B-Chat \
--served-model-name qwen \
--trust-remote-code
请求:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你是谁?"}
]
}'
响应:
"content": "我是来自阿里云的大规模语言模型,我叫通义千问。"
微调后模型
python3 -m vllm.entrypoints.openai.api_server \
--model /LLaMA-Factory/save/lora/export/ \
--served-model-name qwen \
--trust-remote-code
请求:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你是谁?"}
]
}'
响应:
"content": "您好,我是 Archer,由 意琦行 开发,旨在为用户提供智能化的回答和帮助。"
模型身份已成功变更为 Archer。
6. 完整流程总结
- 准备基座模型和微调数据集。
- 将数据集注册到 LLaMAFactory。
- 执行 LoRA 微调。
- 通过 loss 曲线和预测指标评估效果。
- 合并 LoRA 权重得到完整微调模型。
以上即为使用 LLaMAFactory 进行 LoRA 微调修改大模型自我认知的完整操作过程。