Spaces:
Running on L40S
Running on L40S
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: OpenMDW-1.1 | |
| """Convert DCP checkpoint to Hugging Face model.""" | |
| from cosmos_framework.inference.common.init import init_script | |
| init_script( | |
| env={ | |
| "COSMOS_DEVICE": "cpu", | |
| "COSMOS_TRAINING": "1", | |
| } | |
| ) | |
| import json | |
| from pathlib import Path | |
| from typing import Annotated, Any, Callable | |
| import attrs | |
| import safetensors.torch | |
| import torch.distributed.checkpoint as dcp | |
| import tyro | |
| from torch.distributed.checkpoint.filesystem import FileSystemReader | |
| from torch.distributed.checkpoint.state_dict import StateDictOptions, get_model_state_dict | |
| from cosmos_framework.checkpoint.dcp import CustomLoadPlanner | |
| from cosmos_framework.checkpoint.s3_filesystem import S3StorageReader | |
| from cosmos_framework.configs.base.defaults.model_config import OmniMoTModelConfig | |
| from cosmos_framework.inference.common.args import ( | |
| CheckpointOverrides, | |
| ParallelismOverrides, | |
| ResolvedPath, | |
| tyro_cli, | |
| ) | |
| from cosmos_framework.inference.common.checkpoints import register_checkpoints | |
| from cosmos_framework.inference.common.config import serialize_config_dict | |
| from cosmos_framework.inference.common.init import is_rank0 | |
| from cosmos_framework.inference.common.public_model_config import build_public_model_config | |
| from cosmos_framework.inference.model import Cosmos3OmniConfig, Cosmos3OmniModel | |
| from cosmos_framework.model.vfm.omni_mot_model import OmniMoTModel | |
| from cosmos_framework.utils import log | |
| from cosmos_framework.utils.checkpoint_db import CheckpointConfig, sanitize_uri | |
| from cosmos_framework.utils.lazy_config.registry import convert_target_to_string | |
| _INTERNAL_VISUAL_PREFIX = "model.net.language_model.visual." | |
| _EXPORTED_VISUAL_PREFIX = "model.visual." | |
| def _coerce_to_base_model(model_dict: dict[str, Any]) -> None: | |
| """For distillation training configs, rewrite the target to the base | |
| OmniMoTModel so the exported checkpoint only contains the student network.""" | |
| target = model_dict.get("_target_", "") | |
| if "OmniMoTModel" in target: | |
| return | |
| log.info(f"Overriding model target from {target} to OmniMoTModel for export") | |
| model_dict["_target_"] = convert_target_to_string(OmniMoTModel) | |
| config = model_dict["config"] | |
| base_field_names = {f.name for f in attrs.fields(OmniMoTModelConfig)} | |
| extra_keys = [k for k in config if k not in base_field_names and not k.startswith("_")] | |
| for k in extra_keys: | |
| del config[k] | |
| metadata = config.get("_metadata", {}) | |
| metadata["object_type"] = convert_target_to_string(OmniMoTModelConfig) | |
| config["_metadata"] = metadata | |
| class Args(ParallelismOverrides): | |
| checkpoint: CheckpointOverrides = CheckpointOverrides.model_construct() | |
| output_dir: Annotated[ResolvedPath, tyro.conf.arg(aliases=("-o",))] | |
| """Output model directory.""" | |
| config_only: bool = False | |
| """If True, only export config.""" | |
| vit: bool = True | |
| """If True, export ViT weights.""" | |
| def _load_safetensor_weights(model_dir: Path, predicate: Callable[[str], bool]) -> dict: | |
| """Load weights from a safetensors file.""" | |
| index_path = model_dir / "model.safetensors.index.json" | |
| if index_path.exists(): | |
| with open(index_path) as f: | |
| weight_map = json.load(f)["weight_map"] | |
| shards = {v for k, v in weight_map.items() if predicate(k)} | |
| vision_weights = {} | |
| for shard in shards: | |
| tensors = safetensors.torch.load_file(model_dir / shard) | |
| vision_weights.update({k: v for k, v in tensors.items() if predicate(k)}) | |
| else: | |
| tensors = safetensors.torch.load_file(model_dir / "model.safetensors") | |
| vision_weights = {k: v for k, v in tensors.items() if predicate(k)} | |
| return vision_weights | |
| def _rewrite_visual_fqns_for_vfm(state_dict: dict[str, Any]) -> dict[str, Any]: | |
| """Map HF visual tower FQNs to OmniMoTModel's internal visual tower FQNs.""" | |
| remapped_state_dict = {} | |
| for key, value in state_dict.items(): | |
| if key.startswith(_EXPORTED_VISUAL_PREFIX): | |
| key = _INTERNAL_VISUAL_PREFIX + key[len(_EXPORTED_VISUAL_PREFIX) :] | |
| remapped_state_dict[key] = value | |
| return remapped_state_dict | |
| def export_model(args: Args): | |
| register_checkpoints() | |
| checkpoint_args = args.checkpoint.build_checkpoint(checkpoints={}) | |
| args.output_dir.mkdir(parents=True, exist_ok=True) | |
| # Load config | |
| log.info("Loading config...") | |
| model_dict = checkpoint_args.load_model_config_dict() | |
| if not model_dict["config"]["ema"]["enabled"]: | |
| checkpoint_args.use_ema_weights = False | |
| model_dict["config"]["ema"]["enabled"] = False | |
| # Download VLM checkpoint | |
| if args.vit: | |
| vlm_checkpoint_path = model_dict["config"]["vlm_config"]["pretrained_weights"]["backbone_path"] | |
| vlm_checkpoint_path = sanitize_uri(vlm_checkpoint_path) | |
| checkpoint: CheckpointConfig | None = CheckpointConfig.maybe_from_uri(vlm_checkpoint_path) | |
| if checkpoint is None: | |
| raise ValueError(f"Invalid checkpoint path: {vlm_checkpoint_path}") | |
| vlm_checkpoint_path = checkpoint.hf.download() | |
| else: | |
| vlm_checkpoint_path = None | |
| # Load model | |
| log.info("Loading model...") | |
| _coerce_to_base_model(model_dict) | |
| hf_config = Cosmos3OmniConfig(model=build_public_model_config(model_dict)) | |
| hf_config.save_pretrained(args.output_dir) | |
| hf_model = Cosmos3OmniModel(hf_config) | |
| # Save model | |
| log.info("Saving model...") | |
| if not args.config_only: | |
| # Load checkpoint | |
| if checkpoint_args.checkpoint_path.startswith("s3://"): | |
| storage_reader = S3StorageReader( | |
| credential_path=checkpoint_args.credential_path, | |
| path=checkpoint_args.checkpoint_path, | |
| ) | |
| else: | |
| storage_reader = FileSystemReader(checkpoint_args.checkpoint_path) | |
| state_dict = get_model_state_dict(hf_model.model) | |
| dcp.load( | |
| state_dict=state_dict, | |
| storage_reader=storage_reader, | |
| planner=CustomLoadPlanner( | |
| load_ema_to_reg=checkpoint_args.use_ema_weights, | |
| ), | |
| ) | |
| state_dict = get_model_state_dict( | |
| hf_model, | |
| options=StateDictOptions( | |
| full_state_dict=True, | |
| cpu_offload=True, | |
| ), | |
| ) | |
| if not is_rank0(): | |
| return | |
| # Load ViT from VLM checkpoint | |
| if args.vit: | |
| assert vlm_checkpoint_path is not None | |
| vit_state_dict = _load_safetensor_weights( | |
| Path(vlm_checkpoint_path), lambda x: x.startswith("model.visual.") | |
| ) | |
| assert vit_state_dict, "No vision weights found" | |
| state_dict.update(_rewrite_visual_fqns_for_vfm(vit_state_dict)) | |
| # Save checkpoint | |
| hf_model.save_pretrained( | |
| args.output_dir, | |
| state_dict=state_dict, | |
| ) | |
| # Re-write 'config.json' to apply replacements. | |
| hf_config_file = args.output_dir / "config.json" | |
| hf_config_json = json.loads(hf_config_file.read_text()) | |
| hf_config_json["model_type"] = "cosmos3_omni" | |
| serialize_config_dict(hf_config_json, hf_config_file) | |
| # Write 'checkpoint.json' last to indicate that the model is complete. | |
| serialize_config_dict(checkpoint_args.model_dump(mode="json"), args.output_dir / "checkpoint.json") | |
| print(f"Saved model to {args.output_dir}") | |
| def main(): | |
| args = tyro_cli(Args, description=__doc__, config=(tyro.conf.OmitArgPrefixes,)) | |
| export_model(args) | |
| if __name__ == "__main__": | |
| main() | |