o
    ²3IhÑ'  ã                   @   sL   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„ deƒZ
dS )é    )Ú	getLogger)ÚFusion)Úhelper)Ú	OnnxModelc                       s‚   e Zd Zdef‡ fdd„Zdedefdd„Zdededed	B fd
d„Zdededed	B fdd„Z	dededed	B fdd„Z
‡  ZS )Ú
FusionGeluÚmodelc                    s   t ƒ  |dd¡ d S )NÚGeluÚErf)ÚsuperÚ__init__)Úselfr   ©Ú	__class__© úd/home/air/sanwanet/gpt-api/venv/lib/python3.10/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ÚreturnNc                 C   s"  |j d |vr	dS ||j d  }t|ƒdks|d jdkrdS |d }| j |d¡s,dS |j d |vr5dS ||j d  }t|ƒdksI|d jdkrKdS |d }| j |dd|¡}|du r^dS | jj|ddd	dkrkdS |jd }|jd |j d kr|dnd}	||j|	 kr®||j d  }t|ƒdks™|d jdkr›dS |d }
| j |
d
¡s¨dS |
j d }n$| j |d|	|¡}
|
du r½dS | j |
d
¡sÆdS ||
jvrÍdS |j d }|||||
g}| j ||g||¡sådS | j	 
|¡ tjd|g|g| j d¡d}d|_| j |¡ | j| j|j< |  d¡ 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Únameú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Úcreate_node_nameÚdomainÚnodes_to_addÚappendÚthis_graph_nameÚnode_name_to_graph_namer%   Úincrease_counter)r   r   r   r   ÚchildrenÚadd_after_erfÚmul_after_erfÚdivÚsubgraph_inputÚanotherÚmul_halfÚsubgraph_outputÚsubgraph_nodesÚ
fused_noder   r   r   r      sf   



ÿÿ
zFusionGelu.fuse_1c                 C   s,  |j d |vr	dS ||j d  }t|ƒdks|d jdkrdS |d }| j |d¡s,dS |j d |vr5dS ||j d  }t|ƒdksI|d jdkrKdS |d }| j |d¡sXdS |j d |vradS ||j d  }t|ƒdksu|d jdkrwdS |d }| j |dd|¡}|du rŠdS d}	| jj|dd	d
dkr¯| j |dd|¡}	|	du r¦dS | j |	d¡s¯dS | j |d|¡}
|
du r½dS |
j d |jvrÇdS |||||g}|	rÕ| 	|	¡ | j 
||j d g||¡sädS | j |¡ tjd|
j d g|j d g| j d¡d}d|_| j 	|¡ | j| j|j< |  d¡ 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   ÚSqrtg       @r   r"   r&   T)r'   r(   r)   r   r*   r+   r,   Ú
get_parentr-   r5   r.   r/   r0   r   r1   r2   r3   r4   r6   r7   r%   r8   )r   r   r   r   r9   r:   r;   Úmulr<   Ú	sqrt_nodeÚ	root_noderA   rB   r   r   r   r   m   sj   
ÿ ÿ
zFusionGelu.fuse_2c                 C   s  |j d |vr	dS ||j d  }t|ƒdks|d jdkrdS |d }| j |d¡s,dS |j d |vr5dS ||j d  }t|ƒdksI|d jdkrKdS |d }| j |d¡sXdS | j |dd|¡}|du rgdS | jj|ddd	}|dk rvdS | j ||dkr€dnd|¡}	|	du rŠdS |j d |vr“dS ||j d  }t|ƒdks§|d jdkr©dS |d }
|
jd |	j d ksÃ|
jd |	j d ksÃdS |||||
g}| j 	||
j d g||¡sÙdS | j
 |¡ tjd
|	j d g|
j d g| j d
¡d}d|_| j |¡ | j| j|j< |  d
¡ 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,   rD   r-   r.   r/   r0   r   r1   r2   r3   r4   r5   r6   r7   r%   r8   )r   r   r   r   r9   r:   r?   Ú	first_mulÚirG   Úlast_mulrA   rB   r   r   r   r   º   sd   (
ü ÿ
zFusionGelu.fuse_3)Ú__name__Ú
__module__Ú__qualname__r   r   Údictr   Úboolr   r   r   Ú__classcell__r   r   r   r   r      s    T"Mr   N)Úloggingr   Úfusion_baser   Úonnxr   Ú
onnx_modelr   rK   Úloggerr   r   r   r   r   Ú<module>   s   