o
    Ni'5                     @  s   d dl mZ d dlZd dlZd dlmZ d dlZd dlmZ d dl	m
Z
mZ d dlmZmZ d dlmZmZmZmZmZ dd	lmZmZmZmZ G d
d deZdS )    )annotationsN)replace)Conv1D)is_bnb_4bit_availableis_bnb_available)	BaseTunerBaseTunerLayer)6TRANSFORMERS_MODELS_TO_IA3_FEEDFORWARD_MODULES_MAPPING1TRANSFORMERS_MODELS_TO_IA3_TARGET_MODULES_MAPPINGModulesToSaveWrapper_freeze_adapter_get_submodules   )Conv2dConv3dIA3LayerLinearc                      st   e Zd ZU dZdZded< eZedd Z	dd Z
edddZedd Z fddZdddZdddZ  ZS )IA3ModelaP  
    Creates a Infused Adapter by Inhibiting and Amplifying Inner Activations ((IA)^3) model from a pretrained
    transformers model. The method is described in detail in https://huggingface.co/papers/2205.05638

    Args:
        model ([`~transformers.PreTrainedModel`]): The model to be adapted.
        config ([`IA3Config`]): The configuration of the (IA)^3 model.
        adapter_name (`str`): The name of the adapter, defaults to `"default"`.
        low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
            Create empty adapter weights on meta device. Useful to speed up the loading process.

    Returns:
        `torch.nn.Module`: The (IA)^3 model.

    Example:

        ```py
        >>> from transformers import AutoModelForSeq2SeqLM, ia3Config
        >>> from peft import IA3Model, IA3Config

        >>> config = IA3Config(
        ...     peft_type="IA3",
        ...     task_type="SEQ_2_SEQ_LM",
        ...     target_modules=["k", "v", "w0"],
        ...     feedforward_modules=["w0"],
        ... )

        >>> model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")
        >>> ia3_model = IA3Model(config, model)
        ```

    **Attributes**:
        - **model** ([`~transformers.PreTrainedModel`]) -- The model to be adapted.
        - **peft_config** ([`ia3Config`]): The configuration of the (IA)^3 model.
    ia3_strprefixc                 K  s  t  rdd l}ddlm} t rddlm} |dd}|dd}|dd}	t|tr2|	 }
n|}
|r\t|
|j
jr\| }||
jj|
jj|
jd	 |||fd|	i|}|S |rt|
|j
jr| }||
j|
jj|
jjd
 |||fd|	i|}|S t|tj
jrt||fd|	i|}|S t|tj
jrt||fd|	i|}|S t|
tj
jr|d rtd d |d< | _t||fd|	i|}|S t|
tr|d std d |d< | _t||f|	dd|}|S td| d)Nr   r   )Linear8bitLt)
Linear4bitloaded_in_8bitFloaded_in_4bitis_feedforward)has_fp16_weights	thresholdindex)compute_dtypecompress_statistics
quant_typefan_in_fan_outzjfan_in_fan_out is set to True but the target module is `torch.nn.Linear`. Setting fan_in_fan_out to False.zafan_in_fan_out is set to False but the target module is `Conv1D`. Setting fan_in_fan_out to True.T)r   is_target_conv_1d_layerzTarget module zd is not supported. Currently, only `torch.nn.Linear`, `torch.nn.Conv2d`, and `Conv1D` are supported.)r   bitsandbytesbnbr   r   r   pop
isinstancer   get_base_layernncopyupdatestater   r   r   r   weightr    r!   torchr   r   r   warningswarnr"   r   
ValueError)
ia3_configadapter_nametargetkwargsr%   r   r   r   r   r   target_base_layereightbit_kwargs
new_modulefourbit_kwargs r:   I/home/ubuntu/.local/lib/python3.10/site-packages/peft/tuners/ia3/model.py_create_new_moduleL   s|   

%

zIA3Model._create_new_modulec           
      C  s   |  ||}|j|j|t| jddt| jddd}t|tr(|||j d S | j|||fi |}	|| j	vr=|	
d | |||	| d S )Nis_loaded_in_8bitFis_loaded_in_4bit)r"   init_ia3_weightsr   r   r   ) _check_target_module_feedforwardr"   r?   getattrmodelr'   r   update_layerr<   active_adaptersrequires_grad__replace_module)
selfr2   r3   r4   target_nameparentcurrent_keyr   r5   r8   r:   r:   r;   _create_and_replace   s    



zIA3Model._create_and_replacereturnboolc                   s>   t | jtrtt| j }|S t fdd| jD }|S )z
        A helper private method that checks if the target module `key` matches with a feedforward module specified in
        `ia3_config`
        c                 3  s    | ]}  |V  qd S N)endswith).0
target_keykeyr:   r;   	<genexpr>       z<IA3Model._check_target_module_feedforward.<locals>.<genexpr>)r'   feedforward_modulesr   rM   re	fullmatchany)r2   rS   r   r:   rR   r;   r@      s
   z)IA3Model._check_target_module_feedforwardc                 C  sd   | j d u r|d tvrtdtt|d  | _ | jd u r0|d tvr'tdtt|d  | _| S )N
model_typez0Please specify `target_modules` in `peft_config`z5Please specify `feedforward_modules` in `peft_config`)target_modulesr
   r1   setrV   r	   )peft_configmodel_configr:   r:   r;   _prepare_adapter_config   s   



z IA3Model._prepare_adapter_configc                   s>   t | jddrtdt | jddrtdt j|i |S )a  
        This method merges the (IA)^3 layers into the base model. This is needed if someone wants to use the base model
        as a standalone model.

        Args:
            safe_merge (`bool`, `optional`, defaults to `False`):
                If True, the merge operation will be performed in a copy of the original weights and check for NaNs
                before merging the weights. This is useful if you want to check if the merge operation will produce
                NaNs. Defaults to `False`.
            adapter_names (`List[str]`, *optional*):
                The list of adapter names that should be merged. If None, all active adapters will be merged. Defaults
                to `None`.
        r=   Fz>Cannot merge ia3 layers when the model is loaded in 8-bit moder>   z>Cannot merge ia3 layers when the model is loaded in 4-bit mode)rA   rB   r1   super_unload_and_optionally_merge)rG   argsr5   	__class__r:   r;   ra      s
   z%IA3Model._unload_and_optionally_mergeadapters	list[str]tuple[str, str]c                   s   D ]}|j vrtd| dqdd  D }t fdd|D r*tdfdd	 D }fd
d	 D }t|dksHt|dkrLtdt|v r]dfdd D }ntjfdd D  }t|v r}dfdd D }||fS tjfdd D  }||fS )z
        Helper function to check if the arguments to add_weighted_adapter are valid and compatible with the underlying
        model.
        zAdapter z does not existc                 S  s   g | ]	}t |tr|qS r:   )r'   r   )rP   moduler:   r:   r;   
<listcomp>   s    z8IA3Model._check_add_weighted_adapter.<locals>.<listcomp>c                 3  s*    | ] t  fd dD dkV  qdS )c                 3  s    | ]}| j v V  qd S rN   )modules_to_saverP   adapterwrapperr:   r;   rT      rU   zAIA3Model._check_add_weighted_adapter.<locals>.<genexpr>.<genexpr>r   N)sum)rP   re   rm   r;   rT      s    
z7IA3Model._check_add_weighted_adapter.<locals>.<genexpr>zLCannot add weighted adapters targeting the same module with modules_to_save.c                      h | ]
}t  j| jqS r:   )typer]   r[   rk   rG   r:   r;   	<setcomp>       z7IA3Model._check_add_weighted_adapter.<locals>.<setcomp>c                   rq   r:   )rr   r]   rV   rk   rs   r:   r;   rt      ru   r   zQAll adapter configs should have the same type for target and feedforward modules.|c                 3  $    | ]}d  j | j dV  qdS ()Nr]   r[   rk   rs   r:   r;   rT      s   " c                 3      | ]	} j | jV  qd S rN   r{   rk   rs   r:   r;   rT          c                 3  rw   rx   r]   rV   rk   rs   r:   r;   rT      s    
c                 3  r|   rN   r~   rk   rs   r:   r;   rT     r}   )	r]   r1   modulesrY   lenr   joinr\   union)rG   re   rl   modules_to_save_wrapperstarget_module_typesfeedforward_module_typesnew_target_modulesnew_feedforward_modulesr:   )re   rG   r;   _check_add_weighted_adapter   s2   
z$IA3Model._check_add_weighted_adapterweightslist[float]r3   Nonec                   s  |t  j v rdS  j|d\}}t j|d  ||d j|<   j| t j|  fdd j D }|D ]B}t	 j|\}}	}t
|	tr||	jv rX|	j| }
nq=|
j |
_t||D ]\}}||	jv rs|	j| }nqd|
 j|j| 7  _qdq=dS )ac  
        This method adds a new adapter by merging the given adapters with the given weights.

        Args:
            adapters (`list`):
                List of adapter names to be merged.
            weights (`list`):
                List of weights for each adapter.
            adapter_name (`str`):
                Name of the new adapter.
        Nrp   r   )r[   rV   c                   s   g | ]\}} j |vr|qS r:   )r   )rP   rS   _rs   r:   r;   ri   ,  s    z1IA3Model.add_weighted_adapter.<locals>.<listcomp>)listr]   keysr   r   inject_adapterrB   r   named_modulesr   r'   r   ia3_ldatazero_zip)rG   re   r   r3   r   r   key_listrS   r   r4   target_ia3_lrl   r-   current_adapter_ia3_lr:   rs   r;   add_weighted_adapter
  s6   



zIA3Model.add_weighted_adapter)rL   rM   )re   rf   rL   rg   )re   rf   r   r   r3   r   rL   r   )__name__
__module____qualname____doc__r   __annotations__r   tuner_layer_clsstaticmethodr<   rK   r@   r_   ra   r   r   __classcell__r:   r:   rc   r;   r   $   s   
 $
C 

(r   )
__future__r   rW   r/   dataclassesr   r.   transformers.pytorch_utilsr   peft.import_utilsr   r   peft.tuners.tuners_utilsr   r   
peft.utilsr	   r
   r   r   r   layerr   r   r   r   r   r:   r:   r:   r;   <module>   s   