o
    }oi&                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
mZ d dlZd dlZd dlmZ dd Zdd Zd	e	eejf d
ee	eejf e
e f fddZde	eef de	eejf d
e	eejf fddZdddZdS )    N)Path)AnyDictListTuple)TarPathc                    s*    dkr| S d} fdd}t ||| S )Nr   zlayers.(\d+)c                    s   dt t| d   S )Nzlayers.   )strintgroup)matchoffset_value T/home/ubuntu/.local/lib/python3.10/site-packages/nemo/export/utils/lora_converter.py
add_offset%   s   z-replace_number_add_offset.<locals>.add_offset)resub)keyr   patternr   r   r   r   replace_number_add_offset   s
   r   c                 C   s>   g }| | dd | | dd | | dd |S )Nz.lora_kqv_adapter.z$.lora_unfused_kqv_adapter.q_adapter.z$.lora_unfused_kqv_adapter.k_adapter.z$.lora_unfused_kqv_adapter.v_adapter.)appendreplace)r   new_keysr   r   r   rename_qkv_keys+   s
   r   tensorsreturnc                 C   s  t  }t }g d}|  D ]m\}}d|dddd }|dd}|d	d
}|dd}|dd}|dd}|dd}|dd}|dd}|dd}|dd}|dd}|dd}|||< |D ]}d| |v rz|| qlq|t|fS )N)q_projk_projv_projo_proj	down_proj	gate_projup_projzbase_model.	linear_inlora_A
linear_outlora_B	q_adapterr   	k_adapterr   	v_adapterr   lora_dense_attention_adapterr    lora_4htoh_adapterr!   gate_adapterr"   
up_adapterr#   z.adapter_layer z.lora_unfused_kqv_projz.lora_unfused_hto4h_adapterself_attention	self_attndecodermodel.)dictsetitemsr   addlist)r   new_tensorsmodule_namesknown_module_namesmodule_namemodule_weightnew_module_namekmnr   r   r   reformat_module_names_to_hf3   s0   
rA   configlora_weightsc                    s>  t | d }t | d }|| }t | d|}||  |d|  }| d d d }t fdd	t|D }t | d }	t d
 | d }
g }g }| D ]}d|v r_|| d|v rh|| qT|D ]m}d|v r|| d|ks|J t	|D ]}|| ||< t
||  dksJ qn=d|v r|| d
|ksJ tt	|||	|
gD ]#\}}|| |||f| d|f||< t
||  dksJ q|| qk|D ]A}|dd}|dd}|| }d|v r|||< |||< nd|v r|jd }||d }|d ||< |d
 ||< || q|S )a  This function converts nemo style (fused) lora weights to canonical (unfused)
    LoRA weights. Namely, it unfuses the QKV adapter layers and the H-to-4H adapter layers.

    Returns:
        Dict[str, torch.Tensor]: The new LoRA weights with unfused layers.
    hidden_sizenum_attention_headsnum_query_groups   peftlora_tuningadapter_dimc                    s,   g | ]}t  d  |  d  |   qS )rG   )torcharange).0	group_idxheads_per_groupr   r   
<listcomp>j   s    z5convert_lora_weights_to_canonical.<locals>.<listcomp>r   lora_kqv_adapterlora_hto4h_adapterr$   r   r&   z.lora_hto4h_adapter.z).lora_unfused_hto4h_adapter.gate_adapter.z'.lora_unfused_hto4h_adapter.up_adapter.)r
   getrK   catrangerL   keysr   sizer   lenzipreshapepopr   shapesplit)rB   rC   rD   	num_heads	head_sizerF   qkv_total_dimadapter_sizeq_slicek_slicev_sliceqkv_keys_to_updatehto4h_keys_to_updater   new_keyrY   gate_proj_keyup_proj_keyr>   
split_sizegate_up_splitr   rO   r   !convert_lora_weights_to_canonicalU   sj   







rn   Fc                 C   s  t | }|d d}tj|tjd}W d    n1 s w   Y  |dd}|dd}i g| }	t|D ]q}
t|D ]j}|dkrK|d }n|dkrY|d|d	d
 }n|d|d	d|
dd
 }|d}tj|tdd}W d    n1 sw   Y  |
dkr||	|< q@|d | |
 }|	 D ]\}}t
||}||	| |< qq@q:|	d }	|d d dddkrd|d d d< t||	}	|rCt|	\}	}t|jddd t|	| d |d urt|}t|}W d    n1 sw   Y  ni }d|d< |d d d |d< |d d d |d< ||d < t| d!d"}tj||d#d$ W d    n	1 s=w   Y  nrt [}t| d%d"}t|| W d    n	1 sbw   Y  t|	| d
 tj|}tj|dd& t|d'}|j|d(d) W d    n	1 sw   Y  W d    n1 sw   Y  W d    |	|fS W d    |	|fS W d    |	|fS 1 sw   Y  |	|fS )*Nzmodel_config.yamlr)Loadertensor_model_parallel_sizer   pipeline_model_parallel_sizezmodel_weights.ckptmp_rank_02dz/model_weights.ckpttp_rank_	_pp_rank_03drbcpu)map_locationr   
num_layersrH   rI   variantnemo	canonicalT)parentsexist_okz/adapter_model.binLORA	peft_typerJ   alpha
lora_alphatarget_modulesz/adapter_config.jsonw   )indentz/model_config.yaml)r   zw:r4   )arcname)r   openyamlload
SafeLoaderrU   rW   rK   devicer7   r   rn   rA   r   mkdirsavejsondumptempfileTemporaryDirectoryospathdirnamemakedirstarfiler8   )	lora_nemo	save_path	hf_formatdonor_hf_configarchiveconfig_filelora_configtp_sizepp_sizelora_state_dictpptp	ckpt_filefweightslayer_offsetr   valueri   r   hf_config_fileadapter_configtmpdirr   tarr   r   r   convert_lora_nemo_to_canonical   s   







 
>
>
>>r   )FN)r   r   r   r   r   pathlibr   typingr   r   r   r   rK   r   nemo.export.tarutilsr   r   r   r	   TensorrA   rn   r   r   r   r   r   <module>   s*   2"

K