
    g(                    F    d dl mZ d dlZddlmZ ddlmZ  G d de      Zy)	    )annotationsN   )	ONNXModel   )Fusionc                  |     e Zd Zd fdZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ xZS )	
FusionGeluc                (    t         |   |dd       y )NGeluErf)super__init__)selfmodel	__class__s     a/var/www/openai/venv/lib/python3.12/site-packages/onnxruntime/quantization/fusions/fusion_gelu.pyr   zFusionGelu.__init__   s    .    c                    | j                  |||      s&| j                  |||      s| j                  |||      r| j                  j	                  dd       yy)z
        Interface function that tries to fuse a node sequence containing an Erf node into a single
        Gelu node.
        com.microsoftr   N)fuse_1fuse_2fuse_3r   set_opset_import)r   erf_nodeinput_name_to_nodesoutput_name_to_nodes       r   fusezFusionGelu.fuse   sT     KK"57JK{{8%8:MN{{8%8:MNJJ''; Or   c                   |j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j                  |d      sy|j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j	                  |dd|      }|y| j                  |dd	      dk7  ry|j                  d   }|j                  d   |j                   d   k(  rdnd}	||j                  |	   k(  r[||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }
| j                  |
d
      sy|
j                   d   }nH| j	                  |d|	|      }
|
y| j                  |
d
      sy||
j                  vry|j                   d   }|||||
g}| j                  ||g||      sy| j                  j                  |       t        j                  j                  d| j                         |g|g      }d|_        | j                  j!                  |       y)ay  
        This pattern is from PyTorch model
        Fuse Gelu with Erf into one node:
        Pattern 1:
                       +-------Mul(0.5)---------------------+
                       |                                    |
                       |                                    v
                    [root] --> Div -----> Erf  --> Add --> Mul -->
                              (B=1.4142...)       (1)

        Pattern 2:
                       +------------------------------------+
                       |                                    |
                       |                                    v
                    [root] --> Div -----> Erf  --> Add --> Mul -->Mul -->
                              (B=1.4142...)       (1)            (0.5)

        Note that constant input for Add and Mul could be first or second input: like either A=0.5 or B=0.5 is fine.
        r   Fr   AddMulDiv-?MbP?delta      ?r   nameinputsoutputsr   Toutputlenop_typehas_constant_inputmatch_parentfind_constant_inputinputis_safe_to_fuse_nodesnodes_to_removeextendonnxhelper	make_nodecreate_unique_node_namedomainnodes_to_addappend)r   r   r   r   childrenadd_after_erfmul_after_erfdivsubgraph_inputanothermul_halfsubgraph_outputsubgraph_nodes
fused_nodes                 r   r   zFusionGelu.fuse_1#   s   2 ??1%88&xq'9:x=A!!4!4!= &&}a8"*==&}';';A'>?x=A!!4!4!= %4GH;##Cu#=B1$**1-1E1Ea1HH!a]0099*=+?+?+BCH8}!Xa[%8%8E%A{H**8S9&ooa0O((wH[\H**8S9X^^3+2215OxxP)).?:KM`buv##N3[[**557@P[jZk + 

 ,
  ,r   c                p   |j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j                  |d      sy|j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j                  |d      sy|j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j	                  |dd|      }|yd}	| j                  |d	d
      dk7  r*| j	                  |dd|      }	|	y| j                  |	d      sy|j                  d   }
|
|j                  vry|||||g}|	r|j                  |	       | j                  ||j                   d   g||      sy| j                  j                  |       t        j                  j                  d| j                         |
g|j                   d   g      }d|_        | j                   j                  |       y)a&  
        This pattern is from Keras model
        Fuse Gelu with Erf into one node:
                       +------------------------------------------+
                       |                                          |
                       |                                          v
                    [root] --> Div -----> Erf  --> Add --> Mul -->Mul
                              (B=1.4142...)       (A=1)   (A=0.5)

        Note that constant input for Add and Mul could be first or second input: like either A=0.5 or B=0.5 is fine.
        r   Fr   r   r    r&   r!   Nr"   r#   r$   Sqrtg       @r   r'   r   T)r,   r-   r.   r/   r0   r1   r2   r<   r3   r4   r5   r6   r7   r8   r9   r:   r;   )r   r   r   r   r=   r>   r?   mulr@   	sqrt_noderA   rE   rF   s                r   r   zFusionGelu.fuse_2z   si   " ??1%88&xq'9:x=A!!4!4!= &&}a8"*==&}';';A'>?x=A!!4!4!= &&}c:"*==&}';';A'>?x=A!!4!4!=qk%4GH;	##Cu#=B))#vq:MNI **9c:1*xsK!!),)).3::a=/K^`st##N3[[**557@P[^[e[efg[hZi + 

 ,
  ,r   c                .   |j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j                  |d      sy|j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }| j                  |d      sy| j	                  |dd|      }|y| j                  |dd	      }|dk  ryd|z
  }	|j                  |	   }
|j                   d   |vry||j                   d      }t        |      dk7  s|d   j                  dk7  ry|d   }|j                  d   |
k(  s|j                  d   |
k(  sy|||||g}| j                  ||j                   d   g||      sy| j                  j                  |       t        j                  j                  d
| j                         |
g|j                   d   g      }d|_        | j                  j!                  |       y)a?  
        This pattern is from TensorFlow model
        Fuse Gelu with Erf into one node:
                       +----------------------------------------------+
                       |                                              |
                       |                                              v
                    [root] --> Mul -----> Erf    -->   Add --> Mul -->Mul
                               (A=0.7071067690849304)  (B=1)  (B=0.5)

        Note that constant input for Add and Mul could be first or second input: like either A=0.5 or B=0.5 is fine.
        r   Fr   r   r    r&   g   `?r#   r$   r   r'   r   Tr+   )r   r   r   r   r=   r>   rC   	first_muliroot_input_indexrA   last_mulrE   rF   s                 r   r   zFusionGelu.fuse_3   sN   $ ??1%88&xq'9:x=A!!4!4!= &&}a8"*==&}';';A'>?x=A!!4!4!=A;&&x5%%hq:MN	$$Y0B%$Pq5q5")9:??1%88&xq'9:x=A!!4!4!=A;q!^3x~~a7HN7Z#X}hQ))__Q 	
 ##N3[[**557@P[c[j[jkl[mZn + 

 ,
  ,r   )r   r   )r   onnx.NodeProtor   dict[str, list[onnx.NodeProto]]r   dict[str, onnx.NodeProto])r   rP   r   rQ   r   rR   returnbool)	__name__
__module____qualname__r   r   r   r   r   __classcell__)r   s   @r   r	   r	      s    /< < =< 7	<"U U =U 7	U
 
UnJ J =J 7	J
 
JXJ J =J 7	J
 
Jr   r	   )
__future__r   r6   
onnx_modelr   fusionr   r	    r   r   <module>r]      s!    #  " B Br   