【InternLM 大模型实战】第四课

发布时间:2024年01月13日

FINETUNE简介

LLM下游应用中,增量预训练和指令跟随是经常会用到的两种微调模式
在这里插入图片描述

指令跟随微调

使用场景:让模型学会对话模板,根据人类指令进行对话
训练数据:高质量的对话,问答数据

为什么需要指令微调?
因为在对话中模型只是根据我们的提问去拟合训练数据集中的分布,它并没有意识你的意图是在向它提问。
通过指令微调后,便可得到instructed LLM,可以输出我们更加相对满意的结果

在进行指令跟随微调前,先定义三个角色
System:给定一些上下文信息,例如我们想微调一个安全的AI助手,那System就是“你是一个安全的AI助手”。
User:用户提问,在微调时将对话样本的提问赋予此角色
Assistant:根据用户提问,结合System上下文信息,输出回答,在微调时将对话样本的回答赋予此角色

这样便构建好了一个对话模板
在这里插入图片描述
不同的模型使用的指令各不同
在这里插入图片描述
在这里插入图片描述
指令跟随微调的训练
由于希望模型学会的是答案而不是问题,因此训练时只对答案计算损失
在这里插入图片描述

增量预训练微调

使用场景:让基座模型学习到一些新知识,如某个垂类领域的常识
训练数据:文章,书籍,代码等

训练LLM时,是为了让模型学会回答一个陈述句,因此相比指令跟随微调,增量预训练的对话模板中,system和user部分留空,只保留assistant。训练数据也不是对话数据,而是陈述句
在这里插入图片描述
计算损失时同样计算答案的损失即可。
在这里插入图片描述

LoRA & QLoRA

为什么要使用LoRA,如果不使用lora,那么微调时的显存开销会非常大。
lora的原理:比起对大模型的参数全面训练,lora则是在保持原模型参数不变的情况下,在原本的linear旁新增一些可训练分支(Adapter)使得输出结果拟合训练样本,Adapter参数量远小于原本的linear,能大幅减低训练的显存消耗

qlora是对lora的一种改进,使得加载模型到显存时直接量化成4bit,并且gpu满了就会到cpu上进行调度,虽然慢了,但是整个训练还能进行下去

在这里插入图片描述

XTuner简介

傻瓜式:以配置文件的形式封装了大部分微调场景,0基础的非专业人员也能一键开始微调
轻量级:对于7B参数量的LLM,微调所需的显存仅为8GB,满足大部分消费级显卡

功能亮点

适配多种生态

多种微调算法:多种微调策略与算法,覆盖各类SFT场景
适配多种开源生态:支持加载HuggingFace、ModelScope模型或数据集
自动优化加速:开发者无需关注复杂的显存优化与计算加速细节

适配多种硬件

训练方案覆盖NVIDIA20系以上所有显卡
最低只需8GB显存即可微调7B模型
在这里插入图片描述

8GB 显卡玩转LLM

Flash Attention 和 DeepSpeed ZeRO 是 XTuner 最重要的两个优化技巧

Flash Attention

Flash Attention 将Attention 计算并行化。避免了计算过程中 Attention Score NxN的显存占用(训练过程的N都比较大)

DeepSpeed ZeRO

ZeRO优化,通过将训练过程中的参数,梯度和优化器状态切片保存,能够在多GPU训练时显著节省显存
除了将训练中间状态切片外,DeepSpeed 训练时使用FP16的权重,相较于Pytorch的AMP训练在单GPU上也能大幅节省显存。
在这里插入图片描述
为了能让开发者专注于数据,XTuner会自动dispatch Flash Attention,并一键启动DeepSpeed ZeRO
对于QLora,则在启动时使用参数 --deepspeed deepspeed_zero3

下面是优化前与优化后显存占用情况
在这里插入图片描述

动手实战环节

环境配置

创建开发机
创建公钥及配置
安装XTuner并激活

# 如果你是在 InternStudio 平台,则从本地 clone 一个已有 pytorch 2.0.1 的环境:
/root/share/install_conda_env_internlm_base.sh xtuner0.1.9
# 如果你是在其他平台:
conda create --name xtuner0.1.9 python=3.10 -y

# 激活环境
conda activate xtuner0.1.9

代码准备

# 进入家目录 (~的意思是 “当前用户的home路径”)
cd ~
# 创建版本文件夹并进入,以跟随本教程
mkdir xtuner019 && cd xtuner019


# 拉取 0.1.9 的版本源码
git clone -b v0.1.9  https://github.com/InternLM/xtuner
# 无法访问github的用户请从 gitee 拉取:
# git clone -b v0.1.9 https://gitee.com/Internlm/xtuner

# 进入源码目录
cd xtuner

# 从源码安装 XTuner
pip install -e '.[all]'

新建工作文件夹

# 创建一个微调 oasst1 数据集的工作路径,进入
mkdir ~/ft-oasst1 && cd ~/ft-oasst1

微调

准备配置文件

XTuner 提供多个开箱即用的配置文件,用户可以通过下列命令查看:

# 列出所有内置配置
xtuner list-cfg

拷贝一个配置文件到当前目录:

cd ~/ft-oasst1
xtuner copy-cfg internlm_chat_7b_qlora_oasst1_e3 .

配置文件名的解释:

xtuner copy-cfg internlm_chat_7b_qlora_oasst1_e3 .

模型名 internlm_chat_7b
使用算法 qlora
数据集 oasst1
把数据集跑几次 跑3次:e3 (epoch 3 )
*无 chat比如 internlm-7b 代表是基座(base)模型

模型下载

由于下载模型很慢,用教学平台的同学可以直接复制模型

cp -r /root/share/temp/model_repos/internlm-chat-7b ~/ft-oasst1/

数据集下载

由于 huggingface 网络问题,咱们已经给大家提前下载好了,复制到正确位置即可

cd ~/ft-oasst1
# ...-guanaco 后面有个空格和英文句号啊
cp -r /root/share/temp/datasets/openassistant-guanaco .

修改配置文件

cd ~/ft-oasst1
vim internlm_chat_7b_qlora_oasst1_e3_copy.py
# 修改模型为本地路径
- pretrained_model_name_or_path = 'internlm/internlm-chat-7b'
+ pretrained_model_name_or_path = './internlm-chat-7b'

# 修改训练数据集为本地路径
- data_path = 'timdettmers/openassistant-guanaco'
+ data_path = './openassistant-guanaco'

开始微调

# 单卡
## 用刚才改好的config文件训练
xtuner train ./internlm_chat_7b_qlora_oasst1_e3_copy.py

# 多卡
NPROC_PER_NODE=${GPU_NUM} xtuner train ./internlm_chat_7b_qlora_oasst1_e3_copy.py

# 若要开启 deepspeed 加速,增加 --deepspeed deepspeed_zero2 即可

将得到的 PTH 模型转换为 HuggingFace 模型,即:生成 Adapter 文件夹

mkdir hf
export MKL_SERVICE_FORCE_INTEL=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

部署与测试

将 HuggingFace adapter 合并到大语言模型

xtuner convert merge ./internlm-chat-7b ./hf ./merged --max-shard-size 2GB
# xtuner convert merge \
#     ${NAME_OR_PATH_TO_LLM} \
#     ${NAME_OR_PATH_TO_ADAPTER} \
#     ${SAVE_PATH} \
#     --max-shard-size 2GB

与合并后的模型对话

由于不同模型厂商prompt-template不同,我们这里用的基座模型是internlm-chat
所以–prompt-template internlm_chat

# 加载 Adapter 模型对话(Float 16)
xtuner chat ./merged --prompt-template internlm_chat

# 4 bit 量化加载
# xtuner chat ./merged --bits 4 --prompt-template internlm_chat

Demo

修改 cli_demo.py 中的模型路径

- model_name_or_path = "/root/model/Shanghai_AI_Laboratory/internlm-chat-7b"
+ model_name_or_path = "merged"

运行 cli_demo.py 以目测微调效果

python ./cli_demo.py

xtuner chat 的启动参数

启动参数
–prompt-template 指定对话模板
–system 指定SYSTEM文本
–system-template 指定SYSTEM模板
–bits LLM位数
–bot-name bot名称
–with-plugins 指定要使用的插件
–no-streamer 是否启用流式传输
–lagent 是否使用lagent
–command-stop-word 命令停止词
–answer-stop-word 回答停止词
–offload-folder 存放模型权重的文件夹(或者已经卸载模型权重的文件夹)
–max-new-tokens 生成文本中允许的最大 token 数量
–temperature 温度值
–top-k 保留用于顶k筛选的最高概率词汇标记数
–top-p 如果设置为小于1的浮点数,仅保留概率相加高于 top_p 的最小一组最有可能的标记
–seed 用于可重现文本生成的随机种子

自定义微调

场景需求

基于 InternLM-chat-7B 模型,用 MedQA 数据集进行微调,将其往医学问答领域对齐

数据准备

Medication QA 数据集为例

在这里插入图片描述

将数据转为 XTuner 的数据格式

目标格式:(.jsonL)

[{
    "conversation":[
        {
            "system": "xxx",
            "input": "xxx",
            "output": "xxx"
        }
    ]
},
{
    "conversation":[
        {
            "system": "xxx",
            "input": "xxx",
            "output": "xxx"
        }
    ]
}]

开始自定义微调

此时,我们重新建一个文件夹来玩“微调自定义数据集”

mkdir ~/ft-medqa && cd ~/ft-medqa

把前面下载好的internlm-chat-7b模型文件夹拷贝过来。

cp -r ~/ft-oasst1/internlm-chat-7b .

别忘了把自定义数据集,即几个 .jsonL,也传到服务器上。

git clone https://github.com/InternLM/tutorial
cp ~/tutorial/xtuner/MedQA2019-structured-train.jsonl .

准备配置文件

# 复制配置文件到当前目录
xtuner copy-cfg internlm_chat_7b_qlora_oasst1_e3 .
# 改个文件名
mv internlm_chat_7b_qlora_oasst1_e3_copy.py internlm_chat_7b_qlora_medqa2019_e3.py

# 修改配置文件内容
vim internlm_chat_7b_qlora_medqa2019_e3.py
减号代表要删除的行,加号代表要增加的行。

# 修改import部分
- from xtuner.dataset.map_fns import oasst1_map_fn, template_map_fn_factory
+ from xtuner.dataset.map_fns import template_map_fn_factory

# 修改模型为本地路径
- pretrained_model_name_or_path = 'internlm/internlm-chat-7b'
+ pretrained_model_name_or_path = './internlm-chat-7b'

# 修改训练数据为 MedQA2019-structured-train.jsonl 路径
- data_path = 'timdettmers/openassistant-guanaco'
+ data_path = 'MedQA2019-structured-train.jsonl'

# 修改 train_dataset 对象
train_dataset = dict(
    type=process_hf_dataset,
-   dataset=dict(type=load_dataset, path=data_path),
+   dataset=dict(type=load_dataset, path='json', data_files=dict(train=data_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)

XTuner!启动!

xtuner train internlm_chat_7b_qlora_medqa2019_e3.py --deepspeed deepspeed_zero2

pth 转 huggingface

同前述,这里不赘述了。将得到的-pth-模型转换为-huggingface-模型即生成adapter文件夹

部署与测试

同前述。部署与测试

【补充】用 MS-Agent 数据集 赋予 LLM 以 Agent 能力

概述

MSAgent 数据集每条样本包含一个对话列表(conversations),其里面包含了 system、user、assistant 三种字段。其中:

system: 表示给模型前置的人设输入,其中有告诉模型如何调用插件以及生成请求

user: 表示用户的输入 prompt,分为两种,通用生成的prompt和调用插件需求的 prompt

assistant: 为模型的回复。其中会包括插件调用代码和执行代码,调用代码是要 LLM 生成的,而执行代码是调用服务来生成结果的

一条调用网页搜索插件查询“上海明天天气”的数据样本示例如下图所示:
在这里插入图片描述
微调步骤参考前面

添加 serper 环境变量

开始 chat 之前,还要加个 serper 的环境变量:

去 serper.dev 免费注册一个账号,生成自己的 api key。这个东西是用来给 lagent 去获取 google 搜索的结果的。等于是 serper.dev 帮你去访问 google,而不是从你自己本地去访问 google 了。
在这里插入图片描述
添加 serper api key 到环境变量:

export SERPER_API_KEY=abcdefg

xtuner + agent,启动!

xtuner chat ./internlm-chat-7b --adapter internlm-7b-qlora-msagent-react --lagent
文章来源:https://blog.csdn.net/weixin_42567071/article/details/135542041
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。