- 人工智能
- 大模型
- 预训练
- 微调
- LoRA
- RLHF
- 强化学习
- 分布式训练
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
导读
本文基于 PaddleNLP 仓库中 WuDaoCorpusBase.md 文档,系统讲解如何将 WuDaoCorpus2.0 Base 这一 200GB 级中文开源语料,从原始压缩包一步步加工成可供 LLM(如 Llama、ERNIE)直接预训练使用的.bin/.idx数据文件。全文覆盖语料下载解压、中文分词断句、jsonl 格式转换、token 化与索引构建四个环节,并结合 llm/tools/preprocess 目录下的实际脚本源码,说明每个关键参数的作用与底层原理。读完本文,你将具备独立处理百 GB 级中文语料、为不同模型定制预训练数据管线的完整实操能力。
一、数据集概览:WuDaoCorpus2.0 Base 是什么
WuDaoCorpora 是悟道(北京智源人工智能研究院)爬取并开源的中文大规模语料,整体规模约 3TB。目前对外开源的部分为WuDaoCorpus2.0 Base数据集:
| 名称 | 文本类型 | 纯文本大小 | |-|-|-| | WuDaoCorpus2.0 Base | 中文 | 200GB |
关键规模信息(来自 WuDaoCorpusBase.md):
- 纯文本规模约200GB;
- 官方提供的压缩数据约64GB,需先解压再处理;
- 覆盖访谈、历史、百科、教育等多类中文文本,单条样本为完整的文档(doc)而非句子。
在 PaddleNLP 的预训练数据教程汇总表(见 llm/tools/preprocess/README.md)中,该数据集与 CLUECorpusSmall(14GB)、OpenWebText2(70GB)、CLUECorpus2020(200GB)并列,适配 Llama 等模型的预训练流程。
二、数据获取与解压
2.1 下载
在智源数据官网(www.scidb.cn,数据集 IDc6a3fe684227415a9db8e21bac4a15ab)即可直接下载 WuDaoCorpus2.0_base_200G 数据,下载得到的压缩包约 64GB。
2.2 解压
压缩包为 RAR 格式,使用unrar解压:
unrar x WuDaoCorpus2.0_base_200G.rar解压后得到目录WuDaoCorpus2.0_base_200G,其中每个 json 文件内部是[{"content": "...", ...}, ...]形式的数组结构——这一点可以从 words_segmentation.py 中read_wudao的实现得到印证:该函数对data_format=wudao的输入执行json.load(f)后逐条取出js["content"]字段。
三、中文语料预处理:分词与断句(words_segmentation.py)
3.1 为什么要先分词
WuDao 语料规模达 200GB,直接进入 token 化阶段会非常耗时。为此 PaddleNLP 提供 words_segmentation.py 作为可选的预分词步骤:先一次性完成中文分词(为后续 WWM / 整词掩码做准备),再进入 jsonl 转换和 ID 化,避免在create_pretraining_data.py阶段重复运行分词程序。当数据集足够大、或需要多次尝试不同转换参数时,这一步能显著节省总耗时。
3.2 执行命令
python words_segmentation.py \ --input_path ./WuDaoCorpus2.0_base_200G \ --workers 40 \ --data_format wudao \ --cn_seg_func seg \ --output_path ./wudao_lac_cut3.3 参数说明(对照源码)
以 words_segmentation.py 中的get_args为准:
--input_path(必填):输入文件或文件夹路径。源码中os.walk会递归收集目录下所有文件,每个文件分配给一个 worker 进程处理;--output_path:输出目录,默认./tmp,脚本会自动创建;--data_format:输入格式,可选jsonl或wudao,处理 WuDao 原始数据时必须设为wudao。wudao格式读取的是js["content"],而jsonl格式读取的是js["text"];--cn_seg_func:中文分词器,可选lac/seg/jieba,默认jieba。文档命令中使用的seg对应 LAC 的纯分词模式(LAC(mode="seg")),lac则输出词性与分词(LAC(mode="lac"));--workers:多进程数,默认 1。200GB 语料建议开到 40 左右以利用多核;--log_interval:进度打印间隔(按处理完的文件个数计)。
3.4 断句规则与 SOP 预训练任务
该脚本在分词的同时,还完成了一项对预训练至关重要的操作——文本断句。从源码看,其逻辑位于text_to_text:
special_chars = ["\n", "。", "?", "?", " ", ";", ";", "!", "!"] split_chars = ["。", "?", "?", ";", ";", "!", "!"]- 先把连续重复的特殊字符(如多个句号、多个感叹号)压缩为单个,避免它们作为句子分隔符时产生干扰;
- 再将
。?;!等句末标点替换为标点 + "\n",使每行成为一句; - 随后对每一行执行分词,并以空格连接词语,最终写回文件。
为什么需要断句?文档明确说明:预训练需要实现SOP(Sentence Order Prediction,句子顺序预测)任务,这要求训练数据按句子切分并保留句子边界。补充提示:如果语料本身只有一句话(单句文档),建议去除 SOP loss,训练时设置binary_head=False。
3.5 关于分词步骤的注意事项
在 llm/tools/preprocess/README.md 的 Pipeline 说明中强调了三点:
- 分词是中文预训练做WWM(Whole Word Mask,整词掩码)的可选步骤;数据量小时可直接跳过,在
create_pretraining_data.py阶段内部分词即可; - 若此处输入的是 jsonl 多文件,则使用
trans_to_json.py时应开启--no-merge选项; - 分词完成后需要重新执行一次
trans_to_json.py转换,再进入 ID 化阶段,并在 ID 化时设置--cn_splited=True(告知脚本语料已经是分词后的状态)。
四、转换为 jsonl 格式(trans_to_json.py)
4.1 执行命令
分词完成后,使用 trans_to_json.py 将wudao_lac_cut目录下的文件重新转换为统一的 jsonl 格式:
python ./trans_to_json.py \ --input_path ./wudao_lac_cut \ --output_path wudao_corpus_200g.jsonl \ --workers 40在当前目录下产出wudao_corpus_200g.jsonl,每行一个 json 对象,形如:
{"text": "主持人 : 作为 一个 曲线救国 的 路线 我们 没 办法 。\n金鑫 : 考试 和 分数 只是 一个 阶段性 的 评价 手段 , 不是 目的 , ..."} {"text": "武田信玄 是 天生 的 武将 , 一生 开拓 了 八十五万 石至 九十余万 石之多 的 领地 。\n..."}可以看到:text字段内是已经分词(词间以空格分隔)并按句子换行的文本,每个 doc 对应一行。
4.2 参数说明(对照源码)
依据 trans_to_json.py 的get_args:
--input_path(必填):原始文件或文件夹路径;文件夹默认最多递归搜索两层子目录;--output_path(必填):输出文件名,脚本自动追加.jsonl后缀;--json_key:json 字段名,默认text,一般无需修改;--doc_spliter:文档分隔符,默认空字符串,即以空行作为文档切分标志;源码raw_text_to_json中,line.strip() == doc_spliter时判定为文档边界;--min_doc_length:最短文档长度(字符数),默认 10,低于此长度的文档会被过滤;--workers:多进程数,默认 1,每个文件分配给一个 worker;--log_interval:按处理完的文件个数为间隔打印进度;--no-merge:默认会将所有文件转换结果合并到同一个 jsonl;开启后各文件独立输出,适用于后续仍需并行处理的场景;--no-shuffle:默认转换完成后会对全部 doc 执行一次shuf随机打乱,开启该选项可跳过。
从main()的流程可以看到完整链路:收集文件 → 多进程raw_text_to_json→merge_file合并 →shuffle_file打乱,其中每条 doc 均以json.dumps({json_key: doc}, ensure_ascii=False)写出,保证中文不被转义。
五、预训练数据 ID 化(create_pretraining_data.py)
得到统一格式的 jsonl 后,下一步是用 create_pretraining_data.py 将文本 tokenize 为 token id,并生成.bin/.idx索引文件。不同模型的处理方式差异主要体现在是否需要分词、断句、整词掩码、追加 eos上,下面分别以 Llama 与 ERNIE 为例。
5.1 针对 Llama 模型
注意:若使用 Llama 模型,则不需要提前进行分词。请先将WuDaoCorpus2.0_base_200G中的 json 文件预处理为如下格式的 jsonl(未分词、保持自然文本):
{"text": "飞桨是功能完备、开源开放的产业级深度学习平台。飞桨拥有..."} {"text": "PaddleNLP是自然语言..."}之后执行 ID 化:
python -u create_pretraining_data.py \ --model_name "idea-ccnl/ziya-llama-13b-v1" \ --input_path "wudao_corpus_200g.jsonl" \ --output_prefix "wudao_corpus_200g" \ --data_format "JSON" \ --json_key "text" \ --data_impl "mmap" \ --append_eos \ --log_interval 10000 \ --workers 485.2 针对 ERNIE 模型
python -u create_pretraining_data.py \ --model_name "ernie-3.0-base-zh" \ --input_path "wudao_corpus_200g.jsonl" \ --output_prefix "wudao_corpus_200g" \ --data_format "JSON" \ --json_key "text" \ --split_sentences \ --data_impl "mmap" \ --chinese \ --cn_whole_word_segment \ --cn_seg_func "jieba" \ --cn_splited \ --log_interval 10000 \ --workers 48两个关键使用提示(原文档明确说明):
- 由于前面
words_segmentation.py已对语料做过分词,ERNIE 命令中必须加上--cn_splited;如果语料未预分词,则不要使用该选项; --model_name可以替换为 llm 目录 中支持的其他模型;--workers表示 ID 化使用的进程数(对应线程/进程并行数)。
5.3 全量参数详解(对照源码)
依据 create_pretraining_data.py 的get_args:
数据输入输出组:
--model_name_or_path(必填):模型名或词表所在目录,如idea-ccnl/ziya-llama-13b-v1、ernie-3.0-base-zh;使用自定义词表时填词表文件夹地址;--input_path(必填):输入 jsonl 文件或目录;--output_prefix(必填):输出前缀,假设为 XXX 则产出XXX.bin(token id 数据)与XXX.idx(句子/文章位置索引);--data_format:目前仅支持JSON(每行一个文档),默认即可;--json_key:json 文本字段名,默认text;--split_sentences:是否将文档切成句子。GPT/Llama 类模型一般不需要,BERT/ERNIE 类模型需要;--data_impl:可选mmap或lazy。mmap在读取时建立内存映射,lazy直接从文件读取。
中文分词组:
--chinese:中文语料是否需要分词步骤(配合split_sentences使用);--cn_whole_word_segment:是否需要 WWM 整词掩码策略。BERT/ERNIE 需要,GPT 不需要;--cn_seg_func:lac/seg/jieba,默认jieba(速度快),lac更准确但计算量高;--cn_splited:语料已分词时设置,设置后cn_seg_func不再起作用;此时分词逻辑退化为text.split(cn_split_dimer)(见Converter.initializer);--cn_split_dimer:配合cn_splited使用的词间分隔符,默认空格。
公共配置组:
--append_eos:在每个文档末尾追加<eos>token,GPT/Llama 类模型专用,表示文档结束;若 tokenizer 无 eos token 会打印 warning 且不追加(源码中Converter.encode检查eos_token_id);--log_interval:日志打印间隔,按处理的行数/doc 数计;--workers:ID 化进程数;--max_doc_num:处理到指定 doc 数即停止,默认sys.maxsize(不限制);--max_repeated_len:保留的连续重复字符最大长度,默认 100。源码中的remove_repeated_chars使用正则(.)\1{N,}将超过该长度的连续重复字符压缩为单个,用于过滤数据中的噪声刷屏内容。
5.4 底层处理流程(源码级)
main()的核心执行链(对应 create_pretraining_data.py 第 306-380 行):
- 格式判断:
.jsonl直接读取;.zst文件会调用zstandard解压流读取(需安装 zstandard); - dtype 自适应:通过
AutoTokenizer加载 tokenizer,若vocab_size < 2^16 - 1则使用np.uint16存储,否则使用np.int32——这是针对大词表模型的内存优化; - 多进程 token 化:
multiprocessing.Pool(workers, initializer=convert.initializer)中每个 worker 各自加载 tokenizer;Converter.encode按json_key取出文本 → 压缩重复字符 → 按 splitter 断句 →segment_func分词(cn_splited时为按分隔符切分)→tokenizer.tokenize→ WWM 处理 →convert_tokens_to_ids; - 索引构建:通过
indexed_dataset.make_builder(output_prefix + ".bin", data_impl, save_dtype)创建 builder,逐句add_item、逐文档end_document,最后finalize(output_prefix + ".idx")落盘。
5.5 产出物
在当前目录下产出训练所需数据:
wudao_corpus_200g.bin wudao_corpus_200g.idx.bin为全部 token id 的二进制序列,.idx记录每个句子/文档的位置偏移。用户可以直接使用这份数据启动预训练任务。
六、mmap 索引数据集:.bin / .idx 的内部结构
ID 化产出的.idx索引文件遵循 PaddleNLP 自有的MMapIndexedDataset格式(实现于 paddlenlp/data/indexed_dataset.py),理解其结构有助于排查数据问题:
- 文件头魔数为
b"MMIDIDX\x00\x00",随后依次写入版本号、dtype 编码; - 主体包含三部分:sizes(每个样本的 token 长度,
int32数组)、pointers(每个样本在.bin中的起始偏移,int64数组)、doc_idx(文档边界索引,int64数组); - 读取时通过
np.memmap将整个.idx文件映射到内存,避免一次性载入超大索引,同时支持__getitem__按样本号快速定位(pointer, size)。
这也是--data_impl mmap名称的由来:训练启动时对 200GB 语料的索引采用内存映射访问,只在真正读取 token 时才触碰到.bin文件的对应区域。.bin数据按uint16或int32紧凑存储,配合 mmap 机制可以显著降低百 GB 级语料的启动与采样开销。
七、超大数据集的并行拆分与合并(merge.py)
200GB 语料单机串行 ID 化耗时很长。README 与脚本均给出了推荐的并行策略:将 jsonl 拆成多个小文件,用多个create_pretraining_data.py进程并行处理,各自产出独立的.bin/.idx,最后用 merge.py 合并:
python merge.py \ --input /root/data \ --output-prefix /root/data/merged \ --data_impl mmap参数说明(对照 merge.py 源码):
--input:待合并文件所在目录(必须是目录),目录内按序放置1.bin / 1.idx、2.bin / 2.idx……脚本通过扫描.idx/.bin后缀对自动识别前缀,并对缺失配对文件做断言校验;--output-prefix:合并后输出前缀,产出XXX.bin与XXX.idx;--data_impl:mmap或lazy,要求所有待合并文件格式一致。
实现上,脚本用indexed_dataset.make_dataset打开第一个文件以确定 dtype,创建对应 builder(mmap 用MMapIndexedDatasetBuilder),随后按前缀排序逐个merge_file_追加二进制数据,最终统一finalize生成合并索引。整个过程按前缀排序保证了合并后样本顺序稳定。
八、环境依赖与全流程回顾
8.1 环境依赖
根据 llm/tools/preprocess/README.md,运行上述脚本需要以下依赖:
tqdm(进度条)、numpy(数据存储)、pybind11、fast_dataindex(索引构建);lac(可选,LAC 分词)、zstandard(可选,读取.zst压缩输入);- 部分功能需要
g++ >= 4.8编译支持。
安装命令:
pip install tqdm numpy pybind11 fast_dataindex lac zstandard8.2 全流程 Pipeline 回顾
| 步骤 | 脚本 | 输入 → 输出 | 说明 | |-|-|-|-| | 0️⃣ 初始状态 | — | 原始文本(doc 间空行分隔) | 中文默认换行断句 | | 1️⃣ 原始数据转换 | trans_to_json.py | 原始文本 →jsonl| 每行一个{"text": ...}| | ❇️ 可选中文分词 | words_segmentation.py |jsonl/wudao → 分词后文本 | 中文 WWM 预分词,含断句 | | 2️⃣ 数据 ID 化 | create_pretraining_data.py |jsonl→.bin+.idx| token id 序列 + 位置索引 | | 3️⃣ 训练 index 生成 | 训练启动阶段 |.idx→npy样本索引 | 按训练步数生成 train/valid/test 索引 | | 4️⃣ 动态 mask(可选) | Dataset 取数据阶段 | — | Python 层实时 mask |
针对 WuDaoCorpus2.0 Base 的完整命令序列为:unrar x解压 →words_segmentation.py(wudao 格式,--data_format wudao)→trans_to_json.py转换 →create_pretraining_data.py(Llama 路线无需预分词,ERNIE 路线需加--cn_splited)→ 得到wudao_corpus_200g.bin/.idx用于预训练。若语料较大,可拆分成多个 jsonl 并行 ID 化后再用 merge.py 合并。
九、常见注意事项
--data_format必须匹配:处理 WuDao 原始 json 数组时words_segmentation.py需用--data_format wudao(读取content字段),处理通用 jsonl 时用默认的jsonl(读取text字段);- 分词与
cn_splited配对:凡经过words_segmentation.py预分词的语料,ID 化阶段必须加--cn_splited,否则脚本会二次分词导致词边界错乱;未预分词则不要加; - SOP 与断句:需要 SOP 任务时保留断句输出;语料为单句场景建议去除 SOP loss,训练时设置
binary_head=False; append_eos仅用于 GPT 类:Llama 等自回归模型用它标记文档边界;ERNIE 命令中不设置;- 数据清洗:
--max_repeated_len(默认 100)会在 ID 化阶段自动压缩超长重复字符,可结合语料质量自行调整阈值; - 大词表 dtype:词表超过 65535 时自动切换为
int32存储,无需手动干预; - 超大语料加速:先分词、后拆分并行 ID 化、最后 merge,是官方 README 推荐的百 GB 级数据标准打法。
十、延伸阅读
- 数据教程汇总与其他语料流程:llm/tools/preprocess/README.md(含 CLUECorpusSmall、OpenWebText2、CLUECorpus2020 的中文/英文语料处理说明)
- 中文分词与断句实现:words_segmentation.py
- 原始文本转 jsonl 实现:trans_to_json.py
- 数据 ID 化与索引构建实现:create_pretraining_data.py
- mmap 索引数据集格式定义:paddlenlp/data/indexed_dataset.py
- 预训练启动与模型列表:llm/README.md
- 人工智能
- 大模型
- 预训练
- 微调
- LoRA
- RLHF
- 强化学习
- 分布式训练
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
相关推荐
PaddleNLP 中文预训练数据实战:WuDaoCorpus2.0 Base 200GB 语料的获取、分词、ID 化与训练接入全流程
PaddleNLP 中文预训练数据实战:WuDaoCorpus2.0 Base 200GB 语料的获取、分词、ID 化与训练接入全流程 本篇技术指南以 Padd
人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLPPaddleNLP 预训练数据准备指南:CLUECorpus2020 中文 200GB 语料的申请获取与全流程处理
PaddleNLP 预训练数据准备指南:CLUECorpus2020 中文 200GB 语料的申请获取与全流程处理 CLUECorpus2020 是由 CLUE
人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLP大模型数据准备完全指南:PaddleNLP预训练语料预处理与数据集构建教程
大模型数据准备完全指南:PaddleNLP预训练语料预处理与数据集构建教程 PaddleNLP 是功能强大的大模型(LLM)与小语言模型(SLM)开源库,内置丰
人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考