U
    T?ha  ã                   @   sV   d dl Z d dlZd dlZd dlmZmZmZ d dlmZ e  	e
¡ZG dd„ deƒZdS )é    N)ÚTensorProtoÚhelperÚnumpy_helper)ÚBertOnnxModelc                       sŒ   e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )ÚBertOnnxModelTFc                    s   t ƒ  |||¡ d S ©N)ÚsuperÚ__init__)ÚselfÚmodelÚ	num_headsÚhidden_size©Ú	__class__© ú]/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/onnx_model_bert_tf.pyr	      s    zBertOnnxModelTF.__init__c                 C   sp   g }|   ¡ D ]@}|jdkr|  |jd ¡s|  |jd |jd ¡ | |¡ q|  |¡ t 	dt
|ƒ› ¡ d S )NZIdentityr   zRemoved Identity count: )ÚnodesÚop_typeZfind_graph_outputÚoutputÚreplace_input_of_all_nodesÚinputÚappendÚremove_nodesÚloggerÚinfoÚlen)r
   Únodes_to_removeÚnoder   r   r   Úremove_identity   s    

zBertOnnxModelTF.remove_identityc              	   C   s~   |   |ddddgdd ddg¡}|d k	r*|S |   |dddddgdddddg¡}|d k	rX|S |   |dddddgdd dddg¡}|S )	NÚMulÚSubÚReshapeÚCasté   r   ÚSliceÚ	Unsqueeze)Úmatch_parent_path)r
   Zadd_or_sub_before_softmaxÚ
mask_nodesr   r   r   Úmatch_mask_path   s(    

ýýýzBertOnnxModelTF.match_mask_pathc                 C   s\   |   |g ¡}i }|D ]B}|jD ]6}|  |¡}|rt |¡}t|jƒdkr|j||j< qq|S )zi
        Find initializers that is 2D. Returns a dictionary with name as key and shape as value.
        é   )Zget_parent_subgraph_nodesr   Úget_initializerr   Úto_arrayr   ÚshapeÚname)r
   Zcurrent_nodeZparent_nodesZinitializersr   r   ÚinitializerÚtempr   r   r   Ú)get_2d_initializers_from_parent_subgraphs7   s    


z9BertOnnxModelTF.get_2d_initializers_from_parent_subgraphsc                 C   sr  |   ¡ }||krd S || }t|ƒdkr,d S | j|d dd}t|ƒdkrXtd|ƒ d S t|ƒdkrx|d |krx|d S |d jd }|  |d dddd	dd
gddddddgfdddddd	dd
gddddddddgfgd ¡\}}}|rn|rn||d jd krnt d¡ |d }	|  |	¡j	}
|  
tjd
|gdgd|
¡ t |	jd ¡}|  
tjddgdg|d|
¡ d}|S )Nr#   r   T©Ú	recursivez(Found multiple candidates of segment_idsÚConstantOfShaper"   ÚConcatr$   ÚShaper%   ÚSqueezeéÿÿÿÿúSimplify semgent id path...Zinput_shape©ÚinputsÚoutputsZzeros_for_input_shape©r:   r;   Úvalue)Úinput_name_to_nodesr   Úget_graph_inputsÚprintr   Zmatch_parent_pathsr   ÚdebugÚget_graph_by_noder-   Úadd_noder   Ú	make_nodeÚget_attribute_valueÚ	attribute)r
   Úsegment_embeddingÚ	input_idsr>   r   Úgraph_inputsÚsegment_idsÚ_Zsegment_id_pathÚconstantofshape_nodeÚ
graph_nameÚconstantofshape_valuer   r   r   Úfind_segment_idsG   sh    
þø
õûë
 
þüù	z BertOnnxModelTF.find_segment_idsc                 C   s`   |   ¡ }||krd S || }t|ƒdkr,d S | j|d dd}t|ƒdkrR|d S td|ƒ d S )Nr#   r   Tr1   z&Found multiple candidates of input_ids)r>   r   r?   r@   )r
   Úword_embeddingr>   r   rI   r   r   r   Úfind_input_ids‡   s    
zBertOnnxModelTF.find_input_idsc                    sÀ  |   ¡ D ]°}|jdkr|  |ddddddgdd	d d	ddg¡}|d krHq|\}}}}}}	|  |d
¡r|  |d	¡r| j|dd}
‡ fdd„|
D ƒ}t|ƒd	kr¬td|ƒ  d S t|ƒd	krÄ|d   S |  |d ddddddddgddddddddg¡}‡ fdd„|
D ƒ}|r¬|r¬t|ƒd	kr¬|d |d jd kr¬t 	d¡ |d }t
 |jd ¡}|  |¡j}|  t
jd|d gdgd|¡ |  t
jddg|	jd g|d|¡ |	jd   S qd S )NÚSoftmaxÚAddr   r    r"   r$   r%   r   r#   iðØÿÿTr1   c                    s   g | ]}|ˆ kr|‘qS r   r   ©Ú.0r   ©Úexcluded_graph_inputsr   r   Ú
<listcomp>«   s      z3BertOnnxModelTF.find_mask_input.<locals>.<listcomp>z'Found multiple candidates of mask inputr7   r3   r4   r6   r5   c                    s   g | ]}|ˆ kr|‘qS r   r   rT   rV   r   r   rX   À   s      r8   Zinput_shape_for_maskr9   r<   )r   r   r&   Úhas_constant_inputr?   r   r@   r   r   rA   r   rE   rF   rB   r-   rC   rD   )r
   rW   r   Z	mask_pathrC   Zmul_nodeZsub_nodeZ	cast_nodeÚ
slice_nodeZunsqueeze_noderI   r:   Zpath_to_be_simplifiedZduplicated_inputsrL   rN   rM   r   rV   r   Úfind_mask_input—   sŒ    
ýù
ø
ôÿþ
ýü
ýú
üù	zBertOnnxModelTF.find_mask_inputc              
   C   sv  |   |¡}|d kr t d¡ dS |  ||¡}|d krBt d¡ dS |  ||g¡}|d krft d¡ dS |||g| _|  d¡}| j ||¡ |  	|¡j
jjtjkr°| j |¡\}	}|  	|¡rÌ| j |¡\}	}n| j |¡\}}
|  	|¡rø| j |¡\}	}n| j |¡\}}|  d¡}tjjd||||||jd |jd	 |g||gd
d}d|_|  |jd |¡ |  ||  |¡j¡ d S )Nz6Failed to find input_ids. Cannot fuse embedding layer.Fz8Failed to find segment_ids. Cannot fuse embedding layer.z7Failed to find input_mask. Cannot fuse embedding layer.Ú
mask_indexÚembed_outputÚEmbedLayerNormalizationr#   r)   Z
EmbedLayer©r:   r;   r-   zcom.microsoftr   )rQ   r   r   rO   r[   Zbert_inputsZcreate_node_nameÚattention_maskZset_mask_indiceÚfind_graph_inputÚtypeZtensor_typeZ	elem_typer   ZINT32ÚutilsZcast_graph_input_to_int32Zcast_input_to_int32Úonnxr   rD   r   Údomainr   r   rC   rB   r-   )r
   Únormalize_noderP   rG   Úposition_embeddingrH   rJ   Ú
mask_inputr\   ZcastedZsegment_id_cast_nodeZmask_input_cast_noder]   Z
embed_noder   r   r   Úcreate_embedding_subgraphà   sR    







ø
óz)BertOnnxModelTF.create_embedding_subgraphc                 C   sÊ  t  d¡ |  ¡ }|  d¡}|D ]¢}|  |dddgdddg|¡}|dkrLq |\}}}|  |jd ¡}|dkrpq t |¡}	t	|	j
ƒd	krªt  d
|j› d|	j
› ¡ |j}
n t  d|j› d|	j
› ¡  dS |  |d|¡}|dk	r |jdkr |  |¡}t	|ƒd	krt  d|› ¡  dS d}d}| ¡ D ]N\}}|d d	krZ|}t  d|› d|› ¡ n|}t  d|› d|› ¡ q(|dksŒ|dkrœt  d¡  dS t  d¡ |  ||||
¡ |  ¡   qÆq dS )zM
        Automatically detect word, segment and position embeddings.
        z#start processing embedding layer...ÚLayerNormalizationrS   r!   r$   r   r#   Nr)   zFound position embedding. name:z, shape:z(Failed to find position embedding. name:zFFailed to find two embeddings (word and segment) from Add node. Found zFound segment embedding. name:zFound words embedding. name:z.Failed to find both word and segment embeddingzCreate Embedding node)r   r   Úoutput_name_to_nodeÚget_nodes_by_op_typer&   r*   r   r   r+   r   r,   r-   Ú
get_parentr   r0   ÚwarningÚitemsri   Úprune_graph)r
   rk   Úlayer_norm_nodesZlayer_norm_nodeZpos_embed_pathrC   Úreshape_noderZ   r.   r/   rg   Zfirst_parentZ
embeddingsrP   rG   r-   r,   r   r   r   Úprocess_embedding  sd    


ü


ÿ

üz!BertOnnxModelTF.process_embeddingc           	      C   sP   |||fD ]@}|j d }|| }||kr*q
t d|› d|jd › ¡  dS dS )Nr   zCheck attention input failed:z, FT)r   r   rA   r   )	r
   Úmatmul_qÚmatmul_kÚmatmul_vÚparentrk   ÚxZ
root_inputZ	root_noder   r   r   Úcheck_attention_inputW  s    
z%BertOnnxModelTF.check_attention_inputc           #      C   s  |   ¡ }g }d}g }|  d¡}|  d¡}| |¡ | |¡ |D ]š}|  |¡j}|jdkrz|  |dd¡}	|	d k	r@|	}nq@|  |d¡}
|
d ks˜|
jdkrÂ|  |d¡}
|
d ks¶|
jdkrÂt 	d¡ q@|  
|ddd	d
dgdddddg¡}|d krF|  
|dd	d
dgddddg¡}|d krF|  
|dddgdddg¡}|d krFt 	d¡ q@|d }|  
|d
d	ddgddddg¡}|d kr¢|  
|ddgddg¡}|d kr¢t 	d¡ q@|d }|d }|  
|ddddgddddg¡}|d kr
|  
|dddgdddg¡}|d kr
t 	d¡ q@|d }|  
|d
d	ddgddddg¡}|d krf|  
|ddgddg¡}|d krft 	d¡ q@|d }|d }|  
|d
d	ddgddddg¡}|d krÎ|  
|dddgdddg¡}|d krÎt 	d¡ q@|d }|d }|  |d ¡}|d krt 	d¡ q@|  |d d¡s t 	d¡ q@|  
|d dgdg¡pL|  
|d dgdg¡}d}|d }|d krÊt|ƒdkrÊ|  |d jd ¡d krÊ|d jd }|  tjd|g|g|dgd|¡ ||d jd< |  ||||
|¡}|rÐ| j |d jd ¡}t 	d¡ | j |||||||| j| j|
jd |d jd d ¡}|d krDq@|d jdkrtj|d jd tjd gt dd| jt | j| j ƒgg¡ !¡ d!d"} |  "| |¡ tjd	|jd |d jd g|d jd# g|d jd$ d%}!|d jd# |d jd< |  |!|¡ |
jd	krvt# $|  %|
jd ¡¡d }"tj|
jd& tjd'gt dd|"gg¡ !¡ d!d"} |  "| |¡ |
jd& |
jd< |  ||¡ |d7 }| |dd … ¡ | |¡ | |¡ | |¡ | |¡ | |¡ q@t 	d(¡ q@q@|  &|¡ |  '¡  t (d)|› ¡ d S )*Nr   ÚSkipLayerNormalizationrj   rS   r#   )rz   rj   r!   z(Failed to match parent of normalize_nodeZMatMulr!   Z	TransposeZEinsumzFailed to match qkv nodesr7   zFailed to match v pathéþÿÿÿrR   r   zFailed to match qk_pathszFailed to match q pathzFailed to match k pathzCannot find mask_nodes.z;Sub node expected to have an input with constant value 1.0.r6   ZExpandZSqueeze_3d_to_2d_maskÚ_outputé   )ZaxeszCreate an Attention node.r)   Z	_newshapeé   T)r-   Z	data_typeZdimsÚvalsÚrawZ_reshape_outputZ_reshaper_   Z	_modifiedé   zRoot node not matched.zFused Attention count:))rk   rl   ÚextendrB   r-   r   Zmatch_parentrm   r   rA   r&   r(   rY   r   ra   r   rC   r   rD   ry   r`   Zprocess_maskZattention_fusionZcreate_attention_noder   r   r   Zmake_tensorr   ZINT64ÚnpZint64ÚintÚtobytesZadd_initializerr   r+   r*   r   Zupdate_graphr   )#r
   rk   r   Zattention_countZstart_nodesZskip_layer_norm_nodesrq   rf   rM   Zadd_before_layernormrw   Z	qkv_nodesZ
matmul_qkvZv_nodesZadd_vrv   Zqk_nodesZ	matmul_qkZq_nodesZadd_qrt   Zk_nodesZadd_kru   r'   Zsqueeze_nodeZsqueeze_node_nameZsqueeze_output_namerh   Zis_same_rootr\   Úattention_nodeZtensorZreshape_r   r   r   r   Úfuse_attentionb  sL   






ý


ý

















  ÿ2ûø

ô
üÿÿ
òþù	û





zBertOnnxModelTF.fuse_attentionc                 C   s   |   ¡  |  ¡  |  ¡  d S r   )r   rs   Úskip_reshape©r
   r   r   r   Ú
preprocess.  s    zBertOnnxModelTF.preprocessc                 C   sj   d}|   d¡}|D ]:}|  |d¡}|d k	r|jdkr|jd |jd< |d7 }q|dkrft d|› ¡ d S )Nr   r!   r#   zSkip consequent Reshape count: )rl   rm   r   r   r   r   )r
   ÚcountZreshape_nodesrr   rw   r   r   r   rˆ   3  s    

zBertOnnxModelTF.skip_reshapec                 C   sp   |   d¡}|D ]\}|  |ddgddg¡}|d kr2qt d¡ |\}}|  |jd |jd ¡ |  |¡  qlqd S )NZ	Attentionr!   r^   r   z+Remove Reshape before first Attention node.)rl   r&   r   r   r   r   r   Úremove_node)r
   Zattention_nodesr†   ÚpathZreshaperK   r   r   r   Ú%remove_reshape_before_first_attention?  s    


z5BertOnnxModelTF.remove_reshape_before_first_attentionc                 C   s   |   ¡  |  ¡  d S r   )rŽ   rp   r‰   r   r   r   ÚpostprocessK  s    zBertOnnxModelTF.postprocess)Ú__name__Ú
__module__Ú__qualname__r	   r   r(   r0   rO   rQ   r[   ri   rs   ry   r‡   rŠ   rˆ   rŽ   r   Ú__classcell__r   r   r   r   r      s    
@I6A Mr   )ÚloggingÚnumpyrƒ   rd   r   r   r   Zonnx_model_bertr   Ú	getLoggerr   r   r   r   r   r   r   Ú<module>   s   
