U
    T?h                     @   s   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 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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Union)	OnnxModel)torch_onnx_export)	MT5ConfigT5Config)InferenceSessionc                       s6   e Zd ZdZeeef d fddZdd Z  Z	S )	T5Encoderz-T5 encoder outputs only the last hidden state)configc                    s   t    || _|| _d S N)super__init__encoderr   )selfr   r   	__class__ _/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/models/t5/t5_encoder.pyr      s    
zT5Encoder.__init__c                 C   s   |  ||d S )Nr   )r   r   	input_idsattention_maskr   r   r   forward"   s    zT5Encoder.forward)
__name__
__module____qualname____doc__r   r   r   r   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 )T5EncoderInputsc                 C   s   || _ || _d S r   r   r   r   r   r   r   r   '   s    zT5EncoderInputs.__init__F
batch_sizesequence_length
vocab_sizedeviceuse_int32_inputsc           
      C   s   |r
t jnt j}t jd|d | |f||d}t j| |g||d}|dkrvt| D ]$}td|d }	d||d|	f< qPt||S )aI  Create dummy inputs for T5 encoder.

        Args:
            batch_size (int): batch size
            sequence_length (int): sequence length
            vocab_size (int): vocabulary size
            device (torch.device): device of output tensors

        Returns:
            T5EncoderInputs: dummy inputs for encoder
        r      )lowhighsizedtyper$   )r*   r$      N)torchZint32Zint64randintZonesrangerandomr   )
r!   r"   r#   r$   r%   r*   r   r   iZpadding_positionr   r   r   create_dummy+   s    zT5EncoderInputs.create_dummy)returnc                 C   s   dd | j | jfD }|S )Nc                 S   s   g | ]}|d k	r|qS r   r   ).0vr   r   r   
<listcomp>L   s      z+T5EncoderInputs.to_list.<locals>.<listcomp>r   )r   
input_listr   r   r   to_listK   s    zT5EncoderInputs.to_listN)F)r   r   r   r   staticmethodintr,   r$   boolr1   r   r7   r   r   r   r   r   &   s        r   c                	   @   sZ   e Zd Zede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 )T5EncoderHelperTF)r   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dgd	gd
d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 (T5Encoder): 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.
        r+      r    T)parentsexist_okzencoder.onnxr   r   hidden_statesr!   r"   )r   r&   )r   r   rB      )
argsfZexport_paramsZinput_namesZoutput_namesZdynamic_axesZopset_versionZdo_constant_foldingr>   r=   )Zload_external_data)Zsave_as_external_dataZall_tensors_to_one_fileN)r   r   r1   r#   r   parentmkdirtempfileTemporaryDirectoryospathjoinr   tupler7   onnxZ
load_modelr   save)r   r$   r<   r=   r>   r%   r   Zencoder_inputsZtmp_dir_nameZtemp_onnx_model_pathmodelr   r   r   export_onnxQ   sH    


zT5EncoderHelper.export_onnx)inputsc                 C   s6   t |j   t |j   d}| d|S )zRun inference of ONNX model.r   N)numpyZascontiguousarrayr   cpur   run)ort_sessionrR   Z
ort_inputsr   r   r   onnxruntime_inference   s    z%T5EncoderHelper.onnxruntime_inference)rP   rV   r$   r%   c           	      C   sh   t jdd| jj||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   z	max_diff=)r   r1   r   r#   r7   r;   rW   rS   ZamaxabsrT   loggerinfo)	rP   rV   r$   r%   rR   r6   Ztorch_outputsZort_outputsZmax_diffr   r   r   verify_onnx   s     zT5EncoderHelper.verify_onnxN)TFF)F)r   r   r   r8   r
   r,   r$   strr:   rQ   r   rW   r	   r\   r   r   r   r   r;   P   s,      :	    r;   )loggingrJ   r/   rH   pathlibr   typingr   r   rS   rN   r,   Z
onnx_modelr   Ztorch_onnx_export_helperr   Ztransformersr   r   Zonnxruntimer	   	getLoggerr   rZ   nnModuler
   r   r;   r   r   r   r   <module>   s    
*