
    \jA*                         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d Z G d de      Z G d	 d
e      Zy)    )	getLogger)Fusion)NumpyHelper)helper)	OnnxModelc                     t        |       dk7  ryt        |      dk(  r"|d   dk(  xr |d   | d   k(  xr |d   | d   k(  S t        |      dk(  r|d   | d   k(  xr |d   | d   k(  S y)zCheck if skip_shape can broadcast to input_shape for SkipLayerNormalization.

    The kernel supports: input 3D (B,S,H) with skip 3D (1,S,H) or skip 2D (S,H).
       Fr         )len)input_shape
skip_shapes     `/root/.hermes/venv/lib/python3.12/site-packages/onnxruntime/transformers/fusion_skiplayernorm.py_is_broadcast_skipr      s    
 ;1
:!!}!ijm{1~&Ei*UV-[fgh[iJii
:!!}A.R:a=KPQN3RR    c            	       H     e Zd ZdZ	 	 	 d	dedededef fdZd Zd Z	 xZ
S )
FusionSkipLayerNormalizationz
    Fuse Add + LayerNormalization into one node: SkipLayerNormalization.
    Supports broadcasting of the skip input: (1, sequence_length, hidden_size)
    or (sequence_length, hidden_size) will be broadcast to match the input shape.
    modelfused_op_typesearch_op_typesshape_inferc                     t         |   |||       |rH| j                  j                  dddd      | _        | j                  t
        j                  d       y y y )N      )
batch_sizeseq_lenT)updatez,symbolic shape inference disabled or failed.)super__init__r   infer_runtime_shapeshape_infer_helperloggerwarning)selfr   r   r   r   	__class__s        r   r   z%FusionSkipLayerNormalization.__init__%   s`     	?&*jj&D&DTUbcEdmq&D&rD#&&.MN / r   c                    | j                   j                  |j                  d         }| j                   j                  |j                  d         }||y||k(  rt        |      dk(  rdS dS t	        ||      ryt	        ||      ryy)zIdentify which Add input is the skip tensor (the one that may broadcast).

        Returns (skip_index, broadcast):
            skip_index: 0 or 1 (which Add input is skip), -1 if incompatible
            broadcast: True if broadcasting is needed
        r   r
   )Fr	   )r
   F)r
   T)r   T)r!   get_edge_shapeinputr   r   )r$   addshape_ashape_bs       r   get_skip_indexz+FusionSkipLayerNormalization.get_skip_index4   s     ))881F))881F?gog!$W!2:CC gw/gw/r   c           	         | j                   j                  |d|      }||j                  dk7  ry t        |j                        dk7  ry |j                  D ]  }| j                   j                  |       y  || j                  v ry |j                  dk(  }d}d}t        | d      rm| j                  K| j                  |      \  }}|dk  rHt        j                  d|j                  d   |j                  d          y t        j                  d	       y | j                   j                  |d
gd g      }	|	N| j                   j                  |	d   j                  d         #| j                   j                  |	d   dgdg      y |rWt        d      D ]I  }
| j                   j                  ||
|      }|#|j                  d
k(  s3t        j                  d|
        y  | j                   j                  |j                   d         d u}|xs( t        | j                   j#                  ||            dkD  }|j                   }|r|j%                  |j                   d   g       |j                   d   g}|r!|j%                  dd|j                   d   g       | j                   j'                  ||g|||      r| j                  j%                  ||g       d|z
  }|s:|j                  |   |j                  |   |j                  d   |j                  d   gn+|j                  |   |j                  |   |j                  d   g}t)        j*                  | j,                  ||| j                   j/                  | j,                  d            }d|_        |j2                  D ].  }|j4                  dk(  s|j2                  j%                  |g       0 t        |j2                        dk(  r0|j2                  j%                  t)        j6                  dd      g       | j8                  j;                  |       | j<                  | j>                  |j4                  <   y y )Nr   Addr   SimplifiedLayerNormalizationr
   Fr!   zUskip SkipLayerNormalization fusion since shapes of inputs (%s, %s) are not compatiblezHskip SkipLayerNormalization fusion since symbolic shape inference failedGatherConstantOfShapez]skip SkipLayerNormalization broadcast fusion since Add input %d comes from Gather (embedding) SkipLayerNorm)name_prefixinputsoutputsnamecom.microsoftepsilon-q=) r   
get_parentop_typer   r)   get_initializernodes_to_removehasattrr!   r-   r"   debugmatch_parent_pathfind_graph_inputrangefind_graph_outputoutputget_childrenextendis_safe_to_fuse_nodesr   	make_noder   create_node_namedomain	attributer9   make_attributenodes_to_addappendthis_graph_namenode_name_to_graph_name)r$   nodeinput_name_to_nodesoutput_name_to_noder*   	add_input
simplified
skip_index
_broadcastgather_pathiparentadd_has_graph_output#residual_add_has_multiple_consumersoutputs_to_keepr8   input_indexr7   normalize_nodeatts                       r   fusez!FusionSkipLayerNormalization.fuseL   s   jj##D!-@A ;#++. syy>Q 	Izz)))4@	
 $&&& \\%CC


4-.&&2)-)<)<S)A&
J>LLo		!		!
 ghjj223
TFK"tzz'B'B;q>CWCWXYCZ'['czz++KN=N<ORSQTU]
 1X ..sA7JK%&..H*DLLw   $zz;;CJJqMJRVV ^C

(?(?EX(Y$Z]^$^ 	, ++.""CJJqM?3;;q>" /NNBCJJqM23::++S$KJ]_rs  ''d4j.K " ;':)>

1tzzZ[}]ii,cii
.CTZZPQ]S 
 $--""ZZ001C1CQ`0a	N %4N! ~~ ;88y(",,33SE:;
 >++,1((//1F1FyRY1Z0[\$$^4@D@T@TD(()<)<=7 tr   )SkipLayerNormalizationLayerNormalizationT)__name__
__module____qualname____doc__r   strboolr   r-   rd   __classcell__r%   s   @r   r   r      sO     63 OO O 	O
 O0iUr   r   c                   *     e Zd Zdef fdZd Z xZS ) FusionBiasSkipLayerNormalizationr   c                 *    t         |   |ddd       y )Nre   zadd bias)r   r   )r$   r   r%   s     r   r   z)FusionBiasSkipLayerNormalization.__init__   s     8:RT^_r   c           	         t        |j                        dk7  ry g }| j                  j                  |ddgd d g||      }||\  }}n/g }| j                  j                  |g dg d||      }||\  }}}ny t        |      dk(  st        |      dk(  sJ |d   }	|	dk\  ry |j                  |d	      }
|j                  d	|d	   z
     }|j                  d	|	z
     }| j                  j	                  |      }|y t        j                  |      }|t        j                  d
       y t        |j                        d	k7  rt        j                  d       y ||g}| j                  j                  ||j                  ||      st        j                  d       y | j                  j                  |       |
||j                  d   |j                  d   |g}t        j                  d||j                  | j                  j!                  dd            }d|_        |j$                  D ].  }|j&                  dk(  s|j$                  j                  |g       0 t        |j$                        dk(  r0|j$                  j                  t        j(                  dd      g       | j*                  j-                  |       | j.                  | j0                  |j&                  <   y )Nr   r/   MatMul)r/   Castrs   )NNNr   r	   r   r
   zBias weight not foundzBias weight is not 1DzASkip fusing SkipLayerNormalization with Bias since it is not safere   SkipLayerNorm_AddBias_r6   r:   r;   r<   )r   r)   r   rC   r?   r   to_arrayr"   rB   shaperJ   rG   r@   rI   r   rK   rL   rM   rN   r9   rO   rP   rQ   rR   rS   )r$   rT   rU   rV   return_indicenodesr*   _matmul_castadd_input_index	sln_input
bias_input
skip_inputinitializerbias_weightsubgraph_nodesr7   new_noderc   s                      r   rd   z%FusionBiasSkipLayerNormalization.fuse   s   tzz?a

,,TE83DtTlTgivw"NS' MJJ00/1CEXZgE  (-%eW=!Q&#m*<*AAA'*aIImA./	YYq=#334
ZZO 34
 jj00<!**;7LL01{  !Q&LL01zz//M`buvLL\]##N3JJqMJJqM
 ##$KK,,-EG_`	
 * >> 	1Cxx9$""))3%0	1
 x!!"a'%%v'<'<Y'P&QR  *6:6J6J$$X]]3r   )rg   rh   ri   r   r   rd   rm   rn   s   @r   rp   rp      s    `i `FKr   rp   N)loggingr   fusion_baser   fusion_utilsr   onnxr   
onnx_modelr   rg   r"   r   r   rp    r   r   <module>r      sF      $   	8	WU6 WUtJKv JKr   