
    biD                     
   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mZ d dlmZmZmZmZ d d	lmZmZmZ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$ d
dl%m&Z&m'Z'  G d de      Z(y)    N)asdict)Enum)Optional)nn)tqdm)is_bnb_4bit_availableis_bnb_available)	BaseTunerBaseTunerLayercheck_target_module_existsonload_layer)2TRANSFORMERS_MODELS_TO_LORA_TARGET_MODULES_MAPPINGModulesToSaveWrapper_get_submodulesget_quantization_config   )dispatch_aqlm)dispatch_awq)	OFTConfig)dispatch_eetq)dispatch_gptq)dispatch_hqq)dispatch_inc)OFTLayerdispatch_defaultc            	           e Zd ZU dZdZeed<   deddfdZe	d        Z
d	 Zd
 Zdej                  ddfdZe	d        Zdef fdZd defdZd!dZd"dZd Zd Z fdZe	d        Z	 	 	 	 d#dededeee      fdZdeddfdZ	 d$dededeee      dej                  j                  fdZdej                  j                  fdZ  xZ!S )%OFTModelaE  
    Creates Orthogonal Finetuning model from a pretrained model. The method is described in
    https://huggingface.co/papers/2306.07280

    Args:
        model (`torch.nn.Module`): The model to which the adapter tuner layers will be attached.
        config ([`OFTConfig`]): The configuration of the OFT 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 OFT model.

    Example:
        ```py
        >>> from diffusers import StableDiffusionPipeline
        >>> from peft import OFTModel, OFTConfig

        >>> config_te = OFTConfig(
        ...     r=8,
        ...     target_modules=["k_proj", "q_proj", "v_proj", "out_proj", "fc1", "fc2"],
        ...     module_dropout=0.0,
        ...     init_weights=True,
        ... )
        >>> config_unet = OFTConfig(
        ...     r=8,
        ...     target_modules=[
        ...         "proj_in",
        ...         "proj_out",
        ...         "to_k",
        ...         "to_q",
        ...         "to_v",
        ...         "to_out.0",
        ...         "ff.net.0.proj",
        ...         "ff.net.2",
        ...     ],
        ...     module_dropout=0.0,
        ...     init_weights=True,
        ... )

        >>> model = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
        >>> model.text_encoder = OFTModel(model.text_encoder, config_te, "default")
        >>> model.unet = OFTModel(model.unet, config_unet, "default")
        ```

    **Attributes**:
        - **model** ([`~torch.nn.Module`]) -- The model to be adapted.
        - **peft_config** ([`OFTConfig`]): The configuration of the OFT model.
    oft_prefixconfigreturnNc                     t        | j                        dkD  r2|j                  dk7  r"t        | j                  j
                   d      yy)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
ValueError	__class____name__)selfr    s     P/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/peft/tuners/oft/model.py_check_new_adapter_configz"OFTModel._check_new_adapter_configf   sR       !A%FKK6,A>>**+ ,7 7  -B%    c                     t        | |      S N)r   )
oft_configkeys     r+   _check_target_module_existsz$OFTModel._check_target_module_existsu   s    )*c::r-   c                    |t        d      |j                  |j                  |j                  |j                  |j
                  |j                  |j                  |j                  |j                  |j                  t        | j                  dd      t        | j                  dd      d}g d}	|	D ]$  }
t        | j                  |
      }||||
 d<   & t        |t              syt!        | j                  d	      r| j                  j"                  nd } | j$                  |||fd
|i|}|| j&                  vr|j)                  d       | j+                  ||||       y |j-                  ||j                  |j                  |j                  |j                  |j
                  |j                  |j                  |j                  |j                  
       y )NzCurrent Key shouldn't be `None`is_loaded_in_8bitFis_loaded_in_4bit)roft_block_sizemodule_dropoutcoftepsblock_shareuse_cayley_neumannnum_cayley_neumann_termsfan_in_fan_outinit_weightsloaded_in_8bitloaded_in_4bit)gptqaqlmawq)method_quantization_confighf_device_map
device_map)	r6   r7   r8   r9   r:   r;   r<   r=   r?   )r'   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   getattrmodelr   
isinstancer   hasattrrG   _create_new_moduleactive_adaptersrequires_grad__replace_moduleupdate_layer)r*   r0   adapter_nametargettarget_nameparentcurrent_keyoptional_kwargskwargsquant_methodsquant_methodquantization_configrH   
new_modules                 r+   _create_and_replacezOFTModel._create_and_replacey   s    >?? (77(77OO>>%11","?"?(2(K(K(77&33%djj2EuM%djj2EuM
 0) 	TL"9$**\"Z".@S,';<=	T &(+5<TZZ5Y11_cJ000\6s^hslrsJ4#7#77))%0  j&I,,)88)88__NN&22#-#@#@)3)L)L'44   r-   c                 H   t        |||       t        |d      r|j                  }t        j                  d      |j                         D ]  \  }}| j                  |v sd|v st        |d      r|j                  }net        |d      r|j                  }nLt        |d      r|j                  }n3t        |dd       |j                  }nt        |j                               }t        fd|j                         D              r|j                  |j                          y )	N
base_layermetaranknumqweightW_qweightin_proj_weightc              3   <   K   | ]  }|j                   k(    y wr/   )device).0pr`   s     r+   	<genexpr>z+OFTModel._replace_module.<locals>.<genexpr>   s     I188t+Is   )setattrrL   r_   torchrg   named_modulesr   rb   rc   rd   rI   re   next
parametersanyto)	r*   rU   
child_namer\   childnamemodulerd   r`   s	           @r+   rP   zOFTModel._replace_module   s    
J/
 5,'$$E||F#&446 	-LD&t#d):5),"]]FUE*"YYFUH-"\\FU$4d;G"11F!%"2"2"45FIV5F5F5HIIIIfmm,	-r-   rJ   c                    |j                         D ]  \  }}| j                  |vsd|_         | j                  D ]  }| j                  |   j
                  }|dk(  r"|dk(  r%|j                         D ]  \  }}d|v sd|_         L|dk(  rU|j                         D ]A  \  }}t        |t              st        |d      s$|j
                  1d|j
                  _        C t        d| d       y )	NFr#   allr&   Toft_onlyzRequested bias: z, is not implemented.)named_parametersr   requires_gradrN   r%   r&   rm   rK   r   rL   NotImplementedError)r*   rJ   nri   active_adapterr&   rt   ms           r+    _mark_only_adapters_as_trainablez)OFTModel._mark_only_adapters_as_trainable   s   **, 	(DAq{{!#"'	( #22 	ZN##N388Dv~u}!224 /DAq{*./ #$224 4GD!!!X.71f3E!&&J\/3,4 *,<TFBW*XYY	Zr-   c           	      J   g }t               rddlm} |j                  |       t	               rddlm} |j                  |       |j                  t        t        t        t        t        t        t        g       d }|D ]  } |||fd| i|}| n |t        d| d      |S )Nr   )dispatch_bnb_8bit)dispatch_bnb_4bitr0   zTarget module zm is not supported. Currently, only the following modules are supported: `torch.nn.Linear`, `torch.nn.Conv2d`.)r	   bnbr   appendr   r   extendr   r   r   r   r   r   r   r'   )	r0   rR   rS   rX   dispatchersr   r   r\   
dispatchers	            r+   rM   zOFTModel._create_new_module   s      .01 ".01 
	
 
% 	J#FLZZZSYZJ%	
   )8 8 
 r-   rt   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.rJ   )super__getattr__AttributeErrorrI   rJ   )r*   rt   r(   s     r+   r   zOFTModel.__getattr__  sB    	-7&t,, 	-w4::t,,	-s    %::	inferencec           
         i }| j                   j                         D ]U  \  }}t        |      j                         D ci c]$  \  }}|t        |t              r|j
                  n|& }}}|sQd|d<   W |<   |S c c}}w )NTinference_mode)r%   itemsr   rK   r   value)r*   r   config_dictr1   r   kvr    s           r+   get_peft_config_as_dictz OFTModel.get_peft_config_as_dict  s    **002 	0JCKQRW=K^K^K`a41aaJq$$7Q>aFa+/'(	0 "C	 bs   )A<c                     | j                   j                         D ]*  }t        |t        t        f      s|j                  |       , y r/   )rJ   modulesrK   r   r   enable_adapters)r*   enabledru   s      r+   _set_adapter_layerszOFTModel._set_adapter_layers  s<    jj((* 	0F&>3G"HI&&w/	0r-   c                 (    | j                  d       y)zyEnable all adapters.

        Call this if you have previously disabled all adapters and want to re-enable them.
        Tr   N)r   r*   s    r+   enable_adapter_layerszOFTModel.enable_adapter_layers#  s    
 	   .r-   c                     | j                   D ]<  }| j                  |   j                  }|dk7  s"d| d}t        j                  |       > | j                  d       y )Nr#   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   )rN   r%   r&   warningswarnr   )r*   r}   valmsgs       r+   disable_adapter_layerszOFTModel.disable_adapter_layers*  sp    "22 	#N"">277Cf}TUXTY ZG G  c"	# 	   /r-   c                     | j                   j                         D ]U  }t        |t              s|j                  r%t        j                  d       |j                          |j                  |       W || _	        y)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)
rJ   r   rK   r   mergedr   r   unmergeset_adapterr}   )r*   rR   ru   s      r+   r   zOFTModel.set_adapter5  s`     jj((* 	1F&(+==MM"noNN$""<0	1 +r-   c                     t         |           t        | j                  dd      dk(  rt	        d      | j
                  j                  d      rt	        d      y)zVerify that the configuration supports merging.

        Currently gptq quantization and replicated layers do not support merging.
        quantization_methodNrB   z8Cannot merge OFT layers when the model is gptq quantizedlayer_replicationz=Cannot merge OFT layers when base model layers are replicated)r   _check_merge_allowedrI   rJ   r'   r%   get)r*   r(   s    r+   r   zOFTModel._check_merge_allowedL  sX    
 	$&4::4d;vEWXX 34\]] 5r-   c                 ~    | j                   0|d   t        vrt        d      t        t        |d            | _         | S )N
model_typez0Please specify `target_modules` in `peft_config`)target_modulesr   r'   set)r%   model_configs     r+   _prepare_adapter_configz OFTModel._prepare_adapter_configW  sK    %%-L)1cc !STT),B<P\C]^*K& r-   progressbar
safe_mergeadapter_namesc                    |r| j                          | j                  j                         D cg c]  \  }}| j                  |vs| }}}d|rdndz   dz   }t	        || |      D ]  }	 t        | j                  |      \  }	}
}t        |
      5  t        |
d      r)|
j                  |||      }| j                  |	|||
       nCt        |
d      r7|r|
j                  ||	       | j                  |	||
j                         |
       d d d         | j                  S c c}}w # t        $ r Y w xY w# 1 sw Y   xY w)
Nz
Unloading zand merging  rJ   )disabledesc"unload_and_optionally_merge_module)merger   r   r_   )r   r   )r   rJ   rm   r   r   r   r   r   rL   r   rP   r   get_base_layer)r*   r   r   r   r   r1   _key_listr   rU   rS   rT   unloaded_modules                r+   _unload_and_optionally_mergez%OFTModel._unload_and_optionally_mergea  sV    %%'&*jj&>&>&@[FCDKKWZDZC[[~B?'Ik/E 	_C.=djj#.N+ f% 
_6#GH&,&O&O#
- 'P 'O ((ovVV\2
-X((f>S>S>UW]^
_ 
_	_" zz' \
 " 
_ 
_s*   D!D!-D'A9D6'	D32D36D?	rR   c                    |t        | j                  j                               vrt        d| d      | j                  |= | j                  j                         D cg c]  \  }}| j                  |vs| }}}d}|D ]P  }t        | j                  |      \  }}}t        |t              s.|j                  |       |B|j                  dd }R |xs g | _        | j                  ||       yc c}}w )z
        Deletes an existing adapter.

        Args:
            adapter_name (str): Name of the adapter to be deleted.
        zAdapter z does not existN)new_active_adapters)listr%   keysr'   rJ   rm   r   r   rK   r   delete_adapterrN   r}   _delete_auxiliary_adapter)r*   rR   r1   r   r   new_adapterrS   s          r+   r   zOFTModel.delete_adapter  s     tD$4$4$9$9$;<<x~_EFF\*&*jj&>&>&@[FCDKKWZDZC[[ 	<C*4::s;LAvq&(+%%l3&"("8"8";K	< */R&&|&U \s   C36C3c                 *    | j                  |||      S )a  
        This method merges the OFT 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`.

        )r   r   r   r   )r*   r   r   r   s       r+   merge_and_unloadzOFTModel.merge_and_unload  s#    $ 00#
- 1 
 	
r-   c                 &    | j                  d      S )z
        Gets back the base model by removing all the oft modules without merging. This gives back the original base
        model.
        F)r   r   r   s    r+   unloadzOFTModel.unload  s    
 00u0==r-   )F)T)r!   N)TFFN)FFN)"r)   
__module____qualname____doc__r   str__annotations__r   r,   staticmethodr2   r]   rP   r   Moduler   rM   r   boolr   r   r   r   r   r   r   r   r   r   r   rl   r   r   __classcell__)r(   s   @r+   r   r   0   s`   1f FC	 d  ; ;6p-4Zbii ZD Z* ) )V- - 0
/	0+.	^   ! -1  	
  S	*>V3 V4 V0 im

59
RZ[_`c[dRe
	
,> >r-   r   ))r   dataclassesr   enumr   typingr   rl   r   r   peft.import_utilsr   r	   peft.tuners.tuners_utilsr
   r   r   r   
peft.utilsr   r   r   r   rC   r   rD   r   r    r   eetqr   rB   r   hqqr   incr   layerr   r   r    r-   r+   <module>r      s[           E           -B>y B>r-   