XTuner 大模型单卡低成本微调实战

项目地址: tutorial/xtuner/README.md at main · InternLM/tutorial (github.com)

视频地址: XTuner 大模型单卡低成本微调实战

✍课程笔记

Finetune简介

LLM的下游应用中,增量预训练指令跟随是经常会用到两种的微调模式

增量预训练微调

使用场景:让基座模型学习到一些新知识,如某个垂类领域的常识

训练数据:文章、书籍、代码等

指令跟随微调

使用场景:让模型学会对话模板,根据人类指令进行对话

训练数据:高质量的对话、问答数据

为什么要进行指令微调,因为它可以帮助模型更好地适应特定任务和领域,从而提高模型的性能和精度。

指令跟随微调

指令跟随微调是为了得到能够实际对话的LLM

介绍指令跟随微调前,需要先了解如何使用LLM进行对话

在实际对话时,通常会有三种角色

  • System给定一些上下文信息,比如“你是一个安全的AI助手”

  • User实际用户,会提出一些问题,比如“世界第一高峰是?"

  • Assistant根据User的输入,结合System的上下文信息,做出回答,比如“珠穆朗玛峰”

在使用对话模型时,通常是不会感知到这三种角色的

指令微调原理:

增量预训练微调

它不需要指定system的内容,他回答的内容都是陈述句只需要将system和user的值留空即可

LoRA&QLoRA

Xtuner简介

Xtuner在第一节的时候已经简单介绍过了这里在加深一下印象

📖 介绍

XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。

高效

  • 支持大语言模型 LLM、多模态图文模型 VLM 的预训练及轻量级微调。XTuner 支持在 8GB 显存下微调 7B 模型,同时也支持多节点跨设备微调更大尺度模型(70B+)。

  • 自动分发高性能算子(如 FlashAttention、Triton kernels 等)以加速训练吞吐。

  • 兼容 DeepSpeed 🚀,轻松应用各种 ZeRO 训练优化策略。

灵活

  • 支持多种大语言模型,包括但不限于 InternLMMixtral-8x7BLlama2ChatGLMQwenBaichuan

  • 支持多模态图文模型 LLaVA 的预训练与微调。利用 XTuner 训得模型 LLaVA-InternLM2-20B 表现优异。

  • 精心设计的数据管道,兼容任意数据格式,开源数据或自定义数据皆可快速上手。

  • 支持 QLoRALoRA、全量参数微调等多种微调算法,支撑用户根据具体需求作出最优选择。

全能

  • 支持增量预训练、指令微调与 Agent 微调。

  • 预定义众多开源对话模版,支持与开源或训练所得模型进行对话。

  • 训练所得模型可无缝接入部署工具库 LMDeploy、大规模评测工具库 OpenCompassVLMEvalKit

🖊课程实验

基础作业

构建数据集,使用 XTuner 微调 InternLM-Chat-7B 模型, 让模型学习到它是你的智能小助手

按照文档里面的步骤进行构建其中纠正两个地方的错误

错误一:

文档中的/root/code/InternLM/web_demo.py 这个路径应该改为/root/personal_assistant/code/InternLM/web_demo.py 或者都是用第一个路径然后运行时运行第一个路径的文件。

错误二:

运行web_demo.py 以后输入问题会爆出错误

StreamlitAPIException: Failed to load the provided avatar value as an image.

Traceback:
File "/root/personal_assistant/code/InternLM/web_demo.py", line 119, in <module>
    main()
File "/root/personal_assistant/code/InternLM/web_demo.py", line 95, in main
    with st.chat_message("user", avatar=user_avator):

这个因为代码里面是相对路径,将这个相对路径改为绝对路径就可以了

完成以后部署运行结果如下:

由于里面的数据集都是同样的内容所以询问它问题返回的结果都是一样的。

进阶作业

  • 将训练好的Adapter模型权重上传到 OpenXLab、Hugging Face 或者 MoelScope 任一一平台。

首先将我们训练好的merge模型上传到openxlab上面

如何上传文件到openxlab上面可以看大佬的文档OpenXLab平台上传下载笔记 - 知乎 (zhihu.com)

首先创建元文件

Collections:
- Name: "InternLM-chat-7b"
  License: "Apache-2.0"
  Framework: "[]"
  Paper: {}
  Code:
    URL: "https://github.com/InternLM/InternLM"
Models:
- Name: "config.json"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "configuration_internlm.py"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "generation_config.json"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "modeling_internlm.py"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00001-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00002-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00003-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00004-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00005-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00006-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00007-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model-00008-of-00008.bin"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "pytorch_model.bin.index.json"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "special_tokens_map.json"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "tokenization_internlm.py"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "tokenizer.model"
  Results:
  - Task: "Question Answering"
    Dataset: "none"
- Name: "tokenizer_config.json"
  Results:
  - Task: "Question Answering"
    Dataset: "none"

下一步更换Weights的值

如何快速生成Weights信息呢?由于元文件就是一个yaml文档,因此可以基于Python来完成yaml编辑,这里用到一个包ruamel.yaml可以比较好的做到。

安装命令: python -m pip install ruamel.yaml
这个包可以方便的保留yaml中字符串双引号,避免额外的问题。

下面是快速生成Weights的脚本:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.default_flow_style = False
file_path = 'metafile.yml'
# 读取YAML文件内容
with open(file_path, 'r') as file:
 data = yaml.load(file)
# 遍历模型列表
for model in data.get('Models', []):
 # 为每个模型添加Weights键值对,确保名称被正确引用
 model['Weights'] = model['Name']

# 将修改后的数据写回文件
with open(file_path, 'w') as file:
 yaml.dump(data, file)

print("Modifications saved to the file.")

以上假设要修改的元文件名字叫metafile.yml。生成好了后,拷贝(为了备份,原因见下面引用段落到模型文件夹里, 开始构建(上传)模型仓库。

安装openxlab CLI工具

pip install openxlab

登录openxlab输入AK和SK

openxlab login

创建存储库并上传文件

openxlab model create --model-repo='用户名/模型仓库名'  -s  ./metafile.yml

耐心等待上传完成

用户名就是自己的openxlab用户名,这个要取平台上查看。模型仓库名是要建立的新模型仓库名字,符合要求和现有的不重复就可以随便起一个。
平台一些细节:在internstudio上空间超了100G,上传中断或者编辑完保存元文件容易丢失无法继续。上传中断的线上仓库不能在页面直接删除,需要挨个文件全部删除来实现删除仓库的效果。

这里因为上传太多中断了我就将模型文件改为一个了

等待上传完成即可。

这里我直接Fork了InternLM仓库在里面修改了chat/web_demo.py文件和增加了start.py文件

因为模型仓库使用的是openxlab的所以要在web_demo.py 里面增加以下代码

from openxlab.model import download

base_path = './internlm2-chat-7b'
# download internlm2 to the base_path directory using SDK
download(model_repo='OpenLMLab/internlm2-chat-7b',output=base_path)

然后进行应用部署,因为我没有申请资源所以等我的资源到账以后再展示结果。