+
    G-jŒ  ã                   ó†   € ^ RI Ht ^ RIHt ^ RIHt ^ RIHtHtH	t	 ^ RI
Ht ]! ]4      t ! R R]4      t ! R R	]4      tR
# )é    )Ú	getLogger)ÚFusion)ÚFusionUtils)Ú	NodeProtoÚTensorProtoÚhelper©Ú	OnnxModelc                   óØ   a a€ ] tR t^t oRtRV3R lV 3R llltV3R lR ltV3R lR ltR tR	 t	R
 t
R tR tV3R lR ltRV3R lR lltR tR tRR ltR tR tR tRtVtV ;t# )ÚFusionEmbedLayerNoMaskz€
Fuse embedding layer into one node (EmbedLayerNormalization).
It supports the following model types: BERT, DistilBert, ALBert.
c                ó&   <€ V ^8„  d   QhRS[ RS[/# )é   ÚmodelÚdescription)r
   Ústr)ÚformatÚ__classdict__s   "€Ú{/Volumes/fast/ai/experiments/nudenet-smoke/.venv/lib/python3.14/site-packages/onnxruntime/transformers/fusion_embedlayer.pyÚ__annotate__Ú#FusionEmbedLayerNoMask.__annotate__   s   ø€ ÷ ñ ™ið ±cñ ó    c                óˆ   <€ \         SV `  VR RR.V4       \        V4      V n        RV n        RV n        RV n        RV n        R# )ÚEmbedLayerNormalizationÚLayerNormalizationÚSkipLayerNormalizationNF)ÚsuperÚ__init__r   ÚutilsÚshape_inferÚshape_infer_doneÚ	attentionÚ
embed_node)Úselfr   r   Ú	__class__s   &&&€r   r   ÚFusionEmbedLayerNoMask.__init__   sP   ø€ Ü‰ÑØØ%Ø!Ð#;Ð<Øô		
ô ! Ó'ˆŒ
ØˆÔØ %ˆÔð ˆŒØˆŽr   c                óJ   <€ V ^8„  d   QhRS[ RRS[S[ S[ 3,          ,          /# )r   ÚaddÚreturnN)r   Útuple)r   r   s   "€r   r   r   %   s*   ø€ ÷ 	2ñ 	2¡Ið 	2°$¹¹yÉ)Ð?SÕ9TÕ2Tñ 	2r   c                óº   € V P                   P                  VR .^ .4      pVf   R# V P                   P                  VR .^.4      pVf   R# V^ ,          V^ ,          3# )ÚGatherN)r   Úmatch_parent_path)r#   r'   Úgather_0_pathÚgather_1_paths   &&  r   Úmatch_two_gatherÚ'FusionEmbedLayerNoMask.match_two_gather%   sa   € ØŸ
™
×4Ñ4°S¸8¸*ÀqÀcÓJˆØÒ ÙàŸ
™
×4Ñ4°S¸8¸*ÀqÀcÓJˆØÒ Ùà˜QÕ ¨qÕ!1Ð1Ð1r   c                óX   <€ V ^8„  d   QhRS[ RS[S[S[S[ ,          3,          RS[RS[/# )r   Ú	layernormÚinput_name_to_nodesÚis_distil_bertr(   )r   Údictr   ÚlistÚbool)r   r   s   "€r   r   r   0   sG   ø€ ÷ Rñ RáðRñ "¡#¡t©I¥Ð"6Õ7ðRñ ð	Rñ
 
ñRr   c                ó@  € V P                   P                  VRVRR7      V n        V P                  e   R# VP                  ^ ,          V9  d   R# W!P                  ^ ,          ,          p\	        V Uu. uF  qUP
                  NK  	  up4      pV. R	O8X  d…   V F~  pVP
                  R8X  g   K  V P                   P                  V. R
O. RO4      pVf   K=  VR,          P                  ^ ,          VP                  ^ ,          8X  g   Ko  V^,          V n         R# 	  \        V4      ^8X  Ed   V^ ,          P
                  R8X  dî   V^ ,          P                  ^ ,          V9   dÏ   W$^ ,          P                  ^ ,          ,          p	\        V	4      ^8X  dŸ   V	^ ,          P
                  R8X  d‡   V	^ ,          P                  ^ ,          V9   dh   W)^ ,          P                  ^ ,          ,          p
V
 F  pVP
                  R8X  g   K  Wpn         R# 	  \	        V
 Uu. uF  qUP
                  NK  	  up4      pV'       d5   V. RO8w  d*   V. RO8w  d!   V. RO8w  d   \        P                  R4       R# R# V. RO8w  d!   V. R	O8w  d   \        P                  R4       R# R# u upi u upi )ao  Check that LayerNormalization has a child of Attention node or subgraph like Attention.

Args:
    layernorm (NodeProto): LayerNormalization node
    input_name_to_nodes (Dict[str, List[NodeProto]]): map from input name to nodes
    is_distil_bert (bool): whether it is DistilBert or not

Returns:
    bool: whether there is Attention node or subgraph like Attention
Ú	AttentionF)Ú	recursiveTÚMatMulr   ÚAddz<No Attention like subgraph in children of LayerNormalization)r;   r;   r;   r   )r<   r;   ÚMultiHeadAttentionr;   )NNr   r   éÿÿÿÿ)r;   r;   r;   ÚShaper   )r<   r;   r;   r;   r?   r?   )r<   r;   r;   r;   r?   )r<   r;   r;   r;   )r   Úfind_first_child_by_typer!   ÚoutputÚsortedÚop_typer,   ÚinputÚcross_attentionÚlenÚloggerÚdebug)r#   r2   r3   r4   ÚchildrenÚchildÚchildren_typesÚnodeÚpath1ÚgrandchildrenÚnodess   &&&&       r   Úcheck_attention_subgraphÚ/FusionEmbedLayerNoMask.check_attention_subgraph0   sD  € ð  Ÿ™×<Ñ<Ø�{Ð$7À5ð =ó 
ˆŒð �>‰>Ò%Ùà×Ñ˜AÕÐ&9Ô9ÙØ&×'7Ñ'7¸Õ':Õ;ˆÜ¹HÓ E¹H°5§¤¹HÑ EÓFˆð ÒUÔUÛ �Ø—<‘<Ð#;Ö;Ø ŸJ™J×8Ñ8ØÚIÚ*ó�Eð
 Ô(¨U°2­Y¯_©_¸QÕ-?À9×CSÑCSÐTUÕCVÖ-VØ/4°Q­x˜Ô,Ú#ñ !ô ˆx‹=˜AÕ (¨1¥+×"5Ñ"5¸Ô"AÀhÈqÅk×FXÑFXÐYZÕF[Ð_rÔFrØ/¸µ×0BÑ0BÀ1Õ0EÕFˆMä�MÓ" aÔ'Ø! !Õ$×,Ñ,°Ô5Ø! !Õ$×+Ñ+¨AÕ.Ð2EÔEà+¸!Õ,<×,CÑ,CÀAÕ,FÕG�Û!�DØ—|‘| {Ö2Ø)-œÚ#ñ "ô "(ÁEÓ(JÁE¸5¯¬ÁEÑ(JÓ!K�÷ ð Ò"cÔcØ"Ò&]Ô]Ø"Ò&TÔTä—‘Ð[Ô\Ùñ  ð ò "ô ð
 !ò %ô ô —‘Ð[Ô\Ùáùòq !Fùò: )Ks   Á1JÈJc                ó   € V P                   P                  VRR.^^.4      pVf(   V P                   P                  V. RO. RO4      pVf   R# V^ ,          VR,          reVP                  ^ ,          V8w  d   R# V P                   P                  V. RO. R	O3. R
O. RO3.V4      w  rxpVf   R# V^,          p	V P                  P                  V	^ ^ 4      '       d$   V P                  P                  V	^^4      '       g   R# VR,          p
V P                  P                  V
^^4      '       g   R# VR,          pVP                  ^ ,          V8w  d   R# R# )aø  Match position embedding path from input_ids to Gather for DistilBert.

Pattern is like the following:
         (input_ids)
              |
             Shape
               |                          |    Gather (indices=1)
               |       |
               |      Cast (optional)
               |       |
               |      Range (start=0, end=*, delta=1)
               |       |
               |    Unsqueeze
               |    /
              Expand
                |
              Gather
ÚExpandr?   FT)rS   ÚWhereÚReshaper?   )é   rV   r   r   r>   )Ú	UnsqueezeÚRangeÚCastr+   r?   )r   r   rV   r   r   )rW   rX   r+   r?   )r   r   rV   r   éþÿÿÿ)r   r,   rD   Úmatch_parent_pathsr   Úcheck_node_input_value)r#   Úposition_embedding_gatherÚ	input_idsÚoutput_name_to_noderM   ÚexpandÚshapeÚ_Úpath2Ú
range_nodeÚgather_nodeÚ
shape_nodes   &&&&        r   Ú#match_position_embedding_distilbertÚ:FusionEmbedLayerNoMask.match_position_embedding_distilbert„   s>  € ð* —
‘
×,Ñ,Ð-FÈÐSZÐH[Ð^_ÐabÐ]cÓdˆØŠ=Ø—J‘J×0Ñ0Ø)Ú7ÚóˆEð
 Š}Ùà˜a� %¨¥)�Ø�;‰;�q�>˜YÔ&Ùà—j‘j×3Ñ3ØâBÂOÐTÚ:ºLÐIðð  ó
‰ˆ�!ð Š=Ùà˜1•Xˆ
à�J‰J×-Ñ-¨j¸!¸Q×?Ò?ÀDÇJÁJ×DeÑDeÐfpÐrsÐuv×DwÒDwáà˜B•iˆØ—
‘
×1Ñ1°+¸qÀ!×DÒDÙà˜2•Yˆ
Ø×Ñ˜AÕ )Ô+Ùár   c                ó   € R# )aI  Match position embedding path from input_ids to Gather for Roberta.

Roberta Embedding Layer Pattern (* is optional since it might be removed by ORT, ? is the padding word id):
  (input_ids) --> Equal(B=?) -- Not -- Cast(to=6) -- CumSum(axis=1) -- Mul -- Cast(to=7) -- Add(B=1) -- Cast(to=7)* --> Gather
                                        |                              ^
                                        V                              |
                                        +------------------------------+

Roberta new pattern from transformers v4.9:
   (input_ids) --> Equal(B=?) -- Not -- Cast(to=6) -- CumSum(axis=1) -- Add(B=0) -- Mul -- Cast(to=7) -- Add(B=1) --> Gather
                                        |                                           ^
                                        V                                           |
                                        +-------------------------------------------+

start_node = position_embedding_gather
start_index = 1

# match optional Cast node.
parent = self.model.get_parent(start_node, start_index, output_name_to_node)
if parent is None:
    return
if parent.op_type == "Cast":
    if OnnxModel.get_node_attribute(parent, "to") != 7:
        return
    start_node = parent
    start_index = 0

i, path, return_indices = self.model.match_parent_paths(
    start_node,
    [ (['Add', 'Cast', 'Mul', 'CumSum', 'Cast', 'Not', 'Equal'], [start_index, 0, 0, 0, 0, 0, 0]),
      (['Add', 'Cast', 'Mul', 'Add', 'CumSum', 'Cast', 'Not', 'Equal'], [start_index, 0, 0, 0, 0, 0, 0, 0])],
    output_name_to_node)

if path is not None:
    # constant input of Add shall be 1.
    i, value = self.model.get_constant_input(path[0])
    if value != 1:
        return False

    _, self.padding_word_id = self.model.get_constant_input(path[-1])

    return input_ids == path[-1].input[0]
F© ©r#   r]   r^   r_   s   &&&&r   Ú match_position_embedding_robertaÚ7FusionEmbedLayerNoMask.match_position_embedding_robertaÂ   s   € ñZ r   c                óü  € V P                   P                  VRR.^^.V4      pVf   R# Vw  rVV P                   P                  VP                  ^ ,          4      pVe¹   \	        VP
                  4      ^8X  dŸ   VP
                  ^ ,          ^8X  d‡   V P                  P                  V^^ .4      '       dc   V P                  P                  V^^.4      '       d?   \	        VP                  4      ^8X  g'   V P                  P                  V^^.4      '       g   R# V P                   P                  4       pV^8  d#   \        P                  ! VR^ .4      '       g   R# M&V P                  P                  V^^ .4      '       g   R# V P                   P                  V^ V4      p	V	f   R# V	P                  R8X  dD   V P                  P                  V	^^ 4      '       g   R# V P                   P                  V	^ V4      p
MT	p
V
e   V
P                  R8w  d   R# V P                  P                  V
^^4      '       g   R# V P                   P                  V
^ V4      pVe   VP                  R8w  d   R# W+P                  ^ ,          8H  # )aw  Match position embedding path from input_ids to Gather for BERT.

BERT Embedding Layer Pattern:
                            (input_ids)
                           /                                          /          Shape
                        /              |
                      /              Gather (indices=1)
                     /                  |
                    /                  Add (optional, B=0)
                   /                    |
                Gather (segment_ids) Unsqueeze (axes=0)
                   \        |           |
                    \     Gather      Slice (data[1,512], starts=0, ends=*, axes=1, steps=1)
                      \    /            |
                        Add          Gather
                           \       /
                              Add
                               |
                        LayerNormalization
ÚSlicerW   FÚaxesr<   r+   r?   )r   r,   Úget_constant_valuerD   rF   ra   r   r\   Úget_opset_versionr   Úcheck_node_attributeÚ
get_parentrC   )r#   r]   r^   r_   ÚpathÚsliceÚ	unsqueezeÚslice_weightÚopset_versionrL   Úgatherra   s   &&&&        r   Úmatch_position_embedding_bertÚ4FusionEmbedLayerNoMask.match_position_embedding_bertñ   s  € ð, �z‰z×+Ñ+Ø%Ø�kÐ"Ø�ˆFØó	
ˆð Š<ÙàÑˆØ—z‘z×4Ñ4°U·[±[Àµ^ÓDˆàÒ$Ü�L×&Ñ&Ó'¨1Ô,Ø×"Ñ" 1Õ%¨Ô*Ø—
‘
×1Ñ1°%¸¸Q¸C×@Ò@Ø—
‘
×1Ñ1°%¸¸Q¸C×@Ò@Ü�U—[‘[Ó! QÔ&¨$¯*©*×*KÑ*KÈEÐSTÐWXÐVY×*ZÒ*ZáàŸ
™
×4Ñ4Ó6ˆØ˜2ÔÜ×3Ò3°I¸vÈÀs×KÒKÙð Lð —:‘:×4Ñ4°YÀÀAÀ3×GÒGÙà�z‰z×$Ñ$ Y°Ð3FÓGˆØŠ<ÙØ�<‰<˜5Ô Ø—:‘:×4Ñ4°T¸1¸a×@Ò@ÙØ—Z‘Z×*Ñ*¨4°Ð4GÓH‰FàˆFàŠ>˜VŸ^™^¨xÔ7ÙØ—
‘
×1Ñ1°&¸!¸Q×?Ò?Ùà—
‘
×%Ñ% f¨aÐ1DÓEˆØŠ=˜EŸM™M¨WÔ4ÙàŸK™K¨�NÑ*Ð*r   c                ón   € V P                  WV4      '       d   R # V P                  WV4      '       d   R # R# )TF)r{   rg   rk   s   &&&&r   Úmatch_position_embeddingÚ/FusionEmbedLayerNoMask.match_position_embedding9  s7   € Ø×-Ñ-Ð.GÐTg×hÒhÙð ×3Ñ3Ð4MÐZm×nÒnÙár   c                ón	  € VP                   ^,          pV'       d   VP                   ^,          MRpVP                   ^,          pV P                  '       g)   V P                  P                  RR7      V n        RV n        V P                  eú   V P                  P                  V4      pV P                  P                  V4      pV'       d	   V'       g   Q h\        V4      ^8X  d&   \        V4      ^8X  d   V^,          V^,          8X  g   \        P                  RV RV 24       R# V'       dX   V P                  P                  WE4      '       g7   \        P                  RV RV P                  P                  V4       24       R# V P                  P                  VP                   ^ ,          4      p	V	e   \        V	P                  4      ^8w  d   \        P                  R	4       R# V P                  P                  VP                   ^ ,          4      p
V
eD   \        V
P                  4      ^8w  g*   V	P                  ^,          V
P                  ^,          8w  d   \        P                  R
4       R# V'       d‹   V P                  P                  VP                   ^ ,          4      pVeD   \        VP                  4      ^8w  g*   V	P                  ^,          VP                  ^,          8w  d   \        P                  R4       R# V	P                  ^ ,          V
P                  ^ ,          8:  df   \        P                  RVP                   ^ ,           RV	P                  ^ ,           RVP                   ^ ,           RV
P                  ^ ,           24       V'       Ed   V	P                  ^ ,          XP                  ^ ,          8:  df   \        P                  RVP                   ^ ,           RV	P                  ^ ,           RVP                   ^ ,           RVP                  ^ ,           24       V
P                  ^ ,          VP                  ^ ,          8:  df   \        P                  RVP                   ^ ,           RV
P                  ^ ,           RVP                   ^ ,           RVP                  ^ ,           24       R# )zXSanity check of embedding weights, and match hidden_size of weights and shape of inputs.NT)Úupdatez^Cannot fuse EmbedLayerNormalization: input_ids and position_ids not matched in 2nd dimension: z vs FzYCannot fuse EmbedLayerNormalization: input_ids and segment_ids does not have same shape: z != zICannot fuse EmbedLayerNormalization: word embedding table is not expectedzMCannot fuse EmbedLayerNormalization: position embedding table is not expectedzLCannot fuse EmbedLayerNormalization: segment embedding table is not expectedzword_embedding_table (z) size z <= position_embedding_table (z <= segment_embedding_table (zposition_embedding_table ()rD   r    r   Úinfer_runtime_shaper   Úget_edge_shaperF   rG   ÚinfoÚcompare_shaperq   ra   Úwarning)r#   Úword_embedding_gatherÚsegment_embedding_gatherr]   r^   Úsegment_idsÚposition_idsÚinput_ids_shapeÚposition_ids_shapeÚword_embedding_tableÚposition_embedding_tableÚsegment_embedding_tables   &&&&        r   Úcheck_embeddingÚ&FusionEmbedLayerNoMask.check_embeddingG  sü  € à)×/Ñ/°Õ2ˆ	ß;SÐ.×4Ñ4°QÖ7ÐY]ˆØ0×6Ñ6°qÕ9ˆà×$×$Ð$Ø#Ÿz™z×=Ñ=ÀTÐ=ÓJˆDÔØ$(ˆDÔ!à×ÑÒ'Ø"×.Ñ.×=Ñ=¸iÓHˆOØ!%×!1Ñ!1×!@Ñ!@ÀÓ!NÐß"×'9Ð9Ð9ä�OÓ$¨Ô)ÜÐ*Ó+¨qÔ0Ø# AÕ&Ð*<¸QÕ*?Ô?ä—‘Øtð  vEð  uFð  FJð  K]ð  J^ð  _ôñ ç 4×#3Ñ#3×#AÑ#AÀ)×#YÒ#YÜ—‘ØoÐpð  pAð  AEð  FJ÷  FVñ  FV÷  Feñ  Feð  fqó  Frð  Esð  tôñ à#Ÿz™z×<Ñ<Ð=R×=XÑ=XÐYZÕ=[Ó\ÐØÒ'¬3Ð/C×/IÑ/IÓ+JÈaÔ+OÜ�K‰KÐcÔdÙà#'§:¡:×#@Ñ#@ÐAZ×A`ÑA`ÐabÕAcÓ#dÐ à$Ò,ÜÐ+×1Ñ1Ó2°aÔ7Ø$×*Ñ*¨1Õ-Ð1I×1OÑ1OÐPQÕ1RÔRä�K‰KÐgÔhÙçØ&*§j¡j×&CÑ&CÐD\×DbÑDbÐcdÕDeÓ&fÐ#à'Ò/ÜÐ.×4Ñ4Ó5¸Ô:Ø(×.Ñ.¨qÕ1Ð5L×5RÑ5RÐSTÕ5UÔUä—‘ÐjÔkÙð  ×%Ñ% aÕ(Ð,D×,JÑ,JÈ1Õ,MÔMÜ�N‰NØ(Ð)>×)DÑ)DÀQÕ)GÐ(HÈÐPd×PjÑPjÐklÕPmÐOnð  oMð  Ng÷  Nmñ  Nmð  noõ  Npð  Mqð  qxð  yQ÷  yWñ  yWð  XYõ  yZð  x[ð  \ô÷ ˆ;Ø#×)Ñ)¨!Õ,Ð0G×0MÑ0MÈaÕ0PÔPÜ—‘Ø,Ð-B×-HÑ-HÈÕ-KÐ,LÈGÐTh×TnÑTnÐopÕTqÐSrð  sPð  Qi÷  Qoñ  Qoð  pqõ  Qrð  Psð  szð  {R÷  {Xñ  {Xð  YZõ  {[ð  z\ð  ]ôð (×-Ñ-¨aÕ0Ð4K×4QÑ4QÐRSÕ4TÔTÜ—‘Ø0Ð1J×1PÑ1PÐQRÕ1SÐ0TÐT[Ð\t×\zÑ\zÐ{|Õ\}Ð[~ð  \ð  ]u÷  ]{ñ  ]{ð  |}õ  ]~ð  \ð  Fð  G^÷  Gdñ  Gdð  efõ  Ggð  Fhð  iôñ r   c                óJ   <€ V ^8„  d   QhRS[ RS[S[ RS[,          3,          /# )r   Ú
input_namer(   N)r   r)   r   )r   r   s   "€r   r   r   ‘  s*   ø€ ÷ -ñ -©ð -±±c¸4Á)Õ;KÐ6KÕ0Lñ -r   c                ó6  € RpV P                   P                  V4      pVeZ   VP                  P                  P                  \
        P                  8w  d!   V P                  P                  V4      w  rBWB3# Tp WB3# V P                  P                  V4      w  rBWB3# )ap  Cast a graph input or node input to int32.

Args:
    input_name (str): name of graph input or node input

Returns:
    A tuple of casted input name and the cast node.
    int32_output (str): If input is int32, it is the input name, Otherwise it is output name of Cast node.
    input_cast_node (Union[None, NodeProto]): Cast node. It could be None if input is int32.
N)	r   Úfind_graph_inputÚtypeÚtensor_typeÚ	elem_typer   ÚINT32r   Úcast_input_to_int32)r#   r“   Úinput_cast_nodeÚgraph_inputÚint32_outputs   &&   r   Úcast_to_int32Ú$FusionEmbedLayerNoMask.cast_to_int32‘  s™   € ð ˆØ—j‘j×1Ñ1°*Ó=ˆØÒ"Ø×Ñ×+Ñ+×5Ñ5¼×9JÑ9JÔJØ04·
±
×0NÑ0NÈzÓ0ZÑ-�ð Ð,Ð,ð	  *‘ð Ð,Ð,ð -1¯J©J×,JÑ,JÈ:Ó,VÑ)ˆLàÐ,Ð,r   c                óZ   <€ V ^8„  d   QhRS[ RS[RS[RS[RRS[,          RS[ R,          /# )r   r^   r2   r‡   r]   rˆ   NrŠ   )r   r   )r   r   s   "€r   r   r   ¨  sX   ø€ ÷ `ñ `áð`ñ ð`ñ  )ð	`ñ
 $-ð`ð #'©Õ"2ð`ñ ˜D•jñ`r   c	                óF  € . p	V P                  V4      w  rV P                  P                  R4      pVP                  R8X  d(   VP                  ^,          pVP                  ^,          pM&VP                  ^,          pVP                  ^,          pRpVeb   V P                  VP                  ^,          4      w  rúVVVP                  ^ ,          VP                  ^ ,          VP                  ^ ,          VV.pM+VRVP                  ^ ,          VP                  ^ ,          RVV.pVe6   VP                  R4       V P                  V4      w  rjVP                  V4       VR,           VR,           .pV'       d!   Ve   TMVR,           pVP                  V4       \        P                  ! RVVVR7      pR	Vn        VP                   F2  pVP                  R
8X  g   K  VP                  P                  V.4       K4  	  \        VP                  4      ^ 8X  d2   VP                  P                  \        P                  ! R
R4      .4       V	P                  V4       V	 F&  pV P                  V P                  VP                  &   K(  	  V P                   P                  V	4       VV n        V# )a  Create an EmbedLayerNormalization node. Note that segment embedding is optional.

Args:
    input_ids (str): input_ids for word embeddings
    layernorm (NodeProto): LayerNormalization or SkipLayerNormalization node.
    word_embedding_gather (NodeProto): the Gather node for word embedding
    position_embedding_gather (NodeProto): the Gather node for position embedding
    segment_embedding_gather (Union[None, NodeProto]): the Gather node for segment embedding, or None.

Returns:
    NodeProto: the EmbedLayerNormalization node created.
r   r   NÚ Ú_outputÚ_dummy_mask_indexÚ_embedding_sum)ÚoutputsÚnamezcom.microsoftÚepsilongê-�™—q=)rž   r   Úcreate_node_namerC   rD   Úappendr   Ú	make_nodeÚdomainÚ	attributer§   ÚextendrF   Úmake_attributeÚthis_graph_nameÚnode_name_to_graph_nameÚnodes_to_addr"   )r#   r^   r2   r‡   r]   rˆ   rŠ   Úembedding_sum_outputÚembedding_sum_namer²   rb   Ú	node_nameÚgammaÚbetaÚembed_node_inputsr‰   Úembed_node_outputsr§   r"   ÚattrL   s   &&&&&&&&&            r   Úcreate_fused_nodeÚ(FusionEmbedLayerNoMask.create_fused_node¨  sn  € ð. ˆØ×)Ñ)¨)Ó4‰ˆ	à—J‘J×/Ñ/Ð0IÓJˆ	à×ÑÐ 4Ô4Ø—O‘O AÕ&ˆEØ—?‘? 1Õ%‰Dà—O‘O AÕ&ˆEØ—?‘? 1Õ%ˆDà ÐØ#Ò/Ø!×/Ñ/Ð0H×0NÑ0NÈqÕ0QÓR‰NˆKð ØØ%×+Ñ+¨AÕ.Ø)×/Ñ/°Õ2Ø(×.Ñ.¨qÕ1ØØð!Ñð ØØ%×+Ñ+¨AÕ.Ø)×/Ñ/°Õ2ØØØð!Ðð Ò#à×$Ñ$ RÔ(Ø"×0Ñ0°Ó>‰OˆLØ×$Ñ$ \Ô2à'¨)Õ3°YÐATÕ5TÐUÐßØ);Ò)GÑ%ÈYÐYiÕMiˆDØ×%Ñ% dÔ+ä×%Ò%Ø%ØØ&Øô	
ˆ
ð ,ˆ
Ôð ×&Ô&ˆCØ�x‰x˜9Ö$Ø×$Ñ$×+Ñ+¨S¨EÖ2ñ 'ô ˆz×#Ñ#Ó$¨Ô)Ø× Ñ ×'Ñ'¬×)>Ò)>¸yÈ'Ó)RÐ(SÔTð 	×Ñ˜JÔ'Û ˆDØ6:×6JÑ6JˆD×(Ñ(¨¯©Ó3ñ !à×Ñ× Ñ  Ô.à$ˆŒØÐr   c                ó�   € V P                   P                  VP                  ^ ,          VP                  ^ ,          4       RV n        R# )r   TN)r   Úreplace_input_of_all_nodesrA   Úprune_graph)r#   r2   r"   s   &&&r   Úfinish_fusionÚ$FusionEmbedLayerNoMask.finish_fusion
  s5   € Ø�
‰
×-Ñ-¨i×.>Ñ.>¸qÕ.AÀ:×CTÑCTÐUVÕCWÔXàˆÖr   c                ó®   € VP                   R 8H  ;'       d@    \        VP                  4      ^8„  ;'       d     \        VP                  ^,          4      ^ 8„  # )r   )rC   rF   rA   )r#   rL   s   &&r   Ú"is_skip_layer_norm_with_sum_outputÚ9FusionEmbedLayerNoMask.is_skip_layer_norm_with_sum_output  sJ   € Ø—‘Ð 8Ñ8×nÐn¼cÀ$Ç+Á+Ó>NÐQRÑ>R×nÐnÔWZÐ[_×[fÑ[fÐghÕ[iÓWjÐmnÑWnÐnr   c                ó`  € V P                  V4      pVf   R# Vw  rxVP                  ^,          p	VP                  ^,          p
V P                  WRR7      '       g   R# V P                  VR V4      '       g   R# VP                  R8X  d]   V P                  V4      p^pTpV'       d   VP                  ^,          MR pVR J;'       d    V P                  P                  V4      R JpMÈTpVP                  R8X  d   ^ M^p\        VP                  4      V8”  d   VP                  V,          MR pVR J;'       d    V P                  P                  V4      R JpT;'       d!    Wã9   ;'       d    \        W>,          4      ^8„  pVR J;'       d$    VP                  R8g  ;'       g    T;'       g    TpT P                  T	TTTTT
TV'       d   TMR R7      pV'       dE   RVP                  V&   V'       g.   V P                  P                  VVP                  ^,          4       V P                  VV4       R# )NF©r4   r   r<   )r³   r´   Ú_no_use__to_be_removed_T)r/   rD   rP   r�   rC   rÃ   rA   r   Úfind_graph_outputrF   r»   r¾   rÀ   )r#   r2   Úadd_before_layernormr3   r_   Úoptional_segment_gatherÚ
two_gatherr‡   r]   r^   rŠ   Úneed_embedding_sum_outputÚsum_output_indexÚnode_with_sum_outputÚ
sum_outputÚis_sum_graph_outputÚis_sum_used_by_multiple_nodesr"   s   &&&&&&            r   Ú	fuse_gpt2Ú FusionEmbedLayerNoMask.fuse_gpt2  s@  € ð( ×*Ñ*Ð+?Ó@ˆ
ØÒÙà;EÑ8ÐØ)×/Ñ/°Õ2ˆ	Ø0×6Ñ6°qÕ9ˆà×,Ñ,¨YÐ\aÐ,×bÒbÙà×#Ñ#Ð$9¸4ÐAZ×[Ò[Ùð ×ÑÐ 8Ô8Ø(,×(OÑ(OÐPYÓ(ZÐ%Ø ÐØ#,Ð ß0I˜×)Ñ)¨!Ö,ÈtˆJØ#-°TÐ#9×"uÐ"uÀÇ
Á
×@\Ñ@\Ð]gÓ@hÐptÐ@tÑà#7Ð Ø$8×$@Ñ$@ÀEÔ$I™qÈqÐô Ð+×2Ñ2Ó3Ð6FÔFð %×+Ñ+Ð,<Ö=àð ð
 $.°TÐ#9×"uÐ"uÀÇ
Á
×@\Ñ@\Ð]gÓ@hÐptÐ@tÐà×oÐo 
Ñ A×oÐoÄsÐK^ÕKjÓGkÐnoÑGoð *ð *4¸4Ð)?÷ )ð )Ø$×,Ñ,°Ñ5×mÐmÐ9L×mÐmÐPmð &ð
 ×+Ñ+ØØØ!Ø%Ø#ØØ!:ß-@™zÀdð ,ó 	
ˆ
÷ %Ø<UÐ ×'Ñ'Ð(8Ñ9ß&Ø—
‘
×5Ñ5°jÀ*×BSÑBSÐTUÕBVÔWà×Ñ˜9 jÔ1Ùr   c                óJ  € V P                  V4      pVf   R# Vw  rgVP                  ^,          pV P                  WRR7      '       g   R# V P                  WxV4      '       g   R# V P	                  VRV4      '       g   R# V P                  W�WgR4      p	V P                  W4       R# )a”  Fuse embedding layer for DistilBert
Args:
    layernorm (NodeProto): node of LayerNormalization or SkipLayerNormalization
    add_before_layernorm (NodeProto): the Add node before LayerNormalization, or the SkipLayerNormalization itself
    input_name_to_nodes (Dict[str, List[NodeProto]]): map from input name to nodes
    output_name_to_node (Dict[str, List[NodeProto]]): map from output name to nodes
NFTrÆ   )r/   rD   rP   r~   r�   r»   rÀ   )
r#   r2   rÉ   r3   r_   rË   r‡   r]   r^   r"   s
   &&&&&     r   Úfuse_distilbertÚ&FusionEmbedLayerNoMask.fuse_distilbertc  s¯   € ð& ×*Ñ*Ð+?Ó@ˆ
ØÒÙà;EÑ8ÐØ)×/Ñ/°Õ2ˆ	à×,Ñ,¨YÐ\`Ð,×aÒaÙà×,Ñ,Ð-FÐSf×gÒgÙà×#Ñ#Ð$9¸4ÐAZ×[Ò[Ùà×+Ñ+ØÐ"7ÐTXó
ˆ
ð 	×Ñ˜9Ô1Ùr   c                ó<  € V P                   P                  VR.^ .4      pVf   R# V P                  V^ ,          4      pVf   R# Vw  rxVP                  ^,          p	V P	                  WRR7      '       g   R# V P                   P                  VR.^.4      p
V
f   R# V
^ ,          pV P                  W¹V4      '       g!   V P                  W‰V4      '       g   R# TpTpTpV P                  WxV4      '       g   R# V P                  V	VVVV4      pV P                  W4       R# )aŽ  Fuse embedding layer for Bert
Args:
    layernorm (NodeProto): node of LayerNormalization or SkipLayerNormalization
    add_before_layernorm (NodeProto): the Add node before LayerNormalization, or the SkipLayerNormalization itself
    input_name_to_nodes (Dict[str, List[NodeProto]]): map from input name to nodes
    output_name_to_node (Dict[str, List[NodeProto]]): map from output name to nodes
r<   FrÆ   r+   T)	r   r,   r/   rD   rP   r~   r�   r»   rÀ   )r#   r2   rÉ   r3   r_   Úadd_2_gatherrË   r‡   rˆ   r^   Úposition_embedding_pathr]   Útempr"   s   &&&&&         r   Ú	fuse_bertÚ FusionEmbedLayerNoMask.fuse_bertŒ  s:  € ð —z‘z×3Ñ3Ð4HÈ5È'ÐTUÐSVÓWˆØÒÙà×*Ñ*¨<¸­?Ó;ˆ
ØÒÙà:DÑ7Ðà)×/Ñ/°Õ2ˆ	à×,Ñ,¨YÐ\aÐ,×bÒbÙà"&§*¡*×">Ñ">Ð?SÐV^ÐU_ÐbcÐadÓ"eÐØ"Ò*Ùà$;¸AÕ$>Ð!Ø×,Ñ,Ð-FÐSf×gÒgØ×0Ñ0Ð1IÐVi×jÒjÙà+ˆDØ'@Ð$Ø(,Ð%à×#Ñ#Ð$9ÐUn×oÒoÙà×+Ñ+ØØØ!Ø%Ø$ó
ˆ
ð 	×Ñ˜9Ô1Ùr   c                ón  € V P                   P                  VR .^ .4      pVP                  R8X  d   Vf   R# V^ ,          pRpM£V P                   P                  VR.^ .4      pV P                   P                  VR.^.4      pVf   Ve   Vf   R# V^ ,          pV^ ,          pMDVe=   Vf9   V P                   P                  VR .^.4      pVf   R# V^ ,          pV^ ,          pMTpRpV P                  WW#V4      '       d   R# V P	                  WW#4      '       d   R# V P                  WW#4      '       d   R# R# )r<   r   Nr+   )r   r,   rC   rÒ   rÕ   rÛ   )	r#   rL   r3   r_   Úfirst_add_pathrÉ   rÊ   r-   r.   s	   &&&&     r   ÚfuseÚFusionEmbedLayerNoMask.fuse¾  sJ  € ØŸ™×5Ñ5°d¸U¸GÀaÀSÓIˆØ�<‰<Ð/Ô/ØÒ%ÙØ#1°!Õ#4Ð Ø&*Ñ#à ŸJ™J×8Ñ8¸À¸zÈAÈ3ÓOˆMØ ŸJ™J×8Ñ8¸À¸zÈAÈ3ÓOˆMØÒ$¨Ò)BØ!Ò)ÙØ'5°aÕ'8Ð$Ø*7¸Õ*:Ñ'ØÒ*¨}Ò/DØ!%§¡×!=Ñ!=¸dÀUÀGÈaÈSÓ!Q�Ø!Ò)ÙØ'5°aÕ'8Ð$Ø*7¸Õ*:Ñ'à'+Ð$Ø*.Ð'à�>‰>ØÐ(;ÐRi÷
ò 
ñ à×Ñ Ð<O×eÒeÙà�>‰>˜$Ð6I×_Ò_Ùñ `r   )r!   rE   r"   r¿   r   r    r   )zno mask)NFN)N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r/   rP   rg   rl   r{   r~   r�   rž   r»   rÀ   rÃ   rÒ   rÕ   rÛ   rß   Ú__static_attributes__Ú__classdictcell__Ú__classcell__©r$   r   s   @@r   r   r      s‰   ù‡ € ñ÷
õ ÷	2ð 	2÷Rð Ròh<ò|-ò^F+òPòH÷T-ð -÷.`ò `òD ò
oôOòb'òR0÷d"ò "r   r   c                   óT   a a€ ] tR tRt oRV3R lV 3R llltR tV 3R ltRtVtV ;t	# )ÚFusionEmbedLayerNormalizationiã  c                ó    <€ V ^8„  d   QhRS[ /# )r   r   r	   )r   r   s   "€r   r   Ú*FusionEmbedLayerNormalization.__annotate__ä  s   ø€ ÷ -ñ -™iñ -r   c                ó4   <€ \         SV `  VR 4       W n        R# )z	with maskN)r   r   Úuse_mask_index)r#   r   rï   r$   s   &&&€r   r   Ú&FusionEmbedLayerNormalization.__init__ä  s   ø€ Ü‰Ñ˜ Ô,Ø,Ör   c                óð  € V P                   p\        VP                  4      ^8X  d=   VP                  P                  V4       \        P                  RVP                  4       M„\        VP                  4      ^8”  dI   VP                  ^,          '       g0   WP                  ^&   \        P                  RVP                  4       M"\        P                  RVP                  4       R# V F‰  p\        P                  RVP                  4       VP                  R8X  d#   VP                  ^,          VP                  ^&   KV  VP                  R8X  g   Ki  VP                  ^,          VP                  ^&   K‹  	  R# )é   zappend mask to %szreplace mask in %szskip mask in %sNzupdate mask_index in %sr9   r=   )	r"   rF   rD   rª   rG   rH   r§   rC   rA   )r#   Ú
mask_int32Úattention_nodesr"   Úattention_nodes   &&&  r   Úreplace_maskÚ*FusionEmbedLayerNormalization.replace_maskè  s  € ð —_‘_ˆ
Üˆz×ÑÓ  AÔ%Ø×Ñ×#Ñ# JÔ/Ü�L‰LÐ,¨j¯o©oÕ>Ü�×!Ñ!Ó" QÔ&¨z×/?Ñ/?À×/BÔ/BØ",×Ñ˜QÑÜ�L‰LÐ-¨z¯©Õ?ä�L‰LÐ*¨J¯O©OÔ<Ùã-ˆNÜ�L‰LÐ2°N×4GÑ4GÔHØ×%Ñ%¨Ô4Ø*4×*;Ñ*;¸AÕ*>�×$Ñ$ QÓ'Ø×'Ñ'Ð+?Ö?Ø*4×*;Ñ*;¸AÕ*>�×$Ñ$ QÓ'ó .r   c                óÊ  <€ R V n         R V n        R V n        \        SV `  WV4       V P                  f   R # V P
                  '       g)   \        P                  R4       V P                  R4       R # V P                   f7   V P                  f)   \        P                  R4       V P                  R4       R # V P                   '       d   V P                   P                  ^,          pMV P                  P                  ^,          pW$,          pV P                  P                  V4      '       dH   V Uu. uF  qP                  R9   g   K  VNK  	  ppV P                  WF4       V P                  R4       R # WC9  d*   \        P                  RV4       V P                  R4       R # W4,          pVP                  R9   d    V Uu. uF  qP                  R9   g   K  VNK  	  ppXP                  R8X  dH   VP                  ^ ,          p\        V4      \        V4      8X  d   V P                  P!                  V4       V P                  WF4       V P                  R4       R # R # u upi u upi )	NzG--use_mask_index is not set: EmbedLayerNormalization will not have maskz EmbedLayerNormalization(no mask)zLEmbedLayerNormalization will not have mask since attention node is not foundz"EmbedLayerNormalization(with mask)zHEmbedLayerNormalization will not have mask since %s is not a node outputÚ	ReduceSum)r9   r=   )rù   rY   )r!   rE   r"   r   rß   rï   rG   rH   Úincrease_counterrD   r   r•   rC   rö   rF   Únodes_to_removerª   )r#   rL   r3   r_   ró   Úchildren_nodesrô   r$   s   &&&&   €r   rß   Ú"FusionEmbedLayerNormalization.fuseý  sî  ø€ àˆŒØ#ˆÔØˆŒÜ‰‰�TÐ0CÔDà�?‰?Ò"Ùà×"×"Ð"Ü�L‰LÐbÔcØ×!Ñ!Ð"DÔEÙà�>‰>Ò! d×&:Ñ&:Ò&BÜ�L‰LÐgÔhØ×!Ñ!Ð"DÔEÙà�>�>ˆ>ØŸ™×-Ñ-¨aÕ0‰Jà×-Ñ-×3Ñ3°AÕ6ˆJà,Õ8ˆØ�:‰:×&Ñ& z×2Ò2Ù0>Óv±¨Ç,Á,ÐRuÑBuŸt˜t±ˆOÐvØ×Ñ˜jÔ:Ø×!Ñ!Ð"FÔGÙàÔ0Ü�L‰LÐcÐeoÔpØ×!Ñ!Ð"DÔEÙà"Õ.ˆØ�<‰<Ð0Ô0Ù0>Óv±¨Ç,Á,ÐRuÑBuŸt˜t±ˆOÐvØ�|‰|˜{Ô*Ø!ŸZ™Z¨�]�
Ü�~Ó&¬#¨oÓ*>Ô>Ø×(Ñ(×/Ñ/°Ô5Ø×Ñ˜jÔ:Ø×!Ñ!Ð"FÖGñ 1ùò wùò ws   Ä/IÅIÆ>I ÇI )r!   rE   r"   rï   )F)
rá   râ   rã   rä   r   rö   rß   ræ   rç   rè   ré   s   @@r   rë   rë   ã  s    ù‡ € ÷-õ -ò?÷*-Hõ -Hr   rë   N)Úloggingr   Úfusion_baser   Úfusion_utilsr   Úonnxr   r   r   Ú
onnx_modelr
   rá   rG   r   rë   rj   r   r   Ú<module>r     sC   ðõ å Ý $ß /Ñ /Ý  á	�8Ó	€ôP˜Vô PôfGHÐ$:ö GHr   