Spaces:
Running on L40S
Running on L40S
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: OpenMDW-1.1 | |
| import os | |
| from abc import ABC, abstractmethod | |
| from typing import Optional | |
| import torch | |
| from cosmos_framework.utils.config import CheckpointConfig, JobConfig | |
| from cosmos_framework.utils.flags import INTERNAL | |
| from cosmos_framework.model._base import ImaginaireModel | |
| from cosmos_framework.utils import callback | |
| from cosmos_framework.utils.easy_io import easy_io | |
| class AbstractCheckpointer(ABC): | |
| """The checkpointer class. Supports checkpoint saving/loading to both local disk or object store.""" | |
| def __init__( | |
| self, | |
| config_checkpoint: CheckpointConfig, | |
| config_job: JobConfig, | |
| callbacks: Optional[callback.CallBackGroup] = None, | |
| ): | |
| """Constructor of the checkpointer. | |
| Args: | |
| config_checkpoint (CheckpointConfig): The config object for the checkpointer. | |
| """ | |
| self.config_checkpoint = config_checkpoint | |
| # Set the callback functions. | |
| self.callbacks = callbacks | |
| self.save_to_object_store = config_checkpoint.save_to_object_store.enabled | |
| self.load_from_object_store = config_checkpoint.load_from_object_store.enabled | |
| # Set checkpoint directories for local and object store paths | |
| self._local_dirname = os.path.join(config_job.path_local, "checkpoints") | |
| self._object_store_dirname = os.path.join(config_job.path, "checkpoints") | |
| self.strict_resume = config_checkpoint.strict_resume | |
| load_path = config_checkpoint.load_path or None | |
| if not INTERNAL: | |
| from cosmos_framework.utils.checkpoint_db import download_checkpoint_v2 | |
| if load_path: | |
| load_path = download_checkpoint_v2(load_path) | |
| self.load_path = load_path | |
| self.load_training_state = config_checkpoint.load_training_state | |
| self.only_load_scheduler_state = config_checkpoint.only_load_scheduler_state | |
| self.save_thread = None | |
| self.verbose = config_checkpoint.verbose | |
| self.keys_not_to_resume = config_checkpoint.keys_not_to_resume | |
| self.keys_to_skip_loading = getattr(config_checkpoint, "keys_to_skip_loading", []) | |
| self.broadcast_via_filesystem = config_checkpoint.broadcast_via_filesystem | |
| # Create the object store client interface. | |
| if config_checkpoint.load_from_object_store.enabled: | |
| self.load_s3_backend_key = "_ckpt_s3_loader" | |
| easy_io.set_s3_backend( | |
| key="_ckpt_s3_loader", | |
| backend_args={ | |
| "backend": "s3", | |
| "path_mapping": { | |
| "s3://ckpt/": f"s3://{config_checkpoint.load_from_object_store.bucket}/", | |
| }, | |
| "s3_credential_path": config_checkpoint.load_from_object_store.credentials, | |
| }, | |
| ) | |
| else: | |
| self.load_s3_backend_key = None | |
| if config_checkpoint.save_to_object_store.enabled: | |
| self.save_s3_backend_key = "_ckpt_s3_saver" | |
| easy_io.set_s3_backend( | |
| key="_ckpt_s3_saver", | |
| backend_args={ | |
| "backend": "s3", | |
| "path_mapping": { | |
| "s3://ckpt/": f"s3://{config_checkpoint.save_to_object_store.bucket}/", | |
| }, | |
| "s3_credential_path": config_checkpoint.save_to_object_store.credentials, | |
| }, | |
| ) | |
| else: | |
| self.save_s3_backend_key = None | |
| def save( | |
| self, | |
| model: ImaginaireModel, | |
| optimizer: torch.optim.Optimizer, | |
| scheduler: torch.optim.lr_scheduler.LRScheduler, | |
| grad_scaler: torch.amp.GradScaler, | |
| iteration: int, | |
| ) -> None: | |
| pass | |
| def load( | |
| self, | |
| model: ImaginaireModel, | |
| optimizer: Optional[torch.optim.Optimizer] = None, | |
| scheduler: Optional[torch.optim.lr_scheduler.LRScheduler] = None, | |
| grad_scaler: Optional[torch.amp.GradScaler] = None, | |
| ) -> int: | |
| pass | |
| def save_bucket(self): | |
| """Get the bucket name for saving checkpoints.""" | |
| return self.config_checkpoint.save_to_object_store.bucket if self.save_to_object_store else None | |
| def load_bucket(self): | |
| """Get the bucket name for loading checkpoints.""" | |
| return self.config_checkpoint.load_from_object_store.bucket if self.load_from_object_store else None | |
| def save_dirname(self): | |
| return ( | |
| f"s3://{self.save_bucket}/{self._object_store_dirname}" | |
| if self.save_to_object_store | |
| else self._local_dirname | |
| ) | |
| def load_dirname(self): | |
| return ( | |
| f"s3://{self.load_bucket}/{self._object_store_dirname}" | |
| if self.load_from_object_store | |
| else self._local_dirname | |
| ) | |
| def finalize(self) -> None: | |
| """Finalize the checkpointer.""" | |
| if self.save_thread: | |
| self.save_thread.join() | |
| def _read_latest_checkpoint_file(self) -> str | None: | |
| """Get the file name of the latest saved checkpoint. If it doesn't exist, return None. | |
| Returns: | |
| checkpoint_file (str | None): file name of the latest saved checkpoint. | |
| """ | |
| checkpoint_file = None | |
| checkpoint_path = os.path.join(self.load_dirname, "latest_checkpoint.txt") | |
| if easy_io.exists(f"{checkpoint_path}", backend_key=self.load_s3_backend_key): | |
| checkpoint_file = easy_io.load(f"{checkpoint_path}", backend_key=self.load_s3_backend_key).strip() | |
| return checkpoint_file | |
| def has_resumable_checkpoint(self) -> bool: | |
| """True iff a ``latest_checkpoint.txt`` exists in the load directory.""" | |
| return self._read_latest_checkpoint_file() is not None | |
| def _write_latest_checkpoint_file(self, checkpoint_file: str) -> None: | |
| """Track the file name of the latest saved checkpoint. | |
| Args: | |
| checkpoint_file (str): file name of the latest saved checkpoint. | |
| """ | |
| content = f"{checkpoint_file}\n" | |
| checkpoint_path = os.path.join(self.save_dirname, "latest_checkpoint.txt") | |
| easy_io.dump( | |
| content, | |
| checkpoint_path, | |
| backend_key=self.save_s3_backend_key, | |
| ) | |
| def _check_checkpoint_exists(self, checkpoint_path: str) -> None: | |
| """If the file checkpoint_path does not exist, raise an error. | |
| Args: | |
| checkpoint_path (str): full path to the checkpoint. | |
| """ | |
| if not easy_io.exists(f"{checkpoint_path}", backend_key=self.load_s3_backend_key): | |
| raise FileNotFoundError(f"File not found (object store): {checkpoint_path}") | |