Skip to main content

add-model

Add support for a new model family to Halo — the EP (expert-parallel) wrapper, the Liger coverage spec, router-balancing choice, and vendoring (with a removal-on-merge policy). USER-INVOKED ONLY. Use when the user asks to "add a new model", "support <model> for EP/MoE", "vendor a model not in transformers", "wire up Liger for <model>", or extend the model roster (the families listed in agent-docs/models/README.md). Mirrors agent-docs/models/adding-a-model.md.

Source facts

Repository
whitecircle/halo
Last source activity
September 28, 2026 at 21:59
Detected SKILL.md language
English
Stars
816
Forks
38

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
add-model
description
Add support for a new model family to Halo — the EP (expert-parallel) wrapper, the Liger coverage spec, router-balancing choice, and vendoring (with a removal-on-merge policy). USER-INVOKED ONLY. Use when the user asks to "add a new model", "support <model> for EP/MoE", "vendor a model not in transformers", "wire up Liger for <model>", or extend the model roster (the families listed in agent-docs/models/README.md). Mirrors agent-docs/models/adding-a-model.md.
disable-model-invocation
true
allowed-tools
["Read","Edit","Write","Grep","Glob","Bash"]
# Add a new model family Canonical guide: `agent-docs/models/adding-a-model.md` (read it) — it holds the wrapper hooks, every class attribute the machinery reads, and the layout→wrapper table. **`checklist.md`** carries the file-touch list, the traps and the commands; read it before editing. ## Checklist (overview) 1. **Dense or MoE?** Dense `AutoModelForCausalLM` / multimodal `AutoModelForImageTextToText` needs **no EP work** — plain FSDP works as is. Only MoE families need an EP wrapper. 2. **MoE → add an EP wrapper.** Create `src/distributed/expert_parallel/layers/<name>.py` subclassing `EPMoELayerBase` (`base_layer.py`) — or `EPSharedExpertsMoELayerBase`, `EPSeparateGluMoELayerBase`, `EPGroupLimitedMoELayerBase` where the family fits one. The base owns `__init__` and calls one hook per construction step (`_detect_hidden_dim`, `_init_routing`, `_init_shared_experts`, `_init_expert_compute`, `_init_expert_params`); the wrapper supplies `forward` and overrides only the hooks that differ. Dropping the file into `layers/` is the whole registration — `layers/roster.py` imports every module in the package. Set **both** class attrs: `HF_MODULE_NAMES` (the HF block class name(s) — `build_moe_layer_map()` in `patching.py` walks the subclass tree, so there is no map to edit) and `HF_MODEL_TYPES` (the checkpoint `model_type`(s) — without it sharded EP save is rejected and the offline merge resolver finds nothing). `EPExpertGatherMixin.__init_subclass__` (`expert_gather.py`) enforces a paired-override contract, each breach a `TypeError` at import: overriding `gather_expert_state_dict` requires also overriding `merge_shards_to_hf`; declaring `_PER_EXPERT_UNFUSED_KEYS` while overriding the gather, or resolving both it and `_HUB_PER_EXPERT_KEYS`, is refused. Reuse an existing wrapper if the expert-weight layout matches (layout→wrapper table in the guide). 3. **Liger coverage.** Add one `LigerFamilySpec` to `LIGER_FAMILY_SPECS` in `src/kernels/liger/families.py` — there is no per-family applier module; the builder (`src/kernels/liger/builder.py`) turns each spec into the applier the orchestrator dispatches. Name a role only where the kernel reproduces the family's forward exactly. A family upstream Liger already covers sets `delegates_to_upstream=True` and names only the roles it adds. 4. **Router balancing.** Leave `moe_balancing` at `auto` and make the family resolvable — the wrapper hooks and the export contract are in `checklist.md` → *Router balancing*. 5. **Not in transformers yet → vendor.** Copy `configuration_*.py` + `modeling_*.py` into `src/models/<name>/`, register the `Auto*` classes in a module of that package (never its `__init__.py` — package inits carry a docstring only), and trigger that module's import as a module-level side effect of `src/models/loading/model_preparation.py` (the module every loader imports before resolving an `Auto*` class). **Record the removal trigger** — the directory goes when upstream ships the family. A `trust_remote_code` model needs no vendoring: `apply_remote_code_compat_shims()` (`src/models/patches/remote_code_compat.py`) restores the transformers-v5 APIs those files call. 6. **Configs + tests.** Add `examples/sft/<family>/` YAMLs and the required tests: an EP-vs-FSDP equivalence test, a save-and-reload trainer test, a CPU support test, and the Liger numerics case. Exact files and commands in `checklist.md`. All execution (tests, loading) runs **inside the Docker image** — tools are on `PATH` (uv-built, no prefix); see `CLAUDE.md`. ## Sources of truth `agent-docs/models/adding-a-model.md` + `checklist.md` are the guide. The code is the **ultimate** authority: `src/distributed/expert_parallel/` (`base_layer.py`, `patching.py`, the existing `layers/*.py`), `src/kernels/liger/families.py`, and the HF `modeling_*.py` you are wrapping are what actually behave — when a doc, this skill, or memory disagrees, or you are unsure, read the real file before editing. (`CLAUDE.md`: docs-first, the code wins.) Related skill: `checkpoints` (the save/export format the new family must round-trip through — EP gather, per-expert layout, vLLM keys).
View on GitHub