Repository navigation
Add document-boundary-aware sequence packing for MLM and CLM pre-training - #49
Merged
Merged
Conversation
…ning Packing is delegated to trl.data_utils.pack_dataset (best-fit decreasing, documents are never split) and the boundaries are passed to the model per family: decoders get per-document position_ids without an attention_mask (transformers builds the block-diagonal mask for flash_attention_2 / sdpa / eager), ModernBERT gets one document per row and re-packs them with cu_seqlens, and BERT-style encoders get a 3D block-diagonal attention mask with per-document position_ids. run_mlm.py / run_clm.py expose `packing`, `packing_strategy`, `packing_seq_length`, `packing_encoder_mode` (MLM) and `packing_mask_document_starts` (CLM); the default keeps the current behaviour.
- Decoder collator now also emits FlashAttention varlen kwargs (cu_seq_lens_q/k, max_length_q/k) so flash_attention_2 keeps document boundaries for batches larger than one; position_ids alone only work for batch size 1 in transformers' FA2 path. - Fail fast on trl/transformers/torch versions that would silently ignore the boundaries. - Drop scalar dataset columns before pack_dataset (bfd cannot pack them), rely on trl's own truncation, reject packing + pad_to_max_length and packing_seq_length > max_seq_length, refuse the 3D-mask mode for ModernBERT, build the 3D mask from the row's attention_mask, and leave wrapped rows' first token in the loss. - Tests: batches of two rows with a padding segment for CLM and MLM, effective attn_implementation switching, varlen kwargs, scalar-column dropping.
iamtatsuki05
force-pushed
the
feat/sequence-packing
branch
from
September 5, 2026 09:54
3f1a381 to
07ea1c8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds document-boundary-aware sequence packing that both
run_mlm.py(encoders) andrun_clm.py(decoders) can switch on with the same config flags. Default behaviour is unchanged (packing: false).trl.data_utils.pack_dataset(strategy="bfd")packs whole documents into rows ofpacking_seq_lengthtokens (documents longer than a row are truncated); every row carriesseq_lengths.packing_strategy: wrappedreproduces the old concatenate-and-chunk (group_texts) behaviour.PackedCausalLMCollatoremits per-documentposition_ids,labels(padding and, optionally, document-start tokens set to-100), the FlashAttention varlen kwargs (cu_seq_lens_q/k,max_length_q/k) and noattention_mask.flash_attention_2consumes the varlen kwargs;sdpa/eagerget the block-diagonal mask that transformers (>= 4.53, torch >= 2.6) derives from theposition_idsrestarts, which requiresuse_cache=False(set by the script).packing_encoder_mode=unpadsplits rows back into documents; the model's own unpadding re-packs them withcu_seqlens(true packing withflash_attention_2).packing_encoder_mode=maskkeeps the packed row and passes a 3D block-diagonalattention_maskplus per-documentposition_ids.packing_seq_length > max_seq_length,packing + pad_to_max_lengthandmaskmode for ModernBERT are rejected as well.New config keys:
packing,packing_strategy,packing_seq_length,packing_encoder_mode(MLM),packing_mask_document_starts(CLM). Seescripts/constract_llm/train/pt/README.md/README_JA.md.Verification
tox-equivalent (Python 3.12, transformers 4.56.1, trl 0.22.2, torch 2.8 CPU):pytest tests/ -n auto146 passed,ruff check/ruff format --checkclean.tests/mirei/constract_llm/train/language_model/test_packing.py, 16): a packed Llama batch (2 rows + padding segment) matches per-document logits foreagerandsdpa; a packed BERT batch with the 3D mask matches per-document logits; collator shapes / positions / labels / varlen kwargs; unpad-mode masking; argument validation.run_mlm.py(mask and unpad modes) andrun_clm.pywithpacking: trueon a tiny random model: train and eval complete, thepacking_seq_lengthguard raises as intended.flash_attention_2varlen path (decoder) and ModernBERT unpadding under packing. The kwargs followtransformers.modeling_flash_attention_utils._flash_attention_forward(the varlen branch reshapes(batch, seq)row-major); a packed-vs-per-document logits check on a GPU is recommended before a production run.Notes
per_device_train_batch_size × packing_seq_lengthtokens per micro-batch; step counts and the meaning of the total batch change accordingly.use_cache=Falseis persisted in the savedconfig.jsonof packed CLM runs; re-enable it for generation.mainand touches only the tokenize → group / collator hunks ofrun_mlm.py/run_clm.py.