o
    Ni:                     @   s   d dl Z d dlZd dlmZmZmZ d dlZd dlmZ d dl	m  m
Z d dlmZmZ G dd deZG dd dejeZdS )    N)AnyOptionalUnion)BaseTunerLayercheck_adapters_to_mergec                   @   s   e Zd ZdZdZdejddfddZ	dd	ed
e	de
de
ddf
ddZd	efddZd	efddZd	efddZdeddfddZddddZdS )	BoneLayer)
bone_block)bone_r
base_layerreturnNc                 K   sl   || _ i | _ti | _d| _g | _d| _|| _| 	 }t
|tjr-|j|j| _| _d S tdt| )NFTzUnsupported layer type )r
   r	   nnParameterDictr   _disable_adaptersmerged_adapterscast_input_dtype_enabledkwargsget_base_layer
isinstanceLinearin_featuresout_features
ValueErrortype)selfr
   r    r   J/home/ubuntu/.local/lib/python3.10/site-packages/peft/tuners/bone/layer.py__init__   s   zBoneLayer.__init__Fadapter_namerinit_weightsinference_modec                 K   s   |dkrt d| || j|< |  }t|tjr*tjt|| j	dd| j
|< n
tdt|j |dkrQ| j| dksF| j	| dkrJt d| || n|rZ| || n| | | | | j| j|d d	S )
zInternal function to create bone adapter

        Args:
            adapter_name (`str`): Name for the adapter to add.
            r (`int`): Rank for the added adapter.
            init_weights (`bool`): Whether to initialize weights.
        r   z?`r` should be a positive integer value but the value passed is Trequires_gradz0Bone is not implemented for base layers of type batz=The weight matrix must be fully divisible into [r, r] blocks.)r    N)r   r	   r   r   r   r   	Parametertorchzerosr   r   	TypeErrorr   __name__r   reset_bat_parametersreset_bone_parametersreset_bone_parameters_random%_move_adapter_to_device_of_base_layerset_adapteractive_adapters)r   r   r   r   r    r   r
   r   r   r   update_layer0   s    
 

zBoneLayer.update_layerc                 C   s"   t jt|| jdd| j|< d S NTr!   r   r$   r%   r&   r   r   r   r   r   r   r   r   r*   Y   s   "zBoneLayer.reset_bone_parametersc                 C   s(   t jt| j| ||dd| j|< d S r0   r1   r2   r   r   r   r)   \   s   (zBoneLayer.reset_bat_parametersc                 C   s    t jj| j| tdd d S )N   )a)r   initkaiming_uniform_r   mathsqrt)r   r   r   r   r   r+   _   s    z&BoneLayer.reset_bone_parameters_randomscalec                 C   s6   |dkrd S | j D ]}|| j vrq	td q	d S )N   zGScaling operation for Bone not supported! Automatically set scale to 1.r.   r   keyswarningswarnr   r9   active_adapterr   r   r   scale_layerb   s   
zBoneLayer.scale_layerc                 C   s*   | j D ]}|| j vrqtd qd S )Nz?Unscaling operation for Bone not supported! Keeping scale at 1.r;   r?   r   r   r   unscale_layerl   s
   
zBoneLayer.unscale_layerFNr   N)r(   
__module____qualname__adapter_layer_namesother_param_namesr   Moduler   strintboolr/   r*   r)   r+   floatrA   rB   r   r   r   r   r      s*    
)
r   c                	       s   e Zd ZdZ		ddededeeef ddf fd	d
Zddede	e
e  ddfddZd ddZd!dedejfddZd!dedejfddZdejdededejfddZdef fddZ  ZS )"
BoneLinearz,
    Bone implemented in a dense layer.
    r   Tr   r   r   r   Nc                    sD   t    tj| |fi | || _| j|||fi | || _d S rD   )superr   r   _active_adapterr/   bone_fn)r   r
   r   r   r   r   	__class__r   r   r   y   s
   

zBoneLinear.__init__F
safe_mergeadapter_namesc                 C   s  t | |}|s	dS |D ]{}|| j v r|  }|jj}|rV|jj }| jdkr4| 	||}||7 }n| 
|| jjj}|}t| sNtd| d|||j_n*| jdkrp| 	|| jjj}|j j||7  _n| 
|| jjj}|||j_| j| qdS )ab  
        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`.
        Nr#   z1NaNs detected in the merged weights. The adapter z seems to be broken)r   r   r<   r   weightdtypedataclonerR   get_delta_weightget_delta_weight_boner
   r%   isfiniteallr   tor   append)r   rU   rV   r@   r
   
orig_dtypeorig_weightdelta_weightr   r   r   merge   s6   




zBoneLinear.mergec                 C   s   | j s
td dS t| jdkrS| j }|  }|jj}|| j	
 v rJ|  jj }| jdkr;| j||dd}n| j||dd}|||j_t| jdksdS dS )zW
        This method unmerges all merged adapter layers from the base weights.
        z Already unmerged. Nothing to do.Nr   r#   T)re)mergedr=   r>   lenr   popr   rW   rX   r   r<   rY   rZ   rR   r[   r\   r_   )r   r@   r
   ra   rb   rc   r   r   r   unmerge   s   


zBoneLinear.unmergere   c                 C   sd  | j | j}| j | j}|jdko|tjkp|tjk}| j | }|r&| }||j}|	d}|rw|
|	d| ||	d| |dddd}	t|	d|j}
t|
| }||j}|	| | }|ddddj
|j }n(|
|	d| ||	d| |dddd| | }|ddddj
|j }|r|j|d}||| j | _|S )
        Compute the delta weight for the given adapter.

        Args:
            adapter (str):
                The name of the adapter for which the delta weight should be computed.
        cpur   r:         rX   )r   devicerX   r   r%   float16bfloat16rN   r_   sizereshapepermuteeyeinverseshaperY   )r   adapterrb   re   rp   rX   cast_to_fp32weight_boner   ooneinv_I_plus_bwoutput_tensorr   r   r   r[      s4   

0.zBoneLinear.get_delta_weightc                 C   st  | j | j}| j | j}|jdko|tjkp|tjk}| j | }|r&| }|d}|d}	||	 dkr||	 }
||	 }||	 }|r|ddd|f 	d||	
ddd| 
dddj	|ddd|f j |ddd|f< |dd|df |ddddd|
f  |dd|df< nO|ddd|f 	d||	
ddd| 
dddj	|ddd|f j |ddd|f< |dd|df |ddddd|
f  |dd|df< |}n@|r|	d|d|	 |	
ddd| }|
dddj	|j }n|	d|d|	 |	
ddd| }|
dddj	|j }|r8|j|d}||| j | _|S )rj   rk   rl   r   Nr:   rm   ro   )r   rp   rX   r   r%   rq   rr   rN   rs   rt   ru   rx   	transposer_   rY   )r   ry   rb   re   rp   rX   rz   r{   r   r   	last_sizen_blockn_block_sizer   r   r   r   r   r\      sJ   


*
.*
.&&z BoneLinear.get_delta_weight_bonexargsr   c                 O   s  |j }| jr| jr|   | j|g|R i |}n| jr*| j|g|R i |}n| jdkrg| jjj }| j	D ]}|| j
 vrCq9| ||}|| }q9| ||j }| | jj|j }	tj|||	d}nf| j|g|R i |}| j	D ]V}|| j
 vrqv| j
| }
|
d}|d| dkr||d|  | }t|d|f}| ||
j }|tj|jg |jd d |d| |R  dd|
  }qv||}|S )Nr#   )inputrW   biasr   rl   )dim)rX   disable_adaptersrf   ri   r
   rR   rW   rY   rZ   r.   r   r<   r[   _cast_input_dtyper   Flinearrs   padr%   sumrt   rx   r_   )r   r   r   r   previous_dtyperesultrb   r@   rc   r   boner   padding_sizer   r   r   forward9  s<   





@
zBoneLinear.forwardc                    s   t   }d| S )Nzbone.)rP   __repr__)r   reprS   r   r   r   ^  s   
zBoneLinear.__repr__)r   T)FNrE   rC   )r(   rF   rG   __doc__rK   rL   r   rM   r   r   listrd   ri   r%   Tensorr[   r\   r   r   r   __classcell__r   r   rS   r   rO   t   s&    
 
0.?%rO   )r7   r=   typingr   r   r   r%   torch.nnr   torch.nn.functional
functionalr   peft.tuners.tuners_utilsr   r   r   rJ   rO   r   r   r   r   <module>   s   [