This note outlines the process of adding a new model in the torchtitan repo. In most cases, new models should be added first under the torchtitan/experiments folder. For criteria of contributions, please see the Contributing Guidelines therein. In general, please adhere to the Guiding Principles of torchtitan.
For offline explorations, we recommend the same steps, unless otherwise noted.
Please refer to the Llama 3 folder as an example.
The folder should be organized as follows
model.py- NOTE: Please adhere to the guiding principles and write single-device model code.
- NOTE: We prioritize readability over flexibility. The preferred style is to not share modules among different models, except for the most common and complicated ones.
- Define a Model class inheriting from a base model (e.g.
Decoderfromtorchtitan/models/common/decoder.py). - The model class should contain a nested
Configdataclass (inheriting from the base model'sConfig) that holds all architecture hyperparameters.get_nparams_and_flops()will be used to understand model size and compute throughput.update_from_config()updates the model config from training configs (e.g. syncing seq_len, handling hardware-specific settings).
__init__()consumes theConfigto build the model.- Parameter initialization is handled by the
param_initsystem on each module'sConfig. Setparam_init(adict[str, Callable]mapping parameter names to init functions) on every sub-config in the model config registry.init_states()auto-recurses into all submodules, so manual recursive calls are not needed. Override_init_self_buffers()for device-aware buffer initialization (e.g., RoPE, MoE). - Add additional files to reduce the complexity of
model.pyif it grows too large or complex, e.g. moe.py to host theMoE,Router, andGroupedExpertsmodules.
state_dict_adapter.py- Inherit
BaseStateDictAdapterto implement state dict mappings betweentorchtitanmodel definition and other model definitions (e.g. from HuggingFace so that we can save / load model checkpoints in HF formats). - There are multiple ways such adapters could be used
- Checkpoint conversion scripts in
scripts/checkpoint_conversion/will use them to adapt state dicts containing non-shardedtorch.Tensoron CPU. - During training,
CheckpointManagerwill use them to adapt state dicts containing (potentially sharded)DTensoron GPUs to save / load checkpoints in HF format. - In post-training,
to_hf()helps convert a torchtitan model to HF model, which can be used for inference by other frameworks.
- Checkpoint conversion scripts in
- This is optional for offline exploration.
- Inherit
sharding.py- Define
set_<model>_sharding_spec(config, *, loss_parallel, enable_sp, ...)that populatessharding_specon eachModule.Configin the model config (embeddings, norms, attention, feed-forward, output). TP, SP, and inner-attentionLocalMapConfigplacements are expressed declaratively viaShardingConfiginstead of a runtimeparallelize_moduleplan. - Call the helper from
Model.Config.update_from_config()so placements depend on the trainer'sparallelismsettings. - Reuse shared helpers from
torchtitan/models/common/decoder_sharding.py(set_decoder_sharding_spec,set_dense_ffn_sharding,set_gqa_attention_sharding,norm_spec,dense_param_placement,dense_activation_placement) where possible.
- Define
parallelize.py- apply training techniques in the following order
model.parallelize(mesh)— auto-recursive declarative sharding driven bysharding_spec(TP, SP, attentionlocal_map). Replaces per-modelparallelize_moduleplan dicts.- (MoE models)
apply_moe_ep_tpfor expert-parallel + TP on MoE experts (not yet config-based). - activation checkpointing
torch.compile- FSDP / HSDP
- NOTE: currently CP support for language models is enabled via a context manager in
torchtitan/train.py. Ideally no extra work is needed to enable CP.
- apply training techniques in the following order
pipeline.py(optional if model size is small)- apply PP
__init__.py- A dictionary of the actual model configurations, of the type
[str: Model.Config]. - Define
model_registry(flavor)to return aModelSpec, consisting of- model name and flavor
- model config (a
Model.Configdataclass) - parallelizing function, pipelining function
- loss function builder
- state dict adapter
- Model name should be the same as the folder name, which should be added to
torchtitan/models/__init__.pyortorchtitan/experiments/__init__.py. - Read more on
ModelSpec.
- A dictionary of the actual model configurations, of the type
config_registry.py- Define one function for each training configuration (e.g.
llama3_debugmodel,llama3_8b,llama3_70b). - Each function returns a
Trainer.Config(or subclass) instance with all training settings. - Functions can derive from each other via mutation for variants (e.g. flex_attn, float8).
- These are selected at runtime via
--module <model_name> --config <function_name>.
- Define one function for each training configuration (e.g.
README.md- Include instructions to download tokenizers / encoders.
- Include instructions to download model checkpoints for continued pretraining or post training.
- Update the current status of development, including the supported features and coming features.
- This is optional for offline exploration.
- Numerics testing
- One way of doing this E2E is to load the same model checkpoint into the
torchtitanmodel and the HF model, and compare the model output given the same input. This assumes- HF implementation is correct.
- The correctness of a
torchtitanmodel and the corresponding state dict adapter together indicates the correctness of both.
- One way of doing this E2E is to load the same model checkpoint into the
- Loss converging
- If there is a verified baseline, compare the loss curves with the baseline.
- For comparisons within
torchtitan, see the guidelines.
- Performance benchmarking
- Please refer to the benchmarks folder.
- CI tests