441 lines
13 KiB
Markdown
441 lines
13 KiB
Markdown
# AGENTS.md
|
|
|
|
This repository is the reproducible Laoyao 2B MoE pretraining project. It refactors the original hand-written Laoyao training experiment into a Megatron/NVIDIA NeMo style workflow with explicit data construction, tokenizer choice, model definition, training launchers, checkpoint handling, and inference/export tooling.
|
|
|
|
Use this file as the first entry point when operating the repo as an agent.
|
|
|
|
## Repository Purpose
|
|
|
|
The project trains a small MoE language model for practice and infrastructure validation:
|
|
|
|
- Model family: Laoyao 2B MoE.
|
|
- Training backend: Megatron-Bridge / Megatron-Core inside a NeMo 26.06 based Docker image.
|
|
- Tokenizer: GLM-5.2 tokenizer from `zai-org/GLM-5.2`.
|
|
- Main training length: `seq_length=8192`.
|
|
- Main data target: approximately 200B tokens with rebalanced category mix.
|
|
- Main validation: heldout 2.8k public task/dialogue set, converted to Megatron indexed validation data on the training host.
|
|
|
|
The repo is designed to keep source code, manifests, configs, and docs in git while keeping generated corpora, checkpoints, tensorboard logs, and model exports out of git.
|
|
|
|
## Directory Structure
|
|
|
|
- `dataset/`
|
|
- `pretrain/`: pretraining data construction scripts, configs, manifests, and README.
|
|
- `val/`: heldout 2.8k validation data in source JSONL forms and docs.
|
|
- `model/`
|
|
- Megatron/NeMo model architecture config and architecture documentation.
|
|
- `training/`
|
|
- Megatron-Bridge pretraining recipe and training docs.
|
|
- `docker/`
|
|
- NeMo/Megatron Docker image definition and backend notes.
|
|
- `scripts/`
|
|
- Shell entrypoints for data setup, tokenization, Docker image build, training, resume, inference server, and query smoke tests.
|
|
- `tools/`
|
|
- Checkpoint inspection, Megatron DCP probes, HF export, and HF custom model generation tools.
|
|
- `docs/`
|
|
- Case studies and operational notes, especially Megatron-to-HF export pitfalls.
|
|
- `runs/`
|
|
- Runtime outputs, checkpoints, logs, tensorboard files, and exports. Ignored by git.
|
|
|
|
## Important Hosts and Paths
|
|
|
|
Current g0050 training repo:
|
|
|
|
```bash
|
|
/ssd/workspace/yi/laoyao_2b_moe
|
|
```
|
|
|
|
Current g0033 mirror/dev repo:
|
|
|
|
```bash
|
|
/mnt/beegfs/yi/laoyao_2b_moe
|
|
```
|
|
|
|
Current g0050 pretokenized data root:
|
|
|
|
```bash
|
|
/ssd/workspace/yi/laoyao_2b_moe_pretraining_dataset
|
|
```
|
|
|
|
Current main run:
|
|
|
|
```bash
|
|
/ssd/workspace/yi/laoyao_2b_moe/runs/pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000
|
|
```
|
|
|
|
## Data Construction
|
|
|
|
The pretraining target mix is:
|
|
|
|
| Category | Target Ratio | Notes |
|
|
|---|---:|---|
|
|
| `english_web` | 40% | English web text, FineWeb/Ultra-FineWeb style sources. |
|
|
| `english_edu` | 20% | Educational English text; also fills science shortfall when needed. |
|
|
| `chinese_clean` | 10% | Clean Chinese web/text data. |
|
|
| `science` | 10% | Science QA/reasoning sources; may be much smaller in available raw data. |
|
|
| `logic` | 10% | Proof-Pile-2/OpenWebMath/arXiv/AlgebraicStack style high-reasoning text. |
|
|
| `math` | 5% | Math data from cleaned/scored sources. |
|
|
| `code` | 5% | Cleaned multilingual code data. |
|
|
|
|
Core source scripts:
|
|
|
|
- `dataset/pretrain/scripts/download_rebalanced_sources.py`
|
|
- `dataset/pretrain/scripts/build_rebalanced_pretrain_dataset.py`
|
|
- `dataset/pretrain/scripts/wait_and_build_rebalanced_pretrain_200b.sh`
|
|
- `dataset/pretrain/scripts/convert_pretrain_parquet_to_megatron.py`
|
|
|
|
Current g0050 tokenization entrypoint:
|
|
|
|
```bash
|
|
bash scripts/g0050_wait_and_tokenize_glm52_8192.sh
|
|
```
|
|
|
|
This waits for ModelScope parquet downloads, checks a minimum parquet count, then calls:
|
|
|
|
```bash
|
|
bash scripts/preprocess_megatron_bridge_pretrain_direct.sh
|
|
```
|
|
|
|
Important conversion behavior:
|
|
|
|
- Converts parquet directly to Megatron indexed dataset `.bin/.idx` without intermediate JSONL.
|
|
- Uses GLM-5.2 tokenizer from `tokenizer/glm5.2`.
|
|
- Uses `MAX_SEQ_LEN=8192` by default.
|
|
- Writes `manifest.json` with `ok_prefixes` that already include the correct `_text_document` prefix.
|
|
- Writes or consumes `prefix_category_stats.json` when available so training can weight shards by category target mix.
|
|
|
|
Generated Megatron indexed datasets are not committed to git.
|
|
|
|
## Validation Data
|
|
|
|
Source validation data lives in:
|
|
|
|
```bash
|
|
dataset/val/data/
|
|
```
|
|
|
|
It contains a 2,800-example heldout set with seven categories:
|
|
|
|
- `science_reasoning`
|
|
- `logic`
|
|
- `code`
|
|
- `chinese_exam`
|
|
- `math`
|
|
- `chinese_dialogue`
|
|
- `english_dialogue`
|
|
|
|
The training job expects a generated Megatron indexed validation prefix on g0050:
|
|
|
|
```bash
|
|
dataset/val/megatron_8192_glm52/heldout_2p8k_text_document
|
|
```
|
|
|
|
This generated directory is ignored by git. If missing, rebuild it from `dataset/val/data/heldout_2p8k_packed_text.jsonl` using the same GLM-5.2 tokenizer and Megatron indexed dataset writer.
|
|
|
|
## Model Definition
|
|
|
|
The active model implementation is in:
|
|
|
|
```bash
|
|
training/megatron_bridge/laoyao_2b_moe_pretrain.py
|
|
```
|
|
|
|
Key architecture settings:
|
|
|
|
- `num_layers=12`
|
|
- `hidden_size=1536`
|
|
- `num_attention_heads=24`
|
|
- `num_query_groups=4`
|
|
- GQA attention.
|
|
- `ffn_hidden_size=4608` for dense MLP layers.
|
|
- MoE layers at layer indices `{2, 4, 6, 8, 10}`.
|
|
- `num_moe_experts=12`
|
|
- `moe_router_topk=4`
|
|
- `moe_ffn_hidden_size=6144`
|
|
- `moe_router_load_balancing_type="aux_loss"`
|
|
- `moe_aux_loss_coeff=0.02`
|
|
- `moe_z_loss_coeff=0.001`
|
|
- `moe_token_dispatcher_type="alltoall"`
|
|
- `moe_expert_capacity_factor=1.25`
|
|
- `moe_grouped_gemm=True` unless disabled by CLI.
|
|
- `share_embeddings_and_output_weights=True`.
|
|
- `vocab_size=154856`.
|
|
- `normalization="RMSNorm"`, `rms_norm_eps` is Megatron default/runtime aligned.
|
|
- RoPE is Megatron non-interleaved / NeoX half-split style.
|
|
- Attention backend is configured as `flash` through Transformer Engine.
|
|
|
|
The static YAML config is documented under:
|
|
|
|
```bash
|
|
model/nemo_megatron/
|
|
```
|
|
|
|
However, the currently exercised training path is the Python Megatron-Bridge recipe.
|
|
|
|
## Training
|
|
|
|
Current primary resume/training entrypoint on g0050:
|
|
|
|
```bash
|
|
cd /ssd/workspace/yi/laoyao_2b_moe
|
|
bash scripts/resume_pretrain_8192_8gpu_mbs14.sh
|
|
```
|
|
|
|
Main long-run defaults:
|
|
|
|
- Image: `laoyao/nemo-megatron:26.06-flashattn4`
|
|
- Container: `laoyao_pretrain_resume`
|
|
- Data manifest: `/ssd/workspace/yi/laoyao_2b_moe_pretraining_dataset/megatron_bridge/pretrain_8192_glm52_direct_v1/manifest.json`
|
|
- Validation prefix: `dataset/val/megatron_8192_glm52/heldout_2p8k_text_document`
|
|
- `train_iters=184209`
|
|
- `seq_length=8192`
|
|
- `micro_batch_size=14`
|
|
- `global_batch_size=112`
|
|
- `tensor_parallel=1`
|
|
- `pipeline_parallel=1`
|
|
- `expert_parallel=1`
|
|
- `context_parallel=1`
|
|
- `dataset_workers=4`
|
|
- `save_interval=2500`
|
|
- `keep_last_checkpoints=10`
|
|
- `eval_interval=15000`
|
|
- `eval_iters=10`
|
|
- `distributed optimizer` enabled.
|
|
- `overlap_grad_reduce` enabled.
|
|
- `overlap_param_gather` enabled.
|
|
- full activation recompute enabled with `recompute_method=uniform` and `recompute_num_layers=1`.
|
|
|
|
The training recipe logs throughput/MFU-like TFLOP metrics, loss, load balancing loss, z-loss, grad norm, and validation perplexity/loss when validation runs.
|
|
|
|
## Docker Environment
|
|
|
|
Docker files and docs live under:
|
|
|
|
```bash
|
|
docker/nemo/
|
|
```
|
|
|
|
Build entrypoint:
|
|
|
|
```bash
|
|
bash scripts/build_nemo_megatron_image.sh
|
|
```
|
|
|
|
The current image is:
|
|
|
|
```text
|
|
laoyao/nemo-megatron:26.06-flashattn4
|
|
```
|
|
|
|
The image is based on NVIDIA NeMo 26.06 / Megatron-Bridge 0.5.0 style stack and includes flash-attn4/cutlass-related fixes for B300/H200 compatibility. Avoid changing CUDA/NVIDIA stack casually during an active training run.
|
|
|
|
## Resume, Kill, and Status
|
|
|
|
Status check:
|
|
|
|
```bash
|
|
docker ps --format '{{.Names}} {{.Status}} {{.Image}}' | grep -E 'laoyao_pretrain|tensorboard' || true
|
|
nvidia-smi --query-gpu=index,memory.used,utilization.gpu,power.draw --format=csv,noheader,nounits
|
|
awk '/^[[:space:]]*\[[0-9][0-9][0-9][0-9]-.* iteration[[:space:]]+[0-9]+\// {print}' \
|
|
/tmp/laoyao_pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000_resume.log | tail -12
|
|
```
|
|
|
|
Resume training:
|
|
|
|
```bash
|
|
bash scripts/resume_pretrain_8192_8gpu_mbs14.sh
|
|
```
|
|
|
|
Stop training container:
|
|
|
|
```bash
|
|
docker rm -f laoyao_pretrain_resume
|
|
```
|
|
|
|
Before killing, prefer checking the latest checkpoint:
|
|
|
|
```bash
|
|
cat runs/pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000/checkpoints/latest_checkpointed_iteration.txt
|
|
ls -1dt runs/pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000/checkpoints/iter_* | head
|
|
```
|
|
|
|
The separate infra handoff scripts may also exist at:
|
|
|
|
```bash
|
|
/ssd/workspace/yi/infra_handoff/laoyao_infra_scripts
|
|
```
|
|
|
|
If those exist, read their `AGENTS.md` before interrupting a long run for infra users.
|
|
|
|
## Evaluation
|
|
|
|
During training, validation runs every `15000` iterations by default using the heldout 2.8k Megatron indexed validation prefix.
|
|
|
|
Expected metrics:
|
|
|
|
- validation LM loss
|
|
- validation PPL
|
|
- training loss
|
|
- load balancing loss
|
|
- z-loss
|
|
- grad norm
|
|
- throughput / TFLOP/s/GPU
|
|
|
|
TensorBoard output is under the active run directory:
|
|
|
|
```bash
|
|
runs/pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000/tensorboard
|
|
```
|
|
|
|
Do not commit TensorBoard logs.
|
|
|
|
## HF Heldout 2.8k Evaluation
|
|
|
|
After exporting a checkpoint to HF format, run:
|
|
|
|
```bash
|
|
python3 tools/hf_laoyao_moe/eval_heldout_2p8k.py \
|
|
--model-dir runs/hf_exports/iter_0107500 \
|
|
--data dataset/val/data/heldout_2p8k_sft_prompt_completion.jsonl \
|
|
--out-dir runs/hf_eval/heldout_2p8k/iter_0107500 \
|
|
--device cuda \
|
|
--max-length 2048
|
|
```
|
|
|
|
For CPU smoke tests, use a very small sample count:
|
|
|
|
```bash
|
|
python3 tools/hf_laoyao_moe/eval_heldout_2p8k.py \
|
|
--model-dir runs/hf_exports/iter_0107500 \
|
|
--max-items 4 \
|
|
--device cpu \
|
|
--dtype float32 \
|
|
--max-length 512
|
|
```
|
|
|
|
This evaluation follows the tokenizer-swap heldout logic:
|
|
|
|
- Compute prompt-conditioned completion NLL/PPL for all 2.8k examples.
|
|
- Parse MCQ choices only where the prompt has explicit `A.`/`B.`/... choices and the gold completion starts with the answer label.
|
|
- Score each MCQ choice as a continuation.
|
|
- Main accuracy is `mcq_acc_avg_norm`, based on average token logprob.
|
|
- `mcq_acc_sum` is auxiliary and can favor shorter choices.
|
|
|
|
Do not treat all 2.8k examples as MCQ. The set also includes GSM8K, HumanEval/MBPP style code, Chinese dialogue, and English dialogue examples.
|
|
|
|
## Model Weight Exporting
|
|
|
|
The HF export tools are under:
|
|
|
|
```bash
|
|
tools/hf_laoyao_moe/
|
|
```
|
|
|
|
Export command template:
|
|
|
|
```bash
|
|
python3 tools/hf_laoyao_moe/convert_laoyao_dcp_to_hf.py \
|
|
--checkpoint-dir runs/pretrain_8192_8gpu_dp8_mbs14_full_recompute_weighted_heldoutval_resume10000/checkpoints/iter_0107500 \
|
|
--tokenizer-dir tokenizer/glm5.2 \
|
|
--output-dir runs/hf_exports/iter_0107500
|
|
```
|
|
|
|
The export writes:
|
|
|
|
- `model.safetensors`
|
|
- `config.json`
|
|
- tokenizer files
|
|
- HF custom model files
|
|
|
|
Important export/inference alignment details:
|
|
|
|
- HF custom model must use `use_cache=false`; KV cache is not implemented.
|
|
- RMSNorm epsilon must match Megatron runtime, currently `1e-5`.
|
|
- RoPE must match Megatron non-interleaved / NeoX half-split layout.
|
|
- MoE router should account for `moe_expert_capacity_factor=1.25` token dropping behavior.
|
|
- HF dynamic module imports must be relative imports.
|
|
|
|
Read the case study before changing export logic:
|
|
|
|
```bash
|
|
docs/megatron_to_hf_export_notes.md
|
|
```
|
|
|
|
## Inference
|
|
|
|
Megatron-native inference server scripts:
|
|
|
|
```bash
|
|
bash scripts/check_laoyao_megatron_inference_ready.sh
|
|
bash scripts/serve_laoyao_megatron.sh
|
|
bash scripts/query_laoyao_megatron_server.sh
|
|
bash scripts/stop_laoyao_megatron_server.sh
|
|
```
|
|
|
|
The Megatron server is the more trustworthy inference baseline because it uses the native Megatron model stack. HF export is useful for portability and debugging but is not the highest-performance inference path.
|
|
|
|
HF custom model generation after export:
|
|
|
|
```bash
|
|
python3 tools/hf_laoyao_moe/generate_laoyao_hf.py \
|
|
--model-dir runs/hf_exports/iter_0107500 \
|
|
--device cuda \
|
|
--max-new-tokens 32 \
|
|
--prompt "The capital of France is"
|
|
```
|
|
|
|
The HF generation script disables KV cache by default. Do not remove that unless KV cache support has been implemented and tested.
|
|
|
|
## Git and Artifact Policy
|
|
|
|
Commit and push:
|
|
|
|
```bash
|
|
git status --short
|
|
git add <source/docs/scripts only>
|
|
git commit -m "..."
|
|
git push origin main
|
|
```
|
|
|
|
Do not commit:
|
|
|
|
- `runs/`
|
|
- checkpoints
|
|
- TensorBoard logs
|
|
- generated `.bin/.idx` pretraining datasets
|
|
- generated validation Megatron indexed data
|
|
- HF exported weights
|
|
- local caches or `__pycache__`
|
|
|
|
When pushing from g0050, export the machine proxy if direct access fails:
|
|
|
|
```bash
|
|
export http_proxy=http://100.72.0.101:8888
|
|
export https_proxy=http://100.72.0.101:8888
|
|
export HTTP_PROXY=http://100.72.0.101:8888
|
|
export HTTPS_PROXY=http://100.72.0.101:8888
|
|
```
|
|
|
|
When pulling on g0033, use its proxy configuration if needed:
|
|
|
|
```bash
|
|
export http_proxy=http://10.20.34.2:3128
|
|
export https_proxy=http://10.20.34.2:3128
|
|
export HTTP_PROXY=http://10.20.34.2:3128
|
|
export HTTPS_PROXY=http://10.20.34.2:3128
|
|
```
|
|
|
|
## Quick Sanity Checks Before Handoff
|
|
|
|
Run these before claiming the repo is ready:
|
|
|
|
```bash
|
|
bash -n scripts/*.sh
|
|
PYTHONPYCACHEPREFIX=/tmp/laoyao_pycache_check python3 -m py_compile \
|
|
dataset/pretrain/scripts/convert_pretrain_parquet_to_megatron.py \
|
|
training/megatron_bridge/laoyao_2b_moe_pretrain.py \
|
|
tools/*.py tools/hf_laoyao_moe/*.py
|
|
```
|
|
|
|
If `py_compile` fails due to permission denied under `__pycache__`, set `PYTHONPYCACHEPREFIX` as above instead of deleting unrelated cache files.
|