
    h<2                         S SK Jr  S SKrS SKJrJr  S SKJrJrJrJ	r	  S SKJ
r  S SKJr  \" \5      r " S S5      r " S	 S
5      rg)    )	getLoggerN)array_equalndarray)	NodeProtoTensorProtohelpernumpy_helper)onnx_pb)	OnnxModelc            
       n   \ rS rSrS\4S jrS\S\\\4   4S jr	SS\4S jjr
   S S\S	\S
\S-  S\S-  4S jjrS\4S jrS\4S jr\S 5       r\S!S\4S jj5       rS\S\S-  4S jr\S"S\4S jj5       r\S\R.                  4S j5       r\S#S\S\4S jj5       rS\4S jrS rS rS rS rSrg)$FusionUtils   modelc                     Xl         g Nr   )selfr   s     _/var/www/fran/franai/venv/lib/python3.13/site-packages/onnxruntime/transformers/fusion_utils.py__init__FusionUtils.__init__   s     %
    
input_namereturnc                 D   U R                   R                  U5      nUbb  UR                  R                  R                  [
        R                  :w  a0  U R                  U5      u  p4[        R                  SU S35        SU4$ [        R                  SU SUS L 35        SU4$ )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_int32%FusionUtils.cast_graph_input_to_int32   s    jj11*="{'7'7'C'C'M'MQ\QbQb'b%)%=%=j%I"KLL.zl)DE$$0<MkaeNeMfghj  r   c                    US-   U-   nUS:X  a  [        [        R                  5      nOKUS:X  a  [        [        R                  5      nO+US:X  a  [        [        R                  5      nO[        S5      eU R                  XU5      nX54$ )N_int32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_inputFusionUtils.cast_input   s     3&4'!+++,GI%+++,GI%+--.GABB&&zKH	%%r   Nr4   r3   
graph_namec                 |   Uc  USU 3-   nU/nUc  U R                   R                  5       nX;   a+  XA   nU(       a   UR                  S:X  a  UR                  S   /n[        R
                  " SXc/S9nUR                  R                  [        R                  " SU5      /5        U R                   R                  XS9  U$ )N	_cast_to_Castr   )inputsoutputsto)r7   )
r   output_name_to_nodeop_typeinputr   	make_node	attributeextendmake_attributeadd_node)	r   r   r4   r3   r>   r7   r;   parent_noder%   s	            r   r1   FusionUtils.add_cast_node.   s     $7)'<<K &"&**"@"@"B,-9K{22f<%++A./$$VFMR	""F$9$9$$H#IJ

I=r   c                 &    U R                  US5      $ )Nr*   )r5   )r   r   s     r   r    FusionUtils.cast_input_to_int32I   s    z733r   c                    U R                   R                  5       nX!   nU H  nUR                  S:X  d  M  SnUR                   H@  nUR                  S:X  d  M  UR
                  [        [        R                  5      :X  d  M>  Sn  O   U(       d  Mp  UR                  S   nU R                   R                  U5        U R                   R                  Xq5        M     g )Nr:   Fr=   Tr   )r   input_name_to_nodesr?   rB   nameir-   r   r   outputremove_nodereplace_input_of_all_nodes)r   r   rK   nodesnodeis_int32attr3   s           r   remove_cast_int32FusionUtils.remove_cast_int32L   s    "jj<<>#/D||v% >>Cxx4'CEES9J9J5K,K#' * 8"&++a.KJJ**40JJ99+R r   c                 (   SnU R                   U   U;   aO  XU R                   U      ;   a:  X0R                   U      R                  U 5        [        X0R                   U      5      nX R                   U'   X#;   a  X2   R                  U 5        U$ U /X2'   U$ )Nr   )r@   removelenappend)rR   rM   new_input_namerK   old_input_references        r   update_node_inputFusionUtils.update_node_input[   s    JJqM00dRVR\R\]^R_>`6`

1.55d;"%&9**Q-&H"I&

10/66t< #" 48&/""r   c                     UR                   U   nUR                   U   n[        R                  XXs5      nUS:H  =(       a    U R                  U5      (       + n	U	$ )z
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   r]   find_graph_output)
r   rR   rF   rK   node_input_indexparent_input_indexold_input_namer[   r\   parent_can_be_removeds
             r   skip_parentFusionUtils.skip_parentk   s_     $45$**+=>);;DTbx "5!9 j5CZCZ[iCj?j$$r   rR   c                 &   UR                   S;   d   e[        UR                  5      S:  a(  U R                  R	                  UR                  S   5      $ S nUR
                   H+  nUR                  S:X  d  M  [        R                  " U5      nM-     U$ )N)Squeeze	Unsqueeze   axes)	r?   rY   r@   r   get_constant_valuerB   rL   r   get_attribute_value)r   rR   rk   attrs       r   get_squeeze_or_unsqueeze_axes)FusionUtils.get_squeeze_or_unsqueeze_axes   sz    ||7777 tzz?Q::00A??NNDyyF"11$7 # r   attribute_namec                     UnU R                    H+  nUR                  U:X  d  M  [        R                  " U5      nM-     [	        U[
        5      (       a'  [	        U[        [
        45      =(       a
    [        X$SS9$ XB:H  $ )af  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)rB   rL   r   rm   
isinstancelistr   r   )rR   rq   expected_valuedefault_valuevaluern   s         r   check_node_attribute FusionUtils.check_node_attribute   si     NNDyyN*2248 # nd++uwo6oKin<oo**r   tensorc                    [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:w  d(  U R                  [        R                  R                  :w  a  [        S5      eU R                  (       an  [        R                  " [        R                  " U R                  SS9U R                  5      n[        R                  " USS/5      nUR                  5       U l	        U $ [        S5      e)	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)dtyperj   r   zonly raw buffer supported)ru   
onnx_protor   r0   r   rY   dims	data_typeINT8raw_datanumpyreshape
frombuffer	transposetobytes)r|   
int32_dataint32_transposed_datas      r   transpose_2d_int8_tensor$FusionUtils.transpose_2d_int8_tensor   s     &*"8"899RSWX^S_R`abbv{{q F$4$4
8N8N8S8S$SFGG??u'7'7v'VX^XcXcdJ$)OOJA$G!3;;=FO
  899r   c                 $   U R                   S;  a"  [        R                  SU R                    35        UR                  U R                  S   5      nUc  gUR
                  S:H  =(       d(    UR
                  S:H  =(       a    UR                  S   S:H  nU(       a  U(       d  g[        U R                  5      S:X  a  gUR                  U R                  S   5      nUR
                  UR
                  :w  a  gUc  g[        R                  " US:H  5      $ )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: rj   Fr   r~   T)
r?   r!   r"   rl   r@   ndimshaperY   r   all)rR   r   "allow_per_tensor_quantization_onlyscalescale_has_single_element
zero_points         r   check_qdq_node_for_fusion%FusionUtils.check_qdq_node_for_fusion   s     <<EELLFt||nUV((A7 = $)::?#_uzzQ7^5;;WX>]^K^ -6N tzz?a --djjm<
 ::( yyq))r   input_indexc                    [        UR                  5      U:  d   eU R                  R                  UR                  U   5      n[	        U[
        5      (       a'  [	        U[        [
        45      =(       a
    [        X4SS9$ XC:H  $ )zVerify 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
Frs   )rY   r@   r   rl   ru   rv   r   r   )r   rR   r   rw   ry   s        r   check_node_input_value"FusionUtils.check_node_input_value   sk     4::,,,

--djj.EFnd++uwo6oKin<oo**r   c                    / nU R                   R                  5       nU R                   R                  5        Hq  nUR                  S:X  d  M  UR                  S   U;  d  M*  U R                   R                  UR                  S   UR                  S   5        UR                  U5        Ms     U(       a>  U R                   R                  U5        [        R                  S[        U5       S35        gg)z>Remove Identity nodes, except those right before graph output.Identityr   zRemoved z Identity nodesN)r   get_graphs_output_namesrQ   r?   rN   rP   r@   rZ   remove_nodesr!   inforY   )r   nodes_to_removegraph_output_namesrR   s       r   remove_identity_nodes!FusionUtils.remove_identity_nodes   s    !ZZ??AJJ$$&D||z);;q>);;JJ99$++a.$**UV-X#**40	 ' JJ##O4KK(3#7"8HI r   c                 8    U R                   R                  5         g r   )r   remove_cascaded_cast_nodesr   s    r   r   &FusionUtils.remove_cascaded_cast_nodes
  s    

--/r   c                 8    U R                   R                  5         g r   )r   remove_useless_cast_nodesr   s    r   r   %FusionUtils.remove_useless_cast_nodes  s    

,,.r   c                    U R                   R                  SS9nUc  g/ nU R                   R                  5        H  nUR                  S:X  d  M  UR	                  UR
                  S   5      nUR	                  UR                  S   5      nU(       d  MZ  U(       d  Mc  XE:X  d  Mj  [        R                  SUR                   SU 35        UR                  U5        M     U(       Ga_  [        U R                   R                  5       5      n[        U R                   R                  5       5      nU GH  n[        [        UR                  5      U-  5      (       a  [        [        UR
                  5      U-  5      (       dn  [        U R                   R!                  5       UR
                  S      5      S:X  a7  U R                   R#                  UR
                  S   UR                  S   5        O8M  U R                   R%                  UR                  S   UR
                  S   5        U R                   R'                  U5        GM     gg)	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: rj   )r   infer_runtime_shaperQ   r?   get_edge_shaper@   rN   r!   r   rL   rZ   setget_graphs_input_namesr   boolrY   rK   replace_output_of_all_nodesrP   rO   )r   shape_inferr   rR   input_shapeoutput_shapegraph_input_namesr   s           r   remove_useless_reshape_nodes(FusionUtils.remove_useless_reshape_nodes  s   jj44D4AJJ$$&D||y()88AG*99$++a.I;<<K4OKK.tyyk9cdocpq $**40 '  #DJJ$E$E$G H!$TZZ%G%G%I!J'DKK(+==>> TZZ3D!DEE

 > > @A OPTUU

>>tzz!}dkkZ[n] JJ99$++a.$**UV-X

&&t, ( r   r   )r*   )NNN)r   r   r   )T) __name__
__module____qualname____firstlineno__r   r   strtupler   r&   r5   r-   r1   r    rU   staticmethodr]   re   r   r   ro   rz   r   r   r   r   r   r   r   r   r   __static_attributes__ r   r   r   r      sT   &i &!C !E$)<L !&S &( #' !%  4Z	 $J64c 4SC S # # %9 % %*) $  +3 + +, )?)?  . (*	 (*) (* (*T+ +(J0/-r   r   c                   8    \ rS rSr\SS\S\S\4S jj5       rSr	g)	NumpyHelperi2  r|   
fill_zerosr   c                     U(       a2  [        U R                  [        R                  " U R                  5      S9$ [
        R                  " U 5      $ )N)r   r   )r   r   r   tensor_dtype_to_np_dtyper   r	   to_array)r|   r   s     r   r   NumpyHelper.to_array3  sB     kk55f6F6FG 
 $$V,,r   r   N)F)
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   2  s)    	- 	-$ 	-7 	- 	-r   r   )loggingr   r   r   r   onnxr   r   r   r	   r
   r   
onnx_modelr   r   r!   r   r   r   r   r   <module>r      s=   
   & = = &  	8	_- _-D	- -r   