o
    ¢ÄihH  ã                   @   sF   d dl Z d dlZd dlmZ d dlmZ e  e¡ZG dd„ deƒZdS )é    N)Únumpy_helper)ÚBertOnnxModelTFc                       st   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‡  ZS )ÚBertOnnxModelKerasc                    s   t ƒ  |||¡ d S ©N)ÚsuperÚ__init__)ÚselfÚmodelÚ	num_headsÚhidden_size©Ú	__class__© úh/home/kim/smarthome/.venv/lib/python3.10/site-packages/onnxruntime/transformers/onnx_model_bert_keras.pyr      s   zBertOnnxModelKeras.__init__c                 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"BertOnnxModelKeras.match_mask_pathc           
      C   sˆ   g }|||fD ]8}|j d }|| }	|	|krq|	jdkr,|	j d |jd kr,| |	¡ qt d|› d|jd › ¡ dg f  S d|fS )Nr   r   zCheck attention input failed:z, FT)ÚinputÚop_typeÚoutputÚappendÚloggerÚdebug)
r   Úmatmul_qÚmatmul_kÚmatmul_vÚparentÚoutput_name_to_nodeÚreshape_nodesÚxZ
root_inputZ	root_noder   r   r   Úcheck_attention_input+   s   

z(BertOnnxModelKeras.check_attention_inputc           ,      C   sÎ  |   ¡  |  ¡ }g }d}|  d¡}|D ]¿}|  |d¡}|d u s%|jdvrZ|jdkrJ|  |d¡}|d u s9|jdvrIt d|d urC|jnd › ¡ qnt d|d urT|jnd › ¡ q	 |  |g d¢g d¢¡}|d u rpt d	¡ q|\}}	}
}}}t d
¡ |  |g d¢g d¢¡}|d u r’t d¡ q|\}}}}}|  |g d¢g d¢¡}|d urÅ|\}}}|  |g d¢g d¢¡}|d urÄ|\}}}}}}nA|  |g d¢g d¢¡}|d u ré|  |g d¢g d¢¡}|d u rét d¡ q|\}}} }|  |g d¢g d¢¡}|d ur|\}}}}}|d u rt d¡ q|  |g d¢g d¢¡}!|!d u r't d¡ q|!\}"}#}$}%}&|  |d ¡}'|'d u r@t d¡ q|  	|'d d¡sOt d¡ q|  
||&|||¡\}(})|(rÎ| j |'d jd ¡}*t d¡ | jj|*||&|||$|| j| j|jd |jd d}+|+d u rŒq|  |+¡ |d7 }| |||g¡ | |¡ | |¡ | |!¡ | |¡ | |'¡ | |)¡ | |	¡ |  ||	jd |
jd ¡ qt d¡ q|  |¡ |  ¡  t d|› ¡ d S ) Nr   ÚSkipLayerNormalization)r(   ZEmbedLayerNormalizationÚAddr   zFirst input for skiplayernorm: )r)   r   ÚMatMulr   Ú	Transposer*   )Nr   r   r   r   r   zFailed to match qkv nodeszMatched qkv nodes)r+   r   r)   r   r*   )r   r   r   r   r   zFailed to match v path)ÚSoftmaxr   r*   ©r   r   r   )r   r+   r   r)   r   r*   )r   Nr   r   r   r   )r,   r)   r   r*   )r   r   r   N)r,   r)   ÚDivr*   zFailed to match qk path)r   r   r   r   r   zFailed to match q pathzFailed to match k pathzFailed to match mask pathz;Sub node expected to have an input with constant value 1.0.éÿÿÿÿzCreate an Attention node.)Ú
mask_indexZq_matmulZk_matmulZv_matmulZq_addZk_addZv_addr
   r   Zfirst_inputr   zRoot node not matched.zFused Attention count:)Úinput_name_to_nodesr$   Úget_nodes_by_op_typeÚ
get_parentr   r   r   r   r   Úhas_constant_inputr'   Úattention_maskZprocess_maskr   Zattention_fusionZcreate_attention_noder
   r   r   Úadd_nodeÚextendr   Úreplace_node_inputÚremove_nodesZupdate_graphÚinfo),r   r$   Únodes_to_removeZattention_countZskip_layer_norm_nodesZnormalize_noder#   Z	qkv_nodesÚaddZextra_reshape_0ÚmatmulZreshape_qkvZtranspose_qkvZ
matmul_qkvZv_nodesZtranspose_vZ	reshape_vZadd_vZextra_reshape_1r"   Zqk_nodesZ
softmax_qkZsub_qkZ	matmul_qkZq_nodesZmul_qZtranspose_qZ	reshape_qZadd_qZextra_reshape_2r    Zadd_qkZmul_qkZk_nodesZtranspose_kZ	reshape_kZadd_kZextra_reshape_3r!   r   Zis_same_rootr%   r0   Zattention_noder   r   r   Úfuse_attention;   s  


ûý
ù
ý

ýù€
ý


ý





ÿ
õ










z!BertOnnxModelKeras.fuse_attentionc                 C   s   |   ¡  |  ¡  |  ¡  d S r   )Úprocess_embeddingÚ	fuse_maskÚskip_reshape)r   r   r   r   Ú
preprocess×   s   zBertOnnxModelKeras.preprocessc                 C   s~   |   ¡  |  ¡  d}|  d¡}|D ]}|  |d¡}|d ur.|jdkr.|jd |jd< |d7 }q|dkr=t d|› ¡ d S d S )Nr   r   r   zSkip consequent Reshape count: )r1   r$   r2   r3   r   r   r   r:   )r   Úcountr%   Zreshape_noder#   r   r   r   rA   Ü   s   
€ÿzBertOnnxModelKeras.skip_reshapec                 C   s  |j dksJ ‚t d|jd › d¡ |  |g d¢g d¢|¡}|d u r*t d¡ dS |\}}}|  |jd ¡}|d u rBt d	¡ dS t |¡}t	|j
ƒd
kr_t d|j› d|j
› ¡ |j}	nt d|j› d|j
› ¡ dS |  |jd ¡}
|
d urÆt |
¡}t	|j
ƒdkr·|j
d dkr·t | |j
d |j
d
 f¡d¡}|  |¡ t d|
j› d|j
dd … › ¡ d}njt d|
j› d|j
› ¡ dS |  |ddgddg|¡}|d u rÝt d¡ dS |\}}|  |jd ¡}
|
d u rôt d¡ dS t |
¡}t	|j
ƒd
krt d|
j› d|j
› ¡ |
j}nt d|
j› d|j
› ¡ dS |  |d|¡}|d u s3|j dkr:t d¡ dS |  |jd ¡}|d u rNt d¡ dS t |¡}t	|j
ƒd
krlt d|j› d|j
› ¡ |j}nt d|j› d|j
› ¡ dS t d¡ |  ||	||¡ dS )NÚLayerNormalizationz-start fusing embedding from node with output=r   z...)r)   r)   ÚGatherr-   zfailed to match word_embed_pathFzfailed to get word initializeré   zFound word embedding. name:z, shape:z$Failed to find word embedding. name:r   é   Úposition_embeddingzFound position embedding. name:z(Failed to find position embedding. name:rE   r   zfailed to match pos_embed_pathzfailed to get pos initializerzfailed to get gatherz!failed to get segment initializerzFound segment embedding. name:z'Failed to find segment embedding. name:zCreate Embedding nodeT)r   r   r   r   r   Zget_initializerr   r   Zto_arrayÚlenÚshaper:   ÚnameZ
from_arrayZreshapeZadd_initializerr3   Zcreate_embedding_subgraph)r   Únoder$   Zword_embed_pathZ	skip_noder6   Zgather_nodeZword_initializerÚtempZword_embeddingZpos_initializerZtensorrH   Zpos_embed_pathZ
pos_gatherZ	pos_sliceZgatherZsegment_initializerZsegment_embeddingr   r   r   Úfuse_embeddingë   sv   




"
"







z!BertOnnxModelKeras.fuse_embeddingc                 C   sF   t  d¡ |  ¡ }|  ¡ D ]}|jdkr |  ||¡r dS  dS qdS )zM
        Automatically detect word, segment and position embeddings.
        z#start processing embedding layer...rD   N)r   r:   r$   Únodesr   rN   )r   r$   rL   r   r   r   r?   7  s   

ýÿz$BertOnnxModelKeras.process_embeddingc                 C   sr  g }|   ¡ D ]‘}|jdkr—|  |d¡r—|  |g d¢g d¢¡}|d u r#q|\}}}}| j ¡ }|jd |krCtd|jd › d|› ƒ qtj	j
d|gd	gd
dgd}	tj	j
dd	gdgddgd}
tj	j
ddgdgd}|j tj	 dd¡g¡ |  ||jd d¡ | |||g¡ |  |	¡ |  |
¡ |  |¡ q|  |¡ t|ƒdkr§|  ¡  t t|ƒdkr´d¡ d S d¡ d S )Nr   iðØÿÿ)r   r   r   r   )r   r   r   r   r   zCast input z is not mask input r   Zmask_fuse_unsqueeze1_outputZMask_UnSqueeze_1r   )ÚinputsÚoutputsrK   ZaxesZmask_fuse_unsqueeze2_outputZMask_UnSqueeze_2rF   r   Zmask_fuse_cast_output)rP   rQ   Útoz
Fused maskzFailed to fuse mask)rO   r   r4   r   r5   Zget_first_maskr   ÚprintÚonnxÚhelperZ	make_nodeÚ	attributer7   Zmake_attributer8   r6   r9   rI   Úprune_graphr   r:   )r   r;   rL   Z	mask_pathZsub_nodeZ	cast_nodeZ
slice_nodeZunsqueeze_nodeZmask_input_nameZunsqueeze_added_1Zunsqueeze_added_2Zcast_node_2r   r   r   r@   C  sR   
ûû	ý


€
$zBertOnnxModelKeras.fuse_maskc              
   C   s¨   |   d¡}d}|D ]H}|  |g d¢g d¢¡}|d u rq	|\	}}}}}	}
}}}|jd |
jd< |  |¡ |	jd |jd< |  |¡ |jd |jd< |  |¡ |d7 }q	|S )Nr(   r   )	r)   r   r*   r   ÚGelur)   r   r*   r(   )	r   r   r   r   r   r   r   r   r   rG   ©r2   r   r   r   Úremove_node)r   Úskiplayernorm_nodesÚreshape_removedÚskiplayernorm_nodeÚpathÚadd_1Ú	reshape_1Úmatmul_1Ú	reshape_2ÚgeluÚadd_2Ú	reshape_3Úmatmul_2Úskiplayernormr   r   r   Úremove_extra_reshapew  s:   
óö



z'BertOnnxModelKeras.remove_extra_reshapec                 C   sÄ   |   d¡}d}|D ]V}|  |g d¢g d¢¡}|d u rq	|\
}}}}}	}
}}}}|jd |jd< |  |¡ |jd |
jd< |  |¡ |	jd |jd< |  |¡ |jd |jd< |  |¡ |d7 }q	|S )Nr(   r   )
r)   r   r*   r   rX   r)   r   r*   r   r(   )
Nr   r   r   r   r   r   r   r   r   é   rY   )r   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   Z	reshape_4rg   r   r   r   Úremove_extra_reshape_2¢  s@   
òõ




z)BertOnnxModelKeras.remove_extra_reshape_2c                 C   s.   |   ¡ |  ¡  }t d|› d¡ |  ¡  d S )NzRemove z Reshape nodes.)rh   rj   r   r:   rW   )r   r\   r   r   r   ÚpostprocessÖ  s   zBertOnnxModelKeras.postprocess)Ú__name__Ú
__module__Ú__qualname__r   r   r'   r>   rB   rA   rN   r?   r@   rh   rj   rk   Ú__classcell__r   r   r   r   r      s     L4+4r   )	ÚloggingrT   r   Zonnx_model_bert_tfr   Ú	getLoggerrl   r   r   r   r   r   r   Ú<module>   s   
