o
    ۷i.                  	   @   s   d dl Z d dlmZm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mZmZmZ dd	lmZmZ dd
lmZmZ eeZdZeG dd dZG dd dejjZG dd deZG dd deZG dd deZdej j!deddfddZ"ddej j!dede#dB ddfddZ$dS )    N)asdict	dataclass)Callable   )
get_logger)unwrap_module   )"_ALL_TRANSFORMER_BLOCK_IDENTIFIERS_ATTENTION_CLASSES_FEEDFORWARD_CLASSES_get_submodule_from_fqn)AttentionProcessorRegistryTransformerBlockRegistry)HookRegistry	ModelHooklayer_skip_hookc                   @   s   e Zd ZU dZee ed< dZeed< dZ	e
ed< dZe
ed< dZe
ed	< d
Zeed< dd Zdd Zededd fddZdS )LayerSkipConfiga  
    Configuration for skipping internal transformer blocks when executing a transformer model.

    Args:
        indices (`list[int]`):
            The indices of the layer to skip. This is typically the first layer in the transformer block.
        fqn (`str`, defaults to `"auto"`):
            The fully qualified name identifying the stack of transformer blocks. Typically, this is
            `transformer_blocks`, `single_transformer_blocks`, `blocks`, `layers`, or `temporal_transformer_blocks`.
            For automatic detection, set this to `"auto"`. "auto" only works on DiT models. For UNet models, you must
            provide the correct fqn.
        skip_attention (`bool`, defaults to `True`):
            Whether to skip attention blocks.
        skip_ff (`bool`, defaults to `True`):
            Whether to skip feed-forward blocks.
        skip_attention_scores (`bool`, defaults to `False`):
            Whether to skip attention score computation in the attention blocks. This is equivalent to using `value`
            projections as the output of scaled dot product attention.
        dropout (`float`, defaults to `1.0`):
            The dropout probability for dropping the outputs of the skipped layers. By default, this is set to `1.0`,
            meaning that the outputs of the skipped layers are completely ignored. If set to `0.0`, the outputs of the
            skipped layers are fully retained, which is equivalent to not skipping any layers.
    indicesautofqnTskip_attentionFskip_attention_scoresskip_ff      ?dropoutc                 C   sN   d| j   krdksn td| j  dt| j ds#| jr%tdd S d S )Nr   r   z6Expected `dropout` to be between 0.0 and 1.0, but got .r   bCannot set `skip_attention_scores` to True when `dropout` is not 1.0. Please set `dropout` to 1.0.)r   
ValueErrormathiscloser   self r"   P/home/ubuntu/vllm_env/lib/python3.10/site-packages/diffusers/hooks/layer_skip.py__post_init__I   s   zLayerSkipConfig.__post_init__c                 C   s   t | S N)r   r    r"   r"   r#   to_dictQ   s   zLayerSkipConfig.to_dictdatareturnc                 C   s   t di | S )Nr"   )r   )r'   r"   r"   r#   	from_dictT   s   zLayerSkipConfig.from_dictN)__name__
__module____qualname____doc__listint__annotations__r   strr   boolr   r   r   floatr$   r&   staticmethoddictr)   r"   r"   r"   r#   r   (   s   
 r   c                   @   s   e Zd ZdddZdS )AttentionScoreSkipFunctionModer"   Nc                 C   s   |d u ri }|t jjju rI|dd }|dd }|dd }|d ur%|n|d }|d ur/|n|d }|d ur9|n|d }|jd |jd krI|S ||i |S )Nquerykeyvaluer   r   r   )torchnn
functionalscaled_dot_product_attentiongetshape)r!   functypesargskwargsr7   r8   r9   r"   r"   r#   __torch_function__Z   s   z1AttentionScoreSkipFunctionMode.__torch_function__)r"   N)r*   r+   r,   rD   r"   r"   r"   r#   r6   Y   s    r6   c                   @   s6   e Zd ZddededefddZdejj	fd	d
Z
dS )AttentionProcessorSkipHookFr   skip_processor_output_fnr   r   c                 C   s   || _ || _|| _d S r%   )rF   r   r   )r!   rF   r   r   r"   r"   r#   __init__o   s   
z#AttentionProcessorSkipHook.__init__modulec                 O   s   | j r-t| jdstdt  | jj|i |}W d    |S 1 s&w   Y  |S t| jdrB| j|g|R i |}|S | jj|i |}t	j
jj|| jd}|S )Nr   r   p)r   r   r   r   r   r6   fn_reforiginal_forwardrF   r:   r;   r<   r!   rH   rB   rC   outputr"   r"   r#   new_forwardt   s"   
z&AttentionProcessorSkipHook.new_forwardN)Fr   )r*   r+   r,   r   r2   r3   rG   r:   r;   ModulerO   r"   r"   r"   r#   rE   n   s    rE   c                       s4   e Zd Zdef fddZdejjfddZ  Z	S )FeedForwardSkipHookr   c                       t    || _d S r%   superrG   r   r!   r   	__class__r"   r#   rG         

zFeedForwardSkipHook.__init__rH   c                 O   sx   t | jdr'|dd }|d u r|dd }|d u r%t|dkr%|d }|S | jj|i |}tjj	j|| jd}|S )Nr   hidden_statesxr   rI   )
r   r   r   r>   lenrK   rL   r:   r;   r<   rM   r"   r"   r#   rO      s   zFeedForwardSkipHook.new_forward)
r*   r+   r,   r3   rG   r:   r;   rP   rO   __classcell__r"   r"   rV   r#   rQ      s    rQ   c                       s<   e Zd Zdef fddZdd ZdejjfddZ	  Z
S )	TransformerBlockSkipHookr   c                    rR   r%   rS   rU   rV   r"   r#   rG      rX   z!TransformerBlockSkipHook.__init__c                 C   s   t t|j| _|S r%   )r   r>   r   rW   	_metadata)r!   rH   r"   r"   r#   initialize_hook   s   z(TransformerBlockSkipHook.initialize_hookrH   c                 O   sx   t | jdr'| jd||}| jjd u r|}|S | jd||}||f}|S | jj|i |}tj	j
j|| jd}|S )Nr   rY   encoder_hidden_statesrI   )r   r   r   r^   _get_parameter_from_args_kwargs"return_encoder_hidden_states_indexrK   rL   r:   r;   r<   )r!   rH   rB   rC   original_hidden_statesrN   original_encoder_hidden_statesr"   r"   r#   rO      s   	z$TransformerBlockSkipHook.new_forward)r*   r+   r,   r3   rG   r_   r:   r;   rP   rO   r\   r"   r"   rV   r#   r]      s    r]   rH   configr(   c                 C   s   t | | dS )a  
    Apply layer skipping to internal layers of a transformer.

    Args:
        module (`torch.nn.Module`):
            The transformer model to which the layer skip hook should be applied.
        config (`LayerSkipConfig`):
            The configuration for the layer skip hook.

    Example:

    ```python
    >>> from diffusers import apply_layer_skip_hook, CogVideoXTransformer3DModel, LayerSkipConfig

    >>> transformer = CogVideoXTransformer3DModel.from_pretrained("THUDM/CogVideoX-5b", torch_dtype=torch.bfloat16)
    >>> config = LayerSkipConfig(layer_index=[10, 20], fqn="transformer_blocks")
    >>> apply_layer_skip_hook(transformer, config)
    ```
    N)_apply_layer_skip_hook)rH   re   r"   r"   r#   apply_layer_skip   s   rg   namec                 C   s.  |pt }|jr|jrtdt|jds|jrtd|jdkr4tD ]}t	| |r/||_ nq#tdt
| |j}|d u sEt|tjjsNtd|j dt|jdkrYtd	d
}t|D ]\}}||jvriq_d}|jr|jrtd|j d| d t|}t|j}	||	| nB|js|jr| D ]7\}
}t|tr|jstd|j d| d|
 d t|jjj }t|}t!||j|j}	||	| q|jr| D ]*\}
}t|t"rtd|j d| d|
 d t|}t#|j}	||	| qq_|std|j d|j dd S )NzXCannot set both `skip_attention` and `skip_attention_scores` to True. Please choose one.r   r   r   zCould not find a suitable identifier for the transformer blocks automatically. Please provide a valid `fqn` (fully qualified name) that identifies a stack of transformer blocks.zCould not find z in the provided module, or configured `fqn` (fully qualified name) does not identify a `torch.nn.ModuleList`. Please provide a valid `fqn` that identifies a stack of transformer blocks.r   zTLayer index list is empty. Please provide a non-empty list of layer indices to skip.FTz&Applying TransformerBlockSkipHook to 'r   'z(Applying AttentionProcessorSkipHook to 'z!Applying FeedForwardSkipHook to 'zDCould not find any transformer blocks matching the provided indices z and fully qualified name 'z4'. Please check the indices and fqn for correctness.)$_LAYER_SKIP_HOOKr   r   r   r   r   r   r   r	   hasattrr   
isinstancer:   r;   
ModuleListr[   r   	enumerater   loggerdebugr   check_if_exists_or_initializer]   register_hooknamed_modulesr
   is_cross_attentionr   r>   	processorrW   rF   rE   r   rQ   )rH   re   rh   
identifiertransformer_blocksblocks_foundiblockregistryhooksubmodule_name	submodule	output_fnr"   r"   r#   rf      sr   




 
 


rf   r%   )%r   dataclassesr   r   typingr   r:   utilsr   utils.torch_utilsr   _commonr	   r
   r   r   _helpersr   r   hooksr   r   r*   ro   rj   r   	overridesTorchFunctionModer6   rE   rQ   r]   r;   rP   rg   r1   rf   r"   r"   r"   r#   <module>   s&   0(