def build_from_config(cfg: RunConfig, ) -> tuple[TrainingConfig, TrainingMethod, Any, int]:
"""Build method + dataloader from a v3 run config.
1. Instantiate each model in ``cfg.models`` via ``_target_``.
2. Resolve the method class from ``cfg.method["_target_"]``
and construct it with ``(cfg=cfg, role_models=...)``.
3. Return ``(training_args, method, dataloader, start_step)``.
"""
from fastvideo.train.models.base import ModelBase
# --- 1. Build role model instances ---
role_models: dict[str, ModelBase] = {}
for role, model_cfg in cfg.models.items():
model = instantiate(model_cfg, training_config=cfg.training)
if not isinstance(model, ModelBase):
raise TypeError(f"models.{role}._target_ must resolve to a "
f"ModelBase subclass, got {type(model).__name__}")
role_models[role] = model
# --- 2. Build method ---
method_cfg = dict(cfg.method)
method_target = str(method_cfg.pop("_target_"))
method_cls = resolve_target(method_target)
# The student model provides the dataloader.
student = role_models.get("student")
method = method_cls(
cfg=cfg,
role_models=role_models,
)
# --- 3. Gather dataloader and start_step ---
dataloader = (getattr(student, "dataloader", None) if student is not None else None)
start_step = int(getattr(student, "start_step", 0) if student is not None else 0)
return cfg.training, method, dataloader, start_step