一、XTuner简介
XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。
高效
- 支持大语言模型 LLM、多模态图文模型 VLM 的预训练及轻量级微调。XTuner 支持在 8GB 显存下微调 7B 模型,同时也支持多节点跨设备微调更大尺度模型(70B+)。
- 自动分发高性能算子(如 FlashAttention、Triton kernels 等)以加速训练吞吐。
- 兼容 DeepSpeed ,轻松应用各种 ZeRO 训练优化策略。
灵活
- 支持多种大语言模型,包括但不限于 InternLM、Mixtral-8x7B、Llama 2、ChatGLM、Qwen、Baichuan。
- 支持多模态图文模型 LLaVA 的预训练与微调。利用 XTuner 训得模型 LLaVA-InternLM2-20B 表现优异。
- 精心设计的数据管道,兼容任意数据格式,开源数据或自定义数据皆可快速上手。
- 支持 QLoRA、LoRA、全量参数微调等多种微调算法,支撑用户根据具体需求作出最优选择。
全能
- 支持增量预训练、指令微调与 Agent 微调。
- 预定义众多开源对话模版,支持与开源或训练所得模型进行对话。
- 训练所得模型可无缝接入部署工具库 LMDeploy、大规模评测工具库 OpenCompass 及 VLMEvalKit。
二、环境配置
我们首先来配置XTuner实验环境。首先克隆Tutoral仓库到本地:
mkdir -p /root/InternLM/Tutorial
git clone -b camp3 https://github.com/InternLM/Tutorial /root/InternLM/Tutorial
配置Python实验环境:
# 创建虚拟环境
conda create -n xtuner0121 python=3.10 -y
# 激活虚拟环境(注意:后续的所有操作都需要在这个虚拟环境中进行)
conda activate xtuner0121
# 安装一些必要的库
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 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
conda activate xtuner0121
# 执行安装
pip install -e '.[deepspeed]'
随后我们要准备需要微调的模型:InternLM2-chat-1.8B。由于开发机已经有模型文件,因此我们直接创建软链接即可:
# 创建一个目录,用来存放微调的所有资料,后续的所有操作都在该路径中进行
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
│ ├── README.md
│ ├── config.json
│ ├── configuration.json
│ ├── configuration_internlm2.py
│ ├── generation_config.json
│ ├── model-00001-of-00002.safetensors
│ ├── model-00002-of-00002.safetensors
│ ├── model.safetensors.index.json
│ ├── modeling_internlm2.py
│ ├── special_tokens_map.json
│ ├── tokenization_internlm2.py
│ ├── tokenization_internlm2_fast.py
│ ├── tokenizer.model
│ └── tokenizer_config.json
三、前置实验
我们首先来看一看没有经过微调的模型的表现。使用streamlit部署模型应用:
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
我们从浏览器打开应用,并测试回答“请介绍一下你自己”和“你在实战营做什么?”两个问题:
可以看到,模型无法回答这些问题。接下来我们通过进行微调来改变模型的输出。
四、模型微调
1. 数据集
下面我们对模型进行指令微调。首先需要准备微调数据,为了简单,我们就采用以上两个问题作为指令微调数据。
数据位于datas
文件夹下:
cd /root/InternLM/XTuner
mkdir -p datas
在/root/InternLM/XTuner
文件夹创建xtuner_generate_assistant.py
,内容如下:
import json
# 设置用户的名字
name = '幻梦同志'
# 设置需要重复添加的数据次数
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)
以上代码将两条对话数据重复了3750次,作为微调指令数据。随后执行脚本来生成数据文件:
python xtuner_generate_assistant.py
至此我们已经准备好了模型和数据集文件。接下来我们来进行微调参数配置。
2. 微调参数配置
在XTuner
内预置了大量的配置文件。我们使用qlora
算法来进行低成本微调,选择最匹配的配置文件到当前文件夹:
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 ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py
训练完成后,微调的Adapters
位于当前目录的work_dirs
文件夹下。随后我们将pth
的模型参数转换为huggingface
格式参数:
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
最后,我们可以选择将原始模型和Adapters
进行合并,得到最后的模型:
xtuner convert merge /root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b ./hf ./merged --max-shard-size 2GB
3. 微调后模型实验
下一步,我们来测试微调后模型回答上面两个问题的能力。我们可以再次运行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"
使用streamlit
启动应用:
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
我们在浏览器打开应用,并输入相关内容:
模型能够遵循我们的指令。