o
    g3                     @  s@   d dl mZ d dlZddlmZ ddlmZ G dd deZdS )	    )annotationsN   )	ONNXModel   )Fusionc                      s(   e Zd Zd fddZdddZ  ZS )FusionLayerNormalizationmodelr   c                   s   t  |dd d S )NLayerNormalization
ReduceMean)super__init__)selfr   	__class__ h/var/www/visachat/venv/lib/python3.10/site-packages/onnxruntime/quantization/fusions/fusion_layernorm.pyr      s   z!FusionLayerNormalization.__init__reduce_mean_nodeonnx.NodeProtoinput_name_to_nodesdict[str, list[onnx.NodeProto]]output_name_to_nodedict[str, onnx.NodeProto]c                 C  s  | j ||}t|dkst|dkrdS |jd }|d jdks*|d jd |kr,dS t|dkrD|d jdksB|d jd |krDdS d}|D ]}| j|d|dd}|durY nqH|du r`dS | |g d	g d
fg dg dfg|\}}	}
|dk r~dS |	d }||vrdS |	d }| |\}}|du s|dks|dkrdS |	d }| |ddkrdS ||j	d  d }|jdkrdS ||j	d  d }|jdkrdS |g}|
| |
|	dd  |
|||g | ||j	||sdS |jd| |j	d |  }| |ds
dS |jd| |j	d |  }| |ds!dS | j
| tjjd|  |jd ||g|j	d gd}|j
tjdt|g | j| dS )a  
        Interface function that tries to fuse a node sequence containing a ReduceMean node into a single
        LayerNormalization node.

              +----------------------+
              |                      |
              |                      v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
                     (axis=2 or -1)  |      (Y=2)   (axis=2 or -1)  (E-6 or E-12 or 0) ^
                                     |                                                 |
                                     +-------------------------------------------------+

         It also handles cases of duplicated sub nodes exported from older version of PyTorch:

              +----------------------+
              |                      v
              |           +-------> Sub-----------------------------------------------+
              |           |                                                           |
              |           |                                                           v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div  --> Mul --> Add
              |                      ^
              |                      |
              +----------------------+
        r   r   NSubr   DivF)	recursive)SqrtAddr
   Powr   )r   r   r   r   r   )r   r   r
   r   Castr   )r   r   r   r   r   r   g-C6?   g       @Mulr   r	   )nameinputsoutputsepsilon)r   get_childrenleninputop_typefind_first_child_by_typematch_parent_pathsget_constant_inputfind_constant_inputoutputextendis_safe_to_fuse_nodesinput_indexis_constant_with_specified_ranknodes_to_removeonnxhelper	make_nodecreate_unique_node_name	attributemake_attributefloatnodes_to_addappend)r   r   r   r   children
root_inputdiv_nodechildpath_idparent_nodes_sub_nodesecond_add_nodei
add_weightpow_nodemul_nodelast_add_nodesubgraph_nodesweight_input
bias_inputnormalize_noder   r   r   fuse   s   
  




zFusionLayerNormalization.fuse)r   r   )r   r   r   r   r   r   )__name__
__module____qualname__r   rO   __classcell__r   r   r   r   r      s    r   )
__future__r   r4   
onnx_modelr   fusionr   r   r   r   r   r   <module>   s
   