
    bi,                        d Z ddlmZ ddl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 d	d
lmZ d	dlmZ  G d de      Z	 d	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)zC
This module contains the implementation of the LoRA-FA optimizer.
    )annotationsN)Iterable)Callable)is_bf16_available)autocast)	Optimizer   )	PeftModel)infer_devicec                  x     e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 d fdZ ej                         ddd       Z xZS )LoraFAOptimizera;  
    Implements the LoRA-FA optimizer designed specifically for training Low-Rank Adaptation (LoRA) parameters
    efficiently. Note that LoraFAOptimizer is based on adamw-hf in transformers, with only LoRA part modified. Without
    LoRA it will fall back to adamw-hf.

    Args:
        params (Iterable[nn.parameter.Parameter]): Parameters to optimize.
        lr (float, optional): Learning rate (default: 1e-3).
        betas (Tuple[float, float], optional):
            Coefficients for computing running averages of gradient and squared gradient (default: (0.9, 0.999)).
        eps (float, optional): Term added to denominator to improve numerical stability (default: 1e-6).
        weight_decay (float, optional): Weight decay (L2 penalty) (default: 0.0).
        correct_bias (bool, optional): Whether to apply bias correction as in original Adam (default: True).

    Args in sub-function step:
        closure (Callable, optional): A closure that reevaluates the model and returns the loss.

    Reference:
        - LoRA-FA: https://huggingface.co/papers/2308.03303
    c                   |dk  rt        d| d      d|d   cxk  rdk  sn t        d|d    d      d|d   cxk  rdk  sn t        d|d    d      d|k  st        d	| d      |||||d
}t        | 	  ||       y )N        zInvalid learning rate: z - should be >= 0.0r         ?zInvalid beta parameter: z - should be in [0.0, 1.0)   zInvalid epsilon value: )lrbetasepsweight_decaycorrect_bias)
ValueErrorsuper__init__)	selfparamsr   r   r   r   r   defaults	__class__s	           Q/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/peft/optimizers/lorafa.pyr   zLoraFAOptimizer.__init__9   s     86rd:MNOOeAh$$7azA[\]]eAh$$7azA[\]]cz6se;NOPP((
 	*    c           
     H	   d}| |       }| j                   D ]y  }|d   }g }g }t        |d   |d         D ]W  \  }}d|vr|j                  |j                  }	d|v rW|j                  |       |j                  |       t	        |      dk(  r|d|j                  d       dz   }
nt	        |      dk(  r|}
| j                  
   }t	        |      dk(  rt	        |      dk(  r<d|d	<   t        j                  |d         |d
<   t        j                  |d         |d<   n5d|d	<   t        j                  |      |d<   t        j                  |      |d<   t	        |      dk(  r)|d   }|d   }|j                  }d}||j                  z  }t        j                  j                  ||t        j                  |j                  d         j                  |j                        z  z         }t!               }t#               r3t%        |t        j&                        5  d|dz  z  ||z  z  }ddd       nd|dz  z  ||z  z  }j(                  |j                  j(                  k7  r%|j                  |j                  j(                        }|d
   |d   }}|d   \  }}|d	xx   dz  cc<   |j+                  |      j-                  |d|z
         |j+                  |      j/                  ||d|z
         |j1                         j-                  |d         }|d   }|d   r1d||d	   z  z
  }d||d	   z  z
  }|t3        j0                  |      z  |z  }|j5                  |||        |d   dkD  r|j-                  ||d    |d   z         g }g }U|d   |d   }}|d   \  }}|d	xx   dz  cc<   |j+                  |      j-                  |	d|z
         |j+                  |      j/                  |	|	d|z
         |j1                         j-                  |d         }|d   }|d   r1d||d	   z  z
  }d||d	   z  z
  }|t3        j0                  |      z  |z  }|j5                  |||        |d   dkD  s;|j-                  ||d    |d   z         Z | |S # 1 sw Y   dxY w)z
        Performs a single optimization step.

        Arguments:
            closure (`Callable`, *optional*): A closure that reevaluates the model and returns the loss.
        Nscaling_factorr   nameslorar	   r   r   step	exp_avg_Bexp_avg_sq_Bexp_avg
exp_avg_sqg:0yE>)device_typedtyper   r   )alpha)valuer   r   r   r   r   )param_groupszipgradappendlenfindstatetorch
zeros_likeTlinalgpinveyeshapetodevicer   r   r   bfloat16r*   mul_add_addcmul_sqrtmathaddcdiv_)r   closurelossgroupr!   
param_list	name_listpnr/   namer3   ABgrad_B_orindeltaAA_TAA_T_invr)   grad_Br%   r&   beta1beta2denom_B	step_sizebias_correction1bias_correction2r'   r(   denoms                                  r   r$   zLoraFAOptimizer.stepS   s    9D&& s	PE"#34NJIE(OU7^< oP1?qvv~vvQ;%%a($$Q':!+ !1166&>2V;ZA- D 

4(u:?:!+()f-2-=-=jm-Lk*050@0@A0On-()f+0+;+;A+>i(.3.>.>q.Al+ z?a'"1A"1A"#&&K !E qss7D$||00		!''RS*@U@X@XYZYaYa@b8b1bcH"..K(*%+U^^T X&'.!*;&;h@V%WFX X #$na&7"7K(<R!S||qvv||3!'166<<!8.3K.@%BW|I#(>LE5&MQ&MNN5)..vcEk.K %%e,55ffCRWK5X*//166uU|DG %dI^,+.%-1G+G(+.%-1G+G($-		:J0K$KN^$^	JJy')JD^,s2q%+n8M)MO!#J "I +0	*:E,<OZG#(>LE5&MQ&M LL',,T#+,GOOE*33D$cEk3R&OO-225<@E %dI^,+.%-1G+G(+.%-1G+G($-		:J0K$KN^$^	JJwiZJ@ ^,s2q%+n8M)MO_oP	s	Pj uX Xs   RR!)gMbP?g?g+?gư>r   T)r   z Iterable[nn.parameter.Parameter]r   floatr   ztuple[float, float]r   r[   r   r[   r   bool)N)rD   r   )	__name__
__module____qualname____doc__r   r4   no_gradr$   __classcell__)r   s   @r   r   r   #   sv    0 %1!!+0+ + #	+
 + + +4 U]]_@ @r   r   c                0   | j                         D ]  \  }}d|v s|j                  d        |r|t        j                  |      z  n||z  }| j	                         || j                         D 	cg c]  \  }}	|	 c}	}|d|dg}
t        |
      S c c}	}w )a+  
    Helper function to instantiate a lorafa optimizer specifically configured for a given model using the LoRA method.

    This function will:
    - Disable gradient updates for the "lora_A" parameters (these are typically frozen during LoRA training).
    - Compute the scaling factor based on provided `lora_alpha` and rank `r` for proper gradient projection.
    - Create and configure parameter groups for the optimizer including specified learning rate, weight decay, and
      additional optimizer options.

    For hyper-params, LoRA-FA uses the same hyper-params as AdamW, except for the LoRA hyper-params (r, lora_alpha,
    use_rslora). One can always use the same hyper-params such as lr and weight_decay, as AdamW in LoRA tuning.

    Args:
        model (PeftModel): The model containing LoRA-adapted parameters.
        r (int): Rank of the LoRA decomposition.
        lora_alpha (int): Scaling factor for LoRA parameterization.
        lr (float): Learning rate for optimizer updates.
        weight_decay (float): Weight decay for AdamW.
        use_rslora (bool):
            whether to use rslora. In rslora, the lora scaling factor becomes to lora_alpha / math.sqrt(r) instead of
            lora_alpha / r.

    Returns:
        Optimizer: Configured lorafa optimizer instance ready for training.
    lora_AFrZ   )r   r   r"   r!   r   r   )named_parametersrequires_grad_rB   rA   
parametersr   )modelr
lora_alphar   r   
use_rslorarK   paramlora_scaling_r-   s              r   create_lorafa_optimizerro      s    8 --/ (et  '( 1;:		!,
QL &&(*/*@*@*BCwtQdC*!(	
	L <(( Ds   1B
)r   F)rh   r
   ri   intrj   rp   r   r[   r   r[   rk   r\   returnr   )r`   
__future__r   rB   collections.abcr   typingr   r4   torch.nnnnaccelerate.utils.importsr   r   torch.optimr   
peft_modelr
   utils.otherr   r   ro    r   r   <module>r|      s    #  $    6  ! " &qi qj in*)*)*)*-*)38*)HM*)ae*)*)r   