forked from jiuyuan/CPM-9G-8B
Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
p18457032 | e747382e0d | |
p18457032 | 8bcac9af92 | |
p04896573 | 50c194a521 | |
p18457032 | acc100b692 | |
p04896573 | 24b1c46927 | |
p04896573 | 97539a1f44 | |
p04896573 | e4da44fcdc | |
p04896573 | a3d4a6dad5 | |
p04896573 | 0c938e73d0 | |
p18457032 | 994a95f94d | |
p18457032 | 394c3f96e7 | |
p18457032 | 37edc92094 | |
p18457032 | 3dfa6cac94 |
14
README.md
14
README.md
|
@ -2,16 +2,20 @@
|
|||
## 简介
|
||||
启元九格大模型由启元实验室牵头,联合清华大学、哈尔滨工业大学、中国科学院计算技术研究所、北京大学、南开大学等优势单位共同研制。具有高效训练与推理和高效适配与部署的技术特点,具备文本问答、文本分类、机器翻译、文本摘要等自然语言处理能力。
|
||||
|
||||
## 最新消息
|
||||
## 更新信息
|
||||
- 本次启元九格开源两个参数级别模型,分别是百亿级通用基础大模型为8B(80亿)和端侧模型2B(20亿参数)具体的模型训练、推理等内容见:[QUICK START](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/FM_9G/quick_start_clean/readmes/quick_start.md)
|
||||
- 若还在使用旧版本的九格模型训练和推理,请切换分支到[master](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md)
|
||||
|
||||
## 版本更新内容
|
||||
具体的迭代信息如下:
|
||||
具体的迭代信息如下:
|
||||
- 训练:升级了训练代码,提升GPU利用率和并行化,并且2B模型能兼容transformers中的tokenizer(LlamaTokenizerFast)
|
||||
- 推理:支持vllm进行模型推理和部署,可以接入langchain、openai等部署方式;同时可以将端侧模型可以支持GGUF等多种部署格式的部署
|
||||
- LORA代码暂未实现至新版本代码框架中,预计八月份完成,若需要LORA训练,请切换分支至master
|
||||
|
||||
- 推理:支持vllm进行模型推理和部署,可以接入langchain、openai等部署方式;同时可以支持2b模型转换成GGUF等多种部署格式的部署
|
||||
- 由于新架构中多数据集验证发现2B模型进行lora训练效果不及全参数微调,因此建议2B模型全参数微调,8B模型LORA微调在master分支进行
|
||||
|
||||
## 2024.08.19 NOTICE
|
||||
- 由于新架构中多数据集验证发现2B模型进行lora训练效果不及全参数微调
|
||||
- 2B模型采用全参数微调训练,我们在[QUICK START](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/FM_9G/quick_start_clean/readmes/quick_start.md) 中更新了更多关于微调训练的信息
|
||||
- 8B模型LORA微调在master分支进行训练
|
||||
|
||||
# 迈向通用智能的大模型技术系列课程
|
||||
系列课程全方位介绍人工智能和大模型技术的基础知识和前沿课题,理论学习和实践应用相结合。课程既有“人工智能与大模型通论”和“神经网络与预训练模型”等基础知识,也有“九格大模型生态体系”和“领域大模型实战”等实战主题,基本内容包括大模型训练、微调、知识增强、伦理安全、多模态、具身智能、自主智能体等话题,高级选题包括多语言处理、面向科学研究的大模型应用、高效计算技术、评测与数据科学等话题。课程旨在通过一系列精心设计的单元为学习者提供大型通用人工智能的学习之旅。
|
||||
|
|
|
@ -17,20 +17,34 @@ from collections import OrderedDict
|
|||
|
||||
import torch
|
||||
import argparse
|
||||
import os
|
||||
|
||||
parser = argparse.ArgumentParser(description='Load and save model weights with specified paths.')
|
||||
parser.add_argument('--model_path', type=str, required=True, help='Path to the model directory.')
|
||||
parser.add_argument('--output_path', type=str, required=True, help='Path to save the new weights.')
|
||||
parser.add_argument('--layer_num', type=int, required=True, help='The layers of model')
|
||||
|
||||
parser.add_argument('--model_type',type=str,default='fm9g',help='The model type need to be one of "fm9g" or "9g-8b"')
|
||||
parser.add_argument('--task',type=str,default='pt2bin',help='The task need to be one of "pt2bin" or "bin2pt"')
|
||||
# parser.add_argument('--layer_num', type=int, required=True, help='The layers of model')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
src_path = args.model_path
|
||||
dst_path = args.output_path
|
||||
layer_num = args.layer_num
|
||||
dst_path = args.output_path if args.output_path.endswith('/') else args.output_path + ('/')
|
||||
model_type = args.model_type
|
||||
task = args.task
|
||||
|
||||
assert model_type in ['fm9g'], 'The "model_type" must be one of "fm9g"!'
|
||||
assert task in ['pt2bin','bin2pt'], 'The task need to be one of "pt2bin" or "bin2pt"!'
|
||||
|
||||
if model_type == 'fm9g':
|
||||
layer_num = 40
|
||||
|
||||
if not os.path.exists(dst_path):
|
||||
os.makedirs(dst_path)
|
||||
|
||||
|
||||
def convert_hf_to_fm9g():
|
||||
# 2B模型转换bin2pt
|
||||
ckpt = torch.load(src_path)
|
||||
new_ckpt = OrderedDict()
|
||||
|
||||
|
@ -48,14 +62,16 @@ def convert_hf_to_fm9g():
|
|||
new_ckpt[f"encoder.layers.{i}.ffn.ffn.w_in.w_1.weight"] = ckpt[f'model.layers.{i}.mlp.up_proj.weight']
|
||||
new_ckpt[f"encoder.layers.{i}.ffn.ffn.w_out.weight"] = ckpt[f'model.layers.{i}.mlp.down_proj.weight']
|
||||
|
||||
torch.save(new_ckpt, dst_path)
|
||||
torch.save(new_ckpt, f"{dst_path}fm9g.pt")
|
||||
|
||||
def convert_fm9g_to_hf():
|
||||
# 2B模型转换pt2bin
|
||||
state = torch.load(src_path)
|
||||
|
||||
new_state = {}
|
||||
new_state["model.embed_tokens.weight"] = state["input_embedding.weight"]
|
||||
new_state["model.norm.weight"] = state["encoder.output_layernorm.weight"]
|
||||
for lid in range(40):
|
||||
for lid in range(layer_num):
|
||||
print(lid)
|
||||
new_state[f"model.layers.{lid}.self_attn.q_proj.weight"] = state[f"encoder.layers.{lid}.self_att.self_attention.project_q.weight"]
|
||||
new_state[f"model.layers.{lid}.self_attn.k_proj.weight"] = state[f"encoder.layers.{lid}.self_att.self_attention.project_k.weight"]
|
||||
|
@ -70,9 +86,13 @@ def convert_fm9g_to_hf():
|
|||
new_state[f"model.layers.{lid}.post_attention_layernorm.weight"] = state[f"encoder.layers.{lid}.ffn.layernorm_before_ffn.weight"]
|
||||
del state
|
||||
state = None
|
||||
torch.save(new_state, f"{dst_path}pytorch_model.bin")
|
||||
|
||||
torch.save(new_state, f"{dst_path}fm9g.bin")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
convert_hf_to_fm9g()
|
||||
|
||||
if model_type == 'fm9g' and task == 'bin2pt':
|
||||
convert_hf_to_fm9g()
|
||||
elif model_type == 'fm9g' and task == 'pt2bin':
|
||||
convert_fm9g_to_hf()
|
||||
else:
|
||||
raise ValueError('Please check the model type and task!')
|
|
@ -52,6 +52,8 @@
|
|||
- [多机训练](#多机训练)
|
||||
- [参数详细介绍](#参数详细介绍)
|
||||
- [查看训练情况](#查看训练情况)
|
||||
- [模型微调](#模型微调)
|
||||
- [模型格式转换](#模型格式转换)
|
||||
- [模型推理](#模型推理)
|
||||
- [常见问题](#常见问题)
|
||||
|
||||
|
@ -108,9 +110,13 @@ pip install tensorboardX
|
|||
|
||||
|
||||
9.安装vllm(模型推理)
|
||||
我们提供python3.8、python3.10版本的vllm安装包,相关依赖均已封装,可直接安装后执行推理:
|
||||
我们提供基于CUDA12.2环境下python3.8、python3.10版本的vllm安装包,相关依赖均已封装,可直接安装后执行推理:
|
||||
[vllm-0.5.0.dev0+cu122-cp38-cp38-linux_x86_64.whl](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/vllm-0.5.0.dev0%2Bcu122-cp38-cp38-linux_x86_64.whl)
|
||||
[vllm-0.5.0.dev0+cu122-cp310-cp310-linux_x86_64.whl](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/vllm-0.5.0.dev0%2Bcu122-cp310-cp310-linux_x86_64.whl)
|
||||
|
||||
针对CUDA版本不高的用户,我们提供了兼容低版本CUDA的vllm安装包,但经测试最低支持CUDA11.6,因此,如果您的服务器CUDA版本低于11.6,请先将其升级至该版本以上,以确保兼容性和正常运行:
|
||||
[vllm-0.5.0.dev0+cu116-cp38-cp38-linux_x86_64.whl](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/vllm-0.5.0.dev0%2Bcu116-cp38-cp38-linux_x86_64.whl)
|
||||
|
||||
同时,我们也提供了vllm源码,位于/quick_start_clean/tools/vllm-0.5.0.dev0.tar
|
||||
```
|
||||
### docker环境
|
||||
|
@ -140,7 +146,7 @@ CTRP + d
|
|||
[8b_sft_model_v2(.pt格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/sft_8b_v2.zip), [8b_sft_model_v2(.bin格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/8b_sft_model.tar)
|
||||
|
||||
2. 端侧2B模型,下载链接:
|
||||
[2b_sft_model(.pt格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/fm9g_2b_hf_models.tar.gz), [2b_sft_model(.bin格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/2b_sft_model.tar)
|
||||
[2b_sft_model(.pt格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/sft_2b.tar), [2b_sft_model(.bin格式)](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/2b_sft_model.tar)
|
||||
|
||||
## 数据处理流程
|
||||
### 单个数据集处理
|
||||
|
@ -433,6 +439,42 @@ tensorboard –-logdir /apps/fm9g_2b/data/tensorboard/2b_0701 #存放.events文
|
|||
TypeError: MessageToJson() got an unexpected keyword argument 'including_default_value_fields'
|
||||
```
|
||||
|
||||
## 模型微调
|
||||
模型微调列举了两种微调方法:全参数微调以及LORA微调。
|
||||
|
||||
### 全参数微调训练:
|
||||
全参数微调训练与原始模型训练方法基本一致,需要额外注意以下几点:
|
||||
1.数据集类型
|
||||
训练数据集通常包含大量、多样化的数据,覆盖广泛的主题和语言现象,用于学习广泛的知识和技能。通过无监督学习,训练数据集可能不包含显式标签,模型通过预测下一个词或填补缺失词语来学习模式。
|
||||
微调数据集更专注于特定的领域或任务,通常是有标签的,并且标签与目标任务直接相关。例如,微调分类模型时,数据集中的每条数据都有对应的分类标签;微调翻译模型时,数据集中包含源语言和目标语言的句子对。
|
||||
需要根据具体微调任务设计与选择合适的微调数据集。
|
||||
|
||||
2.预训练模型的引入
|
||||
修改训练脚本参数文件:/apps/fm9g_2b/pretrain_dragonfly.sh,引入args["load"]参数,里面补充基于微调的预训练模型的路径即可:
|
||||
```python
|
||||
#基于微调的预训练模型路径
|
||||
args["load"]="../models/sft_2b/"
|
||||
```
|
||||
|
||||
### LORA微调训练:
|
||||
由于新架构中多数据集验证发现2B模型进行LORA训练效果不及全参数微调,因此建议2B模型全参数微调,8B模型LORA微调在master分支进行。
|
||||
|
||||
|
||||
## 模型格式转换
|
||||
模型训练完成后,需将pt格式模型文件转换为bin格式模型文件用于模型推理。
|
||||
我们在本项目中提供了2B模型两种格式相互转换时所用到脚本,脚本位于./quick_start_clean/convert_hf_fm9g.py,应用方法如下:
|
||||
|
||||
```shell
|
||||
python convert_hf_fm9g.py \
|
||||
--model_path /the_path_to_pt_or_bin/ \ #需要转换模型的路径
|
||||
--output_path /the_path_to_target_directory/ \ #转换后新格式模型所存放路径
|
||||
--model_type fm9g \ #2B模型指定fm9g
|
||||
--task pt2bin #任务类型如果pt模型转换为bin模型指定为pt2bin,反之指定为bin2pt
|
||||
```
|
||||
|
||||
8B模型格式转换脚本需要切换至master分支,脚本位于本项目master分支下convert.py。
|
||||
|
||||
|
||||
## 模型推理
|
||||
模型推理列举了两种推理方法:离线批量推理和部署OpenAI API服务推理
|
||||
|
||||
|
@ -498,7 +540,7 @@ python -m vllm.entrypoints.openai.api_server \
|
|||
--tokenizer-mode auto \
|
||||
--dtype auto \
|
||||
--trust-remote-code \
|
||||
--api-key CPMAPI
|
||||
--api-key FM9GAPI
|
||||
#同样需注意模型加载的是.bin格式
|
||||
#与离线批量推理类似,使用端侧2B模型,tokenizer-mode为"auto"
|
||||
#dtype为模型数据类型,设置为"auto"即可
|
||||
|
@ -511,7 +553,7 @@ python -m vllm.entrypoints.openai.api_server \
|
|||
--model ../models/8b_sft_model/ \
|
||||
--tokenizer-mode cpm \
|
||||
--dtype auto \
|
||||
--api-key CPMAPI
|
||||
--api-key FM9GAPI
|
||||
#与离线批量推理类似,使用8B百亿SFT模型,tokenizer-mode为"cpm"
|
||||
```
|
||||
|
||||
|
@ -523,6 +565,14 @@ INFO: Application startup complete.
|
|||
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
部署阶段部分参数说明:
|
||||
```shell
|
||||
1.openai暂不支持配置--repetition_penalty参数。
|
||||
2.如发生OOM(内存溢出)问题,可修改相关参数,在启动服务时一并传入:
|
||||
--max-model-len,默认最大位置嵌入(max_position_embedding)为32768,可以修改为4096。
|
||||
--gpu-memory-utilization,默认该值为0.9,因此占用显存比较高,2B模型可修改为0.2,8B模型可修改为0.5。
|
||||
```
|
||||
|
||||
2. 调用推理API:
|
||||
启动服务端成功后,重新打开一个终端,可参考执行以下python脚本:
|
||||
|
||||
|
@ -530,14 +580,21 @@ INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
|
|||
# client.py
|
||||
from openai import OpenAI
|
||||
# 如果启动服务时指定了api密钥,需要修改为对应的密钥,否则为"EMPTY"
|
||||
openai_api_key = "CPMAPI"
|
||||
openai_api_key = "FM9GAPI"
|
||||
openai_api_base = "http://localhost:8000/v1"
|
||||
client = OpenAI(
|
||||
api_key=openai_api_key,
|
||||
base_url=openai_api_base,
|
||||
)
|
||||
completion = client.completions.create(model="../models/9G/",
|
||||
prompt="San Francisco is a")
|
||||
#指定模型路径,推理prompt以及设置采样参数以控制生成文本
|
||||
completion_params = {
|
||||
"model": "../models/9G/",
|
||||
"prompt": "San Francisco is a",
|
||||
"temperature": 0.8,
|
||||
"top_p": 0.95,
|
||||
"max_tokens": 200
|
||||
}
|
||||
completion = client.completions.create(**completion_params)
|
||||
print("Completion result:", completion)
|
||||
```
|
||||
|
||||
|
@ -549,7 +606,7 @@ print("Completion result:", completion)
|
|||
from openai import OpenAI
|
||||
client = OpenAI(
|
||||
base_url="http://localhost:8000/v1",
|
||||
api_key="CPMAPI",
|
||||
api_key="FM9GAPI",
|
||||
)
|
||||
#每次将上一轮的问题和答案拼接到本轮输入即可
|
||||
completion = client.chat.completions.create(
|
||||
|
|
Loading…
Reference in New Issue