o
    NÆÏiL  ã                   @  s´   d dl mZ d dlZ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mZ dd	lmZmZ e
ƒ rHG d
d„ dejjeƒZe	ƒ rXG dd„ dejjeƒZdS dS )é    )ÚannotationsN)ÚOptional)Úis_bnb_4bit_availableÚis_bnb_available)Úcheck_adapters_to_merge)Údequantize_bnb_weight)Ú	transposeé   )ÚRandLoraLayerÚUniqueBaseGradc                      ón   e Zd Z					d(d)‡ fdd„Zd*d+dd„Zd,dd„Zd-d.dd„Zd/d!d"„Zd0d$d%„Zd1‡ fd&d'„Z	‡  Z
S )2ÚLinear8bitLtr   ç        FTÚ
base_layerútorch.nn.ModuleÚadapter_nameÚstrÚrÚintÚrandlora_alphaÚrandlora_dropoutÚfloatÚfan_in_fan_outÚboolÚinit_weightsÚreturnÚNonec
              	     ó>   t ƒ  ¡  t | |¡ || _|| _| j|||||||	d d S ©N)r   r   r   ©ÚsuperÚ__init__r
   r   Ú_active_adapterÚupdate_layer©Úselfr   r   Ú
randlora_AÚ
randlora_Br   r   r   r   r   Úkwargs©Ú	__class__© úL/home/ubuntu/.local/lib/python3.10/site-packages/peft/tuners/randlora/bnb.pyr!   !   s   

ùzLinear8bitLt.__init__NÚ
safe_mergeÚadapter_namesúOptional[list[str]]c           	      C  sê   t | |ƒ}|s	dS |D ]g}|| j ¡ vrqt d¡ |  |¡}|  ¡ j}|  ¡ j}|j	du r2|j	|_	t
||ƒ}| |j¡ |j¡| }|rTt |¡ ¡ sTtd|› dƒ‚tjj| d¡d|jd |j¡|  ¡ _| ¡  | j |¡ qdS )á†  
            Merge the active adapter weights into the base weights

            Args:
                safe_merge (`bool`, *optional*):
                    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`.
            Nz[Merge RandLora module to 8-bit linear may get different generations due to rounding errors.ú1NaNs detected in the merged weights. The adapter ú seems to be brokenÚcpuF©Úrequires_gradÚhas_fp16_weights)r   Úrandlora_lambdaÚkeysÚwarningsÚwarnÚget_delta_weightÚget_base_layerÚweightÚstateÚSCBr   ÚtoÚdtypeÚdeviceÚtorchÚisfiniteÚallÚ
ValueErrorÚbnbÚnnÚ
Int8Paramsr6   Úreset_gradsÚmerged_adaptersÚappend)	r%   r-   r.   Úactive_adapterÚrandlora_datar=   r>   ÚoutputÚw_datar+   r+   r,   Úmerge=   s8   
ÿ





ÿÿþæzLinear8bitLt.mergec                 C  sà   | j s
t d¡ dS t| jƒdkrn| j ¡ }|| j ¡ vrq
t d¡ |  |¡}|  	¡ j
}|  	¡ j}|jdu r;|j|_t||d}| |j¡ |j¡| }tjj| d¡d|jd |j¡|  	¡ _
| ¡  t| jƒdksdS dS )	ú_
            This method unmerges all merged adapter layers from the base weights.
            úAlready unmerged. Nothing to doNr   z]Unmerge randlora module to 8-bit linear may get different generations due to rounding errors.)r>   r3   Fr4   )Úmergedr9   r:   ÚlenrK   Úpopr7   r8   r;   r<   r=   r>   r?   r   r@   rA   rB   rG   rH   rI   r6   rJ   )r%   rM   rN   r=   r>   rO   rP   r+   r+   r,   Úunmergek   s0   

ÿ



ÿþìzLinear8bitLt.unmergeú list[torch.Tensor, torch.Tensor]c                 C  ó,  | j | }| j| }|du r|j}|j}|jdko"|tjkp"|tjk}| j|  	|¡}| j
|  	|¡}|rE| ¡ }| ¡ }| ¡ }| ¡ }t| j| jƒt| j| jƒ}	}
|dd…d| j…d|	…f  	|¡}|d|
…d| j…dd…f  	|¡}|jdd}t |||¡jdd}|	| jkr||fS |j|jfS ©aL  
            Performs scaling on the smallest random base (randlora_A) and returns randlora_A and randlora_B in the
            correct order to fit the target layers' dimensions

            Args:
                adapter (str):
                    The name of the adapter for which the delta weight should be computed.
            Nr3   r	   )Ú	start_dim)Úend_dim©r&   r'   rB   rA   ÚtyperC   Úfloat16Úbfloat16r7   r@   Úrandlora_gammar   ÚminÚout_featuresÚin_featuresÚmaxÚ	num_basesÚflattenr   ÚapplyÚT©r%   ÚadapterrB   r&   r'   rA   Úcast_to_fp32r7   ra   Úmin_dimÚmax_dimÚsliced_AÚsliced_BÚupdate_BÚupdate_Ar+   r+   r,   Úget_scaled_bases‰   s*   


""
zLinear8bitLt.get_scaled_basesútorch.Tensorc                 C  ó4   |   |¡\}}|| }t|| jƒ}| j| }|| S ©zÖ
            Compute the delta weight for the given adapter.

            Args:
                adapter (str):
                    The name of the adapter for which the delta weight should be computed.
            ©rs   r   r   Úscaling©r%   rk   rq   rr   ÚupdateÚoutput_tensorrx   r+   r+   r,   r;   ¹   s
   	
zLinear8bitLt.get_delta_weightÚxc                 O  s*  | j r| jr
|  ¡  | j|g|¢R i |¤Ž}nx| jr'| j|g|¢R i |¤Ž}nh| j|g|¢R i |¤Ž}| jD ]X}|| j ¡ vr@q6| j||jd\}}t	 
¡  }|ra|j}	|j}
|j|
kra| |
¡}| j| }|| |j¡ƒ}t	jj t	jj ||¡|¡}|rƒ| |	¡}| j| }|||  }q6| |j¡S )a  
            Perform the forward pass using the RandLora adapter.

            Args:
                x (torch.Tensor): Input tensor.

            Returns:
                torch.Tensor: Output tensor after applying the RandLora adaptation.

            Note:
                This method implements the RandLora-specific forward pass. It applies the shared projections
                (randlora_A and randlora_B) along with the per-layer trainable parameters (lambda and gamma) to compute
                the adapter output.
            ©rB   )Údisable_adaptersrT   rW   r   Úactive_adaptersr7   r8   rs   rB   rC   Úis_autocast_enabledrA   r@   r   rH   Ú
functionalÚlinearrx   ©r%   r|   Úargsr(   ÚresultrM   rq   rr   Úrequires_conversionÚexpected_dtypeÚcompute_dtypeÚdropoutÚx_tempÚadapter_outputrx   r+   r+   r,   ÚforwardË   s2   






zLinear8bitLt.forwardc                   ó   t ƒ  ¡ }d| S ©Nz	randlora.©r    Ú__repr__©r%   Úrepr)   r+   r,   r   ý   ó   
zLinear8bitLt.__repr__©r   r   r   FT©r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ©FN©r-   r   r.   r/   r   r   ©r   r   ©N©r   rX   ©r   rt   ©r|   rt   r   rt   ©r   r   ©Ú__name__Ú
__module__Ú__qualname__r!   rQ   rW   rs   r;   rŒ   r   Ú__classcell__r+   r+   r)   r,   r       s    ö
.
0
2r   c                      r   )2Ú
Linear4bitr   r   FTr   r   r   r   r   r   r   r   r   r   r   r   r   r   c
              	     r   r   r   r$   r)   r+   r,   r!     s   

ùzLinear4bit.__init__Nr-   r.   r/   c                 C  sÄ   t | |ƒ}|s	dS |D ]T}|| j ¡ vrqt d¡ |  |¡}|  ¡ j}|j}t	j
 |j|j¡| }|rCt |¡ ¡ sCtd|› dƒ‚t	jj| d¡fddi|¤Ž |j¡|  ¡ _| j |¡ qdS )r0   Nz[Merge RandLora module to 4-bit linear may get different generations due to rounding errors.r1   r2   r3   r5   F)r   r7   r8   r9   r:   r;   r<   r=   Ú__dict__rG   r   Údequantize_4bitÚdataÚquant_staterC   rD   rE   rF   rH   Ú
Params4bitr@   rB   rK   rL   )r%   r-   r.   rM   rN   r=   r(   rP   r+   r+   r,   rQ      s,   
ÿ


ÿ
ÿëzLinear4bit.mergec                 C  s¸   | j s
t d¡ dS t| jƒdkrZ| j ¡ }|| j ¡ vrq
t d¡ |  |¡}|  	¡ j
}|j}tj |j|j¡| }tjj| d¡fddi|¤Ž |j¡|  	¡ _
t| jƒdksdS dS )rR   rS   Nr   z]Unmerge RandLora module to 4-bit linear may get different generations due to rounding errors.r3   r5   F)rT   r9   r:   rU   rK   rV   r7   r8   r;   r<   r=   r¤   rG   r   r¥   r¦   r§   rH   r¨   r@   rB   )r%   rM   rN   r=   r(   rP   r+   r+   r,   rW   I  s$   

ÿ


ÿózLinear4bit.unmergerX   c                 C  rY   rZ   r]   rj   r+   r+   r,   rs   b  s*   


""
zLinear4bit.get_scaled_basesrt   c                 C  ru   rv   rw   ry   r+   r+   r,   r;     s
   
zLinear4bit.get_delta_weightr|   c                 O  s2  | j r| jr
|  ¡  | j|g|¢R i |¤Ž}n|| jr'| j|g|¢R i |¤Ž}nl| j|g|¢R i |¤Ž}| ¡ }| jD ]X}|| j ¡ vrDq:| j||j	d\}}t
 ¡  }|re|j}	|j}
|j|
kre| |
¡}| j| }|| |j¡ƒ}t
jj t
jj ||¡|¡}|r‡| |	¡}| j| }|||  }q:| |j¡S )Nr}   )r~   rT   rW   r   Úcloner   r7   r8   rs   rB   rC   r€   rA   r@   r   rH   r   r‚   rx   rƒ   r+   r+   r,   rŒ   ¡  s4   






zLinear4bit.forwardc                   r   rŽ   r   r‘   r)   r+   r,   r   Æ  r“   zLinear4bit.__repr__r”   r•   r–   r—   r˜   r™   rš   r›   rœ   r   rž   r+   r+   r)   r,   r£     s    ö
)
.
%r£   )Ú
__future__r   r9   Útypingr   ÚbitsandbytesrG   rC   Úpeft.import_utilsr   r   Úpeft.tuners.tuners_utilsr   Úpeft.utils.integrationsr   Úpeft.utils.otherr   Úlayerr
   r   rH   ÚModuler   r£   r+   r+   r+   r,   Ú<module>   s     cþ