|
| 1 | +# Megatron-Style BERT (`MegatronBertForMaskedLM`) Examples |
| 2 | + |
| 3 | +This directory contains example scripts for the Megatron-Bridge `BertBridge`, which converts |
| 4 | +between Hugging Face's `MegatronBertForMaskedLM` architecture and Megatron-Core's |
| 5 | +`megatron.core.models.bert.bert_model.BertModel`. |
| 6 | + |
| 7 | +The examples target `nvidia/megatron-bert-uncased-345m` (24 layers, 1024 hidden size, 345M |
| 8 | +parameters), NVIDIA's original Pre-LayerNorm BERT checkpoint. |
| 9 | + |
| 10 | +## Supported architecture: Pre-LayerNorm only |
| 11 | + |
| 12 | +`BertBridge` targets HF's **`MegatronBertForMaskedLM`** architecture (`transformers` model type |
| 13 | +`megatron-bert`), which is Pre-LayerNorm — LayerNorm is applied *before* self-attention and the |
| 14 | +MLP, matching Megatron-Core's `BertModel` exactly. |
| 15 | + |
| 16 | +> [!WARNING] |
| 17 | +> This bridge does **not** support vanilla `transformers.BertModel`-based checkpoints (e.g. |
| 18 | +> `bert-base-uncased`, `bert-large-uncased`, most BioBERT/SciBERT/etc. variants). Those are |
| 19 | +> **Post-LayerNorm** (LayerNorm applied after the residual add, as in the original BERT paper), |
| 20 | +> which is architecturally different from Megatron-Core's `BertModel`. Converting a Post-LN |
| 21 | +> checkpoint through this bridge would silently load weights into the wrong computational graph |
| 22 | +> and produce incorrect outputs with no error. If a HF config's `model_type` is `bert` rather than |
| 23 | +> `megatron-bert`, it is not supported here. |
| 24 | +
|
| 25 | +`MegatronBertForMaskedLM` also has no pooler/NSP head in this bridge (`add_binary_head=False`), |
| 26 | +matching how the masked-LM checkpoints are published. |
| 27 | + |
| 28 | +The bridge requires `hidden_act="gelu"` because Megatron-Core's BERT masked-LM head hardcodes |
| 29 | +GELU. Decoder and cross-attention configurations are not supported. |
| 30 | + |
| 31 | +## Obtaining a convertible checkpoint |
| 32 | + |
| 33 | +The `nvidia/megatron-bert-uncased-345m` Hugging Face repo only hosts tokenizer files — the |
| 34 | +weights must be downloaded from NVIDIA GPU Cloud (NGC) and converted to HF format first, using |
| 35 | +HF's own conversion script (this is a one-time step, unrelated to Megatron-Bridge): |
| 36 | + |
| 37 | + mkdir -p megatron-bert-uncased-345m-hf |
| 38 | + wget --content-disposition \ |
| 39 | + https://api.ngc.nvidia.com/v2/models/nvidia/megatron_bert_345m/versions/v0.1_uncased/zip \ |
| 40 | + -O megatron-bert-uncased-345m-hf/checkpoint.zip |
| 41 | + git clone https://github.com/huggingface/transformers.git |
| 42 | + git -C transformers checkout fe747d88a3296bd94d426db2717f232f9d4afdb7 |
| 43 | + uv run python transformers/src/transformers/models/megatron_bert/convert_megatron_bert_checkpoint.py \ |
| 44 | + megatron-bert-uncased-345m-hf/checkpoint.zip |
| 45 | + |
| 46 | +The upstream converter writes a pretraining checkpoint without the architecture metadata needed |
| 47 | +by `AutoBridge`. Normalize it to the masked-LM architecture and add the tokenizer assets before |
| 48 | +using the directory with Megatron Bridge: |
| 49 | + |
| 50 | + uv run python - <<'PY' |
| 51 | + from transformers import AutoTokenizer, MegatronBertForMaskedLM |
| 52 | + |
| 53 | + checkpoint_path = "megatron-bert-uncased-345m-hf" |
| 54 | + model = MegatronBertForMaskedLM.from_pretrained(checkpoint_path) |
| 55 | + model.save_pretrained(checkpoint_path, safe_serialization=True) |
| 56 | + tokenizer = AutoTokenizer.from_pretrained("nvidia/megatron-bert-uncased-345m") |
| 57 | + tokenizer.save_pretrained(checkpoint_path) |
| 58 | + PY |
| 59 | + |
| 60 | +This produces a self-contained config, weights, and tokenizer directory that can be used as |
| 61 | +`HF_MODEL_PATH` below. See |
| 62 | +the [`nvidia/megatron-bert-uncased-345m` model card](https://huggingface.co/nvidia/megatron-bert-uncased-345m) |
| 63 | +for full details, including the `-cased` variant. |
| 64 | + |
| 65 | +## Workspace Configuration |
| 66 | + |
| 67 | +All scripts use a `WORKSPACE` environment variable to define the base directory for checkpoints |
| 68 | +and results. By default, this is set to `/workspace`. |
| 69 | + |
| 70 | + export WORKSPACE=/your/custom/path |
| 71 | + export HF_MODEL_PATH=/path/to/converted/megatron-bert-uncased-345m-hf |
| 72 | + |
| 73 | +## Checkpoint Conversion |
| 74 | + |
| 75 | +See [conversion.sh](conversion.sh) for Hugging Face to Megatron import, Megatron to Hugging Face |
| 76 | +export, and round-trip validation. |
| 77 | + |
| 78 | + ./examples/models/bert/megatron-bert/conversion.sh |
| 79 | + |
| 80 | +## Inference (fill-mask) |
| 81 | + |
| 82 | +`MegatronBertForMaskedLM` has no `generate()` method, so "inference" here means masked-token |
| 83 | +prediction rather than text generation. See [inference.sh](inference.sh), which runs |
| 84 | +[fill_mask.py](fill_mask.py) against the original Hugging Face checkpoint and, if present, the |
| 85 | +round-tripped export from `conversion.sh`: |
| 86 | + |
| 87 | + TEXT="Paris is the [MASK] of France." ./examples/models/bert/megatron-bert/inference.sh |
| 88 | + |
| 89 | +`fill_mask.py` uses the Hugging Face `fill-mask` pipeline directly (no Megatron-Core forward |
| 90 | +pass) — its purpose is to sanity-check that a converted checkpoint still produces sensible |
| 91 | +predictions, not to benchmark Megatron inference throughput. |
0 commit comments