
    ^j1                    N   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ dd	lmZmZ erdd
lmZ ddlmZ i Ze ed       G d d                    Z G d d      Z ed      Z	 d	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZdddZ ej4                         Zd dZddddZy)!z
Contains the logic for automatic additional output capture with our forward decorators.
This mostly describe the hooks used and the logic to make capture thread/context safe.
    )annotationsN)
ContextVar)	dataclasswraps)TYPE_CHECKING   )is_torchdynamo_compilingrequires)nn   PreTrainedModel)torch)backendsc                  T    e Zd ZU dZded<   dZded<   dZded	<   dZded
<   dZded<   y)OutputRecordera  
    Configuration for recording outputs from a model via hooks.

    Attributes:
        target_class (Type): The class (e.g., nn.Module) to which the hook will be attached.
        index (Optional[int]): If the output is a tuple/list, optionally record only at a specific index.
        layer_name (Optional[str]): Name of the submodule to target (if needed), e.g., "transformer.layer.3.attn".
        class_name (Optional[str]): Name of the class to which the hook will be attached. Could be the suffix of class name in some cases.
        capture_initial_hidden_state  (bool): Whether to prepend the first module's input as the initial hidden state.
    ztype[nn.Module]target_classr   intindexN
str | None
layer_name
class_nameTboolcapture_initial_hidden_state)	__name__
__module____qualname____doc____annotations__r   r   r   r        n/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/transformers/utils/output_capturing.pyr   r   '   s7    	 "!E3N!J
!!J
!)- $-r"   r   c                  (    e Zd ZdZd Zd Zd Zd Zy)CompileableContextVara  
    Convenience wrapper around a ContextVar for usage with `torch.compile`.
    This behaves exactly as a `ContextVar`, except when compilation is triggered in which case it behaves as a simple
    global variable. This is useful as `torch.compile` cannot trace the `get` method of `ContextVar`. This however means
    that the access to the underlying variable is not thread-safe when compilation is triggered.
    c                D    t        |d       | _        d | _        d| _        y )N)defaultF)r   context_var
global_var	compiling)selfnames     r#   __init__zCompileableContextVar.__init__D   s    %dD9r"   c                f    | j                   r| j                  S | j                  j                         S N)r*   r)   r(   get)r+   s    r#   r0   zCompileableContextVar.getI   s(    >>??"##''))r"   c                j    t               r|| _        d| _        y | j                  j	                  |      S )NT)r
   r)   r*   r(   set)r+   values     r#   r2   zCompileableContextVar.setP   s0    #%#DO!DN##''..r"   c                t    | j                   s|d | _        d| _         y | j                  j                  |       y )NF)r*   r)   r(   reset)r+   tokens     r#   r5   zCompileableContextVar.resetX   s/    >>U]"DO"DN""5)r"   N)r   r   r   r   r-   r0   r2   r5   r!   r"   r#   r%   r%   <   s    
*/*r"   r%   output_collectorTc                :    fd}| j                  |       y)zaInstall the forward hook needed to capture the output described by `key` and `index` in `module`.c                :   t         j                         }||j                         vry r-dk(  r(t        |         dk(  r|   j	                  |d          t        |t              s|   j	                  |       y |   |   j	                  |          y y )Nhidden_statesr   )_active_collectorr0   keyslenappend
isinstancetuple)moduleargsoutputcollected_outputsr   r   keys       r#   output_capturing_hookz;install_output_capuring_hook.<locals>.output_capturing_hooki   s    -113$3D3I3I3K(K'C?,BsK\]`KaGbfgGgc"))$q'2&%(c"))&1E]&c"))&-8 'r"   N)register_forward_hook)rA   rE   r   r   rF   s    ``` r#   install_output_capuring_hookrH   d   s    
9   !67r"   c                   ddl m} | j                         D ]6  \  }}t        ||      st	        || d| |       %t        || d|        8 |D ]  \  }}|j                  duxr t        | |j                        }|j                  duxr |j                  |j                        }	|s|	s\|j                  -|j                  j                  d      }
d|
z   dz   }
|
|dz   v }|st        | ||j                  |j                          y)a  
    Recursively install all output capturing hooks on all submodules of `parent_module`.
    Note that we need to use this recursive approach instead of simply iterating over all modules, because we want
    to respect the `capture_tasks` of all individual submodels (`PreTrainedModel` instances) in the graph. That is, once
    we reach a submodel in the graph, its children should use this submodel's `capture_tasks`, but other parts of the graph
    should not.
    r   r   .)prefixN)modeling_utilsr   named_childrenr?   recursively_install_hooks"install_all_output_capturing_hooksr   r   endswithr   striprH   r   r   )parent_modulemodule_namecapture_tasksr   r,   rA   rE   specsmatch_target_classmatch_class_nametarget_layer_namematchess               r#   rN   rN   z   s)    1 &446 Wf&/2%fQtf.E}U /vQtf>UVW $ n
U"//t;m
=Z_ZlZl@m ++47bK<P<PQVQaQa<b!1+$)$4$4$:$:3$?!$'*;$;c$A!+{S/@@(U[[%JlJlm#nr"   c                   t         j                  t        | j                              xs i }g }|j	                         D ]  \  }}t        |t              s|g}|D ]c  }t        |t              s>d|v rdnd}t        |t              sdn|}t        |t              s|nd}	t        |	||      }|j                  ||f       e  ||nd}t        | ||       t        | dd       y)	z
    Install the output recording hooks on all the modules in `model`. This will take care of correctly dispatching
    the `_can_record_outputs` property of each individual submodels in case of composite models.
    r:   r   r	   N)r   r   r    !_output_capturing_hooks_installedT)_CAN_RECORD_REGISTRYr0   str	__class__itemsr?   listr   r>   rN   setattr)
modelrK   capture_flagsrT   rE   layer_specsrU   r   r   r   s
             r#   rO   rO      s     ),,S-ABHbMM)//1 	/[+t,&-K  	/Ee^4,3)3E3)?TU
,6uc,Bu&LZde  #u.	/	/ )VrFeV];E6=r"   c                    t        | dd      ryt        5  t        | dd      r
	 ddd       yt        |        ddd       y# 1 sw Y   yxY w)z
    Check if the model already has output capturing hooks installed, and install them if it is not already the
    case.
    Note that this is thread-safe, in case 2 (or more) threads want to install them concurrently.
    r\   FN)getattr_hook_installation_lockrO   )rc   s    r#   maybe_install_capturing_hooksri      sR     u95A	  2 5=uE	2 2 	+512 2 2s   AAA
)tie_last_hidden_statesc               &    fd}|  ||       S |S )a  
    Decorator to intercept specific layer outputs through hooks. The hooks are installed only once and lazily,
    the first time output capture is requested with the `output_xxx` kwargs/config.
    The implementation is fully context/thread safe, except when using `torch.compile`, as dynamo is unable to trace
    through `ContextVar` methods.

    Args:
        tie_last_hidden_states (`bool`, *optional*, defaults to `True`):
            Whether to overwrite `out.hidden_states[-1]` with the `out.last_hidden_state`.
            This is true for all language models and should be toggled off only if
            `out.hidden_states[-1]` has to be the hidden state before last layer norm, which
            is needed for some vision models (e.g. CLIP, SigLIP)
    c                2     t                fd       }|S )Nc                v   |j                  dt        | j                  dd            }t        j	                  t        | j                              xs i }|D ci c]3  }d| |j	                  d| t        | j                  d| d            5 }}d|v r*|j	                  dt        | j                  dd            |d<   d|v r*|j	                  dt        | j                  dd            |d	<   |j                         D ci c]  \  }}|s	|j                  dd
      g  }}}t        |      dkD  rt        |        t        j                  |      }		  | g|i |}
t        j                  |	       |D ]  }|dk(  rnsnkt        |
d      r*||   d d ||<   ||   j                  |
j                          n5t        |
d      r)||   d d ||<   ||   j                  |
j"                         t%        ||         |
|<    |du r|
j'                         }
|
S c c}w c c}}w # t        j                  |	       w xY w)Nreturn_dictToutput_Fcross_attentionsoutput_attentionsoutput_cross_attentionsmask_decoder_attentionsoutput_mask_decoder_attentionsr[   r   r:   vision_hidden_stateslast_hidden_state)poprg   configr]   r0   r^   r_   r`   replacer=   ri   r;   r2   r5   hasattrr>   ru   rw   r@   to_tuple)r+   rB   kwargsrn   capturable_flagskrecordable_keysvrD   output_tokenoutputsrE   funcrj   s               r#   wrapperz4capture_outputs.<locals>.wrapped_fn.<locals>.wrapper   sj    !**]GDKKX\4]^K  477DNN8KLRPR * !vzzGA3-PWXYWZm]b9cddO 
 "%55=CZZ'>QSX)Y> 9: ),<<DJJJ'>QSX)YE @A KZJ_J_Ja g$!Qef9b!92!= g g$%)-d3,001BCL6t5d5f5 "''5 ) =/)1 *@A1B31G1L)#.)#.55g6R6RS *=>1B31G1L)#.)#.55g6O6OP$%6s%;<= e#!**,N] !h "''5s   8H
HHH! !H8r   )r   r   rj   s   ` r#   
wrapped_fnz#capture_outputs.<locals>.wrapped_fn   s!    	t4	 
4	l r"   r!   )r   rj   r   s    ` r#   capture_outputsr      s"    8t $r"   )T)
rA   	nn.ModulerE   r^   r   r   r   r   returnNone)rR   r   rS   r^   rT   z list[tuple[str, OutputRecorder]]r   r   r/   )rc   r   rK   r   r   r   )rc   r   r   r   )r   
__future__r   	threadingcontextvarsr   dataclassesr   	functoolsr   typingr   import_utilsr
   r   r   r   rL   r   r]   r   r%   r;   rH   rN   rO   Lockrh   ri   r   r!   r"   r#   <module>r      s   
 #  " !    < 0   	:. .  .&!* !*J **<=  SW888(+8KO8	8,'n'n+.'n?_'n	'nT>: ))..* 2&K Kr"   