o
    8wiH                     @  s   d dl mZ d dlZd dl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 d dlmZmZmZ d d	lmZmZmZ d
dlmZ d
dlmZmZ G dd deZdS )    )annotationsN)asdict)Enum)Optional)tqdm)Conv1D)	BaseTunerBaseTunerLayercheck_target_module_exists)4TRANSFORMERS_MODELS_TO_VBLORA_TARGET_MODULES_MAPPINGModulesToSaveWrapper_get_submodules   )VBLoRAConfig)LinearVBLoRALayerc                      s   e Zd ZU dZdZded< dHdI fd
dZdJddZdKddZdLddZ	e
dd Zdd Ze
dd ZdMddZe
dd  ZdN fd"d#ZdHdOd%d&ZdPdQd)d*ZdRd+d,ZdRd-d.ZdSd0d1Ze
d2d3 Z	'			4dTdUd9d:ZdVd;d<Z	4dWdXd>d?Zd@dA ZdYdZdDdEZdRdFdGZ  ZS )[VBLoRAModela  
    Creates VBLoRA model from a pretrained transformers model.

    The method is described in detail in https://huggingface.co/papers/2405.15179.

    Args:
        model ([`~transformers.PreTrainedModel`]): The model to be adapted.
        config ([`VBLoRAConfig`]): The configuration of the VBLoRA 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 VBLoRA model.

    Example:

        ```py
        >>> from transformers import AutoModelForCausalLM
        >>> from peft import VBLoRAConfig, get_peft_model

        >>> base_model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m")
        >>> config = VBLoRAConfig(
        ...     task_type="SEQ_CLS",
        ...     r=4,
        ...     target_modules=["fc1", "fc2", "k_proj", "out_proj", "q_proj", "v_proj"],
        ...     num_vectors=60,
        ...     vector_length=256,
        ...     save_only_topk_weights=True,
        ... )
        >>> model = get_peft_model(base_model, config)
        ```

    **Attributes**:
        - **model** ([`~transformers.PreTrainedModel`]) -- The model to be adapted.
        - **peft_config** ([`VBLoRAConfig`]): The configuration of the VBLoRAConfig model.
    vblora_strprefixFlow_cpu_mem_usageboolreturnNonec                   s   t  j||||d d S )N)r   )super__init__)selfmodelconfigadapter_namer   	__class__ U/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/peft/tuners/vblora/model.pyr   J   s   zVBLoRAModel.__init__r   r   r   c                 C  s6   t |j|j}t jj||j |j || j|< d S N)	torchzerosnum_vectorsvector_lengthnninituniform_init_vector_bank_boundvblora_vector_bank)r   r   r   r-   r"   r"   r#   _init_vblora_vector_bankM   s   z$VBLoRAModel._init_vblora_vector_bankr   	nn.Modulec                 C  s   t i | _d S r$   )r)   ParameterDictr-   )r   r   r   r   r"   r"   r#   _pre_injection_hookR   s   zVBLoRAModel._pre_injection_hookc                 C  s2   t | jdkr|jdkrt| jj ddS dS )z
        A helper method to check the config when a new adapter is being added.

        Raise a ValueError if there is something wrong with the config or if it conflicts with existing adapters.

        r   nonezf supports only 1 adapter with bias. When using multiple adapters, set bias to 'none' for all adapters.N)lenpeft_configbias
ValueErrorr!   __name__)r   r   r"   r"   r#   _check_new_adapter_configU   s
   
z%VBLoRAModel._check_new_adapter_configc                 C  s
   t | |S r$   )r
   )vblora_configkeyr"   r"   r#   _check_target_module_existse   s   
z'VBLoRAModel._check_target_module_existsc           
   
   C  s   |d u rt dt|do|jd u}|j|d}| || t|tr9|j|| j|j	|j
|j|j|j|jd d S | jd|| j||d|}	|| jvrQ|	d | |||	| d S )NzCurrent Key shouldn't be `None`r5   )fan_in_fan_outr5   )r   r-   rtopkr'   r(   vblora_dropoutinit_logits_std)r9   r-   r   targetFr"   )r6   hasattrr5   r<   r.   
isinstancer   update_layerr-   r=   r>   r'   r(   r?   r@   _create_new_moduleactive_adapterrequires_grad__replace_module)
r   r9   r   rA   target_nameparentcurrent_keyr5   kwargs
new_moduler"   r"   r#   _create_and_replacei   s:   	



zVBLoRAModel._create_and_replacec                   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 ]\}}d|v rct fdd| D sc||jj qGd S )N
base_layerr5   statemetar   c                 3  s    | ]}|j  kV  qd S r$   )device).0prQ   r"   r#   	<genexpr>   s    z.VBLoRAModel._replace_module.<locals>.<genexpr>)setattrrB   rO   weightr5   getattrrP   torR   r%   named_modulesany
parameters)rJ   
child_namerM   childnamemoduler"   rU   r#   rH      s&   




zVBLoRAModel._replace_modulec                 C  s   |  D ]\}}| j|vrd|_q| jD ]H}| j| j}|dkr!q|dkr6|  D ]\}}d|v r4d|_q)q|dkrU| D ]}t|trSt	|drS|jd urSd|j_q>qt
d| dd S )	NFr2   allr5   Tvblora_onlyzRequested bias: z, is not implemented.)named_parametersr   requires_gradactive_adaptersr4   r5   modulesrC   r   rB   NotImplementedError)r   r   nrT   rF   r5   mr"   r"   r#    _mark_only_adapters_as_trainable   s,   

z,VBLoRAModel._mark_only_adapters_as_trainablec                 K  s   t |tr
| }n|}t |tjjr$|d r#td d |d< | _n"t |t	r>d|d< |d s=td d |d< | _nt
d| dtd
|||| j| j| j| j| j| jd		|}|S )Nr<   zjfan_in_fan_out is set to True but the target module is `torch.nn.Linear`. Setting fan_in_fan_out to False.FTis_target_conv_1d_layerzafan_in_fan_out is set to False but the target module is `Conv1D`. Setting fan_in_fan_out to True.zTarget module z is not supported. Currently, only the following modules are supported: `torch.nn.Linear`, `transformers.pytorch_utils.Conv1D`.)	rO   r-   r   r=   r'   r(   r>   r?   r@   r"   )rC   r	   get_base_layerr%   r)   r   warningswarnr<   r   r6   r=   r'   r(   r>   r?   r@   )r9   r-   r   rA   rL   target_base_layerrM   r"   r"   r#   rE      sF   




zVBLoRAModel._create_new_moduler`   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   r`   r    r"   r#   rq      s   zVBLoRAModel.__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"   )rC   r   value)rS   kvr"   r"   r#   
<dictcomp>   s   & z7VBLoRAModel.get_peft_config_as_dict.<locals>.<dictcomp>Tinference_mode)r4   itemsr   )r   rs   config_dictr:   rt   r   r"   r"   r#   get_peft_config_as_dict   s   z#VBLoRAModel.get_peft_config_as_dictTenabledc                 C  s,   | j  D ]}t|ttfr|| qd S r$   )r   rg   rC   r	   r   enable_adapters)r   r|   ra   r"   r"   r#   _set_adapter_layers  s
   
zVBLoRAModel._set_adapter_layersc                 C  s   | 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  s   z!VBLoRAModel.enable_adapter_layersc                 C  sF   | j D ]}| j| j}|dkrd| d}t| q| jdd dS )zDisable all adapters.

        When disabling all adapters, the model output corresponds to the output of the base model.
        r2   z>Careful, disabling adapter layers with bias configured to be 'zL' does not produce the same output as the base model would without adaption.Fr   N)rf   r4   r5   rn   ro   r~   )r   rF   valmsgr"   r"   r#   disable_adapter_layers  s   


z"VBLoRAModel.disable_adapter_layers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   rg   rC   r   mergedrn   ro   unmergeset_adapterrF   )r   r   ra   r"   r"   r#   r     s   



zVBLoRAModel.set_adapterc                 C  s4   | j d u r|d tvrtdtt|d  | _ | S )N
model_typez0Please specify `target_modules` in `peft_config`)target_modulesr   r6   set)r4   model_configr"   r"   r#   _prepare_adapter_config3  s   

z#VBLoRAModel._prepare_adapter_configNprogressbar
safe_mergeadapter_namesOptional[list[str]]c              	     s    fdd j  D }d|rdnd d }t|| |dD ]?}zt j |\}}	}
W n	 ty4   Y qw t|	drN|rC|	j||d	  ||
|	 |	 qt	|	t
r]t||
|	j|	j  q j S )
Nc                      g | ]\}} j |vr|qS r"   r   rS   r:   _r   r"   r#   
<listcomp>D      z<VBLoRAModel._unload_and_optionally_merge.<locals>.<listcomp>z
Unloading zand merging  r   )disabledescrO   )r   r   )r   r[   r   r   rr   rB   mergerH   rm   rC   r   rW   modules_to_saverF   )r   r   r   r   r   key_listr   r:   rJ   rA   rI   r"   r   r#   _unload_and_optionally_merge=  s    

z(VBLoRAModel._unload_and_optionally_mergec                   s   |t  j vrtd| d j|=  fdd j D }d}|D ] }t j|\}}}t|trE|	| |du rE|j
dd }q%|pIg  _
 j||d dS )z
        Deletes an existing adapter.

        Args:
            adapter_name (str): Name of the adapter to be deleted.
        zAdapter z does not existc                   r   r"   r   r   r   r"   r#   r   b  r   z.VBLoRAModel.delete_adapter.<locals>.<listcomp>N)new_active_adapters)listr4   keysr6   r   r[   r   rC   r   delete_adapterrF   _delete_auxiliary_adapter)r   r   r   new_adapterr:   r   rA   r"   r   r#   r   W  s   


zVBLoRAModel.delete_adaptertorch.nn.Modulec                 C  s   | j |||dS )aJ  
        This method merges the VBLoRA layers into the base model. This is needed if someone wants to use the base model
        as a standalone model.

        Args:
            progressbar (`bool`):
                whether to show a progressbar indicating the unload and merge process
            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   r"   r"   r#   merge_and_unloadn  s   zVBLoRAModel.merge_and_unloadc                 C  s   | j ddS )z
        Gets back the base model by removing all the VBLoRA modules without merging. This gives back the original base
        model.
        F)r   r   r   r"   r"   r#   unload  s   zVBLoRAModel.unloaddefaulttuple[int, int]c                 C  s  d}d}d}|   D ]#\}}d|v r|| 7 }q
d|v r$|| 7 }q
|jr-|| 7 }q
| j| jr| j| j}d}|dk rCd}n|dk rJd}n	|d	k rQd}nd
}|| j| j | j| jd  }	|| j| j | j| j | }
t||	 |
 }||fS || }||fS )z`
        Returns the number of savable VB-LoRA parameters and other savable parameters.
        r   vblora_logitsr-   r      g      ?i   g      ?l           )rd   numelre   r4   save_only_topk_weightsr'   r>   int)r   adapterlogits_paramsvector_bank_paramsother_paramsr`   paramr'   factortopk_weight_paramstopk_indices_paramsvblora_paramsr"   r"   r#   get_nb_savable_parameters  s:   z%VBLoRAModel.get_nb_savable_parametersc                 C  s,   |   \}}td|dd|| d dS )z_
        Prints the number of savable VB-LoRA parameters and total savable parameters.
        z1VB-LoRA params to-be-saved (float32-equivalent): z,dz || total params to-be-saved: N)r   print)r   r   r   r"   r"   r#   print_savable_parameters  s   
z$VBLoRAModel.print_savable_parameters)F)r   r   r   r   )r   r   r   r   r   r   )r   r/   r   r   r   r   r   r   )r   r   r   r   )r   r/   r   r   )r`   r   )rs   r   )T)r|   r   r   r   )r   r   )r   r   r   r   )TFFN)r   r   r   r   r   r   )r   r   r   r   )FFN)r   r   r   r   r   r   r   r   )r   )r   r   )r7   
__module____qualname____doc__r   __annotations__r   r.   r1   r8   staticmethodr;   rN   rH   rk   rE   rq   r{   r~   r   r   r   r   r   r   r   r   r   r   __classcell__r"   r"   r    r#   r   !   sD   
 &



,


(		




!$r   )
__future__r   rn   dataclassesr   enumr   typingr   r%   torch.nnr)   r   transformers.pytorch_utilsr   peft.tuners.tuners_utilsr   r	   r
   
peft.utilsr   r   r   r   r   layerr   r   r   r"   r"   r"   r#   <module>   s   