Source code for protomotions.agents.fine_tuning.pretrained_modules
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""Mixin for agents that load frozen modules before model construction."""
from __future__ import annotations
import logging
from typing import Dict
import torch
from torch import nn
from protomotions.agents.common.pretrained import load_pretrained_model_module
log = logging.getLogger(__name__)
[docs]
class PretrainedModulesMixin:
"""Load configured frozen modules through the BaseAgent setup lifecycle.
The mixin is intentionally independent of the training algorithm. PPO-style
fine-tuning and supervised fine-tuning can both populate ``self.pretrained``
before ``create_model()`` and then drop that temporary handle after the model
captures the modules it needs.
"""
pretrained: Dict[str, nn.Module]
def _before_create_model(self) -> None:
super()._before_create_model()
self.pretrained = self._load_pretrained_modules()
def _after_model_reset(self) -> None:
self._post_create_model_hook()
self.pretrained = {}
if torch.cuda.is_available():
torch.cuda.empty_cache()
super()._after_model_reset()
def _after_create_optimizers(self) -> None:
self._print_param_info()
super()._after_create_optimizers()
def _pretrained_module_configs(self):
"""Return the config mapping consumed by ``_load_pretrained_modules``."""
return self.config.pretrained_modules
def _pretrained_module_load_kwargs(self, _name, _pretrained_config) -> dict:
"""Return per-module keyword arguments for ``load_pretrained_model_module``."""
return {}
def _load_pretrained_modules(self) -> Dict[str, nn.Module]:
configs = self._pretrained_module_configs()
modules: Dict[str, nn.Module] = {}
for name, pretrained_config in configs.items():
log.info(
"Loading pretrained module '%s' from %s (module_path=%s)",
name,
pretrained_config.checkpoint_path or "<embedded module_config>",
pretrained_config.module_path,
)
modules[name] = load_pretrained_model_module(
pretrained_config,
device=self.fabric.device,
**self._pretrained_module_load_kwargs(name, pretrained_config),
)
return modules
def _post_create_model_hook(self) -> None:
"""Hook called after create_model(), device transfer, and model reset."""
def _print_param_info(self) -> None:
"""Optional hook for trainable/frozen parameter diagnostics."""