o
    4ѹg%                     @   s   d dl Z d dlZd dlZd dlZed 	ddedefdd	Z				ddeded
efddZ	dddZ
d ddZdd Zdd Zdd Zdd Zdd ZdS )!    NignoreF   onnxquantizeopset_versionc           
      K   sV  | j di |}|dtj|d}tj|dd t|ttfs&|f}|D ]}|	  |dkr@t
|f||||d| q(|dkr\tj rKdnd	}	td
|	 t|||	d q(|dkrtj siJ dt|dr{t|dr{t||dd q(td|  t||dd q(|dkrtj sJ dt|drt|drt||dd q(|S )N
output_dirZ
init_paramT)exist_okr   )data_inr   r   
export_dirtorchscriptcudacpuz#Exporting torchscripts on device {})pathdeviceZ	bladediscz=Currently bladedisc optimization for FunASR only supports GPUencoderdecoder)r   enable_fp16zexport_dir: Z	onnx_fp16z=Currently onnx_fp16 optimization for FunASR only supports GPU )exportgetosr   dirnamemakedirs
isinstancelisttupleeval_onnxtorchr   Zis_availableprintformat_torchscriptshasattr_bladedisc_opt_for_encdec_onnx_opt_for_encdec)
modelr	   r   r   typekwargsZmodel_scriptsr
   mr   r   r   ]/Users/admin/.pyenv/versions/3.10.0/lib/python3.10/site-packages/funasr/utils/export_utils.pyr   
   sP   r   r
   c                    s>  | dd |  }t|tjr| }nt fdd|D }| dd}t| jtr3| jd }n|  }t	j
||}	tjj| ||	|d||  |  |  d		 |rzd
dlm}
m} d
d l}W n   td|	dd}||	}dd |jjD }dd |D }td|	| ||	|dgdd|
j|d d S d S )Nr   r   c                       g | ]}|  qS r   )to).0inputr   r   r)   
<listcomp>G       z_onnx.<locals>.<listcomp>verboseFz.onnxTr1   Zdo_constant_foldingr   Zinput_namesZoutput_namesZdynamic_axesr   )	QuantTypequantize_dynamiczwYou are quantizing the onnx model, please install onnxruntime first. via 
`pip install onnx`
`pip install onnxruntime`.z_quant.onnxc                 S   s   g | ]}|j qS r   )name)r,   nr   r   r)   r/   g   s    c                 S   s(   g | ]}d |v sd|v sd|v r|qS )outputZbias_encoderZbias_decoderr   r,   r(   r   r   r)   r/   h   s    zQuantizing model from {} to {}ZMatMul)Zmodel_inputZmodel_outputZop_types_to_quantizeZper_channelZreduce_rangeZweight_typenodes_to_exclude)r   export_dummy_inputsr   r   Tensorr+   r   export_namestrr   r   joinr   r   export_input_namesexport_output_namesexport_dynamic_axesZonnxruntime.quantizationr3   r4   RuntimeErrorreplaceloadgraphnoder   r    ZQUInt8)r%   r	   r   r   r
   r'   dummy_inputr1   r<   Z
model_pathr3   r4   r   Zquant_model_pathZ
onnx_modelnodesr9   r   r.   r)   r   8   s\   	

r   r   c              	   C   s   |   }|dkr |  } t|tjr| }n	tdd |D }tj| |}t| jt	r?|
tj|| j dd d S |
tj||   dd d S )Nr   c                 S      g | ]}|  qS r   r   r,   ir   r   r)   r/          z!_torchscripts.<locals>.<listcomp>r   r   )r:   r   r   r   r;   r   jittracer<   r=   saver   r   r>   rC   )r%   r   r   rG   model_scriptr   r   r)   r!   w   s   
$r!   Tc              
   C   s   |   } zdd l}W n ty  } z
td W Y d }~nd }~ww |j }||_t + | |j	| d|d}W d    n1 sCw   Y  W d    |S W d    |S 1 s[w   Y  |S )Nr   zhWarning, if you are exporting bladedisc, please install it and try it again: pip install -U torch_blade
T)Zallow_tracingmodel_inputs)
r   torch_blade	Exceptionr   configZConfigr   r   Zno_gradoptimize)r%   rR   r   rS   eZtorch_configZ	opt_modelr   r   r)   _bladedisc_opt   s.   
(rX   c                 C   s6   t |dkr|d | g|dd  R S |d | fS )N   r   )len)r(   xscaler   r   r)   _rescale_input_hook   s   r]   c                 C   s.   t |tr|d | g|dd  R S || S )Nr   rY   )r   r   )r(   r[   yr\   r   r   r)   _rescale_output_hook   s   
r_   c                    s   t d   fdd| jjj}fdd|D }|  } | |  |D ]}|  q%td  d td d	 | jjj	
tjtd
 | jj D ]*\}}|drb|tjtd
 |dryfdd|  D }|| qOd S )Nr   c                    s8   t |tr	|d n|} t |    d S )Nr   )r   r   Zcopy_r   maxdetachabs)r(   r[   r^   val)absmaxr   r)   stat_input_hook   s   "z/_rescale_encoder_model.<locals>.stat_input_hookc                    r*   r   )register_forward_hookr8   )re   r   r)   r/      r0   z*_rescale_encoder_model.<locals>.<listcomp>   i   z$rescale encoder modules with factor=

)r\   Z	self_attnzfeed_forward.w_2c                    s   i | ]	\}}||  qS r   r   )r,   kv)
fp16_scaler   r)   
<dictcomp>   s    z*_rescale_encoder_model.<locals>.<dictcomp>)r   Ztensorr   r   r%   encodersremoveintr   Z	encoders0register_forward_pre_hook	functoolspartialr]   Znamed_modulesendswithrf   r_   
state_dictitemsZload_state_dict)r%   
input_datarm   hookshr5   r(   rt   r   )rd   rk   re   r)   _rescale_encoder_model   s*   





ry   c                    s   |   }t|tjr| }n	tdd |D }t   fdd}| j|}|  } | |  |	  |r:t
| | t| j|d d | _t| jt | _tj| |}|tj|| j d d S )Nc                 S   rI   r   rJ   rK   r   r   r)   r/      rM   z-_bladedisc_opt_for_encdec.<locals>.<listcomp>c                         t| d S Nextendr   r(   r[   Zdecoder_inputsr   r)   get_input_hook      z1_bladedisc_opt_for_encdec.<locals>.get_input_hookrg   z_blade.torchscript)r:   r   r   r;   r   r   r   r   rp   rn   ry   rX   r   rN   rO   rP   r   r   r>   r<   )r%   r   r   rv   r   hookrQ   r   r   r)   r#      s    

 r#   c                    sf  |   }t|tjr| }n	tdd |D }t   fdd}| j|}|  } | |  |	  |r:t
| | | d| j d}td td| d	 tj|sjtjj| ||d
dd|  |  |  d	 | d| j d}td td| d	 tj|rtj|szddlm} W n   tdt|}	|j|	dd}
t|
| d S d S d S )Nc                 S   rI   r   rJ   rK   r   r   r)   r/      rM   z(_onnx_opt_for_encdec.<locals>.<listcomp>c                    rz   r{   r|   r~   r   r   r)   r      r   z,_onnx_opt_for_encdec.<locals>.get_input_hook/z
_hook.onnxz2**************************************************z[_onnx_opt_for_encdec(fp32)]: rh   FT   r2   z_hook_fp16.onnxz[_onnx_opt_for_encdec(fp16)]: r   )float16z}You are converting the onnx model to fp16, please install onnxconverter-common first. via `pip install onnxconverter-common`.)Zkeep_io_types)r:   r   r   r;   r   r   r   r   rp   rn   ry   r<   r   r   r   existsr   r   r?   r@   rA   Zonnxconverter_commonr   rB   rD   Zconvert_float_to_float16rP   )r%   r   r   rv   r   r   Zfp32_model_pathZfp16_model_pathr   Zfp32_onnx_modelZfp16_onnx_modelr   r   r)   r$      sR   


r$   )NFr   r   )NFr   NrJ   )T)r   r   rq   warningsfilterwarningsboolro   r   r=   r   r!   rX   r]   r_   ry   r#   r$   r   r   r   r)   <module>   s:    

0

?
