
    fPi<2                         d dl mZ d dlZd dlmZmZ d dlmZmZmZm	Z	 d dlm
Z d dlmZ  ee          Z G d d          Z G d	 d
          ZdS )    )	getLoggerN)array_equalndarray)	NodeProtoTensorProtohelpernumpy_helper)onnx_pb)	OnnxModelc            
       `   e Zd ZdefdZdedeeef         fdZd defdZ		 	 	 d!ded	e
d
edz  dedz  fdZdefdZdefdZed             Zed"defd            Zdededz  fdZed#defd            Zedej        fd            Zed$dedefd            Zde
fdZd Zd Zd Zd ZdS )%FusionUtilsmodelc                     || _         d S N)r   )selfr   s     y/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/onnxruntime/transformers/fusion_utils.py__init__zFusionUtils.__init__   s     %


    
input_namereturnc                 8   | j                             |          }|Y|j        j        j        t
          j        k    r:|                     |          \  }}t          	                    d| d           d|fS t          	                    d| d|d u            d|fS )NzCasted graph input z	 to int32TzDid not cast graph input z to int32: found F)
r   find_graph_inputtypetensor_type	elem_typer   INT32cast_input_to_int32loggerdebug)r   r   graph_inputcast_output	cast_nodes        r   cast_graph_input_to_int32z%FusionUtils.cast_graph_input_to_int32   s    j11*=="{'7'C'MQ\Qb'b'b%)%=%=j%I%I"KLLDzDDDEEE$$gggkaeNegghhhj  r   int32c                 &   |dz   |z   }|dk    rt          t          j                  }nO|dk    rt          t          j                  }n/|dk    rt          t          j                  }nt          d          |                     |||          }||fS )N_r$   float32float16z"Invalid target_type: {target_type})intr   r   FLOATFLOAT16
ValueErroradd_cast_node)r   r   target_typeoutput_nameto_typer"   s         r   
cast_inputzFusionUtils.cast_input   s     3&4'!!++,,GGI%%++,,GGI%%+-..GGABBB&&z7KHH	I%%r   Nr0   r/   
graph_namec                 h   ||d| z   }|g}|| j                                         }||v r#||         }|r|j        dk    r|j        d         g}t	          j        d||g          }|j                            t	          j        d|          g           | j         	                    ||           |S )N	_cast_to_Castr   )inputsoutputsto)r2   )
r   output_name_to_nodeop_typeinputr   	make_node	attributeextendmake_attributeadd_node)	r   r   r0   r/   r9   r2   r6   parent_noder"   s	            r   r-   zFusionUtils.add_cast_node.   s     $'<7'<'<<K &"&*"@"@"B"B,,,-j9K 0{2f<<%+A./$VF[MRRR	""F$9$$H$H#IJJJ
I*===r   c                 .    |                      |d          S )Nr$   )r1   )r   r   s     r   r   zFusionUtils.cast_input_to_int32I   s    z7333r   c                 j   | j                                         }||         }|D ]}|j        dk    rd}|j        D ]3}|j        dk    r&|j        t          t          j                  k    rd} n4|rB|j	        d         }| j         
                    |           | j                             ||           d S )Nr5   Fr8   Tr   )r   input_name_to_nodesr:   r=   nameir)   r   r   outputremove_nodereplace_input_of_all_nodes)r   r   rD   nodesnodeis_int32attr/   s           r   remove_cast_int32zFusionUtils.remove_cast_int32L   s    "j<<>>#J/ 
	S 
	SD|v%% >  Cx4''CES9J5K5K,K,K#' S"&+a.KJ**4000J99+zRRR
	S 
	Sr   c                 >   d}| j         |         |v r[| || j         |                  v rF|| j         |                                      |            t          || j         |                            }|| j         |<   ||v r||                             |            n| g||<   |S )Nr   )r;   removelenappend)rK   rF   new_input_namerD   old_input_references        r   update_node_inputzFusionUtils.update_node_input[   s    JqM000d>QRVR\]^R_>`6`6`
1.55d;;;"%&9$*Q-&H"I"I&
1000/66t<<<<37&/""r   r   c                     |j         |         }|j         |         }t                              ||||          }|dk    o|                     |           }	|	S )a  
        Before:
              (input)-->parent-->node-->(output)
        After:
              (input)-->parent-->
                |
                +----->node-->(output)

        This function returns a flag whether the parent node can be removed.
        r   )r;   r   rU   find_graph_output)
r   rK   rA   rD   node_input_indexparent_input_indexold_input_namerS   rT   parent_can_be_removeds
             r   skip_parentzFusionUtils.skip_parentk   sf     $45$*+=>);;DBRTbdwxx "5!9 j5CZCZ[iCjCj?j$$r   rK   c                     |j         dv sJ t          |j                  dk    r%| j                            |j        d                   S d }|j        D ]!}|j        dk    rt          j        |          }"|S )N)Squeeze	Unsqueeze   axes)	r:   rQ   r;   r   get_constant_valuer=   rE   r   get_attribute_value)r   rK   ra   attrs       r   get_squeeze_or_unsqueeze_axesz)FusionUtils.get_squeeze_or_unsqueeze_axes   s    |77777 tz??Q:00A???N 	8 	8DyF""1$77r   attribute_namec                     |}| j         D ]!}|j        |k    rt          j        |          }"t	          |t
                    r.t	          |t          t
          f          ot          ||d          S ||k    S )a  Verify that a node has expected value for an attribute.

        Args:
            node (NodeProto): a node to check
            attribute_name (str): name of attribute
            expected_value (Any): expected value of the attribute
            default_value (Any, optional): default value if the attribute does not exist. Defaults to None.

        Returns:
            bool: whether the check is passed or not
        F	equal_nan)r=   rE   r   rc   
isinstancelistr   r   )rK   rf   expected_valuedefault_valuevaluerd   s         r   check_node_attributez FusionUtils.check_node_attribute   s     N 	9 	9DyN**2488nd++ 	+uwo66oKX]in<o<o<ooN**r   tensorc                    t          | t          j                  st          dt	          |                      t          | j                  dk    s| j        t          j        j        k    rt          d          | j	        rdt          j        t          j        | j	        d          | j                  }t          j        |ddg          }|                                | _	        nt          d          | S )	zTranspose a 2-D INT8 TensorProto
        Args:
            tensor (TensorProto): tensor to be transposed
        Returns:
            tensor (TensorProto): transposed tensor
        z3Expected input type is an ONNX TensorProto but got    z'Only INT8 2-D tensors can be transposedint8)dtyper`   r   zonly raw buffer supported)rj   
onnx_protor   r,   r   rQ   dims	data_typeINT8raw_datanumpyreshape
frombuffer	transposetobytes)rp   
int32_dataint32_transposed_datas      r   transpose_2d_int8_tensorz$FusionUtils.transpose_2d_int8_tensor   s     &*"899 	caSWX^S_S_aabbbv{q  F$4
8N8S$S$SFGGG? 	:u'7v'V'V'VX^XcddJ$)OJA$G$G!3;;==FOO 8999r   Tc                    | j         dvr"t                              d| j                     |                    | j        d                   }|dS |j        dk    p|j        dk    o|j        d         dk    }|r|sdS t          | j                  dk    rdS |                    | j        d                   }|j        |j        k    rdS |dS t          j	        |dk              S )	a  Verify if a provided QuantizeLinear (Q) / DequantizeLinear (DQ) node is a good candidate for fusion.
           It is a good candidate for fusion if:
           (1) The Q/DQ node is for per-tensor quantization if allow_per_tensor_quantization_only is `True`
           (2) The Q/DQ node should have constant scale
           (3) The Q/DQ node should have a zero point of 0
        Args:
            node (NodeProto): a Q/DQ node to check
        Returns:
            bool: whether the check is passed or not
        >   QuantizeLinearDequantizeLinearz+Provided node is not a Q/DQ node. Op Type: r`   NFr   rr   T)
r:   r   r   rb   r;   ndimshaperQ   rz   all)rK   r   "allow_per_tensor_quantization_onlyscalescale_has_single_element
zero_points         r   check_qdq_node_for_fusionz%FusionUtils.check_qdq_node_for_fusion   s     <EEELLUt|UUVVV((A77 =5 $):?#_uzQ7^5;WX>]^K^ - 	6N 	5 tz??a4 --djm<<
 :((5 5yq)))r   input_indexc                    t          |j                  |k    sJ | j                            |j        |                   }t	          |t
                    r.t	          |t          t
          f          ot          ||d          S ||k    S )a7  Verify that a node has expected input value

        Args:
            node (NodeProto): a node to check
            input_index (int): index of its input to be verified
            expected_value (Any): expected value of the input

        Returns:
            bool: whether the check is passed or not
        Frh   )rQ   r;   r   rb   rj   rk   r   r   )r   rK   r   rl   rn   s        r   check_node_input_valuez"FusionUtils.check_node_input_value   s     4:,,,,
--dj.EFFnd++ 	+uwo66oKX]in<o<o<ooN**r   c                    g }| j                                         }| j                                         D ]b}|j        dk    rU|j        d         |vrF| j                             |j        d         |j        d                    |                    |           c|rG| j                             |           t          
                    dt          |           d           dS dS )z>Remove Identity nodes, except those right before graph output.Identityr   zRemoved z Identity nodesN)r   get_graphs_output_namesrJ   r:   rG   rI   r;   rR   remove_nodesr   inforQ   )r   nodes_to_removegraph_output_namesrK   s       r   remove_identity_nodesz!FusionUtils.remove_identity_nodes   s    !Z??AAJ$$&& 	1 	1D|z));q>);;;J99$+a.$*UV-XXX#**4000 	JJ##O444KKH3#7#7HHHIIIII	J 	Jr   c                 8    | j                                          d S r   )r   remove_cascaded_cast_nodesr   s    r   r   z&FusionUtils.remove_cascaded_cast_nodes
  s    
--/////r   c                 8    | j                                          d S r   )r   remove_useless_cast_nodesr   s    r   r   z%FusionUtils.remove_useless_cast_nodes  s    
,,.....r   c                 P   | j                             d          }|dS g }| j                                         D ]}|j        dk    r|                    |j        d                   }|                    |j        d                   }|rB|r@||k    r:t                              d|j	         d|            |
                    |           |rTt          | j                                                   }t          | j                                                   }|D ]}t          t          |j                  |z            rt          t          |j                  |z            smt          | j                                         |j        d                            dk    r2| j                             |j        d         |j        d                    n2| j                             |j        d         |j        d                    | j                             |           dS dS )	ziRemove reshape node that is not needed based on symbolic shape inference: input and output has same shapeT)updateNReshaper   zRemove reshape node z* since its input shape is same as output: r`   )r   infer_runtime_shaperJ   r:   get_edge_shaper;   rG   r   r   rE   rR   setget_graphs_input_namesr   boolrQ   rD   replace_output_of_all_nodesrI   rH   )r   shape_inferr   rK   input_shapeoutput_shapegraph_input_namesr   s           r   remove_useless_reshape_nodesz(FusionUtils.remove_useless_reshape_nodes  s   j44D4AAFJ$$&& 	1 	1D|y(()88AGG*99$+a.II 1< 1K<4O4OKKqtyqqdoqq   $**4000 	- #DJ$E$E$G$G H H!$TZ%G%G%I%I!J!J' - -DK((+==>> 	Y TZ3D!DEE!
 > > @ @A OPPTUUU
>>tz!}dkZ[n]]]] J99$+a.$*UV-XXX
&&t,,,,	- 	-- -r   )r$   )NNN)r   r   r   )T)__name__
__module____qualname__r   r   strtupler   r#   r1   r)   r-   r   rN   staticmethodrU   r\   r   r   re   ro   ru   r   r   r   r   r   r   r   r    r   r   r   r      sX       &i & & & &!C !E$)<L ! ! ! !& &S & & & &( #' !%   4Z	 $J   64c 4 4 4 4SC S S S S # # \# % %9 % % % \%*) $     + +3 + + + \+, )?    \. (* (*	 (*) (* (* (* \(*T+ + + + +(J J J0 0 0/ / /- - - - -r   r   c                   4    e Zd Zeddededefd            ZdS )NumpyHelperFrp   
fill_zerosr   c                     |r-t          | j        t          j        | j                            S t          j        |           S )N)r   rt   )r   rv   r   tensor_dtype_to_np_dtyperw   r	   to_array)rp   r   s     r   r   zNumpyHelper.to_array3  sL      	k5f6FGG   
 $V,,,r   N)F)r   r   r   r   r   r   r   r   r   r   r   r   r   2  sL        	- 	- 	-$ 	-7 	- 	- 	- \	- 	- 	-r   r   )loggingr   rz   r   r   onnxr   r   r   r	   r
   ru   
onnx_modelr   r   r   r   r   r   r   r   <module>r      s   
        & & & & & & & & = = = = = = = = = = = = & & & & & &            	8		_- _- _- _- _- _- _- _-D	- - - - - - - - - -r   