# Llama-3
Unsloth对Llama3-8B进行QLoRA训练，最少仅需7.75GB显存，这意味着我们可以在一张1080Ti级别的卡上训练Llama3-8B，其它Firefly、unsloth库中的模型可借鉴llama3的使用方法以此类推。
## 论文
[`The Llama 3 Herd of Models`](https://scontent-lax3-1.xx.fbcdn.net/v/t39.2365-6/452387774_1036916434819166_4173978747091533306_n.pdf?_nc_cat=104&ccb=1-7&_nc_sid=3c67a6&_nc_ohc=DTS7hDTcxZoQ7kNvgG4RrkU&_nc_ht=scontent-lax3-1.xx&gid=A3dKZbFlHdljWrPNA8TkhWm&oh=00_AYCbABVzvTwp7wvKJmAN-2IZeSwABLVkUK0nSbEDvuOaog&oe=66AF7D4D)

## 模型结构
采用标准的decoder-only架构，基于Llama2有几点小改进：1、128K tokens词表的tokenizer，极大提升模型表现；2、在8B/70B上采用grouped query attention（GQA），提升推理性能；3、采用8192 tokens序列进行训练，保证self-attention一般不会跨文档。下图为llama3论文提供的多模态版模型结构：
<div align=center>
    <img src="./doc/structure.png"/>
</div>

## 算法原理
llama3将输入embedding后放入attention、ffn等提取特征，最后利用Softmax将解码器最后一层产生的未经归一化的分数向量（logits）转换为概率分布，其中每个元素表示生成对应词汇的概率，这使得模型可以生成一个分布，并从中选择最可能的词作为预测结果。
<div align=center>
    <img src="./doc/algorithm.png"/>
</div>

## 环境配置
```
mv Firefly-llama3_unsloth Firefly # 去框架名后缀
```

### Docker（方法一）
```
docker pull image.sourcefind.cn:5000/dcu/admin/base/pytorch:2.1.0-ubuntu20.04-dtk24.04.1-py3.10 
# <your IMAGE ID>为以上拉取的docker的镜像ID替换，本镜像为：a4dd5be0ca23
docker run -it --shm-size=32G -v $PWD/Firefly:/home/Firefly -v /opt/hyhal:/opt/hyhal:ro --privileged=true --device=/dev/kfd --device=//dev/dri/ --group-add video --name firefly <your IMAGE ID> bash

cd /home/Firefly
pip install -r requirements.txt # requirements.txt
```

### Dockerfile（方法二）
```
cd Firefly/docker
docker build --no-cache -t firefly:latest .
docker run --shm-size=32G --name firefly -v /opt/hyhal:/opt/hyhal:ro --privileged=true --device=/dev/kfd --device=/dev/dri/ --group-add video -v $PWD/../../Firefly:/home/Firefly -it firefly bash
# 若遇到Dockerfile启动的方式安装环境需要长时间等待，可注释掉里面的pip安装，启动容器后再安装python库：pip install -r requirements.txt。
```

### Anaconda（方法三）
1、关于本项目DCU显卡所需的特殊深度学习库可从光合开发者社区下载安装：
- https://developer.sourcefind.cn/tool/
```
DTK驱动:dtk24.04.1
python:python3.10
torch:2.1.0
torchvision:0.16.0
triton:2.1.0
torchaudio:2.1.2
deepspeed:0.12.3
bitsandbytes:0.42.0
flash-attn:2.0.4
xformers:0.0.25
```

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

2、其它非特殊库参照requirements.txt安装
```
pip install -r requirements.txt # requirements.txt
```

`注意，经过上述基础环境配置后，还需安装`[`unsloth`](./unsloth.zip)，可以解压已修改好的unsloth文件直接用pip安装即可，也可以如下所示，下载unsloth的github源码自己修改安装：
```
# 安装unsloth
cd unsloth
pip install .
```

`若unsloth为github上公开的官网源代码（项目中的unsloth为未修改的源代码）：`
```
# 修改安装后的unsloth
vim /usr/local/lib/python3.10/site-packages/unsloth/kernels/cross_entropy_loss.py:
MAX_FUSED_SIZE = 65536 -> MAX_FUSED_SIZE = 16384
num_warps = 32 -> num_warps = 8 # 位于Fast_CrossEntropyLoss类的_chunked_cross_entropy_forward[(n_rows, n_chunks,)]下面

vim /usr/local/lib/python3.10/site-packages/unsloth/kernels/utils.py
if   BLOCK_SIZE >= 32768: num_warps = 32 -> if   BLOCK_SIZE >= 32768: num_warps = 8
elif BLOCK_SIZE >=  8192: num_warps = 16 -> elif BLOCK_SIZE >=  8192: num_warps = 8
# 位于函数calculate_settings下面

vim /usr/local/lib/python3.10/site-packages/unsloth/models/_utils.py
model_architectures = ["llama", "mistral", "gemma", "gemma2", "qwen2",] -> model_architectures = ["llama", "mistral", "qwen2",] 

vim /usr/local/lib/python3.10/site-packages/unsloth/models/llama.py
Q = Q.transpose(1, 2) -> Q = Q.transpose(1, 2).half()
K = K.transpose(1, 2) -> K = K.transpose(1, 2).half()
V = V.transpose(1, 2) -> V = V.transpose(1, 2).half()
# 位于函数LlamaAttention_fast_forward的elif HAS_FLASH_ATTENTION and attention_mask is None下面
```

`Tips：建议芯片版本>=K100AI、dtk版本>=24.04.1`

## 数据集
若是训练中文模型，建议尝试使用moss数据，英文可尝试ultrachat和WizardLM数据。
项目中已提供迷你数据集供试验，自有数据集可以参考迷你数据集进行制作，训练数据目录结构如下：
```
data/
├── dummy_data.jsonl
```
训练数据为jsonl格式，每一行的数据格式如下，其中conversation字段是必需的，可以根据实际需求添加或删除其他字段：
```
{
    "conversation_id":44,
    "category":"Brainstorming",
    "conversation":[
        {
            "human":"怎么能够有效地提升个人能力？",
            "assistant":"提升个人能力可以通过以下几个方面实现：\n\n1. 学习新知识和技能：阅读相关书籍、参加课程和工作坊、观看教育视频等学习方式，可以帮助你掌握新的知识和技能，从而提升个人能力。\n\n2. 持续练习和实践：不断地练习和实践所学的知识和技能，可以帮助你更好地掌握和应用这些技能，提高你的表现和效率。\n\n3. 寻求反馈和改进：寻求他人的反馈和建议可以帮助你发现自己的不足之处，进一步完善和改进自己的能力。\n\n4. 建立良好的工作和生活习惯：建立良好的工作和生活习惯，如合理安排时间、注意健康、保持积极态度等，可以提高你的工作效率和生活品质，从而提升个人能力。\n\n5. 社交和交流：与他人交流和合作，可以帮助你更好地了解他人的观点和经验，从而提升自己的能力和见识。"
        },
        {
            "human":"对于初学者来说，如何快速掌握编程技能？",
            "assistant":"以下是几个建议，可以帮助初学者快速掌握编程技能：\n\n1. 学习基础知识：建议先学习编程语言的基础知识和语法，例如变量、数据类型、控制结构、函数等。可以通过在线课程、编程书籍、视频教程等方式学习。\n\n2. 实践编程：进行实际的编程练习是非常重要的，可以通过参加编程挑战、编写小项目等方式来进行实践。\n\n3. 寻求反馈：可以寻求他人的反馈和建议，例如在线编程社区、编程导师等，他们可以帮助你发现问题并及时纠正。\n\n4. 阅读优秀代码：阅读和分析优秀的代码可以帮助你学习其他程序员的编程思路和技巧，从而提高自己的编程能力。\n\n5. 不断学习和更新：编程技术和工具在不断更新和发展，因此需要不断学习新的知识和技能，例如学习新的编程语言、框架、工具等，以跟上技术的发展和变化。\n\n总之，学习编程需要耐心和坚持，并且需要不断地实践和学习。通过以上建议，可以帮助初学者快速掌握编程技能。"
        },
        {
            "human":"除了参加编程挑战和阅读代码，还有哪些方式可以提升自己的编程能力呢？",
            "assistant":"除了参加编程挑战和阅读代码，还有以下几种方式可以提升自己的编程能力：\n\n1. 参与开源项目：加入一个开源项目，可以让你了解到实际的软件开发流程和团队合作方式，并且可以与其他开发人员合作，学习和分享编程技巧和经验。\n\n2. 进行代码重构：对已经编写的代码进行重构，可以帮助你了解更好的编程实践和设计模式，从而提高代码的可读性和可维护性。\n\n3. 练习算法和数据结构：算法和数据结构是编程中的重要基础，练习算法和数据结构可以帮助你了解不同的数据结构和算法，从而更好地解决实际问题。\n\n4. 学习软件工程和架构：学习软件工程和架构的知识，可以帮助你了解如何设计和构建可靠、可扩展和可维护的软件系统。\n\n5. 参加编程社区和论坛：参加编程社区和论坛可以让你与其他开发人员分享和讨论编程经验和技巧，了解最新的技术趋势和解决方案。\n\n总之，提升编程能力需要不断地学习和实践，并与其他开发人员和编程专家进行交流和合作，以获取更多的经验和知识。"
        },
        {
            "human":"你有没有推荐的编程挑战网站？",
            "assistant":"当然，以下是一些值得推荐的编程挑战网站：\n\n1. HackerRank：HackerRank 是一个全球领先的技术招聘平台，提供数百种编程挑战和比赛，包括算法、数据结构、数学、SQL、AI 等多个技术领域。\n\n2. LeetCode：LeetCode 是一个在线编程学习和实践平台，提供数千道编程题目，主要涵盖算法和数据结构。\n\n3. Codeforces：Codeforces 是一个全球知名的编程竞赛网站，提供数百个比赛和练习题目，主要涵盖算法和数据结构。\n\n4. Codewars：Codewars 是一个在线编程学习和实践平台，提供数千道编程题目，主要涵盖算法、数据结构、面向对象编程等多个技术领域。\n\n5. Project Euler：Project Euler 是一个非营利性的在线编程挑战平台，提供一系列数学和计算机科学问题，需要用编程语言进行解答。\n\n以上这些编程挑战网站可以帮助你提高编程能力，并且可以与其他编程爱好者进行交流和竞争。"
        },
        {
            "human":"在学习编程的过程中，如何避免陷入困境和放弃呢？",
            "assistant":"学习编程是一个需要长期坚持和不断学习的过程，以下是一些避免陷入困境和放弃的方法：\n\n1. 制定合理的学习计划：制定合理的学习计划，包括学习时间、学习内容、目标等，可以帮助你更好地管理时间和精力，避免学习过程中的松懈和分心。\n\n2. 寻找合适的学习资源：选择适合自己的学习资源，例如在线课程、编程书籍、视频教程等，可以让你更好地了解和掌握编程知识和技能。\n\n3. 寻求帮助和支持：在学习过程中，遇到问题和困难是很正常的，可以寻求他人的帮助和支持，例如参加编程社区、找到编程导师等。\n\n4. 进行实践和项目：实践和项目是学习编程的重要组成部分，可以帮助你更好地了解和掌握编程技能，同时也可以提高学习的兴趣和动力。\n\n5. 坚持并保持兴趣：坚持学习和保持兴趣是学习编程的关键。可以通过参加编程社区、参加编程竞赛、与其他编程爱好者交流等方式来保持兴趣和动力。\n\n总之，学习编程需要耐心和坚持，并需要不断学习和实践。通过以上方法可以帮助你避免陷入困境和放弃。"
        }
    ],
}
```

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

## 训练
### 单机单卡

```
# 将预训练权重放至：NousResearch/Meta-Llama-3-8B-Instruct
export HIP_VISIBLE_DEVICES=0
python train.py --train_args_file train_args/sft/qlora/llama3-8b-sft-qlora.json # 调用unsloth：json中"use_unsloth"设置为true
```

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

## result

参考llama3的对话问答效果：
```
用户：奥运会几年开一次？
Llama-3：奥运会每四年开一次。其中，夏季奥运会和冬季奥运会是分开举办的，分别称为“夏季奥林匹克运动会”和“冬季奥林匹克运动会”。夏季奥运会每四年举办一次，而冬季奥运会也是每四年举办一次，但时间上与夏季奥运会相隔两年。
```

### 精度
DCU K100AI与GPU A800精度一致，训练框架：unsloth。

## 应用场景
### 算法类别
`对话问答`
### 热点应用行业
`制造,广媒,金融,能源,医疗,家居,教育`
## 预训练权重
Hugging Face 预训练权重地址: [Meta-Llama-3-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct) 。

预训练权重快速下载中心：[SCNet AIModels](https://www.scnet.cn/ui/aihub/models) ，项目中的预训练权重可从快速下载通道下载：[Meta-Llama-3-8B-Instruct](https://www.scnet.cn/ui/aihub/models/sugon_scnet/Meta-Llama-3-8B-Instruct) 。
## 源码仓库及问题反馈
- http://developer.sourcefind.cn/codes/modelzoo/firefly-llama3_unsloth.git
## 参考资料
- https://github.com/yangjianxin1/Firefly.git
- https://github.com/unslothai/unsloth.git
