Source code for protomotions.agents.peft.utils.model_state
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""Model-state loading rules for discrete-prior PEFT checkpoints.
The agent should not need to know why a missing key is acceptable. This module
owns those low-level checkpoint rules and exposes one readable entry point:
load a PEFT model state if it is adapter-only or a compatible full training
checkpoint.
"""
from __future__ import annotations
from collections.abc import Iterable
from torch import nn
from protomotions.agents.peft.utils.adapter_state import is_adapter_state_key
from protomotions.agents.utils.normalization import (
materialize_lazy_running_stats_from_state_dict,
)
REFERENCE_FULL_CHECKPOINT_PREFIXES = (
"_actor.prior_with_peft.reference_prior.",
"_actor.prior_with_peft.reference_film_input_norm.",
)
[docs]
def has_reference_state(model_state: dict) -> bool:
"""Return True when a full PEFT checkpoint carries reference-policy state."""
return any(
key.startswith("_actor.prior_with_peft.reference_prior.")
or key.startswith("prior_with_peft.reference_prior.")
or key.startswith("_actor.prior_with_peft.reference_film_input_norm.")
or key.startswith("prior_with_peft.reference_film_input_norm.")
for key in model_state
)
[docs]
def load_compatible_peft_model_state(
module: nn.Module,
model_state: dict,
) -> None:
"""Load adapter-only state or a compatible full PEFT training checkpoint."""
if is_adapter_only_model_state(model_state):
module._actor.load_adapter_state_dict(model_state, strict=True)
return
reference_state_present = has_reference_state(model_state)
if reference_state_present:
module._actor.prior_with_peft.ensure_reference_modules()
materialize_lazy_running_stats_from_state_dict(module, model_state)
missing, unexpected = module.load_state_dict(model_state, strict=False)
optional_prefixes = optional_full_checkpoint_state_prefixes(module)
if reference_state_present:
optional_prefixes = tuple(
prefix
for prefix in optional_prefixes
if prefix not in REFERENCE_FULL_CHECKPOINT_PREFIXES
)
bad_missing = [key for key in missing if not key.startswith(optional_prefixes)]
bad_unexpected = [
key for key in unexpected if not key.startswith(optional_prefixes)
]
if bad_missing or bad_unexpected:
raise RuntimeError(
"Unexpected PEFT model state_dict mismatch: "
f"missing={bad_missing}, unexpected={bad_unexpected}"
)
if reference_state_present:
module._actor.prior_with_peft.mark_reference_loaded()
[docs]
def optional_full_checkpoint_state_prefixes(module: nn.Module) -> tuple[str, ...]:
"""Return state_dict prefixes that are optional for full PEFT checkpoints.
Each module owns the optional state it introduces by defining
``optional_full_checkpoint_state_prefixes()`` with local state_dict
prefixes. This helper qualifies those local prefixes by walking
``named_modules()``, keeping checkpoint compatibility rules close to the
modules that create the state instead of centralizing private path strings.
"""
prefixes: list[str] = []
for module_name, submodule in module.named_modules():
hook = getattr(submodule, "optional_full_checkpoint_state_prefixes", None)
if not callable(hook):
continue
base = f"{module_name}." if module_name else ""
for prefix in _as_prefix_tuple(hook()):
prefixes.append(f"{base}{prefix}")
return tuple(dict.fromkeys(prefixes))
def _as_prefix_tuple(prefixes: str | Iterable[str]) -> tuple[str, ...]:
result = (prefixes,) if isinstance(prefixes, str) else tuple(prefixes)
if not all(isinstance(prefix, str) for prefix in result):
raise TypeError("optional checkpoint state prefixes must be strings.")
return result
[docs]
def is_adapter_only_model_state(model_state: dict) -> bool:
"""Return True when every checkpoint entry is adapter/task state."""
return bool(model_state) and all(is_adapter_state_key(key) for key in model_state)