1818
1919This script works with any model family that uses GPT-style training
2020(Llama, Gemma, Qwen, GPT, etc.). It dynamically loads recipes and supports
21- CLI overrides.
21+ CLI overrides. The --dataset flag selects the dataset type and automatically
22+ infers pretrain vs finetune mode.
2223
2324Usage:
24- Pretrain (single-GPU):
25- uv run python run_recipe.py \
26- --recipe llama32_1b_pretrain_config
27-
28- Pretrain (multi-GPU):
29- uv run torchrun --nproc_per_node=8 run_recipe.py \
30- --recipe llama32_1b_pretrain_config
31-
32- SFT (full finetuning):
33- uv run torchrun --nproc_per_node=8 run_recipe.py \
34- --recipe llama32_1b_sft_config
35-
36- PEFT (LoRA/DoRA):
37- uv run torchrun --nproc_per_node=8 run_recipe.py \
38- --recipe llama32_1b_peft_config
39-
40- With CLI overrides:
41- uv run torchrun --nproc_per_node=8 run_recipe.py \
42- --recipe llama32_1b_pretrain_config \
43- train.train_iters=5000 \
25+ Pretrain (mock data):
26+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
27+ --recipe llama32_1b_pretrain_config \\
28+ --dataset llm-pretrain-mock
29+
30+ Pretrain (real data):
31+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
32+ --recipe llama32_1b_pretrain_config \\
33+ --dataset llm-pretrain \\
34+ 'dataset.blend=[[/data/my_dataset_text_document],null]'
35+
36+ Finetune (SQuAD, default):
37+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
38+ --recipe llama32_1b_sft_config \\
39+ --dataset llm-finetune
40+
41+ Finetune (GSM8K):
42+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
43+ --recipe llama32_1b_sft_config \\
44+ --dataset llm-finetune \\
45+ dataset.dataset_name=gsm8k
46+
47+ Finetune (user-supplied JSONL):
48+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
49+ --recipe llama32_1b_sft_config \\
50+ --dataset llm-finetune-preloaded \\
51+ dataset.dataset_root=/data/my_finetune_data
52+
53+ VLM with HF dataset:
54+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
55+ --recipe qwen3_vl_8b_peft_config \\
56+ --dataset vlm-hf \\
57+ --step_func qwen3_vl_step \\
58+ dataset.maker_name=cord_v2 \\
59+ dataset.hf_processor_path=Qwen/Qwen3-VL-8B-Instruct \\
60+ checkpoint.pretrained_checkpoint=/path/to/checkpoint
61+
62+ VLM with Energon dataset:
63+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
64+ --recipe qwen3_vl_8b_peft_energon_config \\
65+ --dataset vlm-energon \\
66+ --step_func qwen3_vl_step \\
67+ dataset.path=/data/energon \\
68+ checkpoint.pretrained_checkpoint=/path/to/checkpoint
69+
70+ VLM with preloaded JSON:
71+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
72+ --recipe qwen3_vl_8b_peft_config \\
73+ --dataset vlm-preloaded \\
74+ --step_func qwen3_vl_step \\
75+ dataset.train_data_path=/data/vlm_train.json \\
76+ dataset.image_folder=/data/vlm_images \\
77+ dataset.hf_processor_path=Qwen/Qwen3-VL-8B-Instruct \\
78+ checkpoint.pretrained_checkpoint=/path/to/checkpoint
79+
80+ With CLI overrides (Hydra-style, works for any config field):
81+ uv run torchrun --nproc_per_node=8 run_recipe.py \\
82+ --recipe llama32_1b_pretrain_config \\
83+ --dataset llm-pretrain-mock \\
84+ train.train_iters=5000 \\
4485 optimizer.lr=0.0003
4586
46- With VLM step function:
47- uv run torchrun --nproc_per_node=8 run_recipe.py \
48- --recipe qwen25_vl_finetune_config \
49- --step_func vlm_step
50-
51- With packed sequences and custom sequence length:
52- uv run torchrun --nproc_per_node=8 run_recipe.py \
53- --recipe llama32_1b_pretrain_config \
54- --packed_sequence \
55- --seq_length 2048
56-
5787Recipe Arguments:
5888 Generic scripts call recipes with no arguments: recipe().
5989
6797
6898import megatron .bridge .recipes as recipes
6999from megatron .bridge .models .qwen_vl .qwen3_vl_step import forward_step as qwen3_vl_forward_step
100+ from megatron .bridge .recipes .utils .dataset_utils import (
101+ DATASET_TYPES ,
102+ apply_dataset_override ,
103+ infer_mode_from_dataset ,
104+ )
70105from megatron .bridge .training .config import ConfigContainer
71106from megatron .bridge .training .finetune import finetune
72107from megatron .bridge .training .gpt_step import forward_step as gpt_forward_step
83118 "llava_step" : llava_forward_step ,
84119}
85120
86- TRAIN_MODES = {
121+ TRAIN_FUNCTIONS = {
87122 "pretrain" : pretrain ,
88123 "finetune" : finetune ,
89124}
90125
91- # Error message constants
92126ERR_UNKNOWN_STEP = "Unknown step type: {step_type}. Choose from: {choices}"
93127ERR_INFER_MODE_FAILED = (
94- "Unable to infer training mode from recipe name. "
95- "Please include 'pretrain', 'sft', 'peft', or 'finetune' in the recipe name or pass --mode explicitly."
128+ "Unable to infer training mode. "
129+ "Pass --dataset to specify the dataset type, or include 'pretrain' or 'finetune' "
130+ "(or 'sft'/'peft') in the recipe name."
96131)
97132
98133
@@ -102,19 +137,30 @@ def parse_args() -> tuple[argparse.Namespace, list[str]]:
102137 description = "Generic training script for GPT-based models" ,
103138 formatter_class = argparse .RawTextHelpFormatter ,
104139 )
105- parser .add_argument (
106- "--mode" ,
107- type = str ,
108- default = None ,
109- choices = sorted (TRAIN_MODES .keys ()),
110- help = "Training mode (optional). If omitted, inferred from recipe name." ,
111- )
112140 parser .add_argument (
113141 "--recipe" ,
114142 type = str ,
115143 required = True ,
116144 help = "Recipe function name (e.g., llama32_1b_pretrain_config, gemma3_1b_sft_config, gemma3_1b_peft_config)" ,
117145 )
146+ parser .add_argument (
147+ "--dataset" ,
148+ type = str ,
149+ default = None ,
150+ choices = DATASET_TYPES ,
151+ help = (
152+ "Dataset type. Training mode (pretrain/finetune) is inferred from this.\n "
153+ "LLM datasets:\n "
154+ " llm-pretrain GPT pretrain data (set dataset.blend=<path>)\n "
155+ " llm-pretrain-mock Mock pretrain data for testing\n "
156+ " llm-finetune HF finetune dataset (set dataset.dataset_name=squad|gsm8k|openmathinstruct2)\n "
157+ " llm-finetune-preloaded User-supplied JSONL (set dataset.dataset_root=<path>)\n "
158+ "VLM datasets:\n "
159+ " vlm-energon Energon multimodal (set dataset.path=<path>)\n "
160+ " vlm-hf HF VLM dataset (set dataset.maker_name=<name>)\n "
161+ " vlm-preloaded User-supplied VLM JSON (set dataset.train_data_path=<path>)"
162+ ),
163+ )
118164 parser .add_argument (
119165 "--step_func" ,
120166 type = str ,
@@ -227,7 +273,7 @@ def load_forward_step(step_type: str) -> Callable:
227273
228274
229275def infer_train_mode (recipe_name : str ) -> str :
230- """Infer training mode from the recipe name."""
276+ """Infer training mode from the recipe name (fallback when --dataset is not passed) ."""
231277 lowered = recipe_name .lower ()
232278 has_pretrain = "pretrain" in lowered
233279 has_finetune = "finetune" in lowered or "sft" in lowered or "peft" in lowered
@@ -248,15 +294,35 @@ def main() -> None:
248294 args .hf_path ,
249295 )
250296
297+ if args .dataset is not None :
298+ mode = infer_mode_from_dataset (args .dataset )
299+ config = apply_dataset_override (
300+ config ,
301+ dataset_type = args .dataset ,
302+ packed_sequence = args .packed_sequence ,
303+ seq_length = args .seq_length ,
304+ cli_overrides = cli_overrides ,
305+ )
306+ else :
307+ mode = infer_train_mode (args .recipe )
308+
251309 config = process_config_with_overrides (
252310 config ,
253311 cli_overrides = cli_overrides or None ,
254312 )
255313
256- mode = args .mode or infer_train_mode (args .recipe )
314+ # Ensure dataset.seq_length and model.seq_length stay in sync after CLI overrides
315+ if (
316+ hasattr (config , "model" )
317+ and config .model is not None
318+ and hasattr (config , "dataset" )
319+ and config .dataset is not None
320+ ):
321+ if hasattr (config .dataset , "seq_length" ) and config .model .seq_length != config .dataset .seq_length :
322+ config .model .seq_length = config .dataset .seq_length
257323
258324 forward_step = load_forward_step (args .step_func )
259- train_func = TRAIN_MODES [mode ]
325+ train_func = TRAIN_FUNCTIONS [mode ]
260326 train_func (config = config , forward_step_func = forward_step )
261327
262328
0 commit comments