Skip to content

Commit e5c7b8c

Browse files
yaoyu-33claude
andauthored
[misc] feat: Add bidirectional MLM <-> MBridge config translation script (#2630)
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com> Signed-off-by: Yu Yao <yaoyu.094@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 80a8070 commit e5c7b8c

20 files changed

Lines changed: 3754 additions & 105 deletions

‎docs/megatron-lm-to-megatron-bridge.md‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,97 @@
22

33
Megatron Bridge is Python-first: configure models, data, and training via typed Python APIs. All configuration lives in a structured `ConfigContainer` (see [Configuration overview](training/config-container-overview.md)). Any field can be overridden from the command line using Hydra/OmegaConf syntax in the example training scripts.
44

5+
## Automated config translation script
6+
7+
`scripts/translate_mlm_to_bridge.py` translates bidirectionally between Megatron-LM `pretrain_gpt.py` CLI arguments and Megatron Bridge `run_recipe.py` Hydra overrides. It is useful for running loss-correlation experiments between the two frameworks and for migrating existing MLM configs.
8+
9+
### MLM → Bridge (default direction)
10+
11+
```bash
12+
# From a YAML config file (MODEL_ARGS section)
13+
python scripts/translate_mlm_to_bridge.py --yaml model_configs/DeepSeek-V3.yaml
14+
15+
# From inline CLI args
16+
python scripts/translate_mlm_to_bridge.py \
17+
--args "--num-layers 32 --hidden-size 4096 --num-attention-heads 32 --bf16 --swiglu"
18+
19+
# Emit a standalone Bridge recipe Python file (output goes to stdout; use -o to write to a file)
20+
python scripts/translate_mlm_to_bridge.py \
21+
--yaml DeepSeek-V3.yaml --emit recipe --recipe-name deepseek_v3
22+
23+
# Write output to a file instead of stdout
24+
python scripts/translate_mlm_to_bridge.py \
25+
--yaml DeepSeek-V3.yaml -o bridge_overrides.txt
26+
```
27+
28+
### Bridge → MLM (reverse direction)
29+
30+
```bash
31+
# From a Bridge recipe name (defaults exported as MLM args)
32+
python scripts/translate_mlm_to_bridge.py --reverse \
33+
--recipe llama32_1b_pretrain_config
34+
35+
# From a recipe plus inline overrides
36+
python scripts/translate_mlm_to_bridge.py --reverse \
37+
--recipe llama32_1b_pretrain_config \
38+
--args "train.train_iters=1000 model.tensor_model_parallel_size=2"
39+
40+
# From Bridge overrides only (no recipe)
41+
python scripts/translate_mlm_to_bridge.py --reverse \
42+
--args "model.num_layers=32 model.activation_func=silu model.gated_linear_unit=true"
43+
44+
# From a Bridge YAML/OmegaConf config file (e.g. exported ConfigContainer)
45+
python scripts/translate_mlm_to_bridge.py --reverse \
46+
--yaml bridge_config.yaml
47+
```
48+
49+
### Key mappings
50+
51+
| MLM flag | Bridge override | Notes |
52+
|---|---|---|
53+
| `--num-layers N` | `model.num_layers=N` | |
54+
| `--hidden-size N` | `model.hidden_size=N` | |
55+
| `--ffn-hidden-size N` | `model.ffn_hidden_size=N` | |
56+
| `--num-attention-heads N` | `model.num_attention_heads=N` | |
57+
| `--num-query-groups N` | `model.num_query_groups=N` | |
58+
| `--seq-length N` | `model.seq_length=N dataset.sequence_length=N` | Dual mapping |
59+
| `--swiglu` | `model.gated_linear_unit=true model.activation_func=silu` | Expanded to two keys |
60+
| `--squared-relu` | `model.activation_func=squared_relu` | |
61+
| `--data-path PATH [W PATH...]` | `dataset.data_path=PATH` | Space-separated paths (and optional weights) |
62+
| `--bf16` | `mixed_precision=bf16_mixed` | |
63+
| `--fp16` | `mixed_precision=16-mixed` | |
64+
| `--disable-bias-linear` | `model.add_bias_linear=false` | Inverted flag |
65+
| `--untie-embeddings-and-output-weights` | `model.share_embeddings_and_output_weights=false` | Inverted flag |
66+
| `--sequence-parallel` | `model.sequence_parallel=true` | |
67+
| `--tensor-model-parallel-size N` | `model.tensor_model_parallel_size=N` | |
68+
| `--pipeline-model-parallel-size N` | `model.pipeline_model_parallel_size=N` | |
69+
| `--context-parallel-size N` | `model.context_parallel_size=N` | |
70+
| `--micro-batch-size N` | `train.micro_batch_size=N` | |
71+
| `--global-batch-size N` | `train.global_batch_size=N` | |
72+
| `--train-iters N` | `train.train_iters=N` | |
73+
| `--lr LR` | `optimizer.lr=LR` | |
74+
| `--min-lr LR` | `optimizer.min_lr=LR` | |
75+
| `--weight-decay WD` | `optimizer.weight_decay=WD` | |
76+
| `--clip-grad CG` | `optimizer.clip_grad=CG` | |
77+
| `--lr-decay-style S` | `scheduler.lr_decay_style=S` | |
78+
| `--lr-warmup-iters N` | `scheduler.lr_warmup_iters=N` | |
79+
| `--seed S` | `rng.seed=S` | |
80+
| `--save PATH` | `checkpoint.save=PATH` | |
81+
| `--load PATH` | `checkpoint.load=PATH` | |
82+
| `--save-interval N` | `checkpoint.save_interval=N` | |
83+
| `--tokenizer-type T` | `tokenizer.tokenizer_type=T` | |
84+
| `--tokenizer-model M` | `tokenizer.tokenizer_model=M` | |
85+
| `--normalization N` | `model.normalization=N` | |
86+
| `--position-embedding-type T` | `model.position_embedding_type=T` | |
87+
| `--rotary-base N` | `model.rotary_base=N` | |
88+
| `--num-experts N` | `model.num_moe_experts=N` | |
89+
| `--moe-router-topk K` | `model.moe_router_topk=K` | |
90+
| `--mock-data` | `dataset.mock=true` | Use synthetic data (no files needed) |
91+
92+
Flags not present in Bridge (e.g., `--use-mcore-models`, `--use-flash-attn`) are silently skipped with a comment. `--mock-data` translates to `dataset.mock=true`. Unknown flags are listed in a separate section so you can handle them manually.
93+
94+
> **Activation function CLI overrides**: `model.activation_func` can now be set via Hydra CLI string override (e.g. `model.activation_func=silu`, `model.activation_func=gelu`). The string is resolved to the callable in `TransformerConfig.finalize()`. This makes `--swiglu` → `model.gated_linear_unit=true model.activation_func=silu` round-trippable from the CLI.
95+
596
## Quick start
697

798
Run your example training entrypoint and override config keys directly:

‎scripts/training/README.md‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,24 @@ All scripts dynamically import recipes from `megatron.bridge.recipes`, apply use
1414

1515
## Quick Start
1616

17-
For the end-to-end overview of how recipes are structured, overridden, and launched with either `torchrun` or NeMo-Run, see the official [Using Recipes guide](https://docs.nvidia.com/nemo/megatron-bridge/latest/recipe-usage.html).
17+
For the end-to-end overview of how recipes are structured, overridden, and launched, see the official [Using Recipes guide](https://docs.nvidia.com/nemo/megatron-bridge/latest/recipe-usage.html).
1818

19-
### Pretrain
19+
### Pretrain (single-GPU)
2020

2121
```bash
22-
torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_pretrain_config
22+
uv run python run_recipe.py --recipe llama32_1b_pretrain_config
23+
```
24+
25+
### Pretrain (multi-GPU)
26+
27+
```bash
28+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_pretrain_config
2329
```
2430

2531
### Finetune
2632

2733
```bash
28-
torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_sft_config
34+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_sft_config
2935
```
3036

3137
## Usage with Different Models
@@ -34,24 +40,24 @@ Same scripts work across all model families:
3440

3541
```bash
3642
# Llama
37-
torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_pretrain_config
43+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe llama32_1b_pretrain_config
3844

3945
# Gemma
40-
torchrun --nproc_per_node=8 run_recipe.py --recipe gemma3_1b_pretrain_config
46+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe gemma3_1b_pretrain_config
4147

4248
# Qwen
43-
torchrun --nproc_per_node=8 run_recipe.py --recipe qwen3_8b_pretrain_config
49+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe qwen3_8b_pretrain_config
4450

4551
# GPT
46-
torchrun --nproc_per_node=8 run_recipe.py --recipe gpt_126m_pretrain_config
52+
uv run torchrun --nproc_per_node=8 run_recipe.py --recipe gpt_126m_pretrain_config
4753
```
4854

4955
## CLI Overrides
5056

5157
Override any config field using dot notation:
5258

5359
```bash
54-
torchrun --nproc_per_node=8 run_recipe.py \
60+
uv run torchrun --nproc_per_node=8 run_recipe.py \
5561
--recipe llama32_1b_pretrain_config \
5662
train.train_iters=5000 \
5763
optimizer.lr=0.0002 \
@@ -76,7 +82,7 @@ Use `--step_func` to control the step function used during training. Available o
7682
- `llava_step` - LLaVA models
7783

7884
```bash
79-
torchrun --nproc_per_node=8 run_recipe.py \
85+
uv run torchrun --nproc_per_node=8 run_recipe.py \
8086
--recipe qwen25_vl_pretrain_config \
8187
--step_func vlm_step
8288
```

‎scripts/training/run_recipe.py‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,35 @@
2121
CLI overrides.
2222
2323
Usage:
24-
Pretrain:
25-
torchrun --nproc_per_node=8 run_recipe.py \
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 \
2630
--recipe llama32_1b_pretrain_config
2731
2832
SFT (full finetuning):
29-
torchrun --nproc_per_node=8 run_recipe.py \
33+
uv run torchrun --nproc_per_node=8 run_recipe.py \
3034
--recipe llama32_1b_sft_config
3135
3236
PEFT (LoRA/DoRA):
33-
torchrun --nproc_per_node=8 run_recipe.py \
37+
uv run torchrun --nproc_per_node=8 run_recipe.py \
3438
--recipe llama32_1b_peft_config
3539
3640
With CLI overrides:
37-
torchrun --nproc_per_node=8 run_recipe.py \
41+
uv run torchrun --nproc_per_node=8 run_recipe.py \
3842
--recipe llama32_1b_pretrain_config \
3943
train.train_iters=5000 \
4044
optimizer.lr=0.0003
4145
4246
With VLM step function:
43-
torchrun --nproc_per_node=8 run_recipe.py \
47+
uv run torchrun --nproc_per_node=8 run_recipe.py \
4448
--recipe qwen25_vl_finetune_config \
4549
--step_func vlm_step
4650
4751
With packed sequences and custom sequence length:
48-
torchrun --nproc_per_node=8 run_recipe.py \
52+
uv run torchrun --nproc_per_node=8 run_recipe.py \
4953
--recipe llama32_1b_pretrain_config \
5054
--packed_sequence \
5155
--seq_length 2048

0 commit comments

Comments
 (0)