任务
使用 XTuner 微调 InternLM2-Chat-1.8B 实现自己的小助手认知,如下图所示(图中的伍鲜同志需替换成自己的昵称),记录复现过程并截图。
微调介绍
什么是微调
微调(fine-tuning)是一种基于预训练模型,通过少量的调整(fine-tune)来适应新的任务或数据的方法。
在大模型出现以前,很多 CV、NLP 任务也都是基于预训练模型来做的。
微调是在预训练模型的基础上,将模型中一些层的权重参数进行微调,以适应新的数据集或任务。
预训练模型部分已经在大规模数据上得到了训练,它们通常是较为通用且高性能的模型,因此可以很好地作为新任务的起点。微调可以加快模型的收敛速度,降低模型过拟合的风险,并在不消耗过多计算资源的情况下获取较好的模型性能。
微调的两种范式
在大模型的下游应用中,经常会用到两种微调模式:增量预训练 和 指令跟随 。
增量预训练
增量预训练是一种在已有预训练模型(比如:InternLM基座模型)的基础上,利用特定领域的数据进行进一步训练的方法。它的目的是在保持模型原有能力的同时,注入新的领域知识,进一步优化现有的预训练模型,从而提升模型在特定领域任务中的表现(比如:InternLM垂类基座模型)。增量预训练模型能够接受少量的新数据进行更新并适应新的任务,而不需要重新训练整个模型,这种方式可以很好地利用现有的预训练模型的知识,并在新数据上获得更好的性能。
指令跟随
指令跟随是指让模型根据用户输入的指令来执行相应的操作。模型通过对大量自然语言指令和相应操作的数据进行训练,学习如何将指令分解为具体的子任务,并选择合适的模块来执行这些任务(比如:InternLM垂类对话模型)
XTuner介绍
XTuner 的官方仓库是:https://github.com/InternLM/xtuner (欢迎Star)!
XTuner 一个大语言模型&多模态模型微调工具箱。由 MMRazor 和 MMDeploy 联合开发。
- 🤓 傻瓜化: 以 配置文件 的形式封装了大部分微调场景,0基础的非专业人员也能一键开始微调。
- 🍃 轻量级: 对于 7B 参数量的LLM,微调所需的最小显存仅为 8GB : 消费级显卡✅,colab✅
- 功能亮点
- 适配多种生态
- 支持多种微调算法
- 适配多种开源生态(HuggingFace、ModelScope等)
- 自动优化加速器
- 适配多种硬件
下面我们就用 XTuner 微调个人小助手。
微调个人小助手
这里,我的算力资源比较丰富,我就用 30% 的 A100(24G显存)。8G 显存也可以~
环境搭建
克隆 Tutorial 仓库到本地
mkdir -p /root/InternLM/Tutorial
git clone -b camp3 https://github.com/InternLM/Tutorial /root/InternLM/Tutorial
创建虚拟环境,安装环境(有些库之前下载过,有缓存,安装起来比较快)
# 创建虚拟环境
conda create -n xtuner01 python=3.8
# 激活虚拟环境(注意:后续的所有操作都需要在这个虚拟环境中进行)
conda activate xtuner01
# 安装一些必要的库
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
# 安装其他依赖
pip install transformers==4.39.3
pip install streamlit==1.36.0
安装 XTuner
# 创建一个目录,用来存放源代码
mkdir -p /root/InternLM/code
cd /root/InternLM/code
git clone -b v0.1.21 https://github.com/InternLM/XTuner /root/InternLM/code/XTuner
# 进入到源码目录
cd /root/InternLM/code/XTuner
# 执行安装
pip install -e '.[deepspeed]'
# 验证安装结果
xtuner version
准备模型
InternStudio 中提供了模型的本地文件,其他机器可以从 HuggingFace、OpenXLab 或者 Modelscope 进行模型的下载。
# 创建一个目录,用来存放微调的所有资料,后续的所有操作都在该路径中进行
mkdir -p /root/InternLM/XTuner
cd /root/InternLM/XTuner
mkdir -p Shanghai_AI_Laboratory
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b Shanghai_AI_Laboratory/internlm2-chat-1_8b
执行上述操作后,Shanghai_AI_Laboratory/internlm2-chat-1_8b 将直接成为一个符号链接,这个链接指向 /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b 的位置,方便访问!
快速开始
里我们用 internlm2-chat-1_8b 模型,通过 QLoRA 的方式来微调一个自己的小助手认知
微调前的模型
直接启动 Tutorial 中的web服务,通过 web 服务看下微调前的模型如何。
conda activate xtuner01
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
然后将端口映射到本地,在本地访问 web 服务
ssh -CNg -L 8501:127.0.0.1:8501 root@ssh.intern-ai.org.cn -p 开发机端口
运行,提问,结果如下
指令微调
准数据文件,微调模型,让他知道自己到底是谁!我们准备一个数据集文件datas/assistant.json,文件内容为对话数据。
cd /root/InternLM/XTuner
mkdir -p datas
touch datas/assistant.json
为了简化数据文件准备,我们也可以通过脚本生成的方式来准备数据。创建一个脚本文件 xtuner_generate_assistant.py :
cd /root/InternLM/XTuner
touch xtuner_generate_assistant.py
输入脚本内容并保存:
import json
# 设置用户的名字
# 为了训练出我们的小助手,我们需要将脚本中name后面的内容修改为自己的名称。
name = 'Payphone'
# 设置需要重复添加的数据次数
n = 3750
# 初始化数据
data = [
{"conversation": [{"input": "请介绍一下你自己", "output": "我是{}的小助手,内在是上海AI实验室书生·浦语的1.8B大模型哦".format(name)}]},
{"conversation": [{"input": "你在实战营做什么", "output": "我在这里帮助{}完成XTuner微调个人小助手的任务".format(name)}]}
]
# 通过循环,将初始化的对话数据重复添加到data列表中
for i in range(n):
data.append(data[0])
data.append(data[1])
# 将data列表中的数据写入到'datas/assistant.json'文件中
with open('datas/assistant.json', 'w', encoding='utf-8') as f:
# 使用json.dump方法将数据以JSON格式写入文件
# ensure_ascii=False 确保中文字符正常显示
# indent=4 使得文件内容格式化,便于阅读
json.dump(data, f, ensure_ascii=False, indent=4)
然后执行该脚本来生成数据文件。
cd /root/InternLM/XTuner
python xtuner_generate_assistant.py
准备配置文件
我们是对internlm2-chat-1_8b模型进行指令微调,所以与我们的需求最匹配的配置文件是 internlm2_chat_1_8b_qlora_alpaca_e3,这里就复制该配置文件。
cd /root/InternLM/XTuner
# 复制配置文件
xtuner copy-cfg internlm2_chat_1_8b_qlora_alpaca_e3 .
修改配置文件
#######################################################################
# PART 1 Settings #
#######################################################################
- pretrained_model_name_or_path = 'internlm/internlm2-chat-1_8b'
+ pretrained_model_name_or_path = '/root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b'
- alpaca_en_path = 'tatsu-lab/alpaca'
+ alpaca_en_path = 'datas/assistant.json'
evaluation_inputs = [
- '请给我介绍五个上海的景点', 'Please tell me five scenic spots in Shanghai'
+ '请介绍一下你自己', 'Please introduce yourself'
]
#######################################################################
# PART 3 Dataset & Dataloader #
#######################################################################
alpaca_en = dict(
type=process_hf_dataset,
- dataset=dict(type=load_dataset, path=alpaca_en_path),
+ dataset=dict(type=load_dataset, path='json', data_files=dict(train=alpaca_en_path)),
tokenizer=tokenizer,
max_length=max_length,
- dataset_map_fn=alpaca_map_fn,
+ dataset_map_fn=None,
template_map_fn=dict(
type=template_map_fn_factory, template=prompt_template),
remove_unused_columns=True,
shuffle_before_pack=True,
pack_to_max_length=pack_to_max_length,
use_varlen_attn=use_varlen_attn)
开始微调!
使用 xtuner train 命令训练模型!
cd /root/InternLM/XTuner
xtuner train ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py
训练开始啦~
模型转换
正常,我们部署模型是不会直接用 torch 部署的,而是会转换成其他中间格式(可以加速)。这里我们转成 HuggingFace 格式文件。
cd /root/InternLM/XTuner
conda activate xtuner0121
# 先获取最后保存的一个pth文件
pth_file=`ls -t ./work_dirs/internlm2_chat_1_8b_qlora_alpaca_e3_copy/*.pth | head -n 1`
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
xtuner convert pth_to_hf ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py ${pth_file} ./hf
参数名 | 解释 |
---|---|
--fp32 | 代表以fp32的精度开启,假如不输入则默认为fp16 |
--max-shard-size {GB} | 代表每个权重文件最大的大小(默认为2GB) |
模型合并
对于 LoRA 或者 QLoRA 微调出来的模型其实并不是一个完整的模型,而是一个额外的层(Adapter),训练完的这个层最终还是要与原模型进行合并才能被正常的使用。
cd /root/InternLM/XTuner
conda activate xtuner0121
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
xtuner convert merge /root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b ./hf ./merged --max-shard-size 2GB
微调后的结果
微调完成后,我们可以再次运行xtuner_streamlit_demo.py脚本来观察微调后的对话效果,不过在运行之前,我们需要将脚本中的模型路径修改为微调后的模型的路径
# 直接修改脚本文件第18行
- model_name_or_path = "/root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b"
+ model_name_or_path = "/root/InternLM/XTuner/merged"
然后,我们可以直接启动应用。
conda activate xtuner0121
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
运行后,确保端口映射正常,如果映射已断开则需要重新做一次端口映射。
ssh -CNg -L 8501:127.0.0.1:8501 root@ssh.intern-ai.org.cn -p 43551
最后,通过浏览器访问:http://127.0.0.1:8501 来进行对话了。
可以看到,微调成功了!!!