o
    ;ήcpa                     @   sv   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m	Z	m
Z
mZ d dlmZ eeZG dd deZdS )    N)deque)
ModelProto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__ R/tmp/pip-target-vg8gfxp4/lib/python/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 )NIdentityr   zRemoved Identity count: )nodesop_type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   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.
           )get_parent_subgraph_nodesr   get_initializerr   to_arrayr   shapename)r   current_nodeparent_nodesinitializersr!   r   initializertempr   r   r   )get_2d_initializers_from_parent_subgraphs:   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rt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   r<   r&   r=   r)   Squeezer(   r&   r>   )r'   r   r   r   r   r   r   r   Simplify semgent id path...r>   input_shapeinputsoutputsr<   zeros_for_input_shaperE   rF   value)input_name_to_nodesr   get_graph_inputsprintr   match_parent_pathsr   debugget_graph_by_noder3   add_noder   	make_nodeget_attribute_value	attribute)r   segment_embedding	input_idsrJ   r   graph_inputssegment_ids_segment_id_pathconstantofshape_node
graph_nameconstantofshape_valuer   r   r   find_segment_idsJ   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   Tr:   z&Found multiple candidates of input_ids)rJ   r   rK   rL   )r   word_embeddingrJ   r   rV   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|rt|dkr|d |d jd krt	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   ir'   Tr:   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   rA   r?   )r   r   r   r   r   r   r   r   c                    s   g | ]}| v r|qS r   r   rb   rd   r   r   rf      rg   rB   r>   input_shape_for_maskrD   r<   rH   )r   r   r*   has_constant_inputrK   r   rL   r   r   rN   r   rR   rS   rO   r3   rP   rQ   )r   re   r!   	mask_pathrP   mul_nodesub_node	cast_node
slice_nodeunsqueeze_noderV   rE   path_to_be_simplifiedduplicated_inputsrZ   r\   r[   r   rd   r   find_mask_input   s~   





	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.   
EmbedLayerrE   rF   r3   zcom.microsoftr   )r_   r   r   r]   rr   bert_inputscreate_node_nameattention_maskset_mask_indicefind_graph_inputtypetensor_type	elem_typer   INT32utilscast_graph_input_to_int32cast_input_to_int32onnxr   rQ   r   domainr   r   rP   rO   r3   )r   normalize_noder^   rT   position_embeddingrU   rW   
mask_inputrs   castedsegment_id_cast_nodemask_input_cast_nodert   
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rPt d|j|	j
 |j}
nt d	|j|	j
  dS | |d|}|dur|jd
kr| |}t	|dkrt d|  dS d}d}| D ]!\}}|d dkr|}t d|| q|}t d|| q|du s|du rt d  dS t d | ||||
 |    dS qdS )zM
        Automatically detect word, segment and position embeddings.
        z#start processing embedding layer...LayerNormalization)ra   r%   r(   )r   r'   r   Nr   r.   z+Found position embedding. name:{}, shape:{}z4Failed to find position embedding. name:{}, shape:{}ra   zHFailed to find two embeddings (word and segment) from Add node. Found {}z*Found segment embedding. name:{}, shape:{}z(Found words embedding. name:{}, shape:{}z.Failed to find both word and segment embeddingzCreate Embedding node)r   r   output_name_to_nodeget_nodes_by_op_typer*   r0   r   r   r1   r   r2   formatr3   
get_parentr   r9   warningitemsr   prune_graph)r   r   layer_norm_nodeslayer_norm_nodepos_embed_pathrP   reshape_nodern   r7   r8   r   first_parent
embeddingsr^   rT   r3   r2   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   rN   r   )	r   matmul_qmatmul_kmatmul_vparentr   x
root_input	root_noder   r   r   check_attention_inputZ  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 rt	d q |d }| 
|g dg d}|d u r| 
|ddgddg}|d u rt	d q |d }|d }| 
|g dg d}|d u r| 
|g dg d}|d u rt	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 rt|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d |d% jd d }|d u rq |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rt#$| %|
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	d0 q | &| | '  t(d1|  d S )2Nr   SkipLayerNormalizationr   ra   r'   )r   r   r%   z(Failed to match parent of normalize_node)ra   MatMulr%   	Transposer   )r   r   r   r   r   )r   r%   r   r   )r'   r   r   r   )ra   Einsumr   )r   r   r   zFailed to match qkv nodesrA   )r   r%   ra   r   r   zFailed to match v path)r`   ra   r#   r   )r   r   r   r   )r`   ra   r   zFailed to match qk_pathszFailed to match q path)r#   ra   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.r@   ExpandSqueeze_3d_to_2d_mask_output   )axeszCreate an Attention node.r.   	_newshape   T)r3   	data_typedimsvalsrawr%   _reshape_output_reshaperw   	_modified   zRoot node not matched.zFused Attention count:))r   r   extendrO   r3   r   match_parentr   r   rN   r*   r-   ri   r   r|   r   rP   r   rQ   r   rz   process_maskattention_fusioncreate_attention_noder   r   r   make_tensorr   INT64npint64inttobytesadd_initializerr   r1   r0   r   update_graphr   )#r   r   r    attention_countstart_nodesskip_layer_norm_nodesr   r   r[   add_before_layernormr   	qkv_nodes
matmul_qkvv_nodesadd_vr   qk_nodes	matmul_qkq_nodesadd_qr   k_nodesadd_kr   r,   squeeze_nodesqueeze_node_namesqueeze_output_namer   is_same_rootrs   attention_nodetensorreshape_r   r   r   r   fuse_attentione  sJ  


















2


		





zBertOnnxModelTF.fuse_attentionc                 C   s   |    |   |   d S r	   )r"   r   skip_reshaper   r   r   r   
preprocess1  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: )r   r   r   r   r   r   )r   countreshape_nodesr   r   r   r   r   r   6  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 )N	Attentionr%   ru   r   z+Remove Reshape before first Attention node.)r   r*   r   r   r   r   r   remove_node)r   attention_nodesr   pathreshaperX   r   r   r   %remove_reshape_before_first_attentionB  s   


z5BertOnnxModelTF.remove_reshape_before_first_attentionc                 C   s   |    |   d S r	   )r   r   r   r   r   r   postprocessN  s   zBertOnnxModelTF.postprocess)__name__
__module____qualname__r   r"   r-   r9   r]   r_   rr   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   r      s"    
@I6A Mr   )argparseloggingsyscollectionsr   numpyr   r   r   r   r   r   onnx_model_bertr   	getLoggerr   r   r   r   r   r   r   <module>   s   
