o
    ;ήc9                  
   @   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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 d dlmZ d dlmZmZ ejejejed	d	 d d
lmZ d dlmZ d aeddddddddd	dd Zeded ej d dd Z!dd Z"				d)ddZ#					d*ddZ$						d+ddZ%dede&d e'fd!d"Z(d,de&d#e&fd$d%Z)d&d' Z*e+d(kre! Z,e*e, dS dS )-    N)Path)PRETRAINED_LONGFORMER_MODELS)
load_model)version)register_custom_op_symbolic)
parse_args)LongformerModelLongformerSelfAttentionz..)BertOnnxModel)torch_onnx_exportvic
           
      C   s   | j d|||||||||	d
S )Nz"com.microsoft::LongformerAttention)num_heads_iwindow_i)op)
ginputweightbiasmaskglobal_weightglobal_biasglobal_mask	num_headswindow r   a/tmp/pip-target-vg8gfxp4/lib/python/onnxruntime/transformers/models/longformer/convert_to_onnx.pymy_longformer_attention9   s   r   z onnxruntime::LongformerAttention	   za./torch_extensions/build/lib.linux-x86_64-3.8/longformer_attention.cpython-38-x86_64-linux-gnu.soc                  C   s   t  } | jdddtdddt  d | jddd	d
d | jdd | jddd	dd | jdd | jdddd	dd | jdd | jdddtdddgdd |  }|S )z:Parse arguments

    Returns:
        args: Namespace
    z-mz--modelFzlongformer-base-4096z=Checkpoint directory or pre-trained model names in the list: z, )requiredtypedefaulthelpz--export_padding
store_truez{Export padding logic to ONNX graph. If not enabled, user need pad input so that sequence length is multiple of window size.)r   actionr"   )export_paddingz--no_merge_qkvzFStack the weights of q, k and v on dimension 0 instead of dimension 1.)no_merge_qkvz-oz--optimize_onnxz(Use optimizer.py to optimize onnx model.)optimize_onnxz-pz--precisionfp32fp16zLPrecision of model to run: fp32 for full precision, fp16 for mixed precision)r   r    r!   choicesr"   )	argparseArgumentParseradd_argumentstrjoinr   keysset_defaultsr   )parserargsr   r   r   parse_arguments]   sX   

r4   c                 C   s   |r	| j d d n| j d }t|d|}tj|jtj|d}d|d d |d f< tj|jtj|d}d|d d df< |||fS )Nr      )dtypedevice)	attention_windowtorcharange	unsqueezetoonesshapelongzeros)configr%   r7   sequence_length	input_idsattention_maskglobal_attention_maskr   r   r   get_dummy_inputs   s   
rF   c                 C   sP  |  }t|jdkr$|jd dkr$|  dkr$| d d dks&J | }||d}t|jdkrP|jd dkrP|  dkrP| d d dksRJ tj	| j
jdd| jjdd| jjddftd}tdkr||| jd| j }tj	| jjdd| jjdd| jjddftd}	tdkr|	| jd| j }	tdkrtj	| j
j| jj| jjfdd}
|
d| j }
tj	| jj| jj| jjfdd}|d| j }n*tj	| j
j| jj| jj| jj| jjfdd}
|
d| j }
| jj}|d| j }tjj|||
||	||| j| j	}| | ks#J d	|f}|S )
N   r   r5   g     )dim      zUnexpected size)intlenr>   count_nonzeroitemtolistfloatmasked_fillr9   stackqueryr   	transposekeyvalueweight_bias_formatreshape	embed_dimquery_global
key_globalvalue_globalr   opsonnxruntimeLongformerAttentionr   one_sided_attn_window_sizesize)selfhidden_statesrD   is_index_maskedis_index_global_attnis_global_attnr   
input_maskr   r   r   r   attn_outputoutputsr   r   r   &my_longformer_self_attention_forward_4   s|   		  "rk   Fc                 C   s   |dksJ t | |||||S NFrk   )rc   rd   rD   re   rf   rg   output_attentionsr   r   r   (my_longformer_self_attention_forward_4_3  s   	ro   c                 C   s*   |dksJ |d u sJ t | |||||S rl   rm   )rc   rd   rD   layer_head_maskre   rf   rg   rn   r   r   r   *my_longformer_self_attention_forward_4_3_2  s   
rq   modelonnx_model_pathr%   c                 C   s   t | j|tdd\}}}| |||d}ttjtdk r$tdd	t
tjj}tttd}||vrFtdt
tjj td	tj}	|| t_|||f}
t|jjd
d
d t| |
|dg dddgddddddddddddddddddid td|  |	t_dS )a  Export longformer model to ONNX

    Args:
        model (LongformerModel): longformer model
        onnx_model_path (str): output onnx path
        export_padding (bool): whether export padding logic to ONNX so that input string can be any length.

    Raises:
        RuntimeError: This tool requires transformers 4.0.0 or later.
        RuntimeError: LongformerSelfAttention.forward arguments are different.
    cpu)r7   )rD   rE   z4.0.0z/This tool requires transformers 4.0.0 or later. )zwself hidden_states attention_mask layer_head_mask is_index_masked is_index_global_attn is_global_attn output_attentionszgself hidden_states attention_mask is_index_masked is_index_global_attn is_global_attn output_attentionszUself hidden_states attention_mask is_index_masked is_index_global_attn is_global_attnzCurrent argumentsztLongformerSelfAttention.forward arguments are different. Please install supported version (like transformers 4.3.0).T)parentsexist_ok   )rC   rD   rE   
last_statepooler
batch_sizerB   )r   r5   )rC   rD   rE   ry   rz   zcom.microsoftr5   )opset_versioninput_namesoutput_namesdynamic_axescustom_opsetszONNX model exported to N)rF   rA   r9   r7   r   parsetransformers__version__RuntimeErrorr/   inspectgetfullargspecr	   forwardr3   rq   ro   rk   printr   parentmkdirr   )rr   rs   r%   rC   rD   rE   _rV   args_to_funcoriginal_forwardexample_inputsr   r   r   export_longformer.  sX   


r   fp32_model_pathc                 C   sr   t | ddd}t|}|  d}|r ||| td|  |r7|jdd ||| td|  dS dS )a   Optimize longformer onnx model

    Args:
        onnx_model_path (str): path of original ONNX model.
        fp32_model_path (str): path of optimized fp32 model.
        fp16_model_path (str, optional): path of optimized fp16 model. Defaults to None.
    NT)formatload_external_dataFzoptimized fp32 model saved to )keep_io_typeszoptimized fp16 model saved to )r   r
   optimizesave_model_to_filer   convert_float_to_float16)rs   r   fp16_model_pathrr   	optimizeruse_external_data_formatr   r   r   optimize_longformerw  s   r   c                 C   s   | j }|d }| jrdndatt| }t||| j | js$| j	dkrE|dt  d }| j	dkr;|dt  d nd }t
||| d S d S )	Nz.onnxr   r5   r(   _fz
_fp32.onnxr)   z
_fp16.onnx)rr   r&   rX   r   from_pretrainedr   r   r%   r'   	precisionr   )r3   
model_namers   rr   r   r   r   r   r   main  s    r   __main__)NNNN)NNNNF)NNNNNF)N)-r+   r   ossyspathlibr   r9   r   longformer_helperr   onnxr   	packagingr   
torch.onnxr   torch.onnx.symbolic_helperr   r   r	   pathappendr/   dirname__file__onnx_model_bertr
   torch_onnx_export_helperr   rX   r   r^   load_libraryr4   rF   rk   ro   rq   r.   boolr   r   r   __name__r3   r   r   r   r   <module>   sd   ! 
:
\

I