-
Notifications
You must be signed in to change notification settings - Fork 397
Add refactored recipes for finetuning #2268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 39 commits
dbbafca
6478f92
a1db4a9
b6f209a
4b7f37b
3398c09
19ac6fc
0166966
b94bd4e
5e6a1ab
9005e80
4685af1
9079c62
b9c7ba0
f914d6b
8584789
cc4feaa
07b671e
7e7084f
5859eec
61f0ae9
676fbef
940bcfb
ed8e9f1
ddb87f6
c4372f6
1b12226
d26339e
5aa0c12
1406b31
1e71781
b0726bd
528c210
21ed8d9
a365d5c
a06578b
0d5f555
767707b
34d94ea
31cb09a
599a25b
18dab36
2a99c10
271c57d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,8 @@ | |
|
|
||
| from megatron.core.distributed import DistributedDataParallelConfig | ||
|
|
||
| from megatron.bridge.peft.lora import LoRA | ||
| from megatron.bridge.recipes.utils.finetune_utils import default_squad_config | ||
| from megatron.bridge.recipes.utils.optimizer_utils import distributed_fused_adam_with_cosine_annealing | ||
| from megatron.bridge.training.config import ( | ||
| CheckpointConfig, | ||
|
|
@@ -126,3 +128,210 @@ def _pretrain_common() -> ConfigContainer: | |
| ) | ||
|
|
||
| return cfg | ||
|
|
||
|
|
||
| def _sft_common() -> ConfigContainer: | ||
| """Create a base SFT (Supervised Fine-Tuning) ConfigContainer with common defaults. | ||
|
|
||
| This function returns a ConfigContainer template with sensible defaults for full SFT | ||
| (not LoRA/DoRA). The caller MUST set `cfg.model` and `cfg.tokenizer.tokenizer_model` | ||
| before use. | ||
|
|
||
| Key differences from pre-training: | ||
| - Uses HFDatasetConfig with SQuAD as default dataset | ||
| - Lower learning rate (5e-6) suitable for full fine-tuning | ||
| - Fewer training iterations (1000) | ||
| - Smaller batch sizes | ||
| - Supports pretrained_checkpoint loading | ||
| - No PEFT (full parameter training) | ||
|
|
||
| Returns: | ||
| ConfigContainer: Base configuration template for full SFT. | ||
| """ | ||
| # Default output directories | ||
| base_output_dir = os.path.join(os.getcwd(), "nemo_experiments") | ||
| run_output_dir = os.path.join(base_output_dir, "default") | ||
| checkpoint_dir = os.path.join(run_output_dir, "checkpoints") | ||
| tensorboard_dir = os.path.join(run_output_dir, "tb_logs") | ||
|
|
||
| # Default sequence length for SFT | ||
| seq_length = 2048 | ||
|
|
||
| # Packed sequence is enabled by default for training efficiency | ||
| # pad_seq_to_mult should be set to context_parallel_size * 2 if CP > 1 | ||
| packed_sequence = True | ||
| pad_seq_to_mult = 1 # Override in model config if context_parallel_size > 1 | ||
|
|
||
| # Optimizer and scheduler with lower LR for full SFT | ||
| opt_cfg, scheduler_cfg = distributed_fused_adam_with_cosine_annealing( | ||
| lr_warmup_iters=50, | ||
| lr_decay_iters=None, # Defaults to train_iters during validation | ||
| max_lr=5e-6, # Lower LR for full fine-tuning | ||
| min_lr=0.0, | ||
| adam_beta2=0.98, # Common for fine-tuning | ||
| ) | ||
|
|
||
| cfg = ConfigContainer( | ||
| # Model - MUST be set by each recipe before use | ||
| model=None, # type: ignore[arg-type] | ||
| # Training config - shorter training for SFT | ||
| train=TrainingConfig( | ||
| train_iters=1000, | ||
| global_batch_size=128, | ||
| micro_batch_size=1, | ||
| ), | ||
| validation=ValidationConfig( | ||
| eval_interval=100, | ||
| eval_iters=32, | ||
| ), | ||
| # Optimizer and scheduler | ||
| optimizer=opt_cfg, | ||
| scheduler=scheduler_cfg, | ||
| # DDP config - minimal settings, model-specific configs can override | ||
| ddp=DistributedDataParallelConfig( | ||
| check_for_nan_in_grad=True, | ||
| grad_reduce_in_fp32=True, | ||
| ), | ||
| # Dataset config - uses SQuAD with packed sequences by default | ||
| dataset=default_squad_config( | ||
| seq_length=seq_length, packed_sequence=packed_sequence, pad_seq_to_mult=pad_seq_to_mult | ||
| ), | ||
| # Logger config | ||
| logger=LoggerConfig( | ||
| log_interval=1, | ||
| tensorboard_dir=tensorboard_dir, | ||
| log_timers_to_tensorboard=True, | ||
| ), | ||
| # Tokenizer - placeholder, each recipe should set tokenizer_model | ||
| tokenizer=TokenizerConfig( | ||
| tokenizer_type="HuggingFaceTokenizer", | ||
| tokenizer_model=None, # Must be set by each recipe | ||
| ), | ||
| # Checkpoint config with pretrained_checkpoint support | ||
| checkpoint=CheckpointConfig( | ||
| save_interval=100, | ||
| save=checkpoint_dir, | ||
| load=checkpoint_dir, | ||
| pretrained_checkpoint=None, # Set to load from pretrained weights | ||
| ckpt_format="torch_dist", | ||
| fully_parallel_save=True, | ||
| ), | ||
| # RNG config - different seed from pretrain | ||
| rng=RNGConfig(seed=5678), | ||
| # Distributed init config | ||
| dist=DistributedInitConfig(), | ||
| comm_overlap=None, | ||
| # Mixed precision - bf16 by default | ||
| mixed_precision="bf16_mixed", | ||
| # No PEFT for full SFT | ||
| peft=None, | ||
| ) | ||
|
|
||
| return cfg | ||
|
|
||
|
|
||
| def _peft_common() -> ConfigContainer: | ||
| """Create a base PEFT (Parameter-Efficient Fine-Tuning) ConfigContainer with LoRA defaults. | ||
|
|
||
| This function returns a ConfigContainer template with sensible defaults for PEFT | ||
| using LoRA. The caller MUST set `cfg.model` and `cfg.tokenizer.tokenizer_model` | ||
| before use. | ||
|
|
||
| Key differences from full SFT: | ||
| - Higher learning rate (1e-4) suitable for adapter training | ||
| - LoRA enabled by default with standard settings (dim=32, alpha=32) | ||
| - Targets all linear layers: linear_qkv, linear_proj, linear_fc1, linear_fc2 | ||
|
|
||
| Returns: | ||
| ConfigContainer: Base configuration template for PEFT with LoRA. | ||
| """ | ||
| # Default output directories | ||
| base_output_dir = os.path.join(os.getcwd(), "nemo_experiments") | ||
| run_output_dir = os.path.join(base_output_dir, "default") | ||
| checkpoint_dir = os.path.join(run_output_dir, "checkpoints") | ||
| tensorboard_dir = os.path.join(run_output_dir, "tb_logs") | ||
|
|
||
| # Default sequence length for PEFT | ||
| seq_length = 2048 | ||
|
|
||
| # Packed sequence is enabled by default for training efficiency | ||
| # pad_seq_to_mult should be set to context_parallel_size * 2 if CP > 1 | ||
| packed_sequence = True | ||
| pad_seq_to_mult = 1 # Override in model config if context_parallel_size > 1 | ||
|
|
||
| # Optimizer and scheduler with higher LR for PEFT (only training adapters) | ||
| opt_cfg, scheduler_cfg = distributed_fused_adam_with_cosine_annealing( | ||
| lr_warmup_iters=50, | ||
| lr_decay_iters=None, # Defaults to train_iters during validation | ||
| max_lr=1e-4, # Higher LR for adapter training | ||
| min_lr=0.0, | ||
| adam_beta2=0.98, # Common for fine-tuning | ||
| ) | ||
|
|
||
| cfg = ConfigContainer( | ||
| # Model - MUST be set by each recipe before use | ||
| model=None, # type: ignore[arg-type] | ||
| # Training config - shorter training for PEFT | ||
| train=TrainingConfig( | ||
| train_iters=1000, | ||
| global_batch_size=128, | ||
| micro_batch_size=1, | ||
| ), | ||
| validation=ValidationConfig( | ||
| eval_interval=100, | ||
| eval_iters=32, | ||
| ), | ||
| # Optimizer and scheduler | ||
| optimizer=opt_cfg, | ||
| scheduler=scheduler_cfg, | ||
| # DDP config - minimal settings for PEFT | ||
| ddp=DistributedDataParallelConfig( | ||
| check_for_nan_in_grad=True, | ||
| grad_reduce_in_fp32=True, | ||
| ), | ||
| # Dataset config - uses SQuAD with packed sequences by default | ||
| dataset=default_squad_config( | ||
| seq_length=seq_length, packed_sequence=packed_sequence, pad_seq_to_mult=pad_seq_to_mult | ||
| ), | ||
| # Logger config | ||
| logger=LoggerConfig( | ||
| log_interval=1, | ||
| tensorboard_dir=tensorboard_dir, | ||
| log_timers_to_tensorboard=True, | ||
| ), | ||
| # Tokenizer - placeholder, each recipe should set tokenizer_model | ||
| tokenizer=TokenizerConfig( | ||
| tokenizer_type="HuggingFaceTokenizer", | ||
| tokenizer_model=None, # Must be set by each recipe | ||
| ), | ||
| # Checkpoint config with pretrained_checkpoint support | ||
| checkpoint=CheckpointConfig( | ||
| save_interval=100, | ||
| save=checkpoint_dir, | ||
| load=checkpoint_dir, | ||
| pretrained_checkpoint=None, # Set to load from pretrained weights | ||
| ckpt_format="torch_dist", | ||
| fully_parallel_save=True, | ||
| ), | ||
|
Comment on lines
+308
to
+315
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEFT base config fails validation without a pretrained checkpoint.
🛠️ Suggested fix checkpoint=CheckpointConfig(
save_interval=100,
save=checkpoint_dir,
load=checkpoint_dir,
- pretrained_checkpoint=None, # Set to load from pretrained weights
+ pretrained_checkpoint=checkpoint_dir, # Override with actual pretrained weights path
ckpt_format="torch_dist",
fully_parallel_save=True,
),🤖 Prompt for AI Agents |
||
| # RNG config - different seed from pretrain | ||
| rng=RNGConfig(seed=5678), | ||
| # Distributed init config | ||
| dist=DistributedInitConfig(), | ||
| comm_overlap=None, | ||
| # Mixed precision - bf16 by default | ||
| mixed_precision="bf16_mixed", | ||
| # LoRA config with standard defaults | ||
| peft=LoRA( | ||
| target_modules=["linear_qkv", "linear_proj", "linear_fc1", "linear_fc2"], | ||
| dim=32, | ||
| alpha=32, | ||
| dropout=0.0, | ||
| dropout_position="pre", | ||
| lora_A_init_method="xavier", | ||
| lora_B_init_method="zero", | ||
| a2a_experimental=False, | ||
| lora_dtype=None, # Uses model's dtype | ||
| ), | ||
| ) | ||
|
|
||
| return cfg | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we keep this as a separate var and use it for
model.seq_length,dataset.seq_length,dataset.packed_sequence_specs.packed_sequence_size?only one change to make if and when we change the value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes let me push a commit for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 18dab36