前言
项目开始于 2024 年 3 月初,当时获得了一台 A100 算力资源。考虑到算力资源的宝贵性,决定尝试从零训练一个小型号的 LLM。虽然当时已有不少'从零预训练 LLM'的开源项目,但大多训练的数据量或模型较小(几块 4090+ 几十 G 数据),并未暴露出工程上的深层问题,训练细节分享也不够清晰。因此,在制定训练计划时设定了两个目标:
- 模型参数量和数据量不能太小:参数量上达到 B 级别,数据量上达到 T 级别。
- 详细分享训练过程中的各种细节:让没有资源训练的同学了解实践知识;让有资源的同学少走弯路。
参考了 TinyLlama 项目的训练时间,估计可以使用 T 级别的数据训练一个 1B 大小的 LLM(优先保证训练的数据量),耗时两个月左右。考虑到算力有限,决定该 LLM 以中文语料为主(80% 中文,20% 英文),定位是中文 LLM。
给这个 LLM 命名为'Steel'(钢),名称灵感来源于乐队'万能青年旅店'。乐队在做一专时条件有限,自称是在'土法炼钢',但却做出了优秀的专辑。我们训练 LLM 的条件同样有限,但也希望能炼出好'钢'来。
Steel-LLM 项目初期,曾计划收集围观读者的数据并训练到模型中,包括亚文化、冷知识、歌词等。但收到的数据几乎没有,且即使加入这部分数据,效果大概率不如在大机构发布的模型基础上微调。因此,项目后期将收集数据的描述从主页下架。
笔者工作较忙,项目过程中还遇到了算力断供的情况,因此断断续续进行了 8 个月的时间,过程中也得到了社区的支持。最终 Steel-LLM 在 C-Eval 取得了 38 分,CMMLU 上取得了 33 分的成绩,表现超过了一些大几倍的机构发布的早期 LLM。
因为项目周期比较长,内容也不少,有必要写下这篇汇总文章。本文会侧重介绍在做各部分内容的时候遇到的问题、回过头来的思考、以及技术细节。
GitHub 仓库:
https://github.com/zhanshijinwat/Steel-LLM
模型地址:
https://hf-mirror.com/gqszhanshijin/Steel-LLM
https://modelscope.cn/models/zhanshijin/Steel-LLM
数据收集与处理
Steel LLM 使用的全部数据都是开源的。预训练阶段里,多个开源数据集(约 600GB 和 1TB 规模)以及 Python、Java、C++ 代码部分(200GB)占了绝大部分。英文数据较少,只有 Wanjuan1.0 有 400GB。如果读者想现在也预训练一个,可以考虑使用 MAP-NEO、BAAI 的 CCI3.0-HQ 数据集等比较新的数据集。
除了这些大数据量的预训练数据外,还在预训练阶段加入了本应在 SFT 阶段加入的对话数据,比如 Alpaca、Vicuna 等。这些对话数据遵循如下这种对话形式,数据的 prompt 部分在训练时也计算 loss:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
{问题}<|im_end|>
<|im_start|>assistant
{回答}<|im_end|>
当时的想法是:如果往预训练数据里加入对话数据,那么是不是不做 SFT 的模型也能有对话能力? 但实际预训练完的模型回答方式非常四不像,对话和续写的能力都不理想(比如有时候以对话形式交互,它会进行续写)。感兴趣的读者可以下载体验。在预训练阶段加入 SFT 数据的方法在 Qwen 的训练过程中也使用了,但是只在预训练末期的退火阶段加入了 SFT 数据,这种方法预训练出来的模型指令跟随能力应该会比较强。如果预训练全程都杂糅 SFT 数据,这些少量的 SFT 数据会淹没在海量的原始文本中,起的作用会比较小。Steel-LLM 的预训练没有退火阶段,因为退火阶段的核心是'高质量'数据,但是高质量的定义比较模糊。不同类型的数据配比合理可以理解为是一种'高质量',但是开源数据往往并没有给出数据的类型。经过各种规则筛选的数据也可以被称为高质量数据,但是开源数据基本都是经过数据清洗 pipeline 处理的。
Steel LLM 对开源数据集的处理流程如下图所示。'处理为统一格式'和'将文本转化为 token id'的代码在 github 仓库中给出。小一些的数据集使用了阿里的工具进行了过滤,该工具将每个数据处理步骤抽象为一个算子,用户可以方便的配置 yaml 文件实现自定义的数据处理流程。但是有个问题是,data juicer 处理数据的过程中产生的中间缓存有点多,大概占了几百 GB 的空间。Steel-LLM 的数据处理 pipeline 并不是端到端的,比如下图中的'格式 1'和'格式 2'的数据都要回落到硬盘上的,因此需要存同一份数据不同格式的多份拷贝,因此建议机器配有 3~4T 的硬盘空间。如果想在几个小时内处理完数据,需要开多进程,建议有 100GB+ 的 CPU 内存。







