
    zIg1                     |    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	  ee
      Z G d de      Z G d d	e      Zy
)    )	getLogger)Dict)Fusion)helper)	OnnxModelc                   4     e Zd Zdef fdZdedefdZ xZS )FusionLayerNormalizationmodelc                 (    t         |   |dd       y )NLayerNormalization
ReduceMeansuper__init__selfr
   	__class__s     f/var/www/html/answerous/venv/lib/python3.12/site-packages/onnxruntime/transformers/fusion_layernorm.pyr   z!FusionLayerNormalization.__init__   s     4lC    input_name_to_nodesoutput_name_to_nodec           	         g }| j                   j                  ||      }t        |      dk(  st        |      dkD  ry|j                  d   }|d   j                  dk7  s|d   j                  d   |k7  ryt        |      dk(  r(|d   j                  dk7  s|d   j                  d   |k7  ryd}|D ]N  }| j                   j                  |d|d      }	| j                   j                  |d	dgg 
      }
|	|	}G|
J|
d   }P |y| j                   j                  |g dg dfg dg dfg|      \  }}}|dk  ry|d   }||vry|d   }| j                   j                  |      \  }}|
|dk  s|dkD  rt        j                  d|        y|d   }| j                   j                  |d      dk7  ry||j                  d      d   }|j                  d	k(  r'|j                  |       ||j                  d      d   }n|}|j                  dk7  ry||j                  d      d   }|j                  dk7  ry|j                  |       |j                  |       |j                  |dd        |j                  |||g       | j                   j                  ||j                  ||      st        j                  d       y|j                  d	k7  r|n|}|j                  d| j                   j!                  |j                  d   |      z
     }| j                   j#                  |dd      sy|j                  d| j                   j!                  |j                  d   |      z
     }| j                   j#                  |dd      sy| j$                  j                  |       t'        j(                  d|j                  d   ||g|j                  d   g| j                   j+                  dd            }|j,                  j                  t'        j.                  dt1        |            g       | j2                  j                  |       | j4                  | j6                  |j8                  <   y)a  
        Fuse Layer Normalization subgraph into one node LayerNormalization:
              +----------------------+
              |                      |
              |                      v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
                     (axis=2 or -1)  |      (Y=2)   (axis=2 or -1)  (E-6 or E-12 or 0)    ^
                                     |                                               |
                                     +-----------------------------------------------+

         It also handles cases of duplicated sub nodes exported from older version of PyTorch:
              +----------------------+
              |                      v
              |           +-------> Sub-----------------------------------------------+
              |           |                                                           |
              |           |                                                           v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div  --> Mul --> Add
              |                      ^
              |                      |
              +----------------------+
        r      NSub   DivF)	recursiveCast)exclude)SqrtAddr   Powr   )r   r   r   r   r   )r!   r"   r   r#   r   r   )r   r   r   r   r   r   g-C6?zHskip SkipLayerNormalization fusion since epsilon value is not expected:    g       @Mulr"   z4It is not safe to fuse LayerNormalization node. Skipzlayernorm weightzlayernorm biasr   	LayerNormname_prefixinputsoutputsnameepsilon)r
   get_childrenleninputop_typefind_first_child_by_typematch_child_pathmatch_parent_pathsget_constant_inputloggerdebugfind_constant_inputoutputappendextendis_safe_to_fuse_nodesinput_index$is_constant_with_specified_dimensionnodes_to_remover   	make_nodecreate_node_name	attributemake_attributefloatnodes_to_addthis_graph_namenode_name_to_graph_namer,   )r   noder   r   subgraph_nodeschildren
root_inputdiv_nodechild
div_node_1
div_node_2path_idparent_nodes_sub_nodesecond_add_nodei
add_weightpow_node	temp_nodemul_nodelast_add_nodenode_before_weightweight_input
bias_inputnormalize_nodes                             r   fusezFusionLayerNormalization.fuse   sd   , ::**41DEx=AX!2ZZ]
A;%'8A;+<+<Q+?:+Mx=A{""e+x{/@/@/Cz/Q 
	*E<<UEK^jo<pJ 44UVUOUW4XJ%%'%b>
	* #'::#@#@<oNDFXY  $
 q Q;#8#&q/

55oF:qJ4GLLcdncopq?::))(C8A='(:;A>	&!!),*9+;+;A+>?BH !Hu$+HOOA,>?B  E)d#h'l3B/0}hABzz//  	
 LLOP)2):):f)DX)~~a$***@*@ASAZAZ[\A]_g*h&hizz>>|QPbc"((TZZ-C-CHOOTUDVXe-f)fg
zz>>z1N^_##N3)) JJqM<<"))!,-,,-A{,[	
 	  '')>)>y%PZJ[)\(]^  0<@<P<P$$^%8%89r   __name__
__module____qualname__r   r   r   r_   __classcell__r   s   @r   r	   r	      s*    Di D|Qd |Q |Qr   r	   c                   4     e Zd Zdef fdZdedefdZ xZS )FusionLayerNormalizationTFr
   c                 *    t         |   |ddd       y )Nr   r"   TFr   r   s     r   r   z#FusionLayerNormalizationTF.__init__   s     4eTBr   r   r   c                 ,   g }| j                   j                  |g dg dfg dg dfg|      \  }}}|yt        |      dk(  sJ |d   dv r|d	   dv r|d
   dv st        j	                  d       y|dd \  }}}	}
}}|dd \  }}}}d}t        |      dk(  r|d   }|j
                  dk(  sJ | j                   j                  |dd|      }|t        j	                  d       y| j                   j                  |d|      }||n| j                   j                  |d|      }|t        j	                  d       y| j                   j                  |      \  }}||dk  s|dkD  r|t        j	                  d       y|L|j                  d   |j                  vs|j                  d   |j                  vrt        j	                  d       y|L|j                  d   |j                  vs|j                  d   |j                  vrt        j	                  d       y|j                  d   |j                  d	   k7  rt        j	                  d       y||||	|
|||||||g}|J| j                   j                  |dd|      }|t        j	                  d       y|j                  |||g       | j                   j                  ||j                  | j                   j                         | j                   j                               st        j	                  d       y| j                  j                  |       |	j                  d	   }|j                  d   }t!        j"                  d|j                  d   ||g|j                  d   g| j                   j%                  dd            }|j&                  j                  t!        j(                  dt+        |            g       | j,                  j/                  |       | j0                  | j2                  |j4                  <   y)aU  
         Layer Norm from Tensorflow model(using keras2onnx or tf2onnx):
          +------------------------------------+
          |                                    |
          |                                    |
        (Cast_1)                               |
          |                                    |
          |                                    v                                           (B)                             (B)             (A)
         Add --> (Cast_1) --> ReduceMean -->  Sub  --> Mul --> ReduceMean --> (Cast_3) --> Add --> Sqrt --> Reciprocol --> Mul --> Mul --> Sub --> Add
          |                       |                                                                                         |       ^              ^
          |                       |                                                                                         |       |              |
          |                       +--------------------------------------------------(Cast_2)-------------------------------|-------+              |
          |                                                                                                                 v                      |
          +---------------------------------------------------------------------------------------------------------------> Mul--------------------+
        )
r   r%   r%   
Reciprocalr!   r"   r   r%   r   r   )
r   r   Nr   r   r   Nr   r   N)r   r%   r%   rk   r!   r"   r   r   r%   r   r   )r   r   Nr   r   r   r   Nr   r   NNr$   r   )r   r   r   r   z=return indice is exepected in [0, 1], but got {return_indice}      r   r%   zmul_node_3 not foundzroot node is nonegh㈵>zepsilon is not matchedz;reduce_mean_node_1 and mul_node_3 shall link from root nodez%mul_node_2 shall have two same inputszcast_node_2 not foundz$not safe to fuse layer normalizationr   r&   r'   r)   r-   )r
   r4   r/   r6   r7   r1   match_parent
get_parentr5   r0   r;   r<   r9   r   r   r?   r   r@   rA   rB   rC   rD   rE   r:   rF   rG   r,   )r   rH   r   r   return_indicerR   rQ   
sub_node_0
mul_node_0
mul_node_1reciprocol_node	sqrt_node
add_node_0reduce_mean_node_0
mul_node_2
sub_node_1reduce_mean_node_1cast_node_3
mul_node_3node_before_reduce	root_noderU   r-   rI   cast_node_2r\   r]   
fused_nodes                               r   r_   zFusionLayerNormalizationTF.fuse   sG     )-)F)F <  ?! B  G$*
&<L =!Q&&&a F*}Q/?6/Im\]N^bhNhLLXY !	
IUVXVYIZFJ
4F|"&q/K&&&000ZZ,,T5!=PQ
LL/0!ZZ223EqJ]^ " &&'91>QR 	
 LL,-ZZ22:>
7?glw/?KDWLL12$$Q'z/?/??CUC[C[\]C^fpfvfvCvLLVW"$$Q'z/?/??CUC[C[\]C^fpfvfvCvLLVWA*"2"21"55LL@A 
 "**11*faI\]K"45!!#5{K"PQzz//KKJJ**,JJ**,	
 LL?@##N3!''*%%a(
 %% $$Q'zB[[^$,,-A{,[	

 	##V%:%:9eGn%U$VW  ,8<8L8L$$Z__5r   r`   re   s   @r   rg   rg      s*    Ci C_Md _M _Mr   rg   N)loggingr   typingr   fusion_baser   onnxr   
onnx_modelr   ra   r6   r	   rg    r   r   <module>r      sA   
      	8	@Qv @QFcM cMr   