
    Pi(/                        d dl Z d dlmZmZmZmZmZmZmZm	Z	m
Z
 d dlZd dlmZ ed         Z G d de          Zdej        deeej        f         fd	Zdej        d
e
eeef         e	f         ddfdZdee         dededee         fdZ	 ddeeef         dee         deeef         fdZdeeef         de	e         fdZej        deeef         dededeeef         fd            Ze j        dej        ded         fd            Z	 	 	 	 d dee         dededeee                  deee                  deee                  deee                  ddfdZdS )!    N)	AnyDict	GeneratorListLiteralOptionalProtocolSetUnion)nn)q_projk_projv_projoutput_projc                   *    e Zd ZdZdee         fdZdS )AdapterModulez
    Interface for an ``nn.Module`` containing adapter weights.
    Note that an adapter module does not have to explicitly implement this protocol,
    but it must define the ``adapter_params(self)`` method.
    returnc                     dS )a  
        Return a list of strings corresponding to the names of the ``nn.Parameter`` s in
        the model coming from the adapter.
        E.g. if an nn.Module has adapter ``self.proj = nn.Linear(in_dim, out_dim)``,
        then adapter_params should return ``['proj.weight', 'proj.bias']``.

        See LoRALinear's :func:`~torchtune.modules.peft.LoRALinear.adapter_params` for an example.
        N )selfs    q/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/torchtune/modules/peft/_utils.pyadapter_paramszAdapterModule.adapter_params   s	     	    N)__name__
__module____qualname____doc__r   strr   r   r   r   r   r      s=         	S	 	 	 	 	 	 	r   r   modelr   c                    i }|                                  D ]\  }}t          |d          rt          |j                  r|                                }|                    d          D ]@\  }}||v r7|r| d| n|}|                    ||i           |                    |           A|g k    sJ d| d            |S )a  
    Return the subset of parameters from a model that correspond to an adapter.
    Assumes that any adapter class has defined the
    :func:`~torchtune.modules.peft.AdapterModule.adapter_params` method.

    Args:
        model (nn.Module): Instance of model class containing some adapter params.

    Returns:
        Dict[str, nn.Parameter]: the subset of model's state dict containing
        only adapter parameters.

    r   T)recurse.zAdapter params z not converted)named_moduleshasattrcallabler   named_parametersupdateremove)r   r   kvcurrent_adapter_paramsnpfull_keys           r   get_adapter_paramsr/   $   s    N##%% 
H 
H11&'' 		HHQ5E,F,F 		H%&%5%5%7%7"**4*88 5 51...-.5!zzazzzAH"))8Q-888*11!444&",,,G!7GGG -,,r   r   c                 h    |                                  D ]\  }}|                    ||v            dS )a  
    Set trainable parameters for an nn.Module based on a state dict of adapter parameters.

    Args:
        model (nn.Module): Instance of model class containing some adapter params.
        adapter_params (Union[Dict[str, Any], Set]): State dict mapping adapter key names to their
            respective nn.Parameters (i.e. outputs of :func:`~torchtune.modules.peft.get_adapter_params`.)

    Returns:
        None
    N)r&   requires_grad_)r   r   r)   r*   s       r   set_trainable_paramsr2   A   sI     &&(( . .1	n,----. .r   lora_attn_modulesapply_lora_to_mlpapply_lora_to_outputc                 J    | }|r|g dz   }|r|                     d           |S )a  
    Return a list of the names of modules in the model that have LoRA applied. Note that
    the names here are local to their modules and not the fully qualified names from the
    model state dict.


    Args:
        lora_attn_modules (List[LORA_ATTN_MODULES]): list of which linear layers
            LoRA should be applied to in each self-attention block. Options are
            ``{"q_proj", "k_proj", "v_proj", "output_proj"}``.
        apply_lora_to_mlp (bool): whether LoRA is applied to each MLP linear.
        apply_lora_to_output (bool): whether LoRA is applied to the final output projection.

    Returns:
        List[str]: list of module names in the model that have LoRA applied.
    )w1w2w3output)append)r3   r4   r5   lora_module_keyss       r   get_lora_module_namesr=   S   sG    * ) A+.@.@.@@ *)))r   cpu
state_dictdevicec                 N    d fd|                                  D             S )a  
    Return the subset of the full state_dict from a model that correspond to an adapter.
    Assumes that "lora" and "magnitude" are unique names for adapter parameters, and
    that the state_dict is not sharded. All returned parameters are moved to CPU.

    Args:
        state_dict (Dict[str, Any]): Full model state dict.
        device (Optional[str]): device to move adapter parameters to. Default: 'cpu'

    Returns:
        Dict[str, Any]: the subset of model's state dict containing
        only adapter parameters.

    c                     d| v pd| v S )Nlora	magnituder   )xs    r   <lambda>z(get_adapter_state_dict.<locals>.<lambda>   s    6Q;#B+2B r   c                 X    i | ]&\  }} |          ||                               'S r   )to).0r)   r*   adapter_key_filterr@   s      r   
<dictcomp>z*get_adapter_state_dict.<locals>.<dictcomp>   s;    TTT1>P>PQR>S>STAqttF||TTTr   )items)r?   r@   rJ   s    `@r   get_adapter_state_dictrM   p   s9    " CBTTTTT
(8(8(:(:TTTTr   c                 p    d |                                  D             }t          d |D                       S )a  
    Get the keys from a state dict that correspond to LoRALinear modules.

    For example, if state_dict is the state dict of model and model.x.y.z is a
    LoRALinear, this method will return "model.x.y.z", not
    "model.x.y.z.lora_a.weight" or "model.x.y.z.lora_b.weight".

    Args:
        state_dict (Dict[str, Any]): State dict from a model.

    Returns:
        Set[str]: Set of keys in the state dict that correspond to LoRA modules.
    c                 "    g | ]}d |v sd|v 
|S )rC   rD   r   rI   r)   s     r   
<listcomp>z%_get_lora_modules.<locals>.<listcomp>   s*    QQQq1q@P@P@P@P@Pr   c                     g | ]@}|                     d d                               dd                               dd          AS ).lora_a.weight .lora_b.weight
.magnitude)replacerP   s     r   rQ   z%_get_lora_modules.<locals>.<listcomp>   sX     	
 	
 	
  II&++W%r**W\2&&	
 	
 	
r   )keysset)r?   	lora_keyss     r   _get_lora_modulesr[      sR     RQJOO--QQQI	
 	
 		
 	
 	
  r   rankalphac                    t          |           }|D ]}| | d         }| | d         }|                     | dd          }|| | d                             |j                  }||z  |z  |z  }	||	z   }
t          j                            ||	z   d          }||z                      dd          }|
|z  }
|
| | d<   | | d= n| | dxx         ||z  |z  |z  z  cc<   | | d= | | d= | S )	a]  
    Merge LoRA weights into the base model format for efficient inference.
    NOTE: This function modifies state_dict inplace. If you do not want to do that,
    make a copy prior to calling this function.

    For every LoRA module in the state dict, this function will convert its
    base weight then delete the LoRA-specific parameters.

    Args:
        state_dict (Dict[str, Any]): State dict from a model.
        rank (int): The rank of LoRA matrices.
        alpha (float): The alpha value used for scaling LoRA decompositions.

    Returns:
        Dict[str, Any]: The merged state dict.
    rS   rU   rV   Nz.weight   )dim)r[   getrH   dtypetorchlinalgnormview)r?   r\   r]   lora_modulesmodulelora_a_weightlora_b_weightlora_magnitudebase_weightlora_weightmerged_weightweight_normmag_norm_scales                r   get_merged_lora_ckptrr      sz   , %Z00L 2 2"f#<#<#<="f#<#<#<=#6(=(=(=tDD %$%7%7%78;;M<OPPK 4<=8=HK'+5M,++K+,E1+MMK,{:@@QGGN^+M-:J&)))*f00011 &)))***.>*** &0001&00011r   )NNNc              #     K   |                                  D ]@\  }}t          |d          r+t          |j                  rt          |d          rd|_        A	 dV  |                                  D ]@\  }}t          |d          r+t          |j                  rt          |d          rd|_        AdS # |                                  D ]@\  }}t          |d          r+t          |j                  rt          |d          rd|_        Aw xY w)a  
    Temporarily disable the adapters in a model. For example,
    this can be used in DPO for treating the LoRA adapters as the policy model
    and disabling it to treat the base model as the reference model.

    This context manager goes through all modules in the provided neural network model,
    and if a module has an ``adapter_params`` attribute that is callable and a ``disabled`` attribute,
    it sets ``disabled`` to True. Then, the control is given back to caller. When exiting the context manager,
    it sets ``disabled`` back to False for all modules that were temporarily disabled.

    Args:
        model (nn.Module): The model whose adapters are to be temporarily disabled.
    Yields:
        None: This function yields control back to the caller, with the adapters disabled.
    Example:
        >>> with disable_adapter(model):
        ...     # Perform operations with adapters disabled
        ...     pass

    r   disabledTNF)r#   r$   r%   r   rt   )r   _ri   s      r   disable_adapterrv      sQ     , ((** # #	6F,--	#.//	# 
++	#
 #FO	(,,.. 	( 	(IAv 011(V233( FJ//(
 #(	( 	(,,.. 	( 	(IAv 011(V233( FJ//(
 #(	(s   B4 4ADbase_missingbase_unexpectedlora_missinglora_unexpectedc                   	 t          | ||          		fd}|r#|D ] } ||          st          d| d          !|rt          d          |r#|D ] } ||          rt          d| d          !|rt          d          dS )	a  
    A more memory-efficient way to validate that LoRA state dict loading was done properly.

    This function uses a model's LoRA config to check that LoRA and/or base model weights
    are loaded into the full model correctly. This function relies only on the values of missing and
    unexpected as returned by the load_state_dict API with strict=False. This allows us to do the
    validation without any additional calls to .state_dict(), which use additional memory.

    Args:
        lora_attn_modules (List[LORA_ATTN_MODULES]): list of which linear layers
            LoRA should be applied to in each self-attention block. Options are
            ``{"q_proj", "k_proj", "v_proj", "output_proj"}``.
        apply_lora_to_mlp (bool): whether LoRA is applied to each MLP linear.
        apply_lora_to_output (bool): whether LoRA is applied to the final output projection.
        base_missing (Optional[List[str]]): List of missing keys when loading base model weights.
            Default: None
        base_unexpected (Optional[List[str]]): List of unexpected keys when loading base model weights.
            Default: None
        lora_missing (Optional[List[str]]): List of missing keys when loading LoRA weights.
            Default: None
        lora_unexpected (Optional[List[str]]): List of unexpected keys when loading LoRA weights.
            Default: None

    Returns:
        None

    Raises:
        AssertionError:
            If base_missing contains any base model keys, **or**
            if base_unexpected is nonempty, **or**
            if lora_missing contains any LoRA keys, **or**
            if lora_unexpected is nonempty.
    c                 <     t           fdD                       S )Nc                 t    g | ]4}d                      |dg          v pd                      |dg          v 5S )r"   rC   rD   )join)rI   r)   rE   s     r   rQ   zNvalidate_missing_and_unexpected_for_lora.<locals>.<lambda>.<locals>.<listcomp>)  sY     	
 	
 	
 HHa[!!Q&I#((A{3C*D*D*I	
 	
 	
r   )any)rE   rh   s   `r   rF   z:validate_missing_and_unexpected_for_lora.<locals>.<lambda>(  s8    c	
 	
 	
 	
!	
 	
 	
  r   zMissing non-LoRA key z from base model dictz!Unexpected key loading base modelzMissing LoRA key z from adapter state dictzUnexpected key loading adapterN)r=   AssertionError)
r3   r4   r5   rw   rx   ry   rz   is_lora_paramr)   rh   s
            @r   (validate_missing_and_unexpected_for_lorar      s	   T ),.B L   M  W 	W 	WA =## W$%UQ%U%U%UVVVW B@AAA V 	V 	VA}Q V$%T%T%T%TUUUV ?=>>>? ?r   )r>   )NNNN)
contextlibtypingr   r   r   r   r   r   r	   r
   r   rd   r   LORA_ATTN_MODULESr   Moduler   	Parameterr/   r2   boolr=   rM   r[   no_gradintfloatrr   contextmanagerrv   r   r   r   r   <module>r      s       V V V V V V V V V V V V V V V V V V V V V V        GH     H   &bi Dbl1B,C    :.9.&+DcNC,?&@.	. . . .$-.  
#Y	   < 9>U US#XU(0U	#s(^U U U U*$sCx. SX    2 0S#X0
0 0 
#s(^	0 0 0 0f %(29 %(3C)D %( %( %( %(X )-+/(,+/?? ??-.???? ?? 49%	??
 d3i(?? 49%?? d3i(?? 
?? ?? ?? ?? ?? ??r   