本篇介绍如何使用 XTuner 进行大模型训练与微调。

环境配置

1
2
3
4
5
# 在终端执行这些命令
conda create --name xtuner0.1.9 python=3.10 -y
conda activate xtuner0.1.0
pip install ipykernel
python -m ipykernel install --user --name xtuner --display-name xtuner

刷新 notebook, 选择新内核 xtuner

1
2
%cd ~
%mkdir xtuner019 && cd xtuner019
1
!git clone -b v0.1.9 https://github.com/InternLM/xtuner
1
%cd xtuner
1
%pip install -e '.[all]'
1
2
%mkdir ~/ft-oasst1
%cd ~/ft-oasst1
1
import os, sys
1
2
PATH = os.environ['PATH']
PATH
1
2
basedir = os.path.dirname(os.path.dirname(sys.exec_prefix))
basedir
1
2
3
4
%env CONDA_EXE={os.path.join(basedir, 'bin/conda')}
%env CONDA_PREFIX={sys.exec_prefix}
%env CONDA_PYTHON_EXE={os.path.join(basedir, 'bin/python')}
%env PATH={os.path.join(sys.exec_prefix, 'bin')}:$PATH

微调

准备配置文件

1
!xtuner list-cfg
1
%cd ~/ft-oasst1
1
%pwd
1
!xtuner copy-cfg internlm_chat_7b_qlora_oasst1_e3 .
1
!ls

模型下载

1
%cp -r /root/share/temp/model_repos/internlm-chat-7b/ ~/ft-oasst1/
1
!ls internlm-chat-7b/

数据集下载

1
%cd ~/ft-oasst1
1
%cp -r /root/share/temp/datasets/openassistant-guanaco/ .
1
!ls openassistant-guanaco/
1
!tree ~/ft-oasst1

修改配置文件

1
!sed -i "s#pretrained_model_name_or_path = 'internlm/internlm-chat-7b'#pretrained_model_name_or_path = './internlm-chat-7b'#g" /root/ft-oasst1/internlm_chat_7b_qlora_oasst1_e3_copy.py
1
!sed -i "s#data_path = 'timdettmers/openassistant-guanaco'#data_path = './openassistant-guanaco'#g" /root/ft-oasst1/internlm_chat_7b_qlora_oasst1_e3_copy.py
1
!sed -i "s#max_epochs = 3#max_epochs = 1#g" /root/ft-oasst1/internlm_chat_7b_qlora_oasst1_e3_copy.py

开始微调

1
2
# # 常规训练,耗时长
# !xtuner train /root/ft-oasst1/internlm_chat_7b_qlora_oasst1_e3_copy.py
1
2
# 加速训练,耗时相对较短
!xtuner train /root/ft-oasst1/internlm_chat_7b_qlora_oasst1_e3_copy.py --deepspeed deepspeed_zero2
1
!tree /root/ft-oasst1

将 PTH 转为 HuggingFace 模型

即生成 Adapter 文件夹

1
2
%cd /root/ft-oasst1/
%mkdir hf
1
%env MKL_SERVICE_FORCE_INTEL=1
1
!xtuner convert pth_to_hf ./internlm_chat_7b_qlora_oasst1_e3_copy.py ./work_dirs/internlm_chat_7b_qlora_oasst1_e3_copy/epoch_1.pth ./hf
1
!tree .

此时,hf 文件夹即为我们平时所理解的 LoRA 模型文件,即 Adapter

部署

合并 HuggingFace Adapter 到大模型

1
%cd /root/ft-oasst1/
1
%mkdir merged
1
!xtuner convert merge ./internlm-chat-7b/ ./hf/ ./merged --max-shard-size 2GB

与合并后的大模型对话

1
!xtuner chat ./merged --prompt-template internlm_chat --bits 4
1
%ls 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
%%writefile cli_demo.py
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM


model_name_or_path = "./merged"

tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, trust_remote_code=True, torch_dtype=torch.bfloat16, device_map='auto')
model = model.eval()

system_prompt = """You are an AI assistant whose name is InternLM (书生·浦语).
- InternLM (书生·浦语) is a conversational language model that is developed by Shanghai AI Laboratory (上海人工智能实验室). It is designed to be helpful, honest, and harmless.
- InternLM (书生·浦语) can understand and communicate fluently in the language chosen by the user such as English and 中文.
"""

messages = [(system_prompt, '')]

print("=============Welcome to InternLM chatbot, type 'exit' to exit.=============")

while True:
input_text = input("User >>> ")
input_text.replace(' ', '')
if input_text == "exit":
break
response, history = model.chat(tokenizer, input_text, history=messages)
messages.append((input_text, response))
print(f"robot >>> {response}")
1
!python cli_demo.py

自定义微调

1
2
%mkdir ~/ft-medqa
%cd ~/ft-medqa
1
%cp -r /root/ft-oasst1/internlm-chat-7b/ .
1
!git clone https://github.com/InternLM/tutorial
1
%cp /root/ft-medqa/tutorial/xtuner/MedQA2019-structured-train.jsonl .
1
%ls

准备配置文件

1
!xtuner copy-cfg internlm_chat_7b_qlora_oasst1_e3 .
1
%mv internlm_chat_7b_qlora_oasst1_e3_copy.py internlm_chat_7b_qlora_medqa2019_e3.py
1
!sed -i "s#from xtuner.dataset.map_fns import oasst1_map_fn, template_map_fn_factory#from xtuner.dataset.map_fns import template_map_fn_factory#g" internlm_chat_7b_qlora_medqa2019_e3.py
1
!sed -i "s#pretrained_model_name_or_path = 'internlm/internlm-chat-7b'#pretrained_model_name_or_path = './internlm-chat-7b'#g" internlm_chat_7b_qlora_medqa2019_e3.py
1
!sed -i "s#data_path = 'timdettmers/openassistant-guanaco'#data_path = 'MedQA2019-structured-train.jsonl'#g" internlm_chat_7b_qlora_medqa2019_e3.py
1
!sed -i "s#dataset=dict(type=load_dataset, path=data_path),#dataset=dict(type=load_dataset, path='json', data_files=dict(train=data_path)),#g" internlm_chat_7b_qlora_medqa2019_e3.py
1
!sed -i "s#dataset_map_fn=oasst1_map_fn,#dataset_map_fn=None,#g" internlm_chat_7b_qlora_medqa2019_e3.py
1
!xtuner train internlm_chat_7b_qlora_medqa2019_e3.py --deepspeed deepspeed_zero2
1
!tree work_dirs/

把 PTH 转为 HuggingFace

1
%ls
1
%mkdir hf
1
%env MKL_SERVICE_FORCE_INTEL=1
1
!xtuner convert pth_to_hf ./internlm_chat_7b_qlora_medqa2019_e3.py ./work_dirs/internlm_chat_7b_qlora_medqa2019_e3/epoch_3.pth/ ./hf
1
!tree hf
1
%mkdir merged
1
!xtuner convert merge ./internlm-chat-7b/ ./hf ./merged/ --max-shard-size 2GB
1
!xtuner chat ./merged/ --prompt-template internlm_chat --bits 4

使用 XTuner 微调 InternLM-Chat 模型,使得其能够知道它的主人是谁

1
!conda create --name personal_assistant python=3.10 -y
1
!which conda
1
!/opt/miniconda/bin/conda/envs/personal_assistant/bin/ pip install ipykernel && ipykernel install --user --name personal_assistant --display-name personal_assistant

参考文献

  1. XTuner 大模型单卡低成本微调实践
  2. XTuner InternLM-Chat 个人小助手认知微调实践