← 返回博客
[从零训练一个200B大语言模型] 9/25:怎样把材料变成一份训练配方?

[从零训练一个200B大语言模型] 9/25:怎样把材料变成一份训练配方?

上一篇,我们已经把材料清洗好了。现在数据团队交来一篇完整的排序教程:第一章解释题目,第二章推导算法,第三章给出代码,第四章用测试检查结果。文章里既有段落,也有公式、代码和解答。接下来,我们要把这样一篇长文章,做成训练程序可以一段一段读取的材料。

先用一组教学数字看清这个过程。把全文转换成token以后,共有12,000个;四章分别占3,000、3,500、3,000和2,500个。这里的数量用来演示切法,实际文章要经过分词器计数。Token可以先理解为文字切出来的小片段。

如果这一阶段给每个训练窗口安排最多4,000个正文token,整篇就要分段。按顺序每4,000个切一次,会得到:

  1. 第一段:第1至4,000个。包括完整的题目说明,以及算法推导的开头。
  2. 第二段:第4,001至8,000个。包括算法推导的剩余部分,以及代码的前半部分。
  3. 第三段:第8,001至12,000个。包括代码的后半部分,以及全部测试。

一篇12000个正文token的四章教程,按4000个切成三个训练窗口;切口穿过算法和代码章节

原来是一篇人能从头读到尾的教程,切完以后是三份训练材料。每份里面仍保留原来的顺序,程序把它转换成编号,再让模型练习预测下一个token。我们要决定的,是切口放在哪里,以及每份材料应该带着多少前文。

这个例子马上暴露出一个问题:第二段从算法中间开始,第三段从代码中间开始。模型拿到第三段时,前两段并不会自动出现在它眼前。我们需要让切法和材料内容配合起来。

一篇长文章,究竟在哪里切?

先说明为什么要切。训练时,我们要选定一次让模型读取多长的序列,再按这个长度安排显存和计算。序列越长,需要保留和处理的中间结果通常越多;对于完整Attention,位置之间的配对数量也会随长度的平方增长。因此,训练会选择适合当前阶段的窗口长度,特别长的材料再进入长上下文训练安排。

上面的例子给正文留4,000个token,实际训练序列还要计入必要的标记。这是解释切法的教学配置,正式训练长度要结合模型与显存测试确定。

计数时按token走。中文的一千字、英文的一千词和一千行代码,转换后的长度各不相同。先完成分词,才能知道一个窗口能装到哪一句。

最直接的切法,就是图里的固定长度切分。它保持全文顺序,容易持续供数,也可能从一句话、一个推导或一段代码中间切开。大规模预训练可以使用这种方式。NVIDIA的GPT数据集实现按文档编号和token偏移取样,并组织指定长度的输入;程序要识别段落或章节,需要我们另外提供相应的数据处理规则。

对于这篇结构清楚的教程,我会先比较另一种切法:尽量在完整的小节后收住。按示例的四个章节,分别得到3,000、3,500、3,000和2,500个正文token,四份都能装进4,000个正文位置。题目、推导、代码和测试的边界因此保留下来。切口没有破坏句子,是这一步的收益。

下一步要检查每份能否独立读懂。测试章节如果写着“调用上一章的函数”,就把对应函数和必要的输入约定一起带过来,再重新计数。题目和解答能一起装下,就把它们放在同一个窗口。若章节之间依赖很强,整组又超过窗口,就安排更长的训练序列,让模型在同一次计算里真正看到它们之间的关系。

四份正文仍然合计12,000个token。补入的题目、函数或说明要另外计数,再检查每份是否装得下。各份剩余的空间,可以在后面讲短材料组合时继续利用。

遇到单独一节就有6,000个token,也可以继续寻找小节、段落或代码块的边界。某个必须连续保留的单元仍然太长,就把它放进长上下文材料池。普通连续文本则可以按token继续切,并给后一个窗口带上一小段重叠的前文。

例如,仍以4,000个正文token为上限:第一个窗口读第1至4,000个,第二个窗口读第3,501至6,000个。第二个窗口先带上前一段末尾的500个,再接着读2,000个新token。这样它在切口附近有了前文,但能看到的范围仍限于自己这个窗口。

4,000 + 2,500 = 6,500个累计正文token

独立材料只有6,000个,重叠让实际处理量增加500个,约8.3%。标记与填充另计。这500个还可以只作为前文参与计算,把对应的预测损失关闭;它们仍然消耗计算,账本里仍要保留。500是这个教学例子选择的重叠量,实际是否需要、带多少,要看材料依赖和验证结果。

窗口之间的区别要想清楚:模型的参数会通过训练积累经验,上一窗口的具体文字却不会自动留在下一窗口的Attention里。需要前文,就把前文放进当前输入,或者使用更长的窗口。这里在准备训练样本;推理时用于保留已计算前文的KV cache,是生成阶段的另一项机制。

最后,给每个切片留下原文编号、起止token位置和重叠范围。这样我们既能沿着切片找回原文,也能知道哪些内容被重复处理了。分完长材料以后,短材料还有另一项安排:把多个短片段装进一个训练序列。长文切分解决“装不下”,短文组合解决“还有空位”。

训练窗口:模型在一次序列计算中能够读取的这段内容。本文的4,000指示例中的正文token上限。

上下文:模型在当前预测位置能够读取的前文。

重叠:相邻训练窗口都包含的一段原文,用来给后一个窗口提供前文。

同一句话,为什么会有不同的token数?

长文章的切口最终落在token上。现在缩小到教程里的三个片段,看看这把尺子怎样计数。我们分别用GPT-2的公开分词器和Qwen3的公开分词器处理它们。这里选择两个已公开的工具,是为了看清切分差异。下面的结果在2026年10月19日本地运行得到,没有添加对话模板或特殊标记。

原文,空格也保持原样GPT-2Qwen3
保留重复元素。14 token4 token
sorted(xs)5 token3 token
[3, 1, 3]7 token9 token

同一份文字,换一把尺子,数量就变了。Qwen3把第一句切成“保留”“重复”“元素”“。”。代码则切成sorted、(xs和)。切分结果可以跨过我们习惯的词语或符号边界,目的是使用词表里已有的片段来表示原文。

最后一行也很有用:Qwen3在这里反而切得更多。挑分词器时,我们需要一起比较中文、英文、代码、数字与公式。只挑一句切得短的例子,解释不了整个训练集会节省多少计算。

Hugging Face的分词流程说明把这一步分为文字处理、切分、映射到词表编号和添加特殊标记。对于我们的排序教程,空格、缩进和符号都有意义,处理后还要能还原原文。上表六次编码都通过了完整解码还原检查。有些token只包含一个字符的部分字节,因此单独显示一个token时可能看起来不完整;完整序列仍然可以还原文字。

Token:分词器处理文字后得到的一个片段。它可能是一整个词,也可能是词的一部分、一个符号或一段字节。

词表:分词器使用的片段及其编号清单。

编号进入模型以后,会发生什么?

继续看sorted(xs)。在这次Qwen3例子里,三个片段的编号是28298、53322和8。编号的作用是查找。编号大,只表示它在词表里的位置不同。

模型拿到编号以后,去自己的输入表里取出一行数字。这一行就是第四篇讲过的向量。于是三个token变成三行向量,随后进入第一层Attention。一个token编号是一个整数,一个token的向量却包含许多数字。图中把它们分别画成小标签和长条,方便看清这两步。

同一段代码在两个分词器中有不同切分;Qwen3的三个编号分别查到三个向量,每个向量含多个数字

这也解释了一个实际选择。沿用现有模型权重时,我们先沿用它的分词器与特殊标记。模型已经把各个编号和输入表里的各行对应起来了。如果新分词器把同一个编号改成另一段文字,原来的对应关系也会改变。词表扩展或替换需要配套修改输入、输出层并继续训练,因此应作为单独实验安排。

从零训练则可以比较新词表。我的做法是先固定一份覆盖中文、英文、代码和数学的样本,再比较候选的总token数、各类材料的切分长度、还原结果和词表大小。词表越大,输入表和输出预测部分也需要更多空间与计算;切得更短带来的收益,要和这部分成本一起看。选定以后,将词表文件和处理规则固定下来,再用它给全部库存重新计数。

实际接入已有模型时,可以从同一模型版本加载AutoTokenizer与权重,把两者作为一组记录。我们的4T账本也使用最终学生模型的这一把尺子。

Token ID:一个token在词表中的整数编号,用来查表。

Embedding:模型把token编号转换成向量的步骤,以及用于查找这些向量的可训练参数表。

向量:一串数字。这里每个token查到一串数字,表示它进入模型时的特征。

短材料怎样装进同一条训练序列?

长文章切开以后,有些片段没有装满窗口,另外还有许多本来就很短的文档。我们可以把这些短材料组织进同一条训练序列。先用八个位置的小格子看这件事,实际训练会使用更长的序列。

假设文档A有三个正文token,文档B有两个。每份后面再放一个结束标记。把它们分别装进八格序列,需要十六个位置;两份加起来只有七个位置放着正文或结束标记。把它们排进同一条八格序列,就只剩一个空位。

这个整理过程通常叫packing。在相同固定长度的实现中,它能减少为这些材料准备的填充位置;实际吞吐提升还要在所选训练后端测量。同一条序列里可以有多份文档,每份仍保留自己的边界。标准的Megatron预训练已经在取样时拼接文档;Megatron Bridge的文档也特别区分这种预训练处理与微调阶段的packing开关。实现时要选择当前训练路径支持的方式。

两份短文档从两条八格序列装进一条;右侧的注意力网格保留各自文档边界,空位不参与学习

放在一起以后,Attention能不能跨过文档边界?这是需要明确写进配方的选择。

排序教程和一篇天气报道只是排在相邻位置。对这种独立材料,本计划先采用文档内Attention:天气报道看自己的前文,排序教程看自己的前文。图中的两个小三角表示各自从左往右读取,两个三角之间的空白表示彼此不交换信息。结束标记告诉模型一份文档到这里结束;限制读取范围还要由程序中的attention mask落实。

学习目标也跟着边界安排。我们让模型学习一份文档里的下一个token,包括文末的结束标记。结束标记之后、下一份独立文档的第一个token,不拿上一份文档来预测;这处跨文档预测以及填充位置都不计入损失。文档内的位置编号重新从起点计数。NVIDIA的GPT数据集实现把位置、Attention和损失处理分别提供,工程验收也要分别检查。

有联系的材料可以采用另一种组织方式。例如,同一个代码仓库里的函数、测试与说明书,本来就需要互相参照。我们先把它们组成有顺序、保留文件标记的一个训练单元,再允许单元内部交换信息。独立文档隔离与相关文件组合,服务于不同学习任务。

训练序列:一次送入模型的一段有顺序的token。

Packing:把多份材料组织进训练序列,让可用位置更充分地装下内容。

结束标记:表示一份文档到这里结束的特殊token。

Attention mask:规定一个位置可以读取哪些位置的规则。

损失:用来衡量模型预测与训练目标相差多少的数值,训练根据它调整参数。

把4T账本变成每天的配额

现在文档已经变成了可以训练的序列。下一步决定从哪个材料池取内容。

沿用第七篇从零训练案例的容量计划,总工作量上限为4,000B token。各类独立库存和累计读取量已经分开。下面把累计量除以4,000B,得到初始配额:

材料池独立库存,B token累计计划,B token配额
一般英文2,5002,50062.5%
一般中文40080020%
原生代码与文档29559014.75%
数学与科学501002.5%
经过验证的教师代码材料10100.25%
合计3,2554,000100%

例如,下一段计划读取100亿,也就是10B token,就依次分到6.25B、2B、1.475B、0.25B和0.025B。五项相加正好10B。原生代码和教师代码合起来占15%,与第七篇保持一致。

这里按token分配。假如一份英文长文有一万个token,一份中文短文只有一百个,两边各取一百篇,学习量就差了一百倍。工程上可以先把各材料池整理为等长、相同计数口径的训练样本,再按配额混合;有可变长度或填充时,就持续累计实际token并校正取样。Megatron的混合数据集按样本索引与权重组织读取,项目仍要核对样本权重怎样落到token账上。

每类材料内部先打乱顺序,再读取。中文池分到800B、库存400B,平均就是两遍。某些记录被读了几次,要看具体取样方式与停止位置,平均两遍并不要求每份文档都恰好出现两次。训练日志同时记录每类累计token、已覆盖的独立文档和重复量。

4T仍是从零案例的工作量上限。沿用现有权重的路线,从当前模型的能力缺口制定自己的增量配额。两条路线都使用同一套计数与记录方法。

抽样权重:决定训练程序从各类材料中取内容的相对份额。

随机种子:控制随机过程起点的数值。结合相同数据、程序和取样状态,可以重新生成相同顺序。

配额怎样改,才有依据?

表里的百分比给第一组实验一个起点。比如模型的代码表现偏弱,可以比较两份配方:A保持代码15%;B把代码提高到20%,一般英文相应减少5个百分点,其他不变。两份都从同一个检查点开始,处理相同数量的有效token,使用相同训练设置,并记录各自GPU小时。

这次试验只改变一件事:把部分一般英文的学习机会换成代码。随后同时检查代码、中文、一般英文和数学。代码改善了多少,一般阅读有没有退步,决定下一段训练是否采用B。这样,增加某类材料的代价也进入了比较。

先用较小模型筛掉明显不合适的配方,再在目标模型的阶段检查点验证。每一轮记录结果波动,保留独立的最终测试集。第七篇关于新材料与重复材料的比较,也放在这个相同的实验框架里。

2026年10月15日,NVIDIA发布的中期训练研究给了一个值得采用的提醒:基础模型的代理指标未必可靠对应后训练后的表现,团队因此使用固定的短程SFT来比较配方。对于我们想做的代码助手,也可以在各候选上执行同一段短程后训练,再比较实际任务。训练损失下降是一个信号,最终用途上的进步则决定这份配方值不值得继续。

配额可以随阶段变化。团队批准一次调整,就产生一个新版本,并写明从哪个检查点、累计多少token开始使用。已经花掉的各类配额保留在账上,后面的计划按剩余预算重排。

检查点:保存某一时刻模型与训练状态的文件,用于比较、恢复或继续训练。

SFT:用输入与目标回答的示范继续训练,让模型学习怎样按要求完成任务。

最后交给训练团队什么?

这时,“数据准备好了”就有了具体含义。我们交出的包里包含五件东西:

交付物训练团队用它确认什么
分词器文件、版本与文件指纹所有人使用同一套切分和编号
数据清单、来源版本与训练/验证分组这一轮实际用了哪些文档
序列规则长度、结束标记、跨文档Attention、位置与损失怎样处理
分阶段配额与计数口径每类读多少,正文、特殊标记、填充怎样分别记账
取样程序、随机种子与当前读取状态重新启动后怎样接着原来的顺序读

特别是计数口径,要在主训练前对齐。第七篇的4T用于材料与计算规划;运行时分别记录正文token、特殊标记、填充位置和参与损失的位置。把实际处理量与吞吐带回第二篇的计算,才能得到新的工期。结束标记与边界处理造成的差异,也就在这一步变成可检查的数字。

最后做一次很小的验收:固定两份文档,检查文字能否还原、编号是否正确、文档之间能否互相读取、哪些位置参与损失。再让程序读一小段、保存状态、重新启动,检查接下来读到的样本是否与连续运行一致。通过这两步,排序教程才真正从一份合格材料,变成了训练程序可以可靠使用的一部分。

我们现在得到了一份可执行的配方:先固定文字到编号的对应关系,再决定文档怎样组成序列,按token配额混合材料,用对照实验调整份额,最后保存完整版本与读取状态。材料质量、模型能力和实际花费的计算,就可以沿着同一份记录核对。

新文章,直接发到你的邮箱。

AI、工程与实验,每月 1–2 封。

无垃圾邮件,随时取消。