# Yuan2.0-M32
## 论文
`Yuan 2.0-M32: Mixture of Experts with Attention Router`
- https://arxiv.org/abs/2405.17976

## 模型结构
源2.0-M32模型运行时激活参数为37亿，M32在数学竞赛、基础数学、代码生成、综合知识能力、科学推理方面与LLaMA3-700亿不相上下。同时，源2.0-M32大幅提升了模型算力效率，在性能全面对标LLaMA3-700亿的同时，显著降低了在模型训练、微调和推理所需的算力开销，算力消耗仅为LLaMA3的1/19。
<div align=center>
    <img src="./doc/model.png"/>
</div>

## 算法原理
下图左边展示了Yuan2.0架构的MoE层缩放图，在Yuan 2.0中，MoE层取代了前馈层。下图右边展示了MOE层的结构。在Yuan2.0模型中，每个输入token将分配给32个专家中的2个（而在图中，这里以4个专家为例），MOE的输出是选定专家的加权总和，N是层数。

<div align=center>
    <img src="./doc/Attention Router.png" witdh=800 height=300/>
</div>

## 环境配置
-v 路径、docker_name和imageID根据实际情况修改

### Docker（方法一）
```bash
docker pull image.sourcefind.cn:5000/dcu/admin/base/pytorch:2.1.0-centos7.6-dtk24.04-py310
docker run -it --network=host --privileged=true --name=docker_name --device=/dev/kfd --device=/dev/dri --ipc=host --shm-size=32G --group-add video --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -u root -v /path/your_code_data/:/path/your_code_data/ -v /opt/hyhal/:/opt/hyhal/:ro imageID /bin/bash

cd /your_code_path/yuan2.0-m32_pytorch
pip install -r requirements.txt
```

### Dockerfile（方法二）
```bash
cd ./docker
docker build --no-cache -t yuan2.0-m32:latest .

docker run -it --network=host --privileged=true --name=docker_name --device=/dev/kfd --device=/dev/dri --ipc=host --shm-size=32G --group-add video --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -u root -v /path/your_code_data/:/path/your_code_data/ -v /opt/hyhal/:/opt/hyhal/:ro imageID /bin/bash

cd /your_code_path/yuan2.0-m32_pytorch
pip install -r requirements.txt
```

### Anaconda（方法三）
1、关于本项目DCU显卡所需的特殊深度学习库可从光合开发者社区下载安装: https://developer.hpccube.com/tool/

```bash
DTK软件栈：dtk24.04
python：python3.10
torch：2.1
apex: 1.1.0+0dd7f68.abi0.dtk2404.torch2.1
deepspeed: 0.12.3+gita724046.abi0.dtk2404.torch2.1.0
```

Tips：以上dtk软件栈、python、torch等DCU相关工具版本需要严格一一对应

2、其他非特殊库直接按照下面步骤进行安装

```bash
pip install apex-1.1.0+das1.0+0dd7f68.abi0.dtk2404.torch2.1-cp310-cp310-manylinux2014_x86_64.whl
pip install deepspeed-0.12.3+das1.0+gita724046.abi0.dtk2404.torch2.1.0-cp310-cp310-manylinux2014_x86_64.whl
pip install -r requirements.txt
```

## 数据集
### 准备数据集

在训练之前，需要将文本语料库转换为token id并存储在二进制文件中。

1. 数据集中的样本用'\n'分隔，每个样本内的'\n'用'\<n>'代替（程序会在预处理过程中将'\<n>'替换回'\n'），数据集中的每一行都是一个样本；对于用于调优Yuan2.0的数据集，在 `instruction` 和 `response` 之间放一个'\<sep>'作为分隔符。下面是一个finetune数据集的示例：
```text
John买了3件衬衫，每件售价为20美元。此外，他还需要支付所有商品的10%税款。他总共支付了多少钱？<sep>John购买的3件衬衫的总价为3 \times 20 = 60美元。<n>所有商品的税款为总价的10%，即60 \times 0.1 = 6美元。<n>因此，John总共支付的钱数为60 + 6 = 66美元。
每年，Dani作为赢得亚马逊季度最佳买家的奖励，会得到4个一对裤子（每对裤子2条）。如果初始时他有50条裤子，计算出5年后他将拥有多少条裤子。<sep>每年Dani会得到4 \times 2 = 8条裤子，因此5年后他将得到8 \times 5 = 40条裤子。<n>那么，5年后他总共拥有的裤子数量为初始时的50条加上5年内得到的40条，即50 + 40 = 90条裤子。<n>因此，5年后他将拥有90条裤子。
```

2. 数据预处理的脚本[preprocess_data.py](./tools/preprocess_data.py)，代码中的主要变量设置如下:

| 变量名  |  描述   |
| ------------------ | ------------------ |
| `--input` | 存储训练数据集的文件夹路径，数据集应该存储在`.txt`文件中。注意:即使只有一个`.txt`文件需要处理，路径应该是存放.txt文件的地方(即文件夹)，而不是`.txt`文件的路径。|
| `--data-idx` | 这为训练数据集设置了索引。如果只有一个数据集要转换，那么`--data-idx`参数应该设置为'0'。如果有多个训练数据集，设为'0-n'，其中n为训练数据集的个数。 |
| `--tokenizer_path` | tokenizer files 所在路径 |
| `--output_path` | 存储预处理数据的地址, 将为每个数据集创建一个 `.idx` 文件和一个 `.bin` 文件。 |

更多内容可以参考[数据预处理说明文档](./docs/data_process.md).

3. 如果一个数据集是被处理过的，即`--output_path` 路径下存在该数据集的`.idx` 文件和`.bin`文件，程序会自动跳过对该数据集的处理。执行数据预处理代码命令如下：

```bash
# <Specify path> 请根据实际路径进行修改

python ./tools/preprocess_data_yuan.py --input '<Specify path>' --data-idx '0-42' --tokenizer_path './tokenizer' --output_path '<Specify path>'
```

数据集的目录结构如下:
```
├── datasets
│   ├── xxx.idx
│   └── xxx.bin
```

## 训练
1. 提供了用于预训练的文档和[example](./examples)的脚本，这里以`Yuan-2.1B-M32`模型为例。其他使用方法可以参考[预训练说明文档](./docs/pretrain.md)。

2. 预训练模型下载路径可参考[Yuan2.0-M32](https://github.com/IEIT-Yuan/Yuan2.0-M32)的`Model Downloads`部分。

3. 开始训练之前，下列参数需要根据实际情况进行修改：
- `GPUS_PER_NODE` 修改为所需卡数
- `CHECKPOINT_PATH` 预训练模型地址
- `DATA_PATH` 训练数据地址
- `TOKENIZER_MODEL_PATH` tokenzier模型地址
- `TENSORBOARD_PATH` tensorboard路径
- `--use-lf-gate` 激活Localized Filtering-based Attention(LFA)
- `--lf-conv2d-num-pad`参数，训练情况下设置为 `1` ，推理情况下设置为 `0`
- `--use-distributed-optimizer`和`--recompute-method`训练时候控制内存的使用

特别地，如果dataset path如下所示:
```bash
/path/dataset.bin
```
则需要将`DATA_PATH`设置为:
```shell
#DATA_PATH='weight dataset_path'
DATA_PATH='1 /path/dataset'
```

4. 执行：
```bash
bash examples/pretrain_yuan2.0_2.1B.sh
```

## 推理

```bash
python vllm/yuan_inference.py --model_path /path/of/Yuan2-M32-hf
```

## result
<div align=center>
    <img src="./doc/result.png" width=1500 heigh=400/>
</div>

### 精度
测试数据：智源glm_trian_data数据，使用的加速卡:K100。
| device | dtype | params | acc |
| :------: | :------: | :------: | :------: |
| A800 | fp16 |     |     |
| K100 | fp16 |     |     |

## 应用场景
### 算法类别
对话问答

### 热点应用行业
家居,教育,科研

## 源码仓库及问题反馈
- https://developer.hpccube.com/codes/modelzoo/yuan2.0-m32_pytorch

## 参考资料
- https://github.com/IEIT-Yuan/Yuan2.0-M32
