Source code for mstar.model.cosmos3.loader

"""Weight loading for the Cosmos3 generator backbone.

The published checkpoint is the diffusers ``transformer/`` layout: flat
``layers.N.*`` keys with unfused attention projections (``to_q/to_k/to_v`` for
the understanding pathway, ``add_q_proj/add_k_proj/add_v_proj`` for the
generation pathway) and ``_moe_gen``-suffixed GEN MLP/norms. Our backbone
module mirrors that layout one-to-one, so loading needs no key remapping and
no stacked-parameter fusion — only the unused text ``lm_head`` is dropped.
"""

from __future__ import annotations

import json
from pathlib import Path

import torch

# Checkpoint keys deliberately not loaded into the generator backbone. The
# text ``lm_head`` exists in the checkpoint (the understanding tower descends
# from a text LM) but is never used: generation emits flow velocity via
# ``proj_out``, so we do not build or load it.
DROP_KEYS: frozenset[str] = frozenset({"lm_head.weight"})


[docs] def cosmos3_name_remapper(name: str) -> str | None: """Map a checkpoint key to a backbone parameter path, or ``None`` to drop. Identity for every key the backbone owns; ``None`` for the intentional drop-list. Kept explicit so an unexpected checkpoint key surfaces as a coverage failure rather than being silently ignored. """ if name in DROP_KEYS: return None return name
[docs] def read_transformer_weight_keys(checkpoint_dir: str | Path) -> set[str]: """Return every tensor key declared by the ``transformer/`` shard index.""" tdir = Path(checkpoint_dir) / "transformer" index = tdir / "diffusion_pytorch_model.safetensors.index.json" if index.exists(): with open(index) as f: return set(json.load(f)["weight_map"].keys()) # Single-shard fallback: read tensor names from the safetensors header. shards = list(tdir.glob("*.safetensors")) if not shards: raise FileNotFoundError(f"no transformer weights found under {tdir}") from safetensors import safe_open keys: set[str] = set() for shard in shards: with safe_open(shard, framework="pt") as handle: keys.update(handle.keys()) return keys
def _transformer_shard_names(tdir: Path) -> list[str]: """Resolve the ``transformer/`` shard filenames. The diffusers checkpoint indexes its shards under ``diffusion_pytorch_model.safetensors.index.json`` (not the ``model.safetensors`` name the generic shard iterator assumes), so the shard list is read from that index; a single-file checkpoint is the fallback. """ index = tdir / "diffusion_pytorch_model.safetensors.index.json" if index.exists(): with open(index) as f: return sorted(set(json.load(f)["weight_map"].values())) shards = sorted(p.name for p in tdir.glob("*.safetensors")) if not shards: raise FileNotFoundError(f"no transformer weights found under {tdir}") return shards
[docs] def read_transformer_weight_shapes(checkpoint_dir: str | Path) -> dict[str, tuple[int, ...]]: """Return ``{key: shape}`` for every ``transformer/`` tensor by reading only the safetensors headers — no tensor data is materialized. Enables CPU-side shape verification of the meta-built backbone against the checkpoint. """ from safetensors import safe_open tdir = Path(checkpoint_dir) / "transformer" shapes: dict[str, tuple[int, ...]] = {} for shard in _transformer_shard_names(tdir): with safe_open(tdir / shard, framework="pt") as handle: for key in handle.keys(): shapes[key] = tuple(handle.get_slice(key).get_shape()) return shapes
[docs] def load_transformer_weights( model: torch.nn.Module, checkpoint_dir: str | Path, device: str = "cpu", ) -> set[str]: """Stream the ``transformer/`` shards into ``model`` and return loaded keys. Mirrors the meta-device + ``load_hf_weights`` path the other model packages use, but resolves the shard list from the diffusers ``diffusion_pytorch_model`` index (the generic iterator only knows the ``model.safetensors`` name). No stacked-parameter rules: the checkpoint's projections are unfused and match the backbone parameter names directly. Raises if any backbone parameter is left unfilled — the completeness guarantee bagel's loader also enforces. """ from mstar.model.loader import iter_safetensors_file, load_hf_weights tdir = Path(checkpoint_dir) / "transformer" shard_names = _transformer_shard_names(tdir) def _weights(): for shard in shard_names: yield from iter_safetensors_file(tdir / shard, device=device) loaded = load_hf_weights(model, _weights(), name_remapper=cosmos3_name_remapper) expected = set(dict(model.named_parameters()).keys()) missing = expected - loaded if missing: sample = sorted(missing)[:10] more = "…" if len(missing) > 10 else "" raise KeyError( f"Cosmos3 transformer load left {len(missing)} parameter(s) unfilled " f"from {tdir}: {sample}{more}" ) return loaded