
    ^j'#                         d Z ddlmZ ddlmZmZmZ ddlZddlm	Z	 ddl
mZmZ ddlmZ  G d de	j                        Zy)	zBase training task abstraction.

This module provides the base TrainingTask class that encapsulates a complete
forward pass including loss computation. Tasks return a dictionary with loss
components and outputs for logging.
    )nullcontext)AnyDictOptionalN)get_state_dictunwrap_model)
ModelEmaV3c                   @    e Zd ZdZ	 	 	 d(deej                     deej                     def fdZ	 fdZ
	 d)dee   d	d fd
Z	 	 d*dedee   d	eej                     fdZd+ded	eej                     fdZ	 	 	 d,dededeej                     d	ej                  fdZd	efdZ	 	 d*dedee   d	eej                     fdZd)dee   d	dfdZd+defdZd-deej                     ded	eej                     fdZd-deej                     ded	eeef   fdZ	 	 	 d.deeeef      dedeej                     ded	df
dZdefded	eeef   fd Z	 	 	 d/d!eeef   d"eeeef      deded	df
d#Z d$ Z!d%ejD                  d&ejD                  d	eeejD                  f   fd'Z# xZ$S )0TrainingTaska  Base class for training tasks.

    A training task encapsulates a complete forward pass including loss computation.
    Tasks return a dictionary containing the training loss and other components for logging.

    The returned dictionary must contain:
        - 'loss': The training loss for backward pass (required)
        - 'output': Model output/logits for metric computation (recommended)
        - Other task-specific loss components for logging (optional)

    Args:
        device: Device for task tensors/buffers (defaults to cpu)
        dtype: Dtype for task tensors/buffers (defaults to torch default)
        verbose: Enable info logging

    Example:
        >>> task = SomeTask(model, criterion, device=torch.device('cuda'))
        >>>
        >>> # Prepare for distributed training (if needed)
        >>> if distributed:
        >>>     task.prepare_distributed(device_ids=[local_rank])
        >>>
        >>> # Training loop
        >>> result = task(input, target)
        >>> result['loss'].backward()
    Ndevicedtypeverbosec                     t         |           ||nt        j                  d      | _        ||nt        j                         | _        || _        y )Ncpu)super__init__torchr   get_default_dtyper   r   )selfr   r   r   	__class__s       Y/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/timm/task/task.pyr   zTrainingTask.__init__-   sE     	 & 2fU8K#/UU5L5L5N
    c                      t        j                  d      j                  |i |}|j                  | _        |j                  | _        t        |   |i |S )zFMove task to device/dtype, keeping self.device and self.dtype in sync.r   )r   emptytor   r   r   )r   argskwargsdummyr   s       r   r   zTrainingTask.to8   sL    !A!!4262ll[[
wz4*6**r   
device_idsreturnc                     | S )a  Prepare task for distributed training.

        This method wraps trainable components in DistributedDataParallel (DDP)
        while leaving non-trainable components (like frozen teacher models) unwrapped.

        Should be called after task initialization but before training loop.

        Args:
            device_ids: List of device IDs for DDP (e.g., [local_rank])
            **ddp_kwargs: Additional arguments passed to DistributedDataParallel

        Returns:
            self (for method chaining)

        Example:
            >>> task = LogitDistillationTask(student, teacher, criterion)
            >>> task.compile()
            >>> task.prepare_distributed(device_ids=[args.local_rank])
         )r   r   
ddp_kwargss      r   prepare_distributedz TrainingTask.prepare_distributed?   s	    2 r   backendmodec                      y)a'  Compile hot task components before distributed wrapping.

        Subclasses should compile the train/eval modules that do the tensor
        work, not the outer task wrapper. The return value is the eval-facing
        compiled module/callable used by validation and checkpoint export.
        Nr"   r   r%   r&   compile_kwargss       r   compilezTrainingTask.compileZ   s     r   Femac                 :    |rt        | dd      S t        | d|       S )z1Return the module that owns trainable parameters.trainable_module_emaNtrainable_module)getattr)r   r+   s     r   get_trainable_modulez!TrainingTask.get_trainable_moduleh   s%    4!7>>t/66r   decay
use_warmupc                 `    t        | j                         f|||d|| _        | j                  S )z+Create an EMA copy of the trainable module.)r1   r2   r   )r	   r0   r-   )r   r1   r2   r   r   s        r   	setup_emazTrainingTask.setup_eman   sC     %/%%'%
!	%

 %
! (((r   c                 *    | j                  d      duS )z5Return whether this task has an EMA trainable module.Tr+   N)r0   )r   s    r   has_emazTrainingTask.has_ema   s    ((T(2$>>r   c                     | j                         syt        j                  | j                  d      f||d|| _        | j                  S )z3Compile the EMA eval model if one has been created.NTr6   )r%   r&   )r7   r   r*   get_eval_modeleval_model_emar(   s       r   compile_emazTrainingTask.compile_ema   sU     ||~#mmD)

 	
 """r   stepc                     | j                         r;| j                  d      j                  t        | j                               |       yy)z3Update EMA state from the current trainable module.Tr6   )r<   N)r7   r0   updater   )r   r<   s     r   
update_emazTrainingTask.update_ema   s@    <<>%%$%/66|DD]D]D_7`gk6l r   exclude_headc                     | j                         }|r!|j                         D cg c]  }| c}dd S |j                         S c c}w )z/Return parameters to use for gradient clipping.N)r0   
parameters)r   r@   r.   ps       r   get_clip_parametersz TrainingTask.get_clip_parameters   sI    446/::<=!A=crBB**,, >s   	Amodulec                 j    |0|rdnd}t        | |      rt        | |      S | j                  |      }|S )zReturn the eval model/callable used for validation.

        Checkpoint state_dict handling uses unwrap_model separately so DDP and
        compiled wrappers do not leak into saved keys.
        r:   
eval_modelr6   )hasattrr/   r0   )r   rF   r+   	eval_attrs       r   r9   zTrainingTask.get_eval_model   sB     >,/(\ItY'tY//..3.7Fr   c                     i S )z:Return task-owned state outside the eval model state_dict.r"   )r   rF   r+   s      r   get_task_statezTrainingTask.get_task_state   s    	r   statestrictc                      y)z8Load task-owned state outside the eval model state_dict.Nr"   )r   rM   rN   rF   r+   s        r   load_task_statezTrainingTask.load_task_state   s     r   c                     | j                  |      }|i S |rdnd}|rdnd}| j                  |      }|t        ||      i}|r|||<   |S )z3Return checkpoint state entries owned by this task.r6   state_dict_ema
state_dicttask_state_ema
task_state)r9   rL   r   )r   r+   	unwrap_fnrH   	model_keytask_keyrU   rM   s           r   get_checkpoint_statez!TrainingTask.get_checkpoint_state   sk     ((S(1
I(+$	'*#((S(1
N:yAB(E(Or   rS   rU   c                     | j                  |      }||rt        d      t        d      t        |      j                  ||       | j	                  |||       y)z-Load model and task-owned checkpoint entries.r6   Nz4Cannot load EMA checkpoint state before setup_ema().z3Cannot load checkpoint state without an eval model.)rN   )rN   r+   )r9   RuntimeErrorr   load_state_dictrP   )r   rS   rU   r+   rN   rH   s         r   load_checkpoint_statez"TrainingTask.load_checkpoint_state   se     ((S(1
"#YZZTUUZ 00F0KZC@r   c                 z    | j                         }| || urt        |d      r|j                         S t               S )zReturn a no-sync context for gradient accumulation.

        Tasks that wrap a trainable component with DDP delegate to that
        component's no_sync(). Non-distributed tasks use a no-op context.
        no_sync)r0   rI   r_   r   )r   rF   s     r   r_   zTrainingTask.no_sync   s=     **,&"49S>>##}r   inputtargetc                     t         )zPerform forward pass and compute loss.

        Args:
            input: Input tensor [B, C, H, W]
            target: Target labels [B]

        Returns:
            Dictionary with at least 'loss' key containing the training loss
        )NotImplementedError)r   r`   ra   s      r   forwardzTrainingTask.forward   s
     "!r   )NNT)N)inductorN)F)gH.?FN)NF)TNF)NFT)%__name__
__module____qualname____doc__r   r   r   r   boolr   r   listr$   strnnModuler*   r0   floatr4   r7   r;   intr?   rE   r9   r   r   rL   rP   r   rY   r]   r_   Tensorrd   __classcell__)r   s   @r   r   r      s   : .2+/ 		U\\*	 EKK(	 		+ *.  
	: &"& 3-
 
"))	7 7"))9L 7 "$-1	)) ) U\\*	) 
)"? ? &"&## 3-#
 
"))	#"mx} m m
- -Xbii%8 d W_`b`i`iWj Xbii%8 d W[\_ad\dWe   *.DcN+  RYY'	
  
 " 
c3h	, 48AS#XA !c3h0A 	A
 A 
A 	"<<" LL" 
c5<<	 	"r   r   )ri   
contextlibr   typingr   r   r   r   torch.nnrm   timm.utils.modelr   r   timm.utils.model_emar	   rn   r   r"   r   r   <module>rx      s3    # & &   9 +f"299 f"r   