飞桨PFCC社区成员卢畅贡献。卢畅,飞桨 PFCC 成员,飞桨开源之星,飞桨开发者专家(PPDE),长期参加飞桨黑客松、护航计划等开源活动,参与过飞桨执行器预分析性能优化、静态图自动并行架构升级等任务。本期分享的主题是星河社区升级命令行工具,一站式完成大模型实训。
在现代计算框架中,为了高效地处理和存储大规模的数据集,尤其是在这些数据集中存在大量零值的情况下,采用稀疏数据结构变得尤为重要。飞桨是一个领先的深度学习平台,提供了强大的稀疏计算能力,支持从基本的稀疏张量操作到构建复杂的稀疏神经网络。这些工具主要通过 paddle.sparse 命名空间来实现,使得开发者能够高效处理大量包含零值的数据集,从而优化内存使用和计算速度。
工具介绍
星河社区命令行工具(AI Studio CLI)是基于 aistudio_hub sdk 建立的管理工具。借助此工具,用户可以不受开发环境限制,方便快捷地提交模型训练任务,并通过模型产线完成日志监控、效果评估与在线部署。
优势介绍
在 AI 模型训练场景下,通常对 GPU 的要求较高,更大显存、更多卡数的计算资源配置对于提升模型训练的效率和质量至关重要。在 notebook 环境下,通常仅能使用单卡资源,此外,网页端进行长时间的模型训练也可能会遇到页面关闭、浏览器崩溃等不稳定的情况,导致模型训练被迫中断。
通过星河社区命令行工具(AI Studio CLI)可以发起不依赖前端界面响应的模型产线任务(后台任务),调用 V100 32G 多卡集群资源(可支持单机八卡),通过训练结果实现对模型的细致评估、高效部署以及模型文件外部下载等。
图片
更详细的使用教程大家可以查看使用星河社区命令行工具(AI Studio CLI)高效进行模型训练。
https://aistudio.baidu.com/projectdetail/7711823
本项目将使用模型产线完成 Llama2 模型的微调,并使用模型产线部署功能,部署训练好的模型用于在线高性能推理。
PaddleNLP :基于飞桨框架的大模型套件
PaddleNLP是一款简单易用且功能强大的自然语言处理和大语言模型(LLM)开发库,聚合了业界优质预训练模型并提供开箱即用的开发体验,覆盖NLP多场景的模型库搭配产业实践范例可满足开发者灵活定制的需求。
大模型套件特色:
飞桨4D并行分布式策略:PaddleNLP Trainer 支持飞桨4D并行灵活配置(数据并行、张量并行、流水线并行、 分组参数切分并行),屏蔽多硬件编程复杂性,用户可以修改Trainer配置组合多种预训练或精调过程的分布式策略,充分结合大模型4D并行训练能力,能有效提升在多模型、多硬件下的训练性能。
高效精调策略:飞桨大模型套件提供SFT、PEFT等多种精调策略,搭载自研Zero Padding零填充优化策略,有效减少训练数据中pad token的占比,提高模型训练效率。此外,飞桨独创PEFT结合低比特和分布式并行策略,大幅降低大模型精调硬件门槛。
大模型无损量化:大模型套件内置了PaddleSlim团队自研的自适应Shift-SmoothQuant的A8W8量化算法和业界主流GPTQ的W4量化算法,实现了主流大模型的无损量化,有效加速模型推理。
高性能推理:大模型套件高性能推理模块内置动态插入和全环节算子融合策略,极大加快并行推理的速度。同时隐藏了底层实现的细节,实现了开箱即用高性能并行推理能力。
快速上手教程
本教程基于开源项目PaddleNLP,自定义代码包为本项目下 code 文件夹的内容,其余作业任务相关文件在任务环境中可通过 git clone 和 pip install 等方式获取。数据集挂载 Llama2-Chinese-7b-Chat (中文 Llama2 的预训练模型),解压缩后放到 ./data 目录下。在代码包、数据集和相关开源项目拉取完成后,我们会获得如下的文件目录结构:
/home/aistudio # 任务环境的根目录
├── data # 挂载数据的存储目录
│ ├── data278307 # Llama2-Chinese-7b-Chat 权重
├── output # 产出文件的保存路径,持久化存储
│ ├── log # 训练日志
│ └── ...
├── PaddleNLP # 开源项目PaddleNLP代码仓库
│ ├── requirements.txt # 环境依赖
│ └── ...
├── tinydata
│ ├── train.json # 训练数据集
│ └── dev.json # 验证数据集
├── run.sh # 可执行脚本
└── myLora_llama2.json # 模型训练配置文件
注:/home/aistudio/output 目录下的文件会被持久化保存,并支持在产线运行结束后查看文件列表。需要保存的产出文件,请注意设置正确的保存路径。
编写 run.sh
run.sh 中包含了所有需要运行的代码, 我们需要在 run.sh 中配置环境变量、安装依赖、执行训练等操作。换句话说我们要用 run.sh 完成整个训练加导出模型的过程。
配置训练环境
首先我们需要配置训练环境,安装依赖。
#安装 3.0.0b1 版本的飞桨,2.6 版本的飞桨会运行报错
python -m pip install paddlepaddle-gpu==3.0.0b1 -i https://www.paddlepaddle.org.cn/packages/stable/cu118/
#拉取 PaddleNLP 代码仓库
rm -rf PaddleNLP
git clone --branch release/2.8 https://gitee.com/paddlepaddle/PaddleNLP.git --depth 1
#安装 PaddleNLP 依赖
cd PaddleNLP
pip uninstall -y paddlenlp
pip install -r ./requirements.txt
python setup.py bdist_wheel
python setup.py install
cd ...
#解压 llama 权重, 并指定解压的路径
unzip /home/aistudio/data/data278307/Llama2-Chinese-7b-Chat.zip -d /home/aistudio/data/data278307/
准备数据集
本次我们使用 AdvertiseGen 数据集进行模型精调,AdvertiseGen是电商广告文案生成数据集,其以商品网页的标签与文案的信息对应关系为基础构造,是典型的开放式生成任务,在模型基于key-value输入生成开放式文案时,与输入信息的事实一致性需要得到重点关注。
任务描述:给定商品信息的关键词和属性列表kv-list,生成适合该商品的广告文案adv;
数据规模:训练集114k,验证集1k,测试集3k;
数据来源:清华大学CoAI小组;
wget https://bj.bcebos.com/paddlenlp/datasets/examples/AdvertiseGen.tar.gz
#解压数据集
tar -zxvf AdvertiseGen.tar.gz
这里我们为了演示,使用部分数据来进行训练,以下是用来切割数据的代码。
#由于原始训练数据过多,我们需要准备一份小数据集进行微调:
import json
import random
import os
#定义文件路径
file_path = '/home/aistudio/data/tinydata/'
input_file = '/home/aistudio/data/data/train.json'
train_output_file = os.path.join(file_path,'train.json')
dev_output_file = os.path.join(file_path,'dev.json')
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
print(f'目录 {directory} 已创建')
else:
print(f'目录 {directory} 已存在')
#读取输入文件
with open(input_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
#每行都是一个JSON对象,解析它们
data = [json.loads(line) for line in lines]
#随机抽取1600条记录
sampled_data = random.sample(data, 1600)
#按8:2的比例拆分数据集
split_index = int(0.8 * len(sampled_data))
train_data = sampled_data[:split_index]
dev_data = sampled_data[split_index:]
#将数据保存到train.json和dev.json
with open(train_output_file, 'w', encoding='utf-8') as f:
for item in train_data:
f.write(json.dumps(item, ensure_ascii=False) + '\n')
with open(dev_output_file, 'w', encoding='utf-8') as f:
for item in dev_data:
f.write(json.dumps(item, ensure_ascii=False) + '\n')
print(f"Train data saved to {train_output_file}")
print(f"Dev data saved to {dev_output_file}")
切割后的 train.json 和 dev.json 直接放在 code 文件夹下,这样在训练的时候就不需要再次切割数据集了。大家后续可以根据自己的需求来切割数据集或者直接使用原始数据集。
Lora 微调
接下来简单进行 Lora 微调,我们使用 4 卡并行训练模型,命令如下:
#使用 4 卡并行训练模型
python -u -m paddle.distributed.launch --gpus "0,1,2,3" PaddleNLP/llm/finetune_generation.py myLora_llama2.json
#单卡训练模型
#python PaddleNLP/llm/finetune_generation.py myLora_llama2.json
本项目提供的例子单卡也可以跑,大家在A 币有限的情况下可以选择单卡训练。如果爆显存了可以尝试把 myLora_llama2.json 中的 recompute 开关打开。
llama2 部署优化
完成 Lora 微调后,接下来我们将对模型进行部署优化,从动态图转为静态图,并对模型进行量化、高性能部署。
部署的步骤如下:
(1) 合并权重推理
(2) 导出静态图模型
#1. 合并权重推理
#lora_path: LoRA参数和配置路径,对LoRA参数进行初始化,默认为None。
#merge_model_path: 必须,合并参数后保存路径,默认为None。
#device: 运行环境,默认为gpu。
#low_gpu_mem:降低合参时候所需显存,默认为False。如果合参时显存不足,建议开启
python PaddleNLP/llm/merge_lora_params.py
--lora_path /home/aistudio/output/checkpoints/llama2_normal_lora_ckpts/checkpoint-160
--merge_lora_model_path /home/aistudio/output/checkpoints/llama2_lora_merge
--device "gpu"
--low_gpu_mem True
#2. 静态图部署
python PaddleNLP/llm/export_model.py
--model_name_or_path /home/aistudio/output/checkpoints/llama2_lora_merge
--output_path /home/aistudio/output/static_inference_model_llama2
--dtype float16
##3. 静态图推理 用于测试
#python PaddleNLP/llm/predictor.py
#--model_name_or_path /home/aistudio/output/static_inference_model_llama2
#--data_file /home/aistudio/dev.json
#--dtype float16
#--mode static
提交模型产线任务
接下来我们就可以提交模型产线任务。通过依次运行下面的 cell,你可以体验到如何使用星河社区命令行工具(AI Studio CLI)创建自定义代码产线。
#安装 aistudio_hub sdk
pip install --upgrade aistudio-sdk
#用户身份认证,需要填写自己的访问令牌:https://aistudio.baidu.com/account/accessToken
aistudio config --token
#一行命令创建多卡训练任务,使用算力点
aistudio submit job --name ppnlp_llama2_AdvertiseGen_gpu4_pp3.0
--path ./code
--cmd 'sh run.sh'
--payment acoin
--gpus 4
--mount_dataset 278307
#查询已有产线
aistudio jobs
具体参数如下:
前往自定义产线查看训练日志
根据 CLI 返回的 url,可以跳转到自定义产线详情页查看任务运行情况,日志实时刷新。
此外,也可以通过 AI Studio 一级侧导航栏的「模型」板块,进入模型产线列表页,选择对应的自定义产线查看和管理,如下图所示。
输出文件查询与模型评估
运行完成状态(运行成功/运行失败/已停止)的产线支持查看所有输出到 ./output 目录下的文件,以列表形式展示,支持单文件下载,如下图所示。
我们可以在模型评估界面运行命令来测试模型的性能,如下图所示。
评估结果如下:
部署大模型服务
目前我们可以将刚刚训练出来的模型直接部署成 API 使用,下面来介绍如何对模型进行部署。
(一)构建部署包
部署包是用于构建部署服务的压缩包,PaddleNLP 提供了一套基于动态图推理的简单易用UI服务化部署脚本,用户可以快速部署服务化推理。
python -m paddle.distributed.launch --gpus "0" flask_server.py
--model_name_or_path meta-llama/Llama-2-7b-chat
--port 8010
--flask_port 8011
--dtype "float16"
port: Gradio UI 服务端口号,默认8011。
flask_port: Flask服务端口号,默认8010。
其他参数请参见推理文档中推理参数配置。
我们的部署包就放在 infer 文件夹下,文件夹目录如下:
infer
├── PaddleNLP
└── start_server.sh
PaddleNLP 就是code文件夹下提供的压缩包解压出来的,是版本为2.8的 PaddleNLP, start_server.sh 的内容如下,注意部署服务默认对内的转发端口是 8080,我们的 flask 服务需要把开放端口设置为 8080。
pip install --pre --upgrade paddlenlp -f https://www.paddlepaddle.org.cn/whl/paddlenlp.html
python -m pip install paddlepaddle-gpu==3.0.0b1 -i https://www.paddlepaddle.org.cn/packages/stable/cu118/
pip install -r infer/PaddleNLP/requirements.txt
mv chat_template.json static_inference_model_llama2
mv config.json static_inference_model_llama2
mv sentencepiece.bpe.model static_inference_model_llama2
mv tokenizer_config.json static_inference_model_llama2
python infer/PaddleNLP/llm/flask_server.py
--model_name_or_path output/static_inference_model_llama2
--port 8010
--flask_port 8080
--dtype "float16"
--mode static
注意我们需要修改 flask_server.py 里面的红框:
接下来进入部署界面选择模型和上次部署包:
部署成功后截图如下:
接下来我们用脚本来测试一下:
import requests
import json
def send_request(query, history=None):
data = {
"context": query,
"history": history,
"top_k": 0,
"top_p": 0.7, # 0.0 为 greedy_search
"temperature": 0.95,
"repetition_penalty": 1.3,
"max_length": 100,
"src_length": 100,
"min_length": 1,
}
API_URL = "https://15y9f8e0l8xbsa71.aistudio-hub.baidu.com/api/chat"
TOKEN = "替换为你自己的token"
headers = {
"Authorization": f"token {TOKEN}",
"Content-Type": "application/json"
}
res = requests.post(API_URL, json=data, stream=True, headers=headers)
print(res)
text = ""
for line in res.iter_lines():
result = json.loads(line)
if result["error_code"] != 0:
text = "error-response"
break
result = json.loads(line)
bot_response = result["result"]["response"]
if bot_response["utterance"].endswith("[END]"):
bot_response["utterance"] = bot_response["utterance"][:-5]
text += bot_response["utterance"]
print("result -> ", text)
return text
send_request("你好啊")
#send_request("再加一等于多少", ["一加一等于多少", "一加一等于二"])
#send_request("再加一等于多少", [{"utterance": "一加一等于多少"}, {"utterance": "一加一等于二"}])
可以看到服务部署成功:
小结
星河社区命令行工具(AI Studio CLI)提供了一体化的模型训练和部署解决方案,简化了模型训练任务的提交和监控过程,并支持高效的在线部署。通过模型产线,用户能够不依赖前端界面响应,便捷地提交模型训练任务,调用高性能的多卡GPU资源进行训练,并在后台完成日志监控、效果评估与在线部署。这一工具尤其适用于对GPU资源要求较高的AI模型训练场景,解决了在网页端进行长时间训练时可能遇到的不稳定问题,如页面关闭和浏览器崩溃。
星河社区命令行工具和PaddleNLP套件的结合,使得用户在进行大模型训练和部署时能够更加高效灵活,提升了AI模型的训练质量和部署效果,满足了复杂AI应用场景下的需求。