U
    T?h&                     @   s\   d dl mZ d dlmZmZ d dlmZ d dlmZ d dl	m
Z
 eeZG dd deZdS )	    )	getLogger)DictOptional)Fusion)helper)	OnnxModelc                       st   e Zd Zed fddZeedddZeeee ddd	Z	eeee dd
dZ
eeee dddZ  ZS )
FusionGelu)modelc                    s   t  |dd d S )NGeluZErf)super__init__)selfr	   	__class__ V/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/fusion_gelu.pyr      s    zFusionGelu.__init__)input_name_to_nodesoutput_name_to_nodec                 C   s6   |  |||rd S | |||r$d S | ||| d S )N)fuse_1fuse_2fuse_3)r   erf_noder   r   r   r   r   fuse   s
    zFusionGelu.fuse)r   r   returnc                 C   s  |j d |krdS ||j d  }t|dks:|d jdkr>dS |d }| j|dsXdS |j d |krjdS ||j d  }t|dks|d jdkrdS |d }| j|dd|}|dkrdS | jj|ddd	dkrdS |jd }|jd |j d krdnd}	||j|	 krd||j d  }t|dks8|d jdkr<dS |d }
| j|
d
sXdS |
j d }nN| j|d|	|}
|
dkrdS | j|
d
sdS ||
jkrdS |j d }|||||
g}| j||g||sdS | j	
| tjd|g|gd}d|_| j| | j| j|j< dS )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   N   AddMulDiv-?MbP?delta      ?r
   inputsoutputscom.microsoftT)outputlenop_typer	   has_constant_inputmatch_parentfind_constant_inputinputis_safe_to_fuse_nodesnodes_to_removeextendr   	make_nodedomainnodes_to_addappendthis_graph_namenode_name_to_graph_namename)r   r   r   r   childrenadd_after_erfmul_after_erfdivZsubgraph_inputZanothermul_halfZsubgraph_outputsubgraph_nodes
fused_noder   r   r   r      sf    


   zFusionGelu.fuse_1c                 C   s(  |j d |krdS ||j d  }t|dks:|d jdkr>dS |d }| j|dsXdS |j d |krjdS ||j d  }t|dks|d jdkrdS |d }| j|dsdS |j d |krdS ||j d  }t|dks|d jdkrdS |d }| j|dd|}|dkrdS d}	| jj|dd	d
dkrf| j|dd|}	|	dkrRdS | j|	dsfdS | j|d|}
|
dkrdS |
j d |jkrdS |||||g}|	r|	|	 | j
||j d g||sdS | j| tjd|
j d g|j d gd}d|_| j	| | j| j|j< dS )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   Nr   r   r   r"   r   r   r   r    ZSqrtg       @r
   r#   r&   T)r'   r(   r)   r	   r*   r+   r,   
get_parentr-   r4   r.   r/   r0   r   r1   r2   r3   r5   r6   r7   )r   r   r   r   r8   r9   r:   mulr;   Z	sqrt_node	root_noder=   r>   r   r   r   r   k   sj    



 
   zFusionGelu.fuse_2c                 C   s  |j d |krdS ||j d  }t|dks:|d jdkr>dS |d }| j|dsXdS |j d |krjdS ||j d  }t|dks|d jdkrdS |d }| j|dsdS | j|dd|}|dkrdS | jj|ddd	}|dk rdS | j||dkrdnd|}	|	dkrdS |j d |kr,dS ||j d  }t|dksX|d jdkr\dS |d }
|
jd |	j d ks|
jd |	j d ksdS |||||
g}| j	||
j d g||sdS | j
| tjd
|	j d g|
j d gd}d|_| j| | j| j|j< dS )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   Nr   r   r   r"   g   `?r   r    r
   r#   r&   T)r'   r(   r)   r	   r*   r+   r,   r?   r-   r.   r/   r0   r   r1   r2   r3   r4   r5   r6   r7   )r   r   r   r   r8   r9   r<   Z	first_mulirA   Zlast_mulr=   r>   r   r   r   r      s^    
,
 zFusionGelu.fuse_3)__name__
__module____qualname__r   r   r   r   r   boolr   r   r   __classcell__r   r   r   r   r      s
   QJr   N)loggingr   typingr   r   Zfusion_baser   Zonnxr   Z
onnx_modelr   rC   loggerr   r   r   r   r   <module>   s   