1. 配置环境
mkdir -p /root/InternLM/Tutorial
git clone -b camp3 https://github.com/InternLM/Tutorial /root/InternLM/Tutorial
# 创建虚拟环境
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
pip install streamlit==1.36.0
# 创建一个目录,用来存放源代码
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]'
2. 模型准备
# 创建一个目录,用来存放微调的所有资料,后续的所有操作都在该路径中进行
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
#查看目录结构
apt-get install -y tree
tree -l
微调前测试
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
开始微调
cd /root/InternLM/XTuner
mkdir -p datas
touch datas/assistant.json
touch 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)
修改自定义内容如下
import json
# 设置用户的名字
name = '蟹老板'
# 设置需要重复添加的数据次数
n = 3750
# 初始化数据
data = [
{"conversation": [{"input": "请介绍一下你自己", "output": "我是{},专卖好吃不贵的蟹黄堡".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)
执行进行数据下载
python xtuner_generate_assistant.py
选择微调配置文件
xtuner list-cfg -p internlm2
xtuner copy-cfg internlm2_chat_1_8b_qlora_alpaca_e3 .
修改以下内容
启动微调
xtuner train ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py
训练完成后的目录结构为:
├── work_dirs
│ └── internlm2_chat_1_8b_qlora_alpaca_e3_copy
│ ├── 20240626_222727
│ │ ├── 20240626_222727.log
│ │ └── vis_data
│ │ ├── 20240626_222727.json
│ │ ├── config.py
│ │ ├── eval_outputs_iter_95.txt
│ │ └── scalars.json
│ ├── internlm2_chat_1_8b_qlora_alpaca_e3_copy.py
│ ├── iter_96.pth
│ └── last_checkpoint
将原本使用 Pytorch 训练出来的模型权重文件转换为目前通用的 HuggingFace 格式文件
# 先获取最后保存的一个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
转换后目录结构
├── hf
│ ├── README.md
│ ├── adapter_config.json
│ ├── adapter_model.bin
│ └── xtuner_config.py
模型合并:对于 LoRA 或者 QLoRA 微调出来的模型其实并不是一个完整的模型,而是一个额外的层(Adapter),训练完的这个层最终还是要与原模型进行合并才能被正常的使用。
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
微调后对话
首先更改模型路径
# 直接修改脚本文件第18行
- model_name_or_path = "/root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b"
+ model_name_or_path = "/root/InternLM/XTuner/merged"
#运行
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py
对话结果