| """ |
| model_factory.py — model config builder. |
| |
| The old presets dict hardcoded vocab_size and max_seq_len per architecture. |
| That coupled the model to a specific tokenizer and sequence length, which is |
| exactly the thing we're moving away from now that vocab is selectable |
| (32k vs 64k) and T may grow. |
| |
| New API: build_model_config(model_type, size, vocab_size, max_seq_len) returns |
| a ModelArgs with the architectural shape from the preset table and vocab_size |
| + max_seq_len from the caller. |
| """ |
|
|
| from llama3 import ModelArgs |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| ARCH_PRESETS: dict[str, dict[str, dict]] = { |
| "llama-iwslt": { |
| "124m": dict(n_layers=12, n_heads=12, dim=768, intermediate_size=4 * 768, n_kv_heads=12), |
| "500m": dict(n_layers=32, n_heads=16, dim=1024, intermediate_size=3072, n_kv_heads=4), |
| "978m": dict(n_layers=36, n_heads=20, dim=1280, intermediate_size=5120, n_kv_heads=4), |
| "1b": dict(n_layers=36, n_heads=20, dim=1280, intermediate_size=5120, n_kv_heads=4), |
| "2b": dict(n_layers=36, n_heads=32, dim=2048, intermediate_size=5120, n_kv_heads=8), |
| }, |
| } |
|
|
|
|
| def build_model_config( |
| model_type: str, |
| size: str, |
| vocab_size: int, |
| max_seq_len: int, |
| ) -> ModelArgs: |
| """Build a ModelArgs combining architectural preset + runtime vocab/seq_len.""" |
| if model_type not in ARCH_PRESETS: |
| raise ValueError(f"unknown model_type {model_type!r}; " |
| f"expected one of {list(ARCH_PRESETS)}") |
| if size not in ARCH_PRESETS[model_type]: |
| raise ValueError(f"unknown size {size!r} for {model_type}; " |
| f"expected one of {list(ARCH_PRESETS[model_type])}") |
| arch = ARCH_PRESETS[model_type][size] |
| return ModelArgs( |
| vocab_size=vocab_size, |
| max_seq_len=max_seq_len, |
| **arch, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| def load_model(model, path, load_dict_only=False): |
| """Load a model checkpoint into an already-constructed model. |
| |
| Handles both: |
| - new checkpoints saved by the new train.py (keys = state_dict layout) |
| - old checkpoints with torch.compile's '_orig_mod.' prefix |
| """ |
| import torch |
| ckpt = torch.load(path, map_location=torch.device("cpu"), weights_only=False) |
| sd = ckpt["model"] if "model" in ckpt else ckpt |
| |
| sd = {k.replace("_orig_mod.", ""): v for k, v in sd.items()} |
| |
| sd = {k.replace("module.", ""): v for k, v in sd.items()} |
| model.load_state_dict(sd) |
| step = ckpt.get("step", 0) if isinstance(ckpt, dict) else 0 |
| if not load_dict_only: |
| model.train() |
| return model, step |