o
    ¢ÄiSa  ã                   @   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__© úe/home/kim/smarthome/.venv/lib/python3.10/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^   |   |g d¢g d¢¡}|d ur|S |   |g d¢g d¢¡}|d ur"|S |   |g d¢g d¢¡}|S )N)ÚMulÚSubÚReshapeÚCast)é   Nr#   r   )r   r    r"   ÚSliceÚ	Unsqueeze)r#   r   r#   r   r   )r   r    r"   r%   r%   )r#   Nr#   r   r   )Ú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 ]!}|jD ]}|  |¡}|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   sD  |   ¡ }||vr
d S || }t|ƒdkrd S | j|d dd}t|ƒdkr,td|ƒ d S t|ƒdkr<|d |kr<|d S |d jd }|  |d g d¢g d¢fg d¢g d	¢fgd ¡\}}}|r |r ||d
 jd kr t 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$   r"   ÚShape)r#   r   r   r   r   r   ©r3   r"   r4   r%   ÚSqueezer$   r"   r5   )r#   r   r   r   r   r   r   r   éÿÿÿÿúSimplify semgent id path...r5   Zinput_shape©ÚinputsÚoutputsr3   Z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   sX   
þ
õû
ë
þüù	z BertOnnxModelTF.find_segment_idsc                 C   s`   |   ¡ }||vr
d S || }t|ƒdkrd S | j|d dd}t|ƒdkr)|d S td|ƒ d S )Nr#   r   Tr1   z&Found multiple candidates of input_ids)r?   r   r@   rA   )r
   Úword_embeddingr?   r   rJ   r   r   r   Úfind_input_ids‡   s   
zBertOnnxModelTF.find_input_idsc              	      sŽ  |   ¡ D ]À}|jdkrÄ|  |g d¢g d¢¡}|d u rq|\}}}}}}	|  |d¡rÄ|  |d¡rÄ| j|dd}
‡ fdd	„|
D ƒ}t|ƒdkrMtd
|ƒ  d S t|ƒdkrY|d   S |  |d g d¢g d¢¡}‡ 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#   Nr#   r   r   iðØÿÿr#   Tr1   c                    s   g | ]}|ˆ vr|‘qS r   r   ©Ú.0r   ©Úexcluded_graph_inputsr   r   Ú
<listcomp>«   ó    z3BertOnnxModelTF.find_mask_input.<locals>.<listcomp>z'Found multiple candidates of mask inputr   r8   r6   )r   r   r   r   r   r   r   r   c                    s   g | ]}|ˆ v r|‘qS r   r   rU   rW   r   r   rY   À   rZ   r9   r5   Zinput_shape_for_maskr:   r3   r=   )r   r   r&   Úhas_constant_inputr@   r   rA   r   r   rB   r   rF   rG   rC   r-   rD   rE   )r
   rX   r   Z	mask_pathrD   Zmul_nodeZsub_nodeZ	cast_nodeÚ
slice_nodeZunsqueeze_noderJ   r;   Zpath_to_be_simplifiedZduplicated_inputsrM   rO   rN   r   rW   r   Úfind_mask_input—   sz   
ýù

ôÿþ
ýú
üù	€zBertOnnxModelTF.find_mask_inputc              
   C   sv  |   |¡}|d u rt d¡ dS |  ||¡}|d u r!t d¡ dS |  ||g¡}|d u r3t d¡ dS |||g| _|  d¡}| j ||¡ |  	|¡j
jjtjkrX| j |¡\}	}|  	|¡rf| 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   )rR   r   r   rP   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   rE   r   Údomainr   r   rD   rC   r-   )r
   Únormalize_noderQ   rH   Úposition_embeddingrI   rK   Ú
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 ]Ê}|  |g d¢g d¢|¡}|du r#q|\}}}|  |jd ¡}|du r5qt |¡}	t	|	j
ƒdkrRt  d|j› d	|	j
› ¡ |j}
nt  d
|j› d	|	j
› ¡  dS |  |d|¡}|durÚ|jdkrÚ|  |¡}t	|ƒdkrˆt  d|› ¡  dS d}d}| ¡ D ]%\}}|d dkr¨|}t  d|› d	|› ¡ q|}t  d|› d	|› ¡ q|du s¾|du rÆt  d¡  dS t  d¡ |  ||||
¡ |  ¡   dS qdS )zM
        Automatically detect word, segment and position embeddings.
        z#start processing embedding layer...ÚLayerNormalization)rT   r!   r$   )r   r#   r   Nr   r)   zFound position embedding. name:z, shape:z(Failed to find position embedding. name:rT   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Úitemsrk   Úprune_graph)r
   rm   Úlayer_norm_nodesZlayer_norm_nodeZpos_embed_pathrD   Úreshape_noder\   r.   r/   ri   Zfirst_parentZ
embeddingsrQ   rH   r-   r,   r   r   r   Úprocess_embedding  sh   

ü


ÿ

ü€É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   rB   r   )	r
   Úmatmul_qÚmatmul_kÚmatmul_vÚparentrm   Ú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r=|  |dd¡}	|	d ur<|	}nq |  |d¡}
|
d u sL|
jdvra|  |d¡}
|
d u s[|
jdvrat 	d¡ q |  
|g d¢g d	¢¡}|d u r”|  
|g d
¢g d¢¡}|d u r”|  
|g d¢g d¢¡}|d u r”t 	d¡ q |d }|  
|g d¢g d¢¡}|d u r¼|  
|ddgddg¡}|d u r¼t 	d¡ q |d }|d }|  
|g d¢g d¢¡}|d u rè|  
|g d¢g d¢¡}|d u rèt 	d¡ q |d }|  
|g d¢g d¢¡}|d u r|  
|ddgddg¡}|d u rt 	d¡ q |d }|d }|  
|g d¢g d¢¡}|d u r@|  
|g d¢g d¢¡}|d u r@t 	d¡ q |d }|d }|  |d ¡}|d u rZt 	d¡ q |  |d d¡sit 	d¡ q |  
|d dgdg¡p|  
|d dgdg¡}d }|d! }|d u r¾t|ƒd"kr¾|  |d jd ¡d u 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|
jd |d% jd d&}|d u rûq |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r”t# $|  %|
jd ¡¡d }"tj|
jd/ tjd0gt dd|"gg¡ !¡ d)d*} |  "| |¡ |
jd/ |
jd< |  ||¡ |d7 }| |d%d … ¡ | |¡ | |¡ | |¡ | |¡ | |¡ q t 	d1¡ q |  &|¡ |  '¡  t (d2|› ¡ d S )3Nr   ÚSkipLayerNormalizationrl   rT   r#   )r|   rl   r!   z(Failed to match parent of normalize_node)rT   ÚMatMulr!   Ú	Transposer}   )r   r   r   r   r   )r}   r!   r~   r}   )r#   r   r   r   )rT   ÚEinsumr   )r   r   r   zFailed to match qkv nodesr8   )r~   r!   rT   r}   r   zFailed to match v pathéþÿÿÿ)rS   rT   r   r}   )r   r   r   r   )rS   rT   r   zFailed to match qk_pathszFailed to match q path)r   rT   r   )r#   r   r   zFailed to match k pathzCannot find mask_nodes.z;Sub node expected to have an input with constant value 1.0.r7   ZExpandZSqueeze_3d_to_2d_maskÚ_outputé   )ZaxeszCreate an Attention node.r)   )r^   Zq_matmulZk_matmulZv_matmulZq_addZk_addZv_addr   r   Zfirst_inputr   Z	_newshapeé   T)r-   Z	data_typeÚdimsÚvalsÚrawr!   Z_reshape_outputZ_reshapera   Z	_modifiedé   zRoot node not matched.zFused Attention count:))rm   rn   ÚextendrC   r-   r   Zmatch_parentro   r   rB   r&   r(   r[   r   rc   r   rD   r   rE   r{   rb   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
   rm   r   Zattention_countZstart_nodesZskip_layer_norm_nodesrs   rh   rN   Zadd_before_layernormry   Z	qkv_nodesZ
matmul_qkvZv_nodesZadd_vrx   Zqk_nodesZ	matmul_qkZq_nodesZadd_qrv   Zk_nodesZadd_krw   r'   Zsqueeze_nodeZsqueeze_node_nameZsqueeze_output_namerj   Zis_same_rootr^   Úattention_nodeZtensorZreshape_r   r   r   r   Úfuse_attentionb  sH  






ýý











ÿ2ûø

õ
üÿÿ	òþù	û





zBertOnnxModelTF.fuse_attentionc                 C   s   |   ¡  |  ¡  |  ¡  d S r   )r   ru   Úskip_reshape©r
   r   r   r   Ú
preprocess-  s   zBertOnnxModelTF.preprocessc                 C   sn   d}|   d¡}|D ]}|  |d¡}|d ur&|jdkr&|jd |jd< |d7 }q	|dkr5t d|› ¡ d S d S )Nr   r!   r#   zSkip consequent Reshape count: )rn   ro   r   r   r   r   )r
   ÚcountZreshape_nodesrt   ry   r   r   r   rŽ   2  s   
€ÿzBertOnnxModelTF.skip_reshapec                 C   sp   |   d¡}|D ].}|  |ddgddg¡}|d u rqt d¡ |\}}|  |jd |jd ¡ |  |¡  d S d S )NZ	Attentionr!   r`   r   z+Remove Reshape before first Attention node.)rn   r&   r   r   r   r   r   Úremove_node)r
   Zattention_nodesrŒ   ÚpathZreshaperL   r   r   r   Ú%remove_reshape_before_first_attention>  s   


øz5BertOnnxModelTF.remove_reshape_before_first_attentionc                 C   s   |   ¡  |  ¡  d S r   )r”   rr   r   r   r   r   ÚpostprocessJ  s   zBertOnnxModelTF.postprocess)Ú__name__Ú
__module__Ú__qualname__r	   r   r(   r0   rP   rR   r]   rk   ru   r{   r   r   rŽ   r”   r•   Ú__classcell__r   r   r   r   r      s"    
@I6A Lr   )ÚloggingÚnumpyr‰   rf   r   r   r   Zonnx_model_bertr   Ú	getLoggerr–   r   r   r   r   r   r   Ú<module>   s   
