Rate this Page

Source code for torchrl.checkpoint._hydra

# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import annotations

import importlib.util
from collections.abc import Sequence
from pathlib import Path
from typing import TYPE_CHECKING

from torchrl._utils import logger as torchrl_logger
from torchrl.checkpoint._checkpoint import Checkpoint

if TYPE_CHECKING:
    from omegaconf import DictConfig

_has_omegaconf = importlib.util.find_spec("omegaconf") is not None
_has_hydra = importlib.util.find_spec("hydra") is not None

_CONFIG_COMPONENT = "config"


[docs] def resume_config( cfg: DictConfig, checkpoint_path: str | Path, *, overrides: Sequence[str] | None = None, ) -> DictConfig: """Return the configuration of a run resumed from ``checkpoint_path``. The configuration saved with the checkpoint under its ``config`` component is the base and ``overrides`` are applied on top, so ``resume=<path>`` alone rebuilds the original run while ``resume=<path> collector.total_frames=...`` extends it. Interpolations survive because recipes save the configuration unresolved. Config-group overrides such as ``logger@logger=csv``, deletions (``~key``) and bare flags cannot be applied to a saved configuration and are ignored with a warning. When the checkpoint holds no ``config`` component, ``cfg`` is returned unchanged with a warning. Args: cfg (DictConfig): the configuration composed for the current run. checkpoint_path (str or Path): the checkpoint being resumed. overrides (Sequence[str], optional): ``key=value`` overrides applied over the saved configuration. Defaults to the task overrides of the current Hydra run, or none outside a Hydra application. Returns: The configuration to run. Examples: >>> import tempfile >>> from omegaconf import OmegaConf # doctest: +SKIP >>> from torchrl.checkpoint import Checkpoint, resume_config >>> saved = {"budget": 100, "trainer": {"total_frames": "${budget}"}} >>> with tempfile.TemporaryDirectory() as tmpdir: # doctest: +SKIP ... path = Checkpoint(config=saved).save(f"{tmpdir}/checkpoint") ... cfg = resume_config( ... OmegaConf.create({"budget": 5}), path, overrides=["budget=200"] ... ) >>> cfg.trainer.total_frames # doctest: +SKIP 200 """ if not _has_omegaconf: raise ImportError("resume_config requires omegaconf.") from omegaconf import OmegaConf if overrides is None: overrides = _hydra_task_overrides() if _CONFIG_COMPONENT not in Checkpoint.manifest(checkpoint_path)["components"]: torchrl_logger.warning( "Checkpoint %s has no saved configuration; the current configuration " "is used as is.", checkpoint_path, ) return cfg base = OmegaConf.create( Checkpoint.read_component(checkpoint_path, _CONFIG_COMPONENT) ) dotlist = [] for override in overrides: key, separator, value = override.partition("=") if key.startswith("~") or not separator: torchrl_logger.warning( "Override %r is ignored on resume: only key=value overrides apply " "to a saved configuration.", override, ) continue key = key.lstrip("+") if "@" in key or "/" in key: torchrl_logger.warning( "Config-group override %r cannot be applied to a saved " "configuration and is ignored on resume.", override, ) continue dotlist.append(f"{key}={value}") if not dotlist: return base return OmegaConf.merge(base, OmegaConf.from_dotlist(dotlist))
def _hydra_task_overrides() -> list[str]: if not _has_hydra: return [] from hydra.core.hydra_config import HydraConfig try: return list(HydraConfig.get().overrides.task) except ValueError: # Not running under @hydra.main. return []