# 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.sourcefind.cn/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`](https://huggingface.co/datasets/argilla-warehouse/fineweb-edu-dedup-filtered) 用于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。

## 应用场景
### 算法类别
`对话问答`
### 热点应用行业
`制造,广媒,金融,能源,医疗,家居,教育`
## 预训练权重
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

