mindspore-ai / mindspore-ai/hyper-parallel

[RFC] Offline IDX/BIN 使用与转测说明

Open
#177 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
53
Forks
63
Avg merge
23h 45m
Merged PRs (30d)
63

Description

Offline IDX/BIN 使用与转测说明

本文只说明 LLM Offline Indexed Dataset(.idx/.bin)的应用场景,不依赖现有训练 YAML。
内容分为两部分:

  1. 使用转换工具把原始文本转换为 IDX/BIN。
  2. 拿到已有 IDX/BIN 后,检查数据并接入训练。

不测试 VLM、图片或视频数据。转测以命令能否正常结束、数据能否读取、训练能否持续运行和 loss 是否正常等
应用侧可观测结果为准,不把内部索引或 Dataset 实现细节作为验收项。

测试人员不需要分析 position ID、attention mask 或 loss mask 等内部 Tensor;涉及这些开关的用例,只验收
训练能否正常启动和持续运行,以及 loss 是否为有限值。

统一验收标准:

  • 转换或读取命令退出码为 0,日志中没有 ERRORTraceback
  • 训练场景至少连续完成 3 个训练 step,进程无异常,loss 不为 NaNInf
  • 测试人员不需要检查 batch shape、记录长度或内部 Tensor 的具体数值。

一、使用转换工具生成 IDX/BIN

1. 适用场景

转换工具支持 JSON、JSONL 文件、目录或 glob 输入,并根据 --json-keys 读取文本字段。

示例 JSONL:

{"text": "first training document"}
{"text": "second training document"}

转换结果分为两类:

转换模式 使用场景 关键参数 输出记录长度
Non-packed 普通变长文档训练 不设置 --pack-to-seq-len 可以不同
Packed/pre-cut 提前制作定长训练记录 --pack-to-seq-len <seq_length> 固定为 seq_length + 1
2. 生成 Non-packed 数据

Non-packed 模式只进行 tokenization,不在离线阶段补齐或切成定长训练记录。

python -m hyper_parallel.auto_models.components.datasets.tools.offline_preparation \
  --dataset-name-or-path /path/to/train.jsonl \
  --json-keys text \
  --output-prefix /path/to/indexed/train \
  --tokenizer-name-or-path /path/to/tokenizer \
  --tokenizer-use-fast true \
  --workers 8 \
  --append-eod true

不要设置 --pack-to-seq-len

输出:

/path/to/indexed/train_text_document.bin
/path/to/indexed/train_text_document.idx
3. 生成 Packed/pre-cut 数据

Packed 模式用于提前生成与模型训练长度匹配的定长记录。假设训练的 seq_length=2048

python -m hyper_parallel.auto_models.components.datasets.tools.offline_preparation \
  --dataset-name-or-path /path/to/train.jsonl \
  --json-keys text \
  --output-prefix /path/to/indexed/train_packed \
  --tokenizer-name-or-path /path/to/tokenizer \
  --tokenizer-use-fast true \
  --workers 8 \
  --append-eod true \
  --pack-to-seq-len 2048

每条输出记录包含 2049 个 token:

2049 token
├── input_ids = text[:-1]  # 2048
└── labels    = text[1:]   # 2048

输入结束时不足 2049 个 token 的尾部会被丢弃,不写入 PAD。

4. EOD 选项

--append-eod true 会在每个非空文档末尾追加 tokenizer 定义的 EOS/EOD token。

  • 训练时必须使用相同 tokenizer,或提供完全一致的 vocab_sizeeod_token_id
  • tokenizer 必须定义 eos_token_idsep_token_id,否则追加 EOD 会失败。
  • Packed 数据可以设置 --append-eod false,但记录中将没有可用于文档边界处理的 EOD。
5. 检查转换结果

先检查两个文件均存在且非空:

test -s /path/to/indexed/train_text_document.bin
test -s /path/to/indexed/train_text_document.idx

再读取元数据和少量样本:

python -m hyper_parallel.auto_models.components.datasets.tools.read_indexed_dataset \
  --path /path/to/indexed/train_text_document \
  --tokenizer /path/to/tokenizer \
  --num-samples 3

Non-packed 数据应满足:

  • sequence 和 document 数量大于 0。
  • sequence 长度允许不同。
  • token ID 在模型词表范围内。
  • 启用 append-eod 时,非空文档末尾包含正确的 EOD ID。

Packed 数据应满足:

min_length = max_length = seq_length + 1

例如 seq_length=2048 时,所有记录长度必须为 2049。

6. 转换工具限制
  • 输入字段必须与 --json-keys 一致,字段值应为可 tokenization 的文本。
  • 输出目录必须存在或允许创建,并且具有足够的磁盘空间。
  • 同一个 prefix 的 .bin/.idx 必须来自同一次转换。
  • 离线转换和训练必须使用相同的 tokenizer 规则。
  • Packed 数据不支持 PAD;尾部不足完整记录时直接丢弃。
  • --pack-to-seq-len 必须大于 0,并与后续训练的 seq_length 一致。
  • 数据量过小时,Packed 转换可能无法生成任何完整记录。
7. 转换工具转测场景
用例 操作 预期结果
C-1 JSONL 转换为 Non-packed 数据并接入训练 转换和读取命令正常结束,训练至少完成 3 个 step,无异常且 loss 正常
C-2 JSONL 转换为 Packed 数据并接入训练 转换和读取命令正常结束,训练至少完成 3 个 step,无异常且 loss 正常
C-3 指定多个 --json-keys 进行转换 转换命令正常结束,各输出数据均能正常读取
C-4 分别设置 append-eod=true/false 后接入训练 两种配置均至少完成 3 个训练 step,无异常且 loss 正常

二、拿到 IDX/BIN 后接入训练

1. 确认文件和 Dataset prefix

一个 Dataset prefix 对应两个文件:

<prefix>.bin
<prefix>.idx

配置中的 dataset.data_path 填 prefix,不带 .bin.idx 后缀。

文件:
/data/train_text_document.bin
/data/train_text_document.idx

配置:
dataset.data_path: /data/train_text_document

如果不了解数据的制作方式,先使用读取工具查看长度:

python -m hyper_parallel.auto_models.components.datasets.tools.read_indexed_dataset \
  --path /data/train_text_document \
  --tokenizer /path/to/tokenizer \
  --num-samples 3

根据检查结果选择模式:

已有数据特征 is_dataset_from_mr 要求
变长、未提前 packing 的文档 false 不含离线 PAD
固定长度的 Packed/pre-cut 记录 true 每条严格为 seq_length + 1
2. Non-packed 数据配置示例
dataset:
  model_assets:
    tokenizer:
      _target_: hyper_parallel.auto_models.components.datasets.llm.build_tokenizer.AutoTokenizer.from_pretrained
      pretrained_model_name_or_path: /path/to/tokenizer
      tokenizer_type: hf
      use_fast: true
      local_files_only: true

  _target_: hyper_parallel.auto_models.components.datasets.llm.build_indexed_text_dataset
  data_path: /data/train_text_document
  data_config:
    seq_length: 2048
    split: "1, 0, 0"
    is_dataset_from_mr: false
    labels_are_shifted: true

Indexed Dataset 返回的 labels 已经是与 logits 对齐的 next-token labels,因此必须配置
labels_are_shifted: true,避免模型或 loss 再次 shift。未列出的 Dataset 参数使用默认值。转测只检查训练至少
连续完成 3 个 step,无异常且 loss 正常。

3. Packed/pre-cut 数据配置示例
dataset:
  model_assets:
    tokenizer:
      _target_: hyper_parallel.auto_models.components.datasets.llm.build_tokenizer.AutoTokenizer.from_pretrained
      pretrained_model_name_or_path: /path/to/tokenizer
      tokenizer_type: hf
      use_fast: true
      local_files_only: true

  _target_: hyper_parallel.auto_models.components.datasets.llm.build_indexed_text_dataset
  data_path: /data/train_packed_text_document
  data_config:
    seq_length: 2048
    split: "1, 0, 0"
    is_dataset_from_mr: true
    labels_are_shifted: true

Packed Indexed Dataset 同样已经生成 next-token labels,必须配置 labels_are_shifted: true。未列出的 Dataset
参数使用默认值。已有 Packed 数据的记录长度必须为 2049;转测只检查训练至少连续完成 3 个 step,无异常且
loss 正常。

4. 只有 token 元数据时

如果没有可加载的 Hugging Face tokenizer,但明确知道数据使用的词表和 EOD ID,可以使用
pretokenized

dataset:
  model_assets:
    tokenizer:
      _target_: hyper_parallel.auto_models.components.datasets.llm.build_tokenizer.AutoTokenizer.from_pretrained
      pretrained_model_name_or_path: /path/to/stable/tokenizer-identity
      tokenizer_type: pretokenized
      vocab_size: 32000
      eod_token_id: 2
  • vocab_sizeeod_token_id 必须与数据制作阶段完全一致。
  • pretrained_model_name_or_path 使用稳定、可区分该 tokenizer 的身份路径。
  • Pretokenized 模式不能编码或解码原始文本,只适合读取已有 token 数据。

检查命令:

python -m hyper_parallel.auto_models.components.datasets.tools.read_indexed_dataset \
  --path /data/train_text_document \
  --tokenizer-type pretokenized \
  --vocab-size 32000 \
  --eod-token-id 2 \
  --num-samples 3
5. DataLoader 配置示例

两种模式都使用 Indexed 数据源:

dataloader:
  _target_: hyper_parallel.auto_models.components.datasets.FixedBatchDataLoader

  collate_fn:
    _target_: hyper_parallel.auto_models.components.datasets.build_indexed_collate_fn

  get_batch:
    _target_: hyper_parallel.auto_models.components.datasets.ParallelBatch
    source_type: indexed

未列出的 DataLoader 参数使用默认值。

6. EOD 训练选项
dataset:
  data_config:
    reset_position_ids: false
    reset_attention_mask: false
    eod_mask_loss: false
  • reset_position_ids=true:EOD 后 position ID 从 0 重新开始。
  • reset_attention_mask=true:EOD 后的 token 不再关注前一个文档。
  • eod_mask_loss=true:EOD 对应位置不参与 loss。
  • 三项均为 false:token 流按连续序列训练。
7. 已有 IDX/BIN 的使用限制
  • .bin/.idx 必须成对存在,data_path 必须填写 prefix。
  • 必须确认数据是 Non-packed 还是 Packed,不能只根据文件名判断。
  • Packed 数据的制作 seq_length 必须与训练配置一致。
  • 模型 vocab_size 必须大于数据中的最大 token ID。
  • tokenizer 和 EOD ID 必须与数据制作阶段一致。
  • tokenizer 的 PAD ID 如果存在,必须与 EOD/EOS ID 不同。
  • Non-packed 数据配置 is_dataset_from_mr: false
  • Packed 数据配置 is_dataset_from_mr: true,且不允许 PAD。
  • Non-packed 和 Packed Indexed 数据都必须配置 labels_are_shifted: true
  • global_batch_size 必须能被 micro_batch_size * dp_world_size 整除。
  • 数据量至少能够提供一个完整的全局 DP micro-batch。
8. 已有 IDX/BIN 转测场景
用例 操作 预期结果
U-1 接入已有 Non-packed IDX/BIN 至少完成 3 个训练 step,无异常且 loss 正常
U-2 接入已有 Packed IDX/BIN 至少完成 3 个训练 step,无异常且 loss 正常
U-3 使用 Pretokenized 元数据接入 数据正常读取,至少完成 3 个训练 step,无异常且 loss 正常
U-4 分别单独启用 reset_position_idsreset_attention_maskeod_mask_loss 每种配置均至少完成 3 个训练 step,无异常且 loss 正常

更多数据结构说明见 Indexed Dataset 使用教程

schema_version: 1
source: gitcode
gitcode_repo: mindspore/hyper-parallel
gitcode_issue: 348
source_url: https://gitcode.com/mindspore/hyper-parallel/issues/348

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing documentation entry point and the referenced index_dataset_tutorial.md, then compare them with the offline_preparation and read_indexed_dataset commands and dataset YAML examples in this issue. Done means the Non-packed, Packed, pretokenized, and EOD workflows, validation criteria, and C-1–C-4/U-1–U-4 scenarios are documented accurately.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
67/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.