o
    h                     @   s~   d Z ddlmZ ddlmZmZ e rddlZddlmZ e	e
Zeddefdd	Zedd
ddefddZdddZdS )a  
Since, https://github.com/huggingface/transformers/pull/36963, loading is always performed with models on meta
device. But since the `init_empty_weights` and `find_tied_parameters` functions are from accelerate, and accelerate is
somewhat still a soft dependency, we copy the functions here to be used natively in Transformers.

The `init_empty_weights` and `init_on_device` functions were copied from `accelerate.big_modeling.py`, and the
`find_tied_parameters` was copied from `accelerate.utils.modeling.py`
    )contextmanager   )is_torch_availableloggingNFinclude_buffersc                 c   s@    t td| d}|V  W d   dS 1 sw   Y  dS )a   
    A context manager under which models are initialized with all parameters on the meta device, therefore creating an
    empty model. Useful when just initializing the model would blow the available RAM.

    Args:
        include_buffers (`bool`, *optional*):
            Whether or not to also put all buffers on the meta device while initializing.

    Example:

    ```python
    import torch.nn as nn
    from accelerate import init_empty_weights

    # Initialize a model with 100 billions parameters in no time and without using any RAM.
    with init_empty_weights():
        tst = nn.Sequential(*[nn.Linear(10000, 10000) for _ in range(1000)])
    ```

    <Tip warning={true}>

    Any model created under this context manager has no weights. As such you can't do something like
    `model.to(some_device)` with it. To load weights inside your empty model, see [`load_checkpoint_and_dispatch`].
    Make sure to overwrite the default device_map param for [`load_checkpoint_and_dispatch`], otherwise dispatch is not
    called.

    </Tip>
    meta)r   N)init_on_devicetorchdevice)r   f r   x/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/transformers/integrations/accelerate.pyinit_empty_weights$   s   "r   r
   ztorch.devicec                 #   s8   |r  dV  W d   dS 1 sw   Y  dS t jj|r%t jj fdd}d fdd	}|r>dd d	D }ni } fd
d}z;|t j_|rQ|t j_| D ]}tt||tt| qUdV  W t j_|rqt j_| D ]
\}}tt|| qudS t j_|rt j_| D ]
\}}tt|| qw )a)  
    A context manager under which models are initialized with all parameters on the specified device.

    Args:
        device (`torch.device`):
            Device to initialize all parameters on.
        include_buffers (`bool`, *optional*):
            Whether or not to also put all buffers on the meta device while initializing.

    Example:

    ```python
    import torch.nn as nn
    from accelerate import init_on_device

    with init_on_device(device=torch.device("cuda")):
        tst = nn.Linear(100, 100)  # on `cuda` device
    ```
    Nc                    sb   | || |d ur/t | j| }| j| j}|j|d< || j|  fi || j|< d S d S )Nrequires_grad)type_parameters__dict__r   to)modulenameparam	param_clskwargs)r
   old_register_parameterr   r   register_empty_parameterd   s   
&z0init_on_device.<locals>.register_empty_parameterTc                    s6   | |||d |d ur| j |  | j |< d S d S )N)
persistent)_buffersr   )r   r   bufferr   )r
   old_register_bufferr   r   register_empty_bufferl   s   z-init_on_device.<locals>.register_empty_bufferc                 S   s   i | ]}|t t|qS r   )getattrr	   ).0torch_function_namer   r   r   
<dictcomp>s   s    
z"init_on_device.<locals>.<dictcomp>)emptyzerosonesfullc                    s    fdd}|S )Nc                     s    |d< | i |S )Nr
   r   )argsr   )r
   fnr   r   wrapper{   s   zAinit_on_device.<locals>.patch_tensor_constructor.<locals>.wrapperr   )r)   r*   )r
   )r)   r   patch_tensor_constructorz   s   z0init_on_device.<locals>.patch_tensor_constructor)T)	nnModuleregister_parameterregister_bufferkeyssetattrr	   r    items)r
   r   r   r   tensor_constructors_to_patchr+   r"   old_torch_functionr   )r
   r   r   r   r   F   sL   
r   model	nn.Modulec           
      K   s   t | jdd}t | jdd}t| t|  }i }|D ]"}|| }| D ]\}}	|	|u rA||vr:g ||< || | q*q dd | D S )a  
    Find the tied parameters in a given model.

    <Tip warning={true}>

    The signature accepts keyword arguments, but they are for the recursive part of this function and you should ignore
    them.

    </Tip>

    Args:
        model (`torch.nn.Module`): The model to inspect.

    Returns:
        List[List[str]]: A list of lists of parameter names being all tied together.

    Example:

    ```py
    >>> from collections import OrderedDict
    >>> import torch.nn as nn

    >>> model = nn.Sequential(OrderedDict([("linear1", nn.Linear(4, 4)), ("linear2", nn.Linear(4, 4))]))
    >>> model.linear2.weight = model.linear1.weight
    >>> find_tied_parameters(model)
    [['linear1.weight', 'linear2.weight']]
    ```
    F)remove_duplicateTc                 S   s&   g | ]\}}t |gtt| qS r   )sortedlistset)r!   weighttiedr   r   r   
<listcomp>   s   & z(find_tied_parameters.<locals>.<listcomp>)dictnamed_parametersr:   r0   r2   append)
r5   r   all_named_parametersno_duplicate_named_parameterstied_param_namestied_param_groupstied_param_name
tied_param
param_namer   r   r   r   find_tied_parameters   s   rH   )F)r5   r6   )__doc__
contextlibr   utilsr   r   r	   torch.nnr,   
get_logger__name__loggerboolr   r   rH   r   r   r   r   <module>   s   	
!I