本项目旨在构建一个小参数量的中文语言大模型,用于快速入门学习大模型相关知识,如果此项目对你有用,可以点一下start,谢谢!
模型架构:整体模型架构采用开源通用架构,包括:RMSNorm,RoPE,MHA等
实现细节:实现大模型两阶段训练及后续人类对齐,即:分词(Tokenizer) -> 预训练(PTM) -> 指令微调(SFT) -> 人类对齐(RLHF, DPO) -> 测评 -> 量化 -> 部署。
项目已部署,可以在如下网站上体验。
项目特点:
- 公开全部数据及代码,包括预训练数据,tokenizer等;(Tiny LLM Datasets)
- 走通大模型整个流程:分词(Tokenizer) -> 预训练(PTM) -> 指令微调(SFT) -> 人类对齐(RLHF, DPO) -> 测评 -> 部署;
- 公开预训练token 42B,SFT数据400w条,RL数据 17w条;
- 训练 Tokenizer:10G 中文百科文本训练 20K 中文词表,与 Llama2 词表合并,构建Tiny LLM词表;
- 使用 Transformers deepspeed 进行训练,支持多机多卡,支持 Zero 等优化技术;
- 所有代码
Bash
脚本启动,支持不同大小的模型,如16m, 42m, 92m, 210m, 440m等; - 支持 MoE 架构,在 tiny_llm_moe 支持最新共享专家,平衡专家等技术;
- 支持 vLLM 推理框架;
- 支持 llama.cpp 推理框架;
本项目主要有三个分支,推荐学习 主分支,具体区别如下:
- llama2_torch : 模型架构采用原版 Llama2 架构,只是将部分的输入输出修改为适合训练的格式;
main
tiny_llm
: 对齐开源社区模型,使用Transformers库构建底层模型,也使用Transformers库进行多卡多机训练;- tiny_llm_moe : 在
tiny_llm
的基础上,修改MLP
层为MoE模型,使用Transformers库进行多卡多机训练。
注意:
- 因资源限制,本项目的第一要务是走通大模型整个流程,而不是调教比较好的效果,故评测结果分数较低,部分生成错误。
- 详细的数据处理,训练过程见
doc
文件夹(正在整理。。。)
模型已托管在 Huggingface 和 ModeScope 中,可运行代码自动下载。
建议使用 Huggingface 在线加载模型,如果运行不了,在试 ModeScope ;如果需要本地运行,修改model_id
中的路径为本地目录,即可运行。
- python 3.8 and above
- pytorch 2.0 and above
- transformers 4.37.2 and above
- CUDA 11.4 and above are recommended. (if training)
pip install -r requirements.txt
from transformers import AutoTokenizer, AutoModelForCausalLM
from transformers.generation import GenerationConfig
model_id = "wdndev/tiny_llm_sft_92m"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", trust_remote_code=True)
generation_config = GenerationConfig.from_pretrained(model_id, trust_remote_code=True)
sys_text = "你是由wdndev开发的个人助手。"
# user_text = "世界上最大的动物是什么?"
# user_text = "介绍一下刘德华。"
user_text = "介绍一下中国。"
input_txt = "\n".join(["<|system|>", sys_text.strip(),
"<|user|>", user_text.strip(),
"<|assistant|>"]).strip() + "\n"
generation_config.max_new_tokens = 200
model_inputs = tokenizer(input_txt, return_tensors="pt").to(model.device)
generated_ids = model.generate(model_inputs.input_ids, generation_config=generation_config)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(response)
from modelscope import AutoModelForCausalLM, AutoTokenizer
model_id = "wdndev/tiny_llm_sft_92m"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", trust_remote_code=True)
sys_text = "你是由wdndev开发的个人助手。"
# user_text = "世界上最大的动物是什么?"
# user_text = "介绍一下刘德华。"
user_text = "介绍一下中国。"
input_txt = "\n".join(["<|system|>", sys_text.strip(),
"<|user|>", user_text.strip(),
"<|assistant|>"]).strip() + "\n"
model_inputs = tokenizer(input_txt, return_tensors="pt").to(model.device)
generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=200)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(response)
生成效果
问:世界上最大的动物是什么?
答:目前已知最大的动物是蓝鲸(Balaenoptera musculus),这是一个庞大的哺乳动物,属于须鲸亚目、须鲸科中的最大物种。蓝鲸的身长可达30米以上,体重可达175吨。它们在海洋中生活,主要以浮游生物为食,如甲壳类动物和小型鱼类等。由于其巨大的体型和复杂的生态群落,蓝鲸成为海洋旅游的热门景点之一。
问:介绍一下刘德华。
答:刘德华是一位香港流行歌手、演员和导演,他在音乐界的贡献非常巨大。他是华语乐坛历史上最伟大的艺人之一,代表作品包括《爱我身体》和《肥皂泡》。他也经常参演电影和电视剧,并在电视上受到好评。
问:介绍一下中国。
答:中国是位于东亚的大陆,被欧洲以及亚洲和其他大陆所包围。它是中国第二大文明和世界上最大的经济体之一。中国的历史可以追溯到公元前5000年左右,从古至今都有其独特的文化和语言传承者。
LLM分词器的构建方式有两种:一种是自己构造词表,训练一个分词器;另一种是选择开源模型训练好的分词器。
本项目为了方便,从优秀的开源项目中选择词表,考虑到训练的模型较小,且词表大小影响模型大小,故优先选择词表较小的开源项目;经过比较,最终选择 ChatGLM3 的词表,该词表大小为 64798 。
自己构造词表方式见 tokenizer,扩充 LLaMA2的32K词表为50K,增加20K中文词表,详细扩充方式见文档或tokenizer/README.md.
注意:本项目使用的ChatGLM3的词表。
模型结构采用类Llama2的结构,具体包括:RMSNorm,RoPE,MHA等;
具体参数细节如下所示:
model | hidden size | intermediate size | n_layers | n_heads | max context length | params | vocab size |
---|---|---|---|---|---|---|---|
tiny-llm-16m | 120 | 384 | 6 | 6 | 512 | 16M | 64798 |
tiny-llm-42m | 288 | 768 | 6 | 6 | 512 | 42M | 64798 |
tiny-llm-92m | 512 | 1024 | 8 | 8 | 1024 | 92M | 64798 |
tiny-llm-210m | 768 | 2048 | 16 | 12 | 1024 | 210M | 64798 |
tiny-llm-440m | 1024 | 2816 | 24 | 16 | 1024 | 440M | 64798 |
tiny-llm-1_5b | 2048 | 5504 | 24 | 16 | 1024 | 1.5B | 64798 |
因训练数据和微调数据,大部分都是中文数据,所以在C-Eval
和CMMLU
这两个数据集上进行模型的评估;使用OpenCompass工具,进行模型评估,评估分数如下所示:
model | Type | C-Eval | CMMLU |
---|---|---|---|
tiny-llm-92m | Base | 23.48 | 25.02 |
tiny-llm-92m | Chat | 26.79 | 26.59 |
Base模型,采用评测方式 ppl 方式进行评测;Chat模型,采用 gen 方式评测。具体区别如下图所示:
注意:只对常用的两个模型进行了评测,分数较低,其余模型评测意义不大。
网页Demo已部署,可以在如下网站上体验:ModeScope Tiny LLM
如果想在本地运行网页Demo,注意修改 web_demo.py
文件中模型的路径model_id
,输入如下命令即可运行:
streamlit run web_demo.py
Transfomers 框架部署,位于 demo/infer_chat.py
和 demo/infer_func.py
文件中,和其他LLM运行无太大区别,注意输入的拼接即可。
详细vllm部署见 vllm
如果使用CUDA 12 以上和PyTorch 2.1 以上,可以直接使用以下命令安装vLLM。
pip install vllm==0.4.0
否则请参考vLLM官方的安装说明。
安装完成后,还需要以下操作~
- 把
vllm/tinyllm.py
文件复制到env环境对应的vllm/model_executor/models
目录下。 - 然后在vllm/model_executor/models/__init__.py文件增加一行代码
"TinyllmForCausalLM": ("tinyllm", "TinyllmForCausalLM"),
由于模型结构是自己定义的,vllm官方未实现,需要自己手动加入
详细 llama.cpp 部署见 llama.cpp
Tiny LLM 92M 模型已支持 llama.cpp C++ 推理框架,建议在 linux 环境下测试,windows效果不好;
所支持 llama.cpp 为自己修改的版本,仓库链接为: llama.cpp.tinyllm