跳到主要内容
基于 SFT 微调 Llama2 实现自我认知 | 极客日志
Python AI 算法
基于 SFT 微调 Llama2 实现自我认知 综述由AI生成 使用 SFT 微调 Llama2 模型以实现自我认知的完整流程。内容包括环境配置、数据准备、LoRA 微调训练、模型测试与导出,以及通过 FastChat 提供 OpenAI 兼容 API 接口的方法。此外,还展示了如何将微调后的模型与本地知识库框架整合,并补充了常见问题排查与性能优化建议,为垂直领域大模型应用开发提供参考。
魔尊 发布于 2025/2/6 更新于 2026/6/2 25 浏览一、概述
本文主要介绍如何通过监督微调(SFT)调整 Llama2 模型的自我认知能力。通过微调,模型能够更准确地回答关于自身身份或特定设定相关的问题。
微调前效果示例:
微调后效果示例:
通过本文的学习,你将了解如下内容:
如何使用 SFT 微调 Llama2
如何导出微调后的大模型
如何使用 FastChat 实现 OpenAI 兼容的 RESTful API 接口
二、环境与模型选择
环境配置
使用 nvidia-smi 命令查看 GPU 的配置,微调的 GPU 配置如下:
$nvidia -smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.161.03 Driver Version: 470.161.03 CUDA Version: 11.7 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA A800-SXM... Off | 00000000:8E:00.0 Off | 0 |
| N/A 30C P0 69W / 400W | 17320MiB / 81251MiB | 0% Default |
| | | Disabled |
+-------------------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================
+-----------------------------------------------------------------------------+
微调 Llama2 需要 1 个 GPU,建议显存至少 24G,较低的内存会导致加载模型较慢。
开源框架和模型
微调的模型: Chinese-Llama-2-7b
微调框架: LLaMA-Efficient-Tuning
提供 openai 兼容的 RESTful API 框架: FastChat
本地知识库问答应用框架: LangChain-Chatchat由于 Llama2 本身的中文对齐较弱,这里没有直接使用 meta-llama/Llama-2-7b 而是使用 LinkSoul/Chinese-Llama-2-7b 进行微调,微调方法是类似的,感兴趣的可以基于 meta-llama/Llama-2-7b 进行微调。下面详细介绍一下微调的步骤。
三、SFT 微调
1、下载预训练模型 在 HuggingFace 上面搜索模型名称,可以看到下载模型的方式如下:
新建一个 models 文件夹用来存放下载的大模型,使用下面的命令下载预训练模型:
mkdir models
git lfs install
git clone https://huggingface.co/LinkSoul/Chinese-Llama-2-7b
export GIT_LFS_SKIP_SMUDGE=1
2、下载微调框架 使用如下命令,在当前目录下载微调框架 LLaMA-Efficient-Tuning:
git clone https://github.com/hiyouga/LLaMA-Efficient-Tuning.git
进入 LLaMA-Efficient-Tuning 目录:
cd LLaMA-Efficient-Tuning
3、准备微调数据 进入微调框架 LLaMA-Efficient-Tuning 目录后,找到存放微调数据的 data 目录,如下所示:
我们可以查看一下 self_cognition.json 自我认知文件内容如下:
可以看到 <NAME> 和 <AUTHOR> 是占位符,我们只需要复制一份文件,将对应的占位符替换为需要的名称即可。复制一份文件是为了自我认知的模版文件可复用,我替换后的文件内容如下,你可以改成自己的名字:
微调数据准备好了后,需要在 dataset_info.json 中配置如下:
{
"self_cognition" : {
"file_name" : "self_cognition.json" ,
"file_sha1" : "6287a730ada924fc5d9eadc6d8f865e01b7a6f67"
}
}
dataset_info.json 文件会被转换为 python 的字典,self_cognition 就是字典的 key,在微调的时候需要指定的数据集名称就是该 key,file_sha1 文件的摘要可以不填,file_name 就是微调文件的名称,如果该微调文件在 data 目录中,则直接指定名称即可,如果在 data 目录的子目录中,则需要指定子目录的名字,举例如下:
4、开始 SFT 微调 微调数据准备好后就可以开始执行微调了,使用如下命令进行微调:
CUDA_VISIBLE_DEVICES=0 python src/train_bash.py \
--stage sft \
--do_train \
--dataset self_cognition \
--model_name_or_path /ossfs/workspace/models/Chinese-Llama-2-7b \
--output_dir /ossfs/workspace/llama2-sft/checkpoint-01 \
--template default \
--finetuning_type lora \
--lora_target q_proj,v_proj \
--overwrite_cache \
--per_device_train_batch_size 4 \
--gradient_accumulation_steps 4 \
--lr_scheduler_type cosine \
--logging_steps 10 \
--save_steps 2000 \
--learning_rate 1e-3 \
--num_train_epochs 10.0 \
--plot_loss \
--fp16
--stage sft: 训练阶段。这里指定为 sft,表示进行模型的微调(Self-Supervised Fine-Tuning)阶段。
--do_train: 是否进行训练,设置为 True 表示进行训练。还可以设置为(--do_eval:表示评估,--do_predict:表示预测)
--dataset self_cognition: 数据集名称。这里指定为 self_cognition,表示使用自我认知数据集。
--model_name_or_path: 预训练模型的名称或路径。这里指定为 /ossfs/workspace/models/Chinese-Llama-2-7b,表示加载路径下的预训练模型。
--output_dir: 训练输出目录。训练过程中生成的模型和日志将保存在该目录下。
--template default: 模板名称。这里指定为 default,表示使用默认模板。
--finetuning_type lora: 微调类型。这里指定为 lora,表示使用 LoRA(Low-Rank Adaptation)微调方法。
--lora_target q_proj,v_proj: LoRA 微调的目标层。这里指定为 q_proj, v_proj,表示只对这两个层进行微调。
--overwrite_cache: 是否覆盖缓存。设置为 True 表示覆盖缓存。
--per_device_train_batch_size 4: 每个设备的训练批次大小。这里指定为 4,表示每个设备上的训练批次大小为 4。
--gradient_accumulation_steps 4: 梯度累积步数。这里指定为 4,表示每 4 个步骤累积一次梯度。
--lr_scheduler_type cosine: 学习率调度器类型。这里指定为 cosine,表示使用余弦学习率调度器。
--logging_steps 10: 日志记录步数。每训练多少步记录一次训练日志。
--save_steps 2000: 模型保存步数。每训练多少步保存一次模型。
--learning_rate 1e-3: 学习率。这里指定为 1e-3,表示初始学习率为 0.001。
--num_train_epochs 10.0: 训练轮数。这里指定为 10.0,表示进行 10 轮训练。
--plot_loss: 是否绘制损失曲线。设置为 True 表示绘制损失曲线。
--fp16: 是否使用混合精度(half-precision)训练。设置为 True 表示使用混合精度训练。
以上是对该大模型训练命令中各个参数的解释。根据需求,可以根据实际情况进行相应参数的修改。不同的参数设置会对训练过程和结果产生影响,需要根据具体任务和数据集进行调整。
启动微调命令后,输出日志如下,需要用户输入是否需要 wandb (一个深度学习轻量级可视化工具) 将训练结果可视化,我这里选择不可视化训练结果。
微调命令结束后可以看到如下日志输出,从日志中可以看到微调后的模型 checkpoint 的位置、损失曲线的信息以及训练的汇总信息:
在大模型训练过程中,train loss 图像是指每个训练批次的损失值随训练轮次的变化情况。这个图像可以用来解读训练过程中模型的收敛情况和学习进展。
train loss 图像的纵轴表示损失值,横轴表示训练轮次或训练批次。通常,初始阶段的损失值较高,随着训练的进行,损失值会逐渐下降。如果损失值趋向于稳定,说明模型已经收敛,训练效果良好。如果损失值下降很慢,可能需要更多的训练轮次或调整模型超参数。如果损失值波动较大,可能存在过拟合或其他问题,需要进一步调整模型或数据。
解读 train loss 图像时,可以观察以下几个方面:
初始阶段的损失值高低,较高的初始损失值可能表明模型初始化不合适,需要调整初始化方法。
损失值下降的速率,较快的下降速率可能表明模型对数据的学习能力较强,但也可能存在过拟合的风险。
损失值的稳定性,稳定的损失值说明模型已经收敛,训练效果较好。如果损失值在一定范围内波动,可以考虑增加训练轮次或使用正则化等方法进一步优化模型。
训练过程中的异常情况,如损失值突然上升或跳跃,可能表明出现了问题,需要检查模型或数据是否存在异常。
总之,train loss 图像可以提供对模型训练过程的直观理解,帮助调整模型和优化训练策略,以达到更好的训练效果。
train loss 的值下降到什么范围表示模型的训练效果较好?
train loss 的值下降到一个较低的范围可以表示模型的训练效果较好。具体的判断标准可以根据具体的任务和数据集来确定,没有一个统一的阈值。
一种常见的做法是观察 train loss 图像的趋势,如果随着训练的进行,train loss 不断下降并趋于稳定,说明模型对训练数据的拟合效果较好,训练效果较好。
此外,可以根据验证集的表现来评估模型的训练效果。如果验证集的损失值也在下降并趋于稳定,且与训练集的损失值相近,说明模型在训练集和验证集上都能取得较好的效果,训练效果较好。
需要注意的是,train loss 仅仅是一个指标,不能完全代表模型的训练效果。还需要综合考虑模型在其他指标上的表现,如准确率、精确率、召回率等,以及在实际应用场景中的效果。
5、测试微调后的模型 微调框架 LLaMA-Efficient-Tuning 中提供了三种测试使用微调模型的方式,如下所示:
api_demo.py:使用 api 的方式调用微调模型
cli_demo.py:在命令行中调用微调模型
web_demo.py:在 web 页面中调用微调模型
由于服务器没有外网访问的地址,所以使用 cli_demo.py 命令行的方式手动测试微调后的模型,启动命令如下:
CUDA_VISIBLE_DEVICES=0 python src/cli_demo.py \
--model_name_or_path /ossfs/workspace/models/Chinese-Llama-2-7b \
--checkpoint_dir /ossfs/workspace/llama2-sft/checkpoint-01\
--template llama2
查看 cli_demo.py 源码,调用了 ChatModel.stream_chat(query, history),ChatModel 的构造方法中调用了 get_infer_args(args)。
get_infer_args(args) 如下所示,可以看到只有 LoRA 的微调支持指定多个 checkpoint:
在模型参数中可以看到指定 checkpoint_dir 时可以使用 , 分隔多个 checkpoint:
所以如果你使用 LoRA 进行微调,那么当有多个微调任务,生成多个 checkpoint 时,多个 checkpoint 可以使用 , 分隔,假设你微调了两个 checkpoint:/ossfs/workspace/llama2-sft/checkpoint-01 和 /ossfs/workspace/llama2-sft/checkpoint-02,那么你可以使用下面的命令测试两个微调后的模型:
CUDA_VISIBLE_DEVICES=0 python src/cli_demo.py \
--model_name_or_path /ossfs/workspace/models/Chinese-Llama-2-7b \
--checkpoint_dir /ossfs/workspace/llama2-sft/checkpoint-01,/ossfs/workspace/llama2-sft/checkpoint-02\
--template default
因为我这里只微调了自我认知,并且将在微调的时候指定 --output_dir /ossfs/workspace/llama2-sft/checkpoint-01,所以使用下面的命令来测试微调后的模型即可:
CUDA_VISIBLE_DEVICES=0 python src/cli_demo.py \
--model_name_or_path /ossfs/workspace/models/Chinese-Llama-2-7b \
--checkpoint_dir /ossfs/workspace/llama2-sft/checkpoint-01\
--template default
运行测试命令需要再次加载模型,比较耗时,需要耐心等待,运行成功后可以看到如下输出:
6、导出微调后的模型 经过前面的微调,如果微调后的模型通过了测试就可以将微调后的模型导出,使用如下命令即可:
CUDA_VISIBLE_DEVICES=0 python src/export_model.py \
--model_name_or_path /ossfs/workspace/models/Chinese-Llama-2-7b \
--checkpoint_dir /ossfs/workspace/llama2-sft/checkpoint-01\
--output_dir /ossfs/workspace/sft-models/my-llama5 \
--template default
这里使用 --output_dir 将模型导出到 /ossfs/workspace/sft-models/my-llama5 目录中,可以看到目录中包括如下内容:
7、微调模型提供 RESTful API 接口 经过前面的步骤,我们已经将自己微调后的模型导出了,现在我们可以使用 FastChat 将模型发布为 OpenAI 兼容的 RESTful API 以便外部服务使用。
FastChat 为其支持的模型提供与 OpenAI 兼容的 API,因此您可以使用 FastChat 作为 OpenAI API 的本地直接替代品。FastChat 服务器与 openai-python 库和 cURL 命令兼容。
Chat Completions
Completions
Embeddings
python3 -m fastchat.serve.controller
然后,启动模型,通过 --model-path 指定模型的路径,这里我们指定前面微调后的模型路径 /ossfs/workspace/sft-models/my-llama5
python3 -m fastchat.serve.model_worker --model-path /ossfs/workspace/sft-models/my-llama5
python3 -m fastchat.serve.openai_api_server --host localhost --port 8000
目标 openai_api_server.py 是实现一个完全兼容 OpenAI 的 API 服务器,因此模型可以直接与 openai-python 库一起使用。
pip install --upgrade openai
import openai
openai.api_key = "EMPTY"
openai.api_base = "http://localhost:8000/v1"
model = "my-llama5"
completion = openai.ChatCompletion.create(
model=model,
messages=[{"role" : "user" , "content" : "你是谁" }]
)
print (completion.choices[0 ].message.content)
在 jupyterlab 中运行上面的代码,输出结果如下:
8、微调模型和本地知识库整合 因为后面打算学习了解一下将大模型和知识库整合,所以我这里先使用本地知识库问答应用框架 LangChain-Chatchat 和微调后的模型整合。下面我先简单介绍一下整合的步骤。
首先下载 Langchain-Chatchat,使用如下命令:
git clone https://github.com/chatchat-space/Langchain-Chatchat.git
进入 Langchain-Chatchat,使用下面的命令安装 python 依赖库:
cd Langchain-Chatchat
pip install -r requirements.txt
pip install -r requirements_api.txt
cp configs/model_config.py.example configs/model_config.py
在 model_config.py 配置文件需要修改如下内容,在 llm_model_dict 指定模型的地址,并且设置 LLM_MODEL 的名称和 llm_model_dict 的 key 对应:
llm_model_dict = {
"llama2" : {
"local_model_path" : "/ossfs/workspace/sft-models/my-llama5" ,
"api_base_url" : "http://localhost:8888/v1" ,
"api_key" : "EMPTY"
}
}
LLM_MODEL = "llama2"
接下来就可以使用下面的命令启动 llm_api.py:
启动成功后可以使用下面的代码在 jupyterlab 中进行验证:
import openai
openai.api_key = "EMPTY"
openai.api_base = "http://localhost:8888/v1"
model = "llama2"
def get_answer (content ):
completion = openai.ChatCompletion.create(
model=model,
messages=[{"role" : "user" , "content" : content}]
)
print ('用户:' , content)
print ('模型:' , completion.choices[0 ].message.content)
get_answer('你是谁' )
get_answer('你叫什么名字' )
四、常见问题与优化建议
1. 显存不足(OOM) 如果在训练过程中遇到 OOM 错误,可以尝试以下方法:
减小 --per_device_train_batch_size。
增大 --gradient_accumulation_steps 以保持有效 batch size。
使用 --bf16 代替 --fp16(如果硬件支持)以节省显存。
启用 --flash_attention_2(如果环境支持)以提高效率。
2. 损失不下降 如果训练过程中 loss 不下降,可能是以下原因:
学习率过高,尝试降低 --learning_rate。
数据质量差,检查 self_cognition.json 格式是否正确。
模型未正确加载,确认 --model_name_or_path 路径无误。
3. 推理速度慢
使用量化技术(如 INT8/INT4)减少模型体积。
使用 vLLM 等高性能推理引擎替代原生 FastChat。
开启 Tensor Parallelism 在多卡环境下加速推理。
五、总结 本文详细介绍了利用 SFT 技术微调 Llama2 模型以实现特定自我认知的完整流程。从环境搭建、数据准备、模型训练到导出及 API 服务化,涵盖了大模型垂直应用开发的核心环节。通过 LoRA 高效微调,可以在有限的计算资源下实现模型能力的定向增强。后续可结合 RAG 技术进一步提升模型在特定领域的知识问答能力。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online