README.md 12.6 KB
Newer Older
chenzk's avatar
v1.0.8  
chenzk committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# Llama
彻底开源预训练大模型,本项目能够预训练出超出qwen2.5、llama3效果的大语言模型,为一些人工智能大厂的训练代码。

目前各种SOTA NLP大模型算法都与Llama高度相似,故Llama适合作为算法研发的蓝底,本项目首次从数据集、预训练到调优完全开源大模型算法代码,帮助全世界所有算法研究人员共同研究以促进人类文明进步。
<div align=center>
    <img src="./doc/llm.png"/>
</div>

## 论文
`Open and Efficient Foundation Language Models`
- https://arxiv.org/pdf/2302.13971

## 模型结构
Llama系列采用极简Decoder-only结构,Llama源自基本的transformer结构,主体为attention(QKV自点积)+ffn(全连接),最后外加一个softmax进行概率转换输出即可,为了使数据分布归一化方便训练收敛,在attention、ffn、softmax前分别再加一个RMS Norm。

总体而言,Llama系列模型结构高度相似,llama1在GPT基础上引入旋转矩阵解决之前绝对位置编码复杂的问题,引入RMSNorm解决LayerNorm计算量大的问题,llama2在llama1的基础上引入GQA进一步减小计算量, llama3在llama2的基础上引入蒸馏、剪枝、量化等再进一步减小计算量,模型中其它模块(如flash-attn2、KV cache)只是增加训练推理效率的模块,本项目兼容Llama系列,以下分别为读者提供Llama的简图和详图帮助读者全方位理解。
<div align=center>
    <img src="./doc/llama3.png"/>
</div>

<div align=center>
    <img src="./doc/llama3_detail.png"/>
</div>

Facebook官网最原始的llama3请参考代码:[`Llama3`](https://github.com/meta-llama/llama3/blob/main/llama/model.py),本项目中的llama结构在ffn等层上略有修改,其它不同点只是模型规模参数和实现方式,读者若需要纯原版llama3可自行修改。

## 算法原理
整个Llama算法都体现出大道至简的思想。

原理采用极简的纯矩阵计算,llama将输入embedding(将语句根据词汇量和词的位置、属性转换成数字化矩阵)后放入attention+ffn等提取特征,最后利用Softmax将解码器最后一层产生的未经归一化的分数向量(logits)转换为概率分布,其中每个元素表示生成对应词汇的概率,这使得模型可以生成一个分布,并从中选择最可能的词作为预测结果,然后一个字一个预测出来就是咱们看到的对话生成效果。

损失函数采用最简单方便的CE(cross entropy) loss便可。
<div align=center>
    <img src="./doc/algorithm.png"/>
</div>

## 环境配置
```
mv nanotron_pytorch nanotron # 去框架名后缀
```

### Docker(方法一)
```
docker pull image.sourcefind.cn:5000/dcu/admin/base/pytorch:2.3.0-py3.10-dtk24.04.3-ubuntu20.04
# <your IMAGE ID>为以上拉取的docker的镜像ID替换,本镜像为:b272aae8ec72
docker run -it --shm-size=64G -v $PWD/nanotron:/home/nanotron -v /opt/hyhal:/opt/hyhal:ro --privileged=true --device=/dev/kfd --device=/dev/dri/ --group-add video --name llama <your IMAGE ID> bash
cd /home/nanotron
pip install -r requirements.txt
pip install -e . #安装nanotron==0.4库
pip install whl/rotary_emb-0.1.0+das.opt2.dtk24043-cp310-cp310-manylinux_2_28_x86_64.whl # 安装rotary_emb==0.1.0
```
### Dockerfile(方法二)
```
cd cd /home/nanotron/docker
docker build --no-cache -t llama:latest .
docker run --shm-size=64G --name llama -v /opt/hyhal:/opt/hyhal:ro --privileged=true --device=/dev/kfd --device=/dev/dri/ --group-add video -v $PWD/../../nanotron:/home/nanotron -it llama bash
# 若遇到Dockerfile启动的方式安装环境需要长时间等待,可注释掉里面的pip安装,启动容器后再安装python库:pip install -r requirements.txt。
cd /home/nanotron
pip install -e . #安装nanotron==0.4库
pip install whl/rotary_emb-0.1.0+das.opt2.dtk24043-cp310-cp310-manylinux_2_28_x86_64.whl # 安装rotary_emb==0.1.0
```
### Anaconda(方法三)
1、关于本项目DCU显卡所需的特殊深度学习库可从光合开发者社区下载安装:
- https://developer.hpccube.com/tool/
```
DTK驱动:dtk24.04.3
python:python3.10
torch:2.3.0
torchvision:0.18.1
torchaudio:2.1.2
triton:2.1.0
flash-attn:2.6.1
deepspeed:0.14.2
apex:1.3.0
xformers:0.0.25
```

`Tips:以上dtk驱动、python、torch等DCU相关工具版本需要严格一一对应。`

2、其它非特殊库参照requirements.txt安装
```
cd /home/nanotron
pip install -r requirements.txt
pip install -e . #安装nanotron==0.4库
pip install whl/rotary_emb-0.1.0+das.opt2.dtk24043-cp310-cp310-manylinux_2_28_x86_64.whl # 安装rotary_emb==0.1.0
```

## 数据集
实验性的迷你数据集[`openwebtext-10k`](./openwebtext-10k.tar.xz)源于openwebtext,仅供试验,实际训练中读者可在HF下载`*.parquet`开源数据集使用,或将自己的数据集按HF的官方说明制作成此类格式使用。

数据集在训练之前需要用tokenlizer处理成NLP模型的输入tokens,Facebook官方采用tiktoken库制作tockens便可训练出SOTA模型:[`llama3 tokenizer`](https://github.com/meta-llama/llama3/blob/main/llama/tokenizer.py),本项目可根据读者需求自由选择各种HF的开源tokenlizer,将其填写在`config``.yaml`中便可自动被项目调用。

`openwebtext-10k`用于tiny llama预训练示例,[`fineweb-edu-dedup`](http://113.200.138.88:18080/aidatasets/argilla-warehouse/fineweb-edu-dedup-filtered.git) 用于smollm预训练示例(HF公司自研人工智能模型),从SCNet快速下载通道下载后重命名即可,原始`fineweb-edu-dedup`数据(`*.parquet`)可通过以下命令转换成`fineweb-edu-dedup-ds`数据(`*.ds`),`datatrove`制作`*.ds`数据参考[`Nanosets`](./docs/nanoset.md):
```
sh convert_data_to_ds.sh
```
```
datatrove库Tokenizer bug solve: Exception: Is a directory (os error 21)

vim /usr/local/lib/python3.10/site-packages/datatrove/utils/tokenization.py , line 19
modify:
# return Tokenizer.from_file(name_or_path)
return Tokenizer.from_file(name_or_path + "/tokenizer.json")
```

```
datasets库load_dataset bug solve: OSError: Not enough disk space.

vim /usr/local/lib/python3.10/site-packages/datatrove/pipeline/readers/huggingface.py , line 95
modify:
def run(self, data: DocumentsPipeline = None, rank: int = 0, world_size: int = 1) -> DocumentsPipeline:
        from datasets import load_dataset  # type: ignore
to:
def run(self, data: DocumentsPipeline = None, rank: int = 0, world_size: int = 1) -> DocumentsPipeline:
        from datasets import load_dataset  # type: ignore
        import datasets
        datasets.builder.has_sufficient_disk_space = lambda needed_bytes, directory='.': True
```

项目中已包含`tokenlizer`[`dummy`](./robot-test/dummy-tokenizer-wordlevel)[`cosmo2`](./HuggingFaceTB/cosmo2-tokenizer) ,其它tokenizer(如:llama3)根据读者需求可自行下载。

预训练数据的完整目录结构如下:
```
/home/nanotron
    ├── openwebtext-10k.tar.xz
    ├── stas/openwebtext-10k
        ├── dataset_infos.json
        ├── openwebtext-10k.py
        ├── process.txt
        └── README.md
    ├── datasets/fineweb-edu-dedup
        ├── train-00000-of-00002.parquet
        ├── train-00001-of-00002.parquet
    └── datasets/fineweb-edu-dedup-ds
        ├── 00000_unshuffled.ds
        ├── 00000_unshuffled.ds.index
        ├── 00000_unshuffled.ds.metadata
        ...
```
`备注:`本项目灵活度大,仅适于算法基础较好的研究人员使用,对算法基础和代码基础有一定的需求,其它人员可能存在一定的上手门槛,可参考光源上预训练项目[`allamo_pytorch`](http://developer.sourcefind.cn/codes/modelzoo/allamo_pytorch.git)中的简单预训练代码llama3__scratch进行上手学习。

## 训练
### 单机多卡
本项目的最大特点是完全开源、营造自由科研环境,项目中的算法、模型读者可自由修改、研发以提出自己的算法来为社会做贡献,在[`llama`](./src/nanotron/models/llama.py)修改模型文件,但为了方便介绍,本步骤说明以小规模模型tiny llama作为示例:
```
cd /home/nanotron
sh train.sh # 不同卡数的训练方式参照train.sh中的说明,完整规模llama3的训练方式可参考train.sh中的说明。
# 遇到Do you wish to run the custom code? [y/N],填y。

# 其它功能正在优化中,欢迎共同优化和拓展。
```

```
datasets库load_dataset bug solve: OSError: Not enough disk space.

vim /home/nanotron/src/nanotron/dataloader.py , line 22
modify:
try:
    import datasets
to:
try:
    import datasets
    datasets.builder.has_sufficient_disk_space = lambda needed_bytes, directory='.': True
```

Facebook原版llama3的模型参数可参考[`Llama-3.1-8B`](./checkpoints/Nanotron-Llama-3.1-8B/model_config.json)[`Llama-3.2-3B`](./checkpoints/Nanotron-Llama-3.2-3B/model_config.json),这两个参数文件根据以下命令可获取:
```
sh convert_hf_to_nanotron.sh # Llama系列的基础模型皆支持转换

# 若已预训练完成某个模型,可转换成HF格式权重进行发布,以及用其它开源库继续微调,不同模型请读者根据具体参数修改此文件中的相应参数进行转换。
# sh convert_nanotron_to_hf.sh
```

为了方便读者借鉴HF官方的预训练方式,项目中还提供了`smollm`的预训练示例,参考文档[`pre-training`](https://github.com/huggingface/smollm/tree/main/pre-training)
```
sh train_smollm1_135M_demo.sh # Demo仅供试用,细节请自行研究,若读者具备超算集群,可参照launch.slurm编写自己具体的slurm脚本。
```


`Tips :`通过本项目获得自主研发模型的预训练权重后,后续微调模型放在[`LLaMA-Factory`](https://github.com/hiyouga/LLaMA-Factory.git)[`ollama`](https://github.com/ollama/ollama.git)、公开「后训练」一切的[`open-instruct`](https://github.com/allenai/open-instruct.git)等工具中进行更方便。

更多资料可参考源项目的[`README_origin`](./README_origin.md)

## 推理
```
sh infer.sh # 以checkpoints/10中的权重作为示例,其他权重请参照此示例修改权重路径。
```

更多资料可参考源项目的[`README_origin`](./README_origin.md)

## result
由于示例训练数据较少、模型为简化模型且训练时间短,此推理仅供参考显示效果,以方便读者了解项目使用方法,根据官方示例所得:

`输入: `
```
input: [CLS] the [UNK] [UNK] [UNK] is [SEP]
```

`输出:`
```
generation: [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP] [SEP]
```
上述重复字符为示例Demo的tokenlizer过于简单导致的正常现象,更换一个复杂的tokenlizer便可输出正常结果,例如使用`cosmo2-tokenizer`预训练:
```
CUDA_DEVICE_MAX_CONNECTIONS=1 torchrun --nproc_per_node=4 run_train.py --config-file examples/config_tiny_llama_cosmo2tokenizer.yaml
```
由此可见,不同tokenlizer会对训练结果造成明显差别,故建议实际训练中选择设计更好的tokenlizer。

### 精度
DCU与GPU精度一致,推理框架:pytorch。

## 应用场景
### 算法类别
`对话问答`
### 热点应用行业
`制造,广媒,金融,能源,医疗,家居,教育`
## 预训练权重
预训练权重快速下载中心:[SCNet AIModels](http://113.200.138.88:18080/aimodels) ,项目中的预训练权重可从快速下载通道下载:[Llama-3.1-8B](http://113.200.138.88:18080/aimodels/meta-llama/Meta-Llama-3.1-8B.git)[Llama-3.2-3B](http://113.200.138.88:18080/aimodels/meta-llama/Llama-3.2-3B.git)

Hugging Face下载地址为:[meta-llama/Llama-3.1-8B](https://huggingface.co/meta-llama/Llama-3.1-8B)[meta-llama/Llama-3.2-3B](https://huggingface.co/meta-llama/Llama-3.2-3B) 
## 源码仓库及问题反馈
- http://developer.sourcefind.cn/codes/modelzoo/nanotron_pytorch.git
## 参考资料
- https://github.com/huggingface/nanotron.git
- https://github.com/meta-llama/llama3.git
- https://github.com/hiyouga/LLaMA-Factory.git
- https://github.com/ollama/ollama.git
- https://github.com/allenai/open-instruct.git