
    biQO                        d dl mZ d dlZd dlmZ d dlmZmZ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 d	d
lmZ d	dlmZ d	dlmZ d	dlmZmZ ddZddZ G d dee	j                  j8                        Zy)    )annotationsN)contextmanager)AnyOptionalUnion)remove_hook_from_submodules)nn)PushToHubMixin)DUMMY_MODEL_CONFIG   )
PeftConfig)	PeftModel)
MixedModel)_set_adapter_set_trainablec                   t        | dd      s| S t        | dd      sit        | dd      s[t        | dd      sMt        | d      r| j                          y
t        | d      r#d	 }| j                         j	                  |       y
y
y
y
y
)zD
    Prepares the model for gradient checkpointing if necessary
    is_gradient_checkpointingTis_loaded_in_8bitFis_loaded_in_4bitis_quantizedenable_input_require_gradsget_input_embeddingsc                &    |j                  d       y )NT)requires_grad_)moduleinputoutputs      K/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/peft/mixed_model.pymake_inputs_require_gradzK_prepare_model_for_gradient_checkpointing.<locals>.make_inputs_require_grad3   s    %%d+    N)getattrhasattrr   r   register_forward_hook)modelr   s     r   )_prepare_model_for_gradient_checkpointingr%   "   s    
 55t< 	*E25-u55.%0567,,.U23, &&(>>?WX 4	 1 6 	3r    c                v    ddl m} | j                  |vr%t        d| j                  j                   d|       y )Nr   )COMPATIBLE_TUNER_TYPESzThe provided `peft_type` 'zE' is not compatible with the `PeftMixedModel`. Compatible types are: )tuners.mixedr'   	peft_type
ValueErrorvalue)peft_configr'   s     r   _check_config_compatibler-   9   sK    4$::()>)>)D)D(E F%%;$<>
 	
 ;r    c                  H    e Zd ZdZdd fdZedd       Zedd       Zedd       Zd Z	d Z
d fdZd d	Zd d
Zed        Zd!d"dZd#dZd$dZd$dZd dZd dZd Zd Zed%d       Zd&dZd'dZd(dZ	 	 d)	 	 	 	 	 	 	 d*dZe	 	 	 d+	 	 	 	 	 	 	 	 	 	 	 d,d       Z xZS )-PeftMixedModela,  
    PeftMixedModel for loading mixing different types of adapters for inference.

    This class does not support loading/saving, and it shouldn't usually be initialized directly. Instead, use
    `get_peft_model` with the argument `mixed=True`.

    <Tip>

    Read the [Mixed adapter types](https://huggingface.co/docs/peft/en/developer_guides/mixed_models) guide to learn
    more about using different adapter types.

    </Tip>

    Example:

    ```py
    >>> base_model = ...  # load the base model, e.g. from transformers
    >>> peft_model = PeftMixedModel.from_pretrained(base_model, path_to_adapter1, "adapter1").eval()
    >>> peft_model.load_adapter(path_to_adapter2, "adapter2")
    >>> peft_model.set_adapter(["adapter1", "adapter2"])  # activate both adapters
    >>> peft_model(data)  # forward pass using both adapters
    ```

    Args:
        model (`torch.nn.Module`):
            The model to be tuned.
        config (`PeftConfig`):
            The config of the model to be tuned. The adapter type must be compatible.
        adapter_name (`str`, `optional`, defaults to `"default"`):
            The name of the first adapter.
        low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
            Create empty adapter weights on meta device. Useful to speed up the loading process.
    c                z   t         |           t        |       t        |       d | _        t        |||i|      | _        | j                  ||       t        |dt              | _
        t        | j                  d      r=t        | j                  j                  d      rd| j                  j                  _        y y y )Nconfigpretraining_tpr   )super__init__r-   r%   modules_to_saver   
base_modelset_modules_to_saver!   r   r1   r"   r2   )selfr$   r,   adapter_name	__class__s       r   r4   zPeftMixedModel.__init__f   s     -1%8#$U\;,GV  l;eX/AB
 4??H-'$//:P:PRb2c45DOO""1 3d-r    c                .    | j                   j                  S N)r6   r,   r8   s    r   r,   zPeftMixedModel.peft_configv   s    ***r    c                .    | j                   j                  S r<   )r6   active_adapterr=   s    r   r?   zPeftMixedModel.active_adapterz   s    ---r    c                .    | j                   j                  S r<   )r6   active_adaptersr=   s    r   rA   zPeftMixedModel.active_adapters~   s    ...r    c                   d}d}| j                         D ]g  \  }}|j                         }|dk(  rt        |d      r|j                  }|j                  j
                  dk(  r|dz  }||z  }|j                  sc||z  }i ||fS )zg
        Returns the number of trainable parameters and number of all parameters in the model.
        r   ds_numel
Params4bit   )named_parametersnumelr"   rC   r:   __name__requires_grad)r8   trainable_params	all_param_param
num_paramss         r   get_nb_trainable_parametersz*PeftMixedModel.get_nb_trainable_parameters   s    
 	--/ 	/HAuJQ75*#="^^

 ''<7'!^
#I"" J. 	/   **r    c           	     d    | j                         \  }}t        d|dd|ddd|z  |z  d       y)a  
        Prints the number of trainable parameters in the model.

        Note: print_trainable_parameters() uses get_nb_trainable_parameters() which is different from
        num_parameters(only_trainable=True) from huggingface/transformers. get_nb_trainable_parameters() returns
        (trainable parameters, all parameters) of the Peft Model which includes modified backbone transformer model.
        For techniques like LoRA, the backbone transformer model is modified in place with LoRA modules. However, for
        prompt tuning, the backbone transformer model is unmodified. num_parameters(only_trainable=True) returns number
        of trainable parameters of the backbone transformer model which can be different.
        ztrainable params: z,dz || all params: z || trainable%: d   z.4fN)rO   print)r8   rJ   rK   s      r   print_trainable_parametersz)PeftMixedModel.print_trainable_parameters   sU     '+&F&F&H#) !1" 5 6$R. )!11I=cBD	
r    c                z    	 t         |   |      S # t        $ r |dk(  r t        | j                  |      cY S w xY w)z1Forward missing attributes to the wrapped module.r6   )r3   __getattr__AttributeErrorr!   r6   )r8   namer:   s     r   rU   zPeftMixedModel.__getattr__   sC    	27&t,, 	2|#4??D11	2s    %::c                &     | j                   |i |S )z,
        Forward pass of the model.
        )r6   r8   argskwargss      r   forwardzPeftMixedModel.forward   s     t///r    c                :     | j                   j                  |i |S )z"
        Generate output.
        )r6   generaterY   s      r   r^   zPeftMixedModel.generate   s      (t''888r    c              #     K   	 | j                   j                          d | j                   j                          y# | j                   j                          w xY ww)z.
        Disables the adapter module.
        N)r6   disable_adapter_layersenable_adapter_layersr=   s    r   disable_adapterzPeftMixedModel.disable_adapter   s>     
	4OO224OO113DOO113s   A= AAAc                    t        |       	 || j                  |<   | j                  j                  | ||       | j                  ||       y# t        $ r || j                  v r| j                  |=  w xY w)a   
        Add an adapter to the model based on the passed configuration.

        This adapter is not trained. To load a trained adapter, check out [`PeftModel.load_adapter`].

        The name for the new adapter should be unique.

        The new adapter is not automatically set as the active adapter. Use [`PeftModel.set_adapter`] to set the active
        adapter.

        Args:
            adapter_name (`str`):
                The name of the adapter to be added.
            peft_config ([`PeftConfig`]):
                The configuration of the adapter to be added.
            low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
                Create empty adapter weights on meta device. Useful to speed up the process when loading saved
                adapters.

                <Tip>

                Don't use `low_cpu_mem_usage=True` when creating a new PEFT adapter for training (training is untested
                and discouraged for PeftMixedModel in general).

                </Tip>
        )low_cpu_mem_usageN)r-   r,   r6   inject_adapter	Exceptionr7   )r8   r9   r,   rd   s       r   add_adapterzPeftMixedModel.add_adapter   s}    6 	!-	-8D\*OO**4Qb*c 	  l;  	t///$$\2	s   -A &A3c           	         t        |dd       x}y | j                  t        |      | _        n| j                  j                  |       t	        | |t        |dd              y )Nr5   )module_names)r!   r5   setupdater   )r8   r,   r9   r5   s       r   r7   z"PeftMixedModel.set_modules_to_save   s^    &{4EtLLOU'#&#7D   ''8t\M^`d8efr    c           	     P   t        |t              r|g}t        |      t        | j                  j	                               z
  }|r;t        dt        |       dt        | j                  j	                                      | j                  j                  |       t        | |       y)a  
        Sets the active adapter(s) for the model.

        Note that the order in which the adapters are applied during the forward pass may not be the same as the order
        in which they are passed to this function. Instead, the order during the forward pass is determined by the
        order in which the adapters were loaded into the model. The active adapters only determine which adapters are
        active during the forward pass, but not the order in which they are applied.

        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]`):
                The name of the adapter(s) to be activated.
        Adapter(s)   not found, available adapters: N)

isinstancestrrj   r,   keysr*   sortedr6   set_adapterr   r8   r9   
mismatcheds      r   rs   zPeftMixedModel.set_adapter   s    , lC((>L&T-=-=-B-B-D)EE
fZ011QRXY]YiYiYnYnYpRqQrs  	##L1T<(r    c           	     8   t        |t              r|g}t        |      t        | j                  j	                               z
  }|r;t        dt        |       dt        | j                  j	                                      | j                  j                  |       y )Nrm   rn   )	ro   rp   rj   r,   rq   r*   rr   r6   delete_adapterrt   s      r   rw   zPeftMixedModel.delete_adapter"  s    lC((>L&T-=-=-B-B-D)EE
fZ011QRXY]YiYiYnYnYpRqQrs  	&&|4r    c                :     | j                   j                  |i |S )a  
        This method merges the adapter 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`.
        )r6   merge_and_unloadrY   s      r   ry   zPeftMixedModel.merge_and_unload.  s      0t//@@@r    c                :     | j                   j                  |i |S )z
        Gets back the base model by removing all the adapter modules without merging. This gives back the original base
        model.
        )r6   unloadrY   s      r   r{   zPeftMixedModel.unload?  s     
 &t%%t6v66r    c                H    t        d| j                  j                   d      )Nz&get_layer_status is not supported for .	TypeErrorr:   rH   r=   s    r   get_layer_statuszPeftMixedModel.get_layer_statusF  #    @AXAX@YYZ[\\r    c                H    t        d| j                  j                   d      )Nz&get_model_status is not supported for r}   r~   r=   s    r   get_model_statuszPeftMixedModel.get_model_statusI  r   r    c                ,    t        j                  |      S r<   )r   _split_kwargs)clsr[   s     r   r   zPeftMixedModel._split_kwargsL  s    &&v..r    c                2    t        j                  | ||      S )N)is_trainable)r   _check_new_adapter_config)r8   r,   r   s      r   r   z(PeftMixedModel._check_new_adapter_configP  s    224S_``r    c                r    t        j                  | ||g|i |}| j                  | j                         |S )a  
        Load a trained adapter into the model.

        The name for the new adapter should be unique.

        The new adapter is not automatically set as the active adapter. Use [`PeftModel.set_adapter`] to set the active
        adapter.

        Args:
            adapter_name (`str`):
                The name of the adapter to be added.
            peft_config ([`PeftConfig`]):
                The configuration of the adapter to be added.
            is_trainable (`bool`, *optional*, defaults to `False`):
                Whether the adapter should be trainable or not. If `False`, the adapter will be frozen and can only be
                used for inference.
            torch_device (`str`, *optional*, defaults to None):
                The device to load the adapter on. If `None`, the device will be inferred.
            autocast_adapter_dtype (`bool`, *optional*, defaults to `True`):
                Whether to autocast the adapter dtype. Defaults to `True`. Right now, this will only cast adapter
                weights using float16 and bfloat16 to float32, as this is typically required for stable training, and
                only affect select PEFT tuners.
            ephemeral_gpu_offload (`bool`, *optional*, defaults to `False`):
                Whether to use ephemeral GPU offloading for partially loaded modules. Defaults to `False`.
            low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
                Create empty adapter weights on meta device before loading the saved weights. Useful to speed up the
                process.
            kwargs: (`optional`):
                Additional arguments to modify the way the adapter is loaded, e.g. the token for Hugging Face Hub.
        )r   load_adapterrs   rA   )r8   model_idr9   rZ   r[   r   s         r   r   zPeftMixedModel.load_adapterS  s<    @ ''hVtVvV--.r    c                H    t        d| j                  j                   d      )Nz)Model card creation is not supported for  (yet).NotImplementedErrorr:   rH   )r8   
output_dirs     r   create_or_update_model_cardz*PeftMixedModel.create_or_update_model_cardx  s#    !$MdnnNeNeMffm"noor    c                H    t        d| j                  j                   d      )NzSaving is not supported for r   r   )r8   save_directorysafe_serializationselected_adaptersr[   s        r   save_pretrainedzPeftMixedModel.save_pretrained{  s%     "$@AXAX@YY`"abbr    c                   ddl m}m} |o |t        j                  ||j                  dd      |j                  dd      |j                  dd      |j                  dd               j                  |fi |}n1t        |t              r	| |_        nt        d	|j                         |j                  |vrt        d
|j                   d      t        |dd      Kt        t        |j                  j!                               j#                  ddh            dkD  rt%        |       |j&                  r|rt        d      | |_         | |||      } |j(                  ||fd|i| |S )a  
        Instantiate a PEFT mixed model from a pretrained model and loaded PEFT weights.

        Note that the passed `model` may be modified inplace.

        Args:
            model (`nn.Module`):
                The model to be adapted.
            model_id (`str` or `os.PathLike`):
                The name of the PEFT configuration to use. Can be either:
                    - A string, the `model id` of a PEFT configuration hosted inside a model repo on the Hugging Face
                      Hub.
                    - A path to a directory containing a PEFT configuration file saved using the `save_pretrained`
                      method (`./my_peft_config_directory/`).
            adapter_name (`str`, *optional*, defaults to `"default"`):
                The name of the adapter to be loaded. This is useful for loading multiple adapters.
            is_trainable (`bool`, *optional*, defaults to `False`):
                Whether the adapter should be trainable or not. If `False`, the adapter will be frozen and use for
                inference
            config ([`~peft.PeftConfig`], *optional*):
                The configuration object to use instead of an automatically loaded configuration. This configuration
                object is mutually exclusive with `model_id` and `kwargs`. This is useful when configuration is already
                loaded before calling `from_pretrained`.
            low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
                Create empty adapter weights on meta device before loading the saved weights. Useful to speed up the
                process.
            kwargs: (`optional`):
                Additional keyword arguments passed along to the specific PEFT configuration class.
        r   )PEFT_TYPE_TO_CONFIG_MAPPING PEFT_TYPE_TO_MIXED_MODEL_MAPPINGN	subfolderrevision	cache_diruse_auth_token)r   r   r   r   z+The input config must be a PeftConfig, got zAdapter of type z# is not supported for mixed models.hf_device_mapcpudiskr   zRCannot set a prompt learning adapter to trainable when loading pretrained adapter.r   )mappingr   r   r   _get_peft_typegetfrom_pretrainedro   inference_moder*   r:   r)   r!   lenrj   r   valuesintersectionr   is_prompt_learningr   )	r   r$   r   r9   r   r1   r[   r   r   s	            r   r   zPeftMixedModel.from_pretrained  s   P 	[ >0))$jjd;#ZZ
D9$jjd;#)::.>#E oh2 +12F 
+(4$4F!J6K[K[J\]^^ #CC/0@0@/AAdeffE?D1=3##**,-::E6?KD
D (.$$qrr(4$4F! E6<08\WWPVWr    )default)r$   	nn.Moduler,   r   r9   rp   returnNone)r   zdict[str, PeftConfig])r   rp   )r   z	list[str])rW   rp   )rZ   r   r[   r   )F)r9   rp   r,   r   rd   boolr   r   )r,   r   r9   rp   r   r   )r9   zUnion[str, list[str]]r   r   )r[   zdict[str, Any])r,   r   r   r   r   r   )r   rp   r9   rp   rZ   r   r[   r   )r   rp   )FN)r   rp   r   r   r   zOptional[list[str]]r[   r   )r   FN)r$   r   r   zstr | os.PathLiker9   rp   r   r   r1   zOptional[PeftConfig]r[   r   ) rH   
__module____qualname____doc__r4   propertyr,   r?   rA   rO   rS   rU   r\   r^   r   rb   rg   r7   rs   rw   ry   r{   r   r   classmethodr   r   r   r   r   r   __classcell__)r:   s   @r   r/   r/   C   sd    D6  + + . . / /+2
(209 4 4%<Ng )D
5A"7]] / /a#Jp $)15	cc !c /	c
 c 
 &"'+LL $L 	L
 L %L L Lr    r/   )r$   r   r   r   )r,   r   r   r   )
__future__r   os
contextlibr   typingr   r   r   torchaccelerate.hooksr   r	   transformers.utilsr
   peft.utils.constantsr   r1   r   
peft_modelr   tunersr   utilsr   r   r%   r-   Moduler/    r    r   <module>r      sT    # 	 % ' '  8  - 3  !  /Y.
N^UXX__ Nr    