a
    Ad,                     @   sn   d dl Zd dlZd dlZd dlZd dlmZ G dd dZG dd deZ	G dd deZ
G d	d
 d
eZdS )    N)sharedc                   @   s$   e Zd Zdd Zdd Zdd ZdS )ReplaceHelperc                 C   s
   g | _ d S N)replacedself r   I/var/www/html/stable-diffusion-webui/modules/sd_disable_initialization.py__init__
   s    zReplaceHelper.__init__c                 C   s:   t ||d }|d u rd S | j|||f t||| |S r   getattrr   appendsetattrr   objfieldfuncoriginalr   r   r	   replace   s    zReplaceHelper.replacec                 C   s,   | j D ]\}}}t||| q| j   d S r   )r   r   clear)r   r   r   r   r   r   r	   restore   s    zReplaceHelper.restoreN)__name__
__module____qualname__r
   r   r   r   r   r   r	   r   	   s   
r   c                       s:   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Z  ZS )DisableInitializationa  
    When an object of this class enters a `with` block, it starts:
    - preventing torch's layer initialization functions from working
    - changes CLIP and OpenCLIP to not download model weights
    - changes CLIP to not make requests to check if there is a new version of a file you already have

    When it leaves the block, it reverts everything to how it was before.

    Use it like this:
    ```
    with DisableInitialization():
        do_things()
    ```
    Tc                    s   t    || _d S r   )superr
   disable_clip)r   r   	__class__r   r	   r
   .   s    
zDisableInitialization.__init__c                 C   s:   t ||d }|d u rd S | j|||f t||| |S r   r   r   r   r   r	   r   2   s    zDisableInitialization.replacec                    s,  dd }d d fdd
} fdd} fdd	}d
d dd fdd
}dd fdd
}dd fdd
}  tjjd|   tjjd|   tjjd|  jr(  td| _  tjj	jj
d| _  tjjd| _  tjd| _  tjd| _  tjjd| _d S )Nc                  _   s   d S r   r   argskwargsr   r   r	   
do_nothing=   s    z3DisableInitialization.__enter__.<locals>.do_nothing)
pretrainedc                    s    j |dd i|S )Nr#   )create_model_and_transforms)r#   r    r!   r   r   r	   .create_model_and_transforms_without_pretrained@   s    zWDisableInitialization.__enter__.<locals>.create_model_and_transforms_without_pretrainedc                    s(    j d g|R | i d|}| |_|S )N)config
state_dict)CLIPTextModel_from_pretrainedname_or_path)pretrained_model_name_or_path
model_argsr!   resr   r   r	   r(   C   s    zFDisableInitialization.__enter__.<locals>.CLIPTextModel_from_pretrainedc                     s,   | dd d | dd   }  j | i |S )Nr      )/   )1transformers_modeling_utils_load_pretrained_modelr   r   r   r	   r0   H   s    zZDisableInitialization.__enter__.<locals>.transformers_modeling_utils_load_pretrained_modelc                 _   s   |dks|dkr |d dkr d S zB| |g|R ddi|}|d u r^| |g|R ddi|}|W S  t y   | |g|R ddi| Y S 0 d S )NzShttps://huggingface.co/openai/clip-vit-large-patch14/resolve/main/added_tokens.jsonzopenai/clip-vit-large-patch14r   zadded_tokens.jsonlocal_files_onlyTF)	Exception)r   urlr    r!   r,   r   r   r	   *transformers_utils_hub_get_file_from_cacheL   s    zSDisableInitialization.__enter__.<locals>.transformers_utils_hub_get_file_from_cacheF)r1   c                   s    j | g|R i |S r   )%transformers_utils_hub_get_from_cacher3   r1   r    r!   r   r4   r   r	   r5   Z   s    zNDisableInitialization.__enter__.<locals>.transformers_utils_hub_get_from_cachec                   s    j | g|R i |S r   )0transformers_tokenization_utils_base_cached_filer6   r7   r   r	   r8   ]   s    zYDisableInitialization.__enter__.<locals>.transformers_tokenization_utils_base_cached_filec                   s    j | g|R i |S r   ),transformers_configuration_utils_cached_filer6   r7   r   r	   r9   `   s    zUDisableInitialization.__enter__.<locals>.transformers_configuration_utils_cached_filekaiming_uniform__no_grad_normal__no_grad_uniform_r$   from_pretrained_load_pretrained_modelcached_fileZget_from_cache)r   torchnninitr   	open_clipr$   ldmmodulesencodersCLIPTextModelr(   transformersmodeling_utilsPreTrainedModelr0   tokenization_utils_baser8   configuration_utilsr9   utilshubr5   )r   r"   r%   r(   r0   r5   r8   r9   r   r7   r	   	__enter__<   s$    zDisableInitialization.__enter__c                 C   s   |    d S r   r   r   exc_typeexc_valexc_tbr   r   r	   __exit__o   s    zDisableInitialization.__exit__)T)	r   r   r   __doc__r
   r   rO   rU   __classcell__r   r   r   r	   r      s
   
3r   c                   @   s    e Zd ZdZdd Zdd ZdS )InitializeOnMetaa  
    Context manager that causes all parameters for linear/conv2d/mha layers to be allocated on meta device,
    which results in those parameters having no values and taking no memory. model.to() will be broken and
    will need to be repaired by using LoadStateDictOnMeta below when loading params from state dict.

    Usage:
    ```
    with sd_disable_initialization.InitializeOnMeta():
        sd_model = instantiate_from_config(sd_config.model)
    ```
    c                    s   t jjrd S dd | tjjdfdd| tjjd fdd | tjjdfdd| tjj	dd	d  d S )
Nc                 S   s   d| d< | S )Nmetadevicer   )xr   r   r	   
set_device   s    z.InitializeOnMeta.__enter__.<locals>.set_devicer
   c                     s    | i |S r   r   r   )linear_initr\   r   r	   <lambda>       z,InitializeOnMeta.__enter__.<locals>.<lambda>c                     s    | i |S r   r   r   )conv2d_initr\   r   r	   r^      r_   c                     s    | i |S r   r   r   )mha_initr\   r   r	   r^      r_   toc                  _   s   d S r   r   r   r   r   r	   r^      r_   )
r   cmd_opts&disable_model_loading_ram_optimizationr   r@   rA   LinearConv2dMultiheadAttentionModuler   r   )r`   r]   ra   r\   r	   rO      s    zInitializeOnMeta.__enter__c                 C   s   |    d S r   rP   rQ   r   r   r	   rU      s    zInitializeOnMeta.__exit__N)r   r   r   rV   rO   rU   r   r   r   r	   rX   s   s   rX   c                       s:   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Z  ZS )LoadStateDictOnMetaa  
    Context manager that allows to read parameters from state_dict into a model that has some of its parameters in the meta device.
    As those parameters are read from state_dict, they will be deleted from it, so by the end state_dict will be mostly empty, to save memory.
    Meant to be used together with InitializeOnMeta above.

    Usage:
    ```
    with sd_disable_initialization.LoadStateDictOnMeta(state_dict):
        model.load_state_dict(state_dict, strict=False)
    ```
    Nc                    s2   t    || _|| _|pi | _| jd| _d S )N )r   r
   r'   rZ   weight_dtype_conversiongetdefault_dtype)r   r'   rZ   rk   r   r   r	   r
      s
    

zLoadStateDictOnMeta.__init__c                 C   s    | dd\}}| j|| jS )N.   )splitrk   rl   rm   )r   keyZkey_first_term_r   r   r	   get_weight_dtype   s    z$LoadStateDictOnMeta.get_weight_dtypec                    s   t jjrd S j
j
fddd
fdd	tjjd	fdd	tjjd	fd
dtjj	d	fddtjj
d	 fdd tjjd	fddtjjd	fddtjjd	fddd S )Nc                    s  g }|j  D ]\}}|d u r q|| }	|	d }
|
d ur\|
j|	d||	< ||	 |jr|
d urp|
jn|j}tj	j
jtj| |d|jd|j |< q|jD ]2}|| }	|	d }
|
d ur|
||	< ||	 q| |||g|R i | |D ]}	||	d  qd S )N)dtyperZ   rt   )requires_grad)_parametersitemspoprb   rs   r   is_metart   r@   rA   	parameter	Parameter
zeros_likerv   _buffers)r   moduler'   prefixr    r!   Zused_param_keysnameparamrq   Zsd_paramrt   )rZ   sdr   r   r	   load_from_state_dict   s*    
(
z;LoadStateDictOnMeta.__enter__.<locals>.load_from_state_dictTc                    s,   | krdd |  D }| |||d dS )a  torch makes a lot of copies of the dictionary with weights, so just deleting entries from state_dict does not help
            because the same values are stored in multiple copies of the dict. The trick used here is to give torch a dict with
            all weights on meta device, i.e. deleted, and then it doesn't matter how many copies torch makes.

            In _load_from_state_dict, the correct weight will be obtained from a single dict with the right weights (sd).

            The dangerous thing about this is if _load_from_state_dict is not called, (if some exotic module overloads
            the function and does not call the original) the state dict will just fail to load because weights
            would be on the meta device.
            c                 S   s"   i | ]\}}||j d |jdqS )rY   ru   )rb   rt   ).0kvr   r   r	   
<dictcomp>   r_   zJLoadStateDictOnMeta.__enter__.<locals>.load_state_dict.<locals>.<dictcomp>)strictN)rx   )r   r   r'   r   )r   r   r	   load_state_dict   s    z6LoadStateDictOnMeta.__enter__.<locals>.load_state_dictr   c                     s    g| R i |S r   r   r   )r   module_load_state_dictr   r	   r^      r_   z/LoadStateDictOnMeta.__enter__.<locals>.<lambda>_load_from_state_dictc                     s    g| R i |S r   r   r   )r   module_load_from_state_dictr   r	   r^      r_   c                     s    g| R i |S r   r   r   )linear_load_from_state_dictr   r   r	   r^      r_   c                     s    g| R i |S r   r   r   )conv2d_load_from_state_dictr   r   r	   r^      r_   c                     s    g| R i |S r   r   r   )r   mha_load_from_state_dictr   r	   r^      r_   c                     s    g| R i |S r   r   r   )layer_norm_load_from_state_dictr   r   r	   r^      r_   c                     s    g| R i |S r   r   r   )group_norm_load_from_state_dictr   r   r	   r^      r_   )T)r   rc   rd   r'   rZ   r   r@   rA   rh   re   rf   rg   	LayerNorm	GroupNormr   r   )r   rZ   r   r   r   r   r   r   r   r   r   r   r	   rO      s    zLoadStateDictOnMeta.__enter__c                 C   s   |    d S r   rP   rQ   r   r   r	   rU      s    zLoadStateDictOnMeta.__exit__)N)	r   r   r   rV   r
   rs   rO   rU   rW   r   r   r   r	   ri      s
   >ri   )ldm.modules.encoders.modulesrD   rC   r@   Ztransformers.utils.hubrH   rE   r   r   r   rX   ri   r   r   r   r	   <module>   s   U