o
    8wiS                     @  s   d dl mZ d dlZd dlZd dlmZmZ d dl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 d d	lmZ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)asdictreplace)Enum)Optional)nn)Conv1D)is_bnb_4bit_availableis_bnb_available)	BaseTunerBaseTunerLayercheck_target_module_exists)6TRANSFORMERS_MODELS_TO_IA3_FEEDFORWARD_MODULES_MAPPING1TRANSFORMERS_MODELS_TO_IA3_TARGET_MODULES_MAPPINGModulesToSaveWrapper_freeze_adapter_get_submodules   )Conv2dConv3dIA3LayerLinearc                      s  e Zd ZU dZdZded< dDdE fdd	Zed
d Zedd Z	dFddZ
dd ZedGddZdd ZdH fddZdDdIddZdJd!d"ZdKd#d$ZdKd%d&ZdLd)d*Zed+d, Z	-dMdNd2d3ZdOdPd5d6ZdQd7d8ZdRd9d:ZdSd>d?ZdTdBdCZ  ZS )U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prefixFlow_cpu_mem_usageboolc                   s   t  j||||d d S )N)r   )super__init__)selfmodelconfigadapter_namer   	__class__ R/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/peft/tuners/ia3/model.pyr   N   s   zIA3Model.__init__c                 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_layerr   copyupdatestater-   r.   r/   r0   weightr1   r2   torchr   r   r   warningswarnr3   r   
ValueError)
ia3_configr#   targetkwargsr6   r(   r)   r*   r+   r,   target_base_layereightbit_kwargs
new_modulefourbit_kwargsr&   r&   r'   _create_new_moduleQ   s|   

%

zIA3Model._create_new_modulec                 C  s
   t | |S N)r   )rB   keyr&   r&   r'   _check_target_module_exists   s   
z$IA3Model._check_target_module_existsr!   	nn.ModulereturnNonec                 C  s&   |  D ]\}}| j|vrd|_qd S )NF)named_parametersr   requires_grad)r    r!   npr&   r&   r'    _mark_only_adapters_as_trainable   s
   
z)IA3Model._mark_only_adapters_as_trainablec           
      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)r3   init_ia3_weightsr,   r*   r+   ) _check_target_module_feedforwardr3   rW   getattrr!   r8   r   update_layerrI   active_adaptersrequires_grad__replace_module)
r    rB   r#   rC   target_nameparentcurrent_keyr,   rD   rG   r&   r&   r'   _create_and_replace   s    



zIA3Model._create_and_replacec                   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 rJ   )endswith).0
target_keyrK   r&   r'   	<genexpr>       z<IA3Model._check_target_module_feedforward.<locals>.<genexpr>)r8   feedforward_modulesr   r   re	fullmatchany)rB   rK   r,   r&   re   r'   rX      s
   z)IA3Model._check_target_module_feedforwardc                   s   t ||| t|dr|j}t|ds |j|_t|dr |j|_t|dd d ur>t|dr3|j|j_n|j|_||jj t	d |
 D ]\}}| j|v rdt fdd| D sd||jj qGd S )N
base_layerbiasr<   metac                 3  s    | ]}|j  kV  qd S rJ   )device)rc   rS   rn   r&   r'   rf      rg   z+IA3Model._replace_module.<locals>.<genexpr>)setattrhasattrrl   r=   rm   rY   r<   toro   r>   named_modulesr   rk   
parameters)r    r_   
child_namerG   childnamemoduler&   rp   r'   r]      s&   





zIA3Model._replace_modulerx   c                   s8   zt  |W S  ty   |dkr t| j| Y S w )z1Forward missing attributes to the wrapped module.r!   )r   __getattr__AttributeErrorrY   r!   )r    rx   r$   r&   r'   rz      s   zIA3Model.__getattr__	inferencec                 C  sF   i }| j  D ]\}}dd t| D }|rd|d< q|||< |S )Nc                 S  s&   i | ]\}}|t |tr|jn|qS r&   )r8   r   value)rc   kvr&   r&   r'   
<dictcomp>   s   & z4IA3Model.get_peft_config_as_dict.<locals>.<dictcomp>Tinference_mode)peft_configitemsr   )r    r|   config_dictrK   r}   r"   r&   r&   r'   get_peft_config_as_dict   s   z IA3Model.get_peft_config_as_dictTc                 C  s,   | j  D ]}t|ttfr|| qd S rJ   )r!   modulesr8   r   r   enable_adapters)r    enabledry   r&   r&   r'   _set_adapter_layers   s
   
zIA3Model._set_adapter_layersc                 C     | j dd dS )zyEnable all adapters.

        Call this if you have previously disabled all adapters and want to re-enable them.
        Tr   Nr   r    r&   r&   r'   enable_adapter_layers      zIA3Model.enable_adapter_layersc                 C  r   )zDisable all adapters.

        When disabling all adapters, the model output corresponds to the output of the base model.
        Fr   Nr   r   r&   r&   r'   disable_adapter_layers  r   zIA3Model.disable_adapter_layersr#   str | list[str]c                 C  sF   | j  D ]}t|tr|jrtd |  || q|| _	dS )a   Set the active adapter(s).

        Additionally, this function will set the specified adapters to trainable (i.e., requires_grad=True). If this is
        not desired, use the following code.

        ```py
        >>> for name, param in model_peft.named_parameters():
        ...     if ...:  # some check on name (ex. if 'lora' in name)
        ...         param.requires_grad = False
        ```

        Args:
            adapter_name (`str` or `list[str]`): Name of the adapter(s) to be activated.
        zJAdapter cannot be set when the model is merged. Unmerging the model first.N)
r!   r   r8   r   mergedr?   r@   unmergeset_adapteractive_adapter)r    r#   ry   r&   r&   r'   r   
  s   



zIA3Model.set_adapterc                 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   rA   setrh   r   )r   model_configr&   r&   r'   _prepare_adapter_config!  s   



z IA3Model._prepare_adapter_configNmerge
safe_mergeadapter_namesOptional[list[str]]c           
   	     s   t  jddrtdt  jddrtd |  fdd j D }|D ]S}zt j|\}}}W n	 ty?   Y q)w t|drY|rN|j||d	  	|||
 | q)t|tr||j|j }	t|	drv|rr|	j||d	 |	
 }	t|||	 q) j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`.
        rU   Fz>Cannot merge ia3 layers when the model is loaded in 8-bit moderV   z>Cannot merge ia3 layers when the model is loaded in 4-bit modec                      g | ]\}} j |vr|qS r&   r   rc   rK   _r   r&   r'   
<listcomp>H      z9IA3Model._unload_and_optionally_merge.<locals>.<listcomp>rl   r   r   )rY   r!   rA   _unloading_checksrt   r   r{   rr   r   r]   r9   r8   r   modules_to_saver   rq   )
r    r   r   r   key_listrK   r_   rC   r^   rG   r&   r   r'   _unload_and_optionally_merge1  s2   



z%IA3Model._unload_and_optionally_mergetorch.nn.Modulec                 C  s   | j ||dS )u  
        This method merges the IA³ layers into the base model. This is needed if someone wants to use the base model as
        a standalone model.

        Args:
            safe_merge (`bool`):
                whether to activate the safe merging check to check if there is any potential Nan in the adapter
                weights
            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`.

        Example:

        ```py
        >>> from transformers import AutoModelForCausalLM
        >>> from peft import PeftModel

        >>> base_model = AutoModelForCausalLM.from_pretrained("tiiuae/falcon-40b")
        >>> peft_model_id = "smangrul/falcon-40B-int4-peft-lora-sfttrainer-sample"
        >>> model = PeftModel.from_pretrained(base_model, peft_model_id)
        >>> merged_model = model.merge_and_unload()
        ```
        r   r   )r    r   r   r&   r&   r'   merge_and_unload_  s   zIA3Model.merge_and_unloadc                 C  s   | j ddS )u   
        Gets back the base model by removing all the IA³ modules without merging. This gives back the original base
        model.
        F)r   r   r   r&   r&   r'   unloadz  s   zIA3Model.unloadc                   s   | j vrtd| d j |=  fdd j D }d}|D ] }t j|\}}}t|trA|| |du rA|jdd }q!|pEg  _	 j
||d dS )z
        Deletes an existing adapter.

        Args:
            adapter_name (str): Name of the adapter to be deleted.
        Adapter  does not existc                   r   r&   r   r   r   r&   r'   r     r   z+IA3Model.delete_adapter.<locals>.<listcomp>N)new_active_adapters)r   rA   r!   rt   r   r8   r   delete_adapterr[   r   _delete_auxiliary_adapter)r    r#   r   new_adapterrK   r   rC   r&   r   r'   r     s   



zIA3Model.delete_adapter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.
        r   r   c                 S  s   g | ]	}t |tr|qS r&   )r8   r   )rc   ry   r&   r&   r'   r     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 rJ   )r   rc   adapterwrapperr&   r'   rf     rg   zAIA3Model._check_add_weighted_adapter.<locals>.<genexpr>.<genexpr>r   N)sum)rc   r   r   r'   rf     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   r   r   r&   r'   	<setcomp>      z7IA3Model._check_add_weighted_adapter.<locals>.<setcomp>c                   r   r&   )r   r   rh   r   r   r&   r'   r     r   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   r   r   r&   r'   rf     s   " c                 3      | ]	} j | jV  qd S rJ   r   r   r   r&   r'   rf         c                 3  r   r   r   rh   r   r   r&   r'   rf     s    
c                 3  r   rJ   r   r   r   r&   r'   rf     r   )	r   rA   r   rk   lenr   joinr   union)r    r   r   modules_to_save_wrapperstarget_module_typesfeedforward_module_typesnew_target_modulesnew_feedforward_modulesr&   )r   r    r'   _check_add_weighted_adapter  s2   
z$IA3Model._check_add_weighted_adapterweightslist[float]c                   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.
        Nr   r   )r   rh   c                   r   r&   r   r   r   r&   r'   r     r   z1IA3Model.add_weighted_adapter.<locals>.<listcomp>)listr   keysr   r   inject_adapterr!   r   rt   r   r8   r   ia3_ldatazero_zip)r    r   r   r#   r   r   r   rK   r   rC   target_ia3_lr   r=   current_adapter_ia3_lr&   r   r'   add_weighted_adapter  s6   



zIA3Model.add_weighted_adapter)F)r   r   )r!   rM   rN   rO   )rN   r   )rx   r   )r|   r   )T)rN   rO   )r#   r   rN   rO   )TFN)r   r   r   r   r   r   )FN)r   r   r   r   rN   r   )rN   r   )r#   r   rN   rO   )r   r   rN   r   )r   r   r   r   r#   r   rN   rO   )__name__
__module____qualname____doc__r   __annotations__r   staticmethodrI   rL   rT   ra   rX   r]   rz   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r&   r&   r$   r'   r   '   s8   
 $
C

 	
	



.


(r   )"
__future__r   ri   r?   dataclassesr   r   enumr   typingr   r>   r   transformers.pytorch_utilsr   peft.import_utilsr	   r
   peft.tuners.tuners_utilsr   r   r   
peft.utilsr   r   r   r   r   layerr   r   r   r   r   r&   r&   r&   r'   <module>   s   