U
    T?h                     @   s   d dl Z d dlZd dlZd dlmZ d dlmZ d dlZd dl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 e eZG dd	 d	e	jjZG d
d dZG dd dZdS )    N)Path)List)	OnnxModel)torch_onnx_export)WhisperConfig)InferenceSessionc                       s2   e Zd ZdZdeed fddZdd Z  ZS )	WhisperEncoderz2Whisper encoder outputs only the last hidden statehf)config
model_implc                    s    t    || _|| _|| _d S N)super__init__encoderr
   r   )selfr   r
   r   	__class__ i/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/models/whisper/whisper_encoder.pyr      s    
zWhisperEncoder.__init__c                 C   s&   | j dkr| |S | jj|d S )NZopenair   )r   r   modelr   input_featuresr   r   r   forward"   s    

zWhisperEncoder.forward)r	   )	__name__
__module____qualname____doc__r   strr   r   __classcell__r   r   r   r   r      s   r   c                   @   s@   e Zd Zdd ZedeeeejedddZ	e
ddd	Zd
S )WhisperEncoderInputsc                 C   s
   || _ d S r   	input_idsr   r   r   r   r   )   s    zWhisperEncoderInputs.__init__F
batch_sizesequence_lengthfeature_sizedeviceuse_int32_inputsc                 C   s   t j| ||f|d}t|S )ah  Create dummy inputs for Whisper encoder.

        Args:
            batch_size (int): batch size
            sequence_length (int): sequence length
            feature_size (int): feature size for spectrogram input
            device (torch.device): device of output tensors

        Returns:
            WhisperEncoderInputs: dummy inputs for encoder
        )sizer&   )torchZrandnr   )r#   r$   r%   r&   r'   r   r   r   r   create_dummy,   s
    z!WhisperEncoderInputs.create_dummy)returnc                 C   s   | j d krg S | j gS r   r    )r   r   r   r   to_listF   s    
zWhisperEncoderInputs.to_listN)F)r   r   r   r   staticmethodintr)   r&   boolr*   r   r,   r   r   r   r   r   (   s    r   c                   @   sX   e Zd ZedejeeeedddZee	dddZ
edeeejed	d
dZdS )WhisperEncoderHelperTF)r&   onnx_model_pathverboseuse_external_data_formatr'   c                 C   s   | j }tjdd|j||d}t|jjddd t }t	j
|d}	t|	jjddd t| t| |rr|	n|ddgdgd	d
ddd	ddddd||d |rtj|	dd}
tj|
|ddd W 5 Q R X dS )a  Export encoder to ONNX

        Args:
            encoder (WhisperEncoder): encoder object
            device (torch.device): device of encoder object
            onnx_model_path (str): onnx path
            verbose (bool, optional): print verbose information. Defaults to True.
            use_external_data_format (bool, optional): use external data format or not. Defaults to False.
           i  r"   T)parentsexist_okzencoder.onnxr   hidden_statesr#   r%   r$   )r      r4   )r   r8   )r!   r7      )
argsfZexport_paramsZinput_namesZoutput_namesZdynamic_axesZopset_versionZdo_constant_foldingr3   r2   )Zload_external_data)Zsave_as_external_dataZall_tensors_to_one_fileN)r
   r   r*   Znum_mel_binsr   parentmkdirtempfileTemporaryDirectoryospathjoinr   tupler,   onnxZ
load_modelr   save)r   r&   r1   r2   r3   r'   r
   Zencoder_inputsZtmp_dir_nameZtemp_onnx_model_pathr   r   r   r   export_onnxM   sF    



z WhisperEncoderHelper.export_onnx)inputsc                 C   s$   dt |j   i}| d|S )zRun inference of ONNX model.r!   N)numpyZascontiguousarrayr!   cpurun)ort_sessionrG   Z
ort_inputsr   r   r   onnxruntime_inference   s     z*WhisperEncoderHelper.onnxruntime_inference)r   rK   r&   r'   c           	      C   sb   t jdd||d}| }| | }t||}tt|  |d  }t	
d|  |S )zQCompare the result from PyTorch and OnnxRuntime to verify the ONNX model is good.      )r#   r$   r&   r'   r   z	max_diff=)r   r*   r,   r0   rL   rH   ZamaxabsrI   loggerinfo)	r   rK   r&   r'   rG   Z
input_listZtorch_outputsZort_outputsZmax_diffr   r   r   verify_onnx   s     z WhisperEncoderHelper.verify_onnxN)TFF)F)r   r   r   r-   r)   r&   r   r/   rF   r   rL   r   r   rR   r   r   r   r   r0   L   s*      9    r0   )loggingr@   r>   pathlibr   typingr   rH   rD   r)   Z
onnx_modelr   Ztorch_onnx_export_helperr   Ztransformersr   Zonnxruntimer   	getLoggerr   rP   nnModuler   r   r0   r   r   r   r   <module>   s   
$