๐Ÿ“ฆ Dataset Pipeline

Data Loading and Preprocessing for All Training Stages

2
Files
4
Dataset Classes
~218
Lines
๐Ÿ
Python
๐Ÿ”ต Pretrain ๐ŸŸข SFT ยท Chat Template ๐ŸŸก DPO ยท Preference ๐Ÿ”ด RLAIF ยท RL
๐Ÿณ Kitchen Analogy

Think of the dataset module as ingredient preparation stations in a professional kitchen. Each station (Dataset class) takes raw ingredients (JSONL data) and prepares them differently depending on the dish being made โ€” the Pretrain station washes and chops text into uniform pieces, the SFT station marinates conversations into chat templates, the DPO station carefully selects the best and worst preparations for comparison, and the RLAIF station stages prompts for the chef (RL agent) to improvise with. Every station outputs precisely formatted batches, ready for the training "oven."

Architecture Overview

classDiagram
    class Dataset {
        <<PyTorch>>
        +__len__()
        +__getitem__(index)
    }
    class PretrainDataset {
        -data: List
        -max_length: int
        +__init__(data_path, tokenizer, max_length)
        +__getitem__(index) โ†’ (X, Y, loss_mask)
    }
    class SFTDataset {
        -data: List
        +create_chat_prompt(conversations)
        +generate_labels(input_ids)
        +__getitem__(index) โ†’ (X, Y, loss_mask)
    }
    class DPODataset {
        -data: List
        +__getitem__(index) โ†’ (x_cho, y_cho, m_cho, x_rej, y_rej, m_rej)
    }
    class RLAIFDataset {
        -data: List
        +create_chat_prompt(conversations)
        +__getitem__(index) โ†’ (prompt, answer)
    }
    Dataset <|-- PretrainDataset
    Dataset <|-- SFTDataset
    Dataset <|-- DPODataset
    Dataset <|-- RLAIFDataset
    

Key Classes & Functions

NameTypeFileDescription
PretrainDatasetClasslm_dataset.pyLoads JSONL, tokenizes with BOS/EOS, pads to max_length; labels=-100 for padding tokens
SFTDatasetClasslm_dataset.pyApplies chat template via apply_chat_template(), computes loss only on assistant turns
DPODatasetClasslm_dataset.pyPairs chosen/rejected conversations with corresponding loss masks
RLAIFDatasetClasslm_dataset.pyBuilds prompts with add_generation_prompt=True for PPO/GRPO/SPO training
pre_processing_chatFunctionlm_dataset.pyRandomly injects system prompts (10 bilingual options, 20% chance) via add_system_ratio
post_processing_chatFunctionlm_dataset.pyStrips empty <think></think> tags with 95% probability
create_chat_promptMethodlm_dataset.pyHandles tool calling by injecting function schemas into the system message
generate_labelsMethodlm_dataset.pyMasks non-assistant tokens to -100; loss only between bos_id and eos_id markers

Data Flow

sequenceDiagram
    participant JSONL as JSONL Files
    participant HF as HuggingFace Loader
    participant DS as Dataset Class
    participant TK as Tokenizer
    participant DL as DataLoader
    participant TR as Trainer

    JSONL->>HF: load_dataset("json")
    HF->>DS: raw samples
    DS->>TK: tokenize text/chat
    TK-->>DS: input_ids, attention_mask
    DS->>DS: generate_labels / loss_mask
    DS->>DL: (X, Y, loss_mask) batches
    DL->>TR: collated mini-batches
    TR->>TR: compute loss (masked)
    

Interactions & Dependencies

ComponentDepends OnInteraction
PretrainDatasetHuggingFace datasets, tokenizerLoads JSONL, tokenizes raw text to fixed-length sequences
SFTDatasettokenizer.apply_chat_templateFormats multi-turn conversations using the model's chat template
SFTDatasetpre_processing_chatRandomly adds system prompt before tokenization
SFTDatasetpost_processing_chatStrips empty think tags to control reasoning format
DPODatasetSFTDataset logicReuses chat template + labeling for chosen/rejected pairs
RLAIFDatasettokenizer, reward modelProduces prompts; answers used downstream for reward computation
All DatasetsPyTorch DataLoaderConsumed by DataLoader with custom collate or default batching
generate_labelsbos_id / eos_id tokensScans token IDs to create loss masks targeting assistant segments

Deep-Dive Topics

๐Ÿ’ฌ Chat Template Processing

How apply_chat_template() converts multi-turn conversations into token sequences, handling system messages, tool calls, and role markers for proper formatting.

๐ŸŽฏ Loss Mask Generation

The logic behind generate_labels(): scanning for bos/eos markers to compute loss only on assistant responses, avoiding training on user prompts or padding.

โš–๏ธ DPO Data Format

How chosen/rejected conversation pairs are structured, tokenized in parallel, and returned with separate loss masks for Direct Preference Optimization training.

Directory Map

dataset/
โ”œโ”€โ”€ __init__.py           # Package init
โ””โ”€โ”€ lm_dataset.py        # ~218 lines โ€” All dataset classes & helpers
    โ”œโ”€โ”€ pre_processing_chat()  # System prompt injection
    โ”œโ”€โ”€ post_processing_chat() # Think-tag cleanup
    โ”œโ”€โ”€ PretrainDataset       # Raw text tokenization
    โ”œโ”€โ”€ SFTDataset            # Chat template + loss masking
    โ”œโ”€โ”€ DPODataset            # Preference pair formatting
    โ””โ”€โ”€ RLAIFDataset          # RL prompt generation

Configuration Reference

ParameterLocationDefaultDescription
max_lengthPretrainDataset / SFTDataset512Maximum sequence length; shorter sequences are padded, longer truncated
add_system_ratiopre_processing_chat0.2Probability of injecting a random system prompt (20%)
empty_think_ratiopost_processing_chat0.05Probability of keeping empty think tags (5% keep, 95% strip)
data_pathAll Dataset classesโ€”Path to JSONL training data file
tokenizerAll Dataset classesโ€”HuggingFace tokenizer instance with chat template
bos_idSFTDataset.generate_labelstokenizer.bos_idBegin-of-sequence marker for assistant response boundaries
eos_idSFTDataset.generate_labelstokenizer.eos_idEnd-of-sequence marker for assistant response boundaries
add_generation_promptRLAIFDatasetTrueAppends generation prompt token for RL inference

Code Examples

Loading an SFT Dataset

Python โ€” SFT dataset initialization
from dataset.lm_dataset import SFTDataset
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("MiniMind2")
dataset = SFTDataset(
    data_path="data/sft_train.jsonl",
    tokenizer=tokenizer,
    max_length=512
)

# Each item: (input_ids, labels, loss_mask)
X, Y, loss_mask = dataset[0]
print(f"Sequence length: {len(X)}")
print(f"Active loss tokens: {loss_mask.sum().item()}")

DPO Preference Pair Access

Python โ€” DPO dataset usage
from dataset.lm_dataset import DPODataset
from torch.utils.data import DataLoader

dpo_dataset = DPODataset(
    data_path="data/dpo_train.jsonl",
    tokenizer=tokenizer,
    max_length=512
)

loader = DataLoader(dpo_dataset, batch_size=4, shuffle=True)

for batch in loader:
    x_chosen, y_chosen, mask_chosen, \
    x_rejected, y_rejected, mask_rejected = batch
    # Feed to DPO trainer for preference optimization
    break