
    `ib                         S SK JrJr  S SKrS SKrS SKrS SKrS SKJ	r	  S SK
JrJrJrJrJrJr  \R"                  " \5      r " S S5      rg)    )ListTupleN)deque)
ModelProtoTensorProtonumpy_helperhelperexternal_data_helper
save_modelc                      \ rS rSrS rS rS rS rS rS r	S r
S	 rS
 rS rS r\S 5       rS r\S 5       rS rS rS rS1S jrS1S jrS1S jr/ 4S jrSS/ S4S jrS r  S2S jrS3S jrS3S jrS rS r S4S jr!S  r"S4S! jr#S1S" jr$S# r%S1S$ jr&S% r'S& r(S1S' jr)S5S( jr*\S) 5       r+S* r,S1S+ jr-S5S, jr.S- r/S. r0S/ r1S0r2g)6	OnnxModel   c                     Xl         0 U l        g Nmodelnode_name_counter)selfr   s     g/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/onnxruntime_tools/transformers/OnnxModel.py__init__OnnxModel.__init__   s    
!#    c                     0 nU R                   R                  R                   H5  nUR                   H"  nX1;  a  U/X'   M  X   R	                  U5        M$     M7     U$ r   )r   graphnodeinputappend)r   input_name_to_nodesr   
input_names       r   r   OnnxModel.input_name_to_nodes   sZ     JJ$$))D"jj
87;f'3'3::4@	 ) * #"r   c                     0 nU R                   R                  R                   H  nUR                   H  nX!U'   M	     M     U$ r   )r   r   r   output)r   output_name_to_noder   output_names       r   r#   OnnxModel.output_name_to_node    s@     JJ$$))D#{{37K0  + * #"r   c                 B    U R                   R                  R                  $ r   )r   r   r   r   s    r   nodesOnnxModel.nodes'   s    zz$$$r   c                 .    U R                   R                  $ r   )r   r   r'   s    r   r   OnnxModel.graph*   s    zzr   c                     XR                   R                  R                  ;   a0  U R                   R                  R                  R                  U5        g g r   )r   r   r   remover   r   s     r   remove_nodeOnnxModel.remove_node-   s;    ::##(((JJ!!((. )r   c                 8    U H  nU R                  U5        M     g r   )r/   )r   nodes_to_remover   s      r   remove_nodesOnnxModel.remove_nodes1   s    #DT" $r   c                 d    U R                   R                  R                  R                  U/5        g r   r   r   r   extendr.   s     r   add_nodeOnnxModel.add_node5   s"    

$$dV,r   c                 b    U R                   R                  R                  R                  U5        g r   r6   )r   nodes_to_adds     r   	add_nodesOnnxModel.add_nodes8   s     

$$\2r   c                 d    U R                   R                  R                  R                  U/5        g r   )r   r   initializerr7   )r   tensors     r   add_initializerOnnxModel.add_initializer;   s"    

$$++VH5r   c                 d    U R                   R                  R                  R                  U/5        g r   )r   r   r   r7   )r   r   s     r   	add_inputOnnxModel.add_input>   s"    

%%ug.r   c                     [        U[        5      (       a  [        U[        5      (       d   e[        [        U R                  5      5       H&  nU R                  U   U:X  d  M  X R                  U'   M(     g r   )
isinstancestrrangelenr   )r   old_input_namenew_input_namejs       r   replace_node_inputOnnxModel.replace_node_inputA   sS    .#..:nc3R3RRRs4::'Azz!}. .

1 (r   c                 ~    U R                   R                  R                   H  n[        R	                  X1U5        M     g r   )r   r   r   r   rN   )r   rK   rL   r   s       r   replace_input_of_all_nodes$OnnxModel.replace_input_of_all_nodesH   s,    JJ$$))D((~N *r   c                     [        U[        5      (       a  [        U[        5      (       d   e[        [        U R                  5      5       H&  nU R                  U   U:X  d  M  X R                  U'   M(     g r   )rG   rH   rI   rJ   r"   )r   old_output_namenew_output_namerM   s       r   replace_node_outputOnnxModel.replace_node_outputL   sU    /3//JPS4T4TTTs4;;'(A{{1~0!0A )r   c                 ~    U R                   R                  R                   H  n[        R	                  X1U5        M     g r   )r   r   r   r   rV   )r   rT   rU   r   s       r   replace_output_of_all_nodes%OnnxModel.replace_output_of_all_nodesS   s,    JJ$$))D))$Q *r   c                 z    U R                   R                  R                   H  nUR                  U:X  d  M  Us  $    g r   )r   r   r?   name)r   r\   r@   s      r   get_initializerOnnxModel.get_initializerW   s2    jj&&22F{{d" 3 r   c                     U R                   R                  R                   Vs/ s H  o"R                  U:X  d  M  UPM     sn$ s  snf r   )r   r   r   op_type)r   r`   ns      r   get_nodes_by_op_typeOnnxModel.get_nodes_by_op_type]   s5    ::++00I0aII4H0IIIs
   AANc                     Uc  U R                  5       n/ nUR                   H&  nXB;   d  M
  X$    H  nUR                  U5        M     M(     U$ r   )r   r"   r   )r   r   r   childrenr"   s        r   get_childrenOnnxModel.get_children`   sP    '"&":":"<kkF,/7DOOD) 8 " r   c                     Uc  U R                  5       n/ nUR                   H  nXB;   d  M
  UR                  X$   5        M     U$ r   )r#   r   r   )r   r   r#   parentsr   s        r   get_parentsOnnxModel.get_parentsk   sG    &"&":":"<ZZE+29:   r   c                     Uc  U R                  5       n[        UR                  5      U::  a  g UR                  U   nXC;  a  g X4   $ r   )r#   rJ   r   )r   r   ir#   r   s        r   
get_parentOnnxModel.get_parentu   sI    &"&":":"<tzz?a

1+"))r   c                     [        UR                  5       HO  u  pVXc;   d  M  X6   nUR                  U:X  a
  Xt;  a  Xu4s  $ [        R	                  SU SUR                   35        MQ     g)a  
Find parent node based on constraints on op_type.

Args:
    node (str): current node name.
    parent_op_type (str): constraint of parent node op_type.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    exclude (list): list of nodes that are excluded (not allowed to match as parent).

Returns:
    parent: The matched parent node. None if not found.
    index: The input index of matched parent node. None if not found.
zTo find first z
, current NN)	enumerater   r`   loggerdebug)r   r   parent_op_typer#   excluderm   r   parents           r   match_first_parentOnnxModel.match_first_parent   sd     "$**-HA+,3>>^38M!9$LL>.1AFNNK[!\] . r   c                    Uc   eUb  US:  d   eUc  U R                  5       nUc*  U R                  XXE5      u  pxUb  UR                  U5        U$ U[        UR                  5      :  a/  [
        R                  SU S[        UR                  5       35        gU R                  XU5      nUb  UR                  U:X  a  Xu;  a  U$ Ub%  [
        R                  SU SUR                   35        g)a  
Find parent node based on constraints on op_type and index.
When input_index is None, we will find the first parent node based on constraints, and return_indice will be appended the corresponding input index.

Args:
    node (str): current node name.
    parent_op_type (str): constraint of parent node op_type.
    input_index (int or None): only check the parent given input index of current node.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    exclude (list): list of nodes that are excluded (not allowed to match as parent).
    return_indice (list): a list to append the input index when input_index is None.

Returns:
    parent: The matched parent node.
Nr   zinput_index z >= node inputs zExpect z, Got )	r#   rx   r   rJ   r   rs   rt   rn   r`   )	r   r   ru   input_indexr#   rv   return_indicerw   indexs	            r   match_parentOnnxModel.match_parent   s    , "kQ&666&"&":":"< 33DJ]gMF($$U+M#djj/)LL<}4DS_DUVW4GH&..N"BvG\MLL7>"2&8HIJr   c                     [        U5       HY  u  pE[        U[        5      (       d  [        U[        5      (       d   e/ nU R	                  XS   US   X65      nU(       d  MU  XGU4s  $    g)Nr      )NN)rr   rG   r   r   match_parent_path)r   r   pathsr#   rm   pathr|   matcheds           r   match_parent_pathsOnnxModel.match_parent_paths   si     'GAdD))Ze-D-DDDM,,T7DGEXhGw=00 ( r   c           
      *   [        U5      [        U5      :X  d   eUc  U R                  5       nUn/ n[        U5       HR  u  pU R                  UU	X8   U/ US9n
U
c!  [        R                  SU SX8    SU	 3SS9    gUR                  U
5        U
nMT     U$ )a  
Find a sequence of input edges based on constraints on parent op_type and index.
When input_index is None, we will find the first parent node based on constraints, and return_indice will be appended the corresponding input index.

Args:
    node (str): current node name.
    parent_op_types (str): constraint of parent node op_type of each input edge.
    parent_input_index (list): constraint of input index of each input edge. None means no constraint.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    return_indice (list): a list to append the input index when there is no constraint on input index of an edge.

Returns:
    parents: a list of matched parent node.
N)rv   r|   zFailed to match index=z parent_input_index=z	 op_type=T)
stack_info)rJ   r#   rr   r~   rs   rt   r   )r   r   parent_op_typesparent_input_indexr#   r|   current_nodematched_parentsrm   r`   matched_parents              r   r   OnnxModel.match_parent_path   s    ( &'3+??@?&"&":":"<#O4JA!..|/6/A/D/B79=J / LN %5aS8LM_MbLcclmtluv(,  ."">2)L 5 r   c                 $   U R                  X5      n[        U5      n[        U5      S:  ae  UR                  5       nUR                  U:X  a  U$ U(       a+  U R                  Xs5      nU H  nUR                  U5        M     [        U5      S:  a  Me  g Nr   )rf   r   rJ   popr`   
appendleft)	r   r   
child_typer   	recursivere   dqr   childs	            r   find_first_child_by_type"OnnxModel.find_first_child_by_type   s    $$T?8_"gk668L##z1##,,\O%EMM%( & "gk r   c                 J   Uc  U R                  5       nU R                  X5      n[        U5      n[        U5      S:  ae  UR	                  5       nUR
                  U:X  a  U$ U(       a+  U R                  Xs5      nU H  nUR                  U5        M     [        U5      S:  a  Me  g r   )r#   rj   r   rJ   r   r`   r   )	r   r   parent_typer#   r   ri   r   r   rw   s	            r   find_first_parent_by_type#OnnxModel.find_first_parent_by_type  s    &"&":":"<""4=7^"gk668L##{2##**<M%FMM&) & "gk r   c                 @   U R                  S5       H_  nUR                  S   U:X  d  M  UR                   H7  nUR                  S:X  d  M  [        R
                  " UR                  5      s  s  $    Ma     U R                  U5      nUb  [        R
                  " U5      $ g )NConstantr   value)rb   r"   	attributer\   r   to_arraytr]   )r   r$   r   attr?   s        r   get_constant_valueOnnxModel.get_constant_value  s    --j9D{{1~,>>Cxx7*+44SUU;; * : **;7"((55r   c                 r    [        UR                  5       H  u  p#U R                  U5      nUc  M  X$4s  $    g)Nrq   )rr   r   r   )r   r   rm   r   r   s        r   get_constant_inputOnnxModel.get_constant_input-  s9    !$**-HA++E2E x .
 r   c                 v    U R                  U5      u  pEUb#  UR                  S:X  a  [        XR-
  5      U:  a  U$ g)Nr   r   )r   sizeabs)r   r   expected_valuedeltarm   r   s         r   find_constant_inputOnnxModel.find_constant_input5  s<    **40qS9O5PSX5XHr   c           	          U R                  U5      nUc  [        R                  U SU S35        g[        UR                  5      U:w  a+  [        R                  U SU SU SUR                   35        gg)N z is not initializer.Fz shall have z dimensions. Got shape T)r   rs   rt   rJ   shape)r   r$   
dimensionsdescriptionr   s        r   $is_constant_with_specified_dimension.OnnxModel.is_constant_with_specified_dimension<  sw    ''4=LLK=+6JKLu{{z)LLK=+l:,Nefkfqfqerstr   c                 ,    U R                  XU5      S:  $ r   )r   )r   r   r   r   s       r   has_constant_inputOnnxModel.has_constant_inputH  s    ''eDIIr   c                 r   Uc  U R                  5       nX1R                  S      n/ n[        U5      n[        U5      S:  av  UR	                  5       nXr;   a  M&  Xu;  aI  UR                  U5        UR                   H(  nX;   d  M
  X8   nU H  n	UR                  U	5        M     M*     [        U5      S:  a  Mv  U$ r   )r   r"   r   rJ   r   r   r   )
r   	root_node
stop_nodesr   re   unique_nodesr   r   r"   r   s
             r   get_children_subgraph_nodes%OnnxModel.get_children_subgraph_nodesK  s    &"&":":"<&'7'7':;8_"gk668L)/##L1*11F4#6#>%-EMM%0 &. 2 "gk r   c                     U R                   R                  nUR                  nU Hv  nUR                  S:X  d  M  UR	                  [
        R                  " [
        R                  " U5      R                  [        R                  5      UR                  5      5        Mx     UR                   GH9  nUR                  S;   a  UR                   H  nUR                  S:X  d  M  UR                  R                  S:X  d  M1  UR	                  [         R"                  " S[
        R                  " [
        R                  " UR                  5      R                  [        R                  5      5      5      5        M     UR                  S:X  d  M  UR                   HM  nUR                  S:X  d  M  UR$                  S:X  d  M'  UR	                  [         R"                  " SS5      5        MO     GM<     UR&                   GH  nUR(                  R*                  R,                  [.        R0                  :X  d  M8  U R3                  UR                  5      nUb  SUR(                  R*                  l        Ms  UR                  nUR                  S-   nU R5                  Xx5        [         R6                  " SU/U/S9n	U	R                  R9                  [         R"                  " S[;        [.        R<                  5      5      /5        U R?                  U	5        GM     UR@                   H  n
U
R(                  R*                  R,                  [.        R0                  :X  d  M7  U
R                  S-   nU
R                  nU RC                  X5        U R5                  X5        [         R6                  " SU/U/S9n	U	R                  R9                  [         R"                  " S[;        [.        R0                  5      5      /5        U R?                  U	5        M     g )	Nr   )r   ConstantOfShaper   Castto
   _float16)inputsoutputs)"r   r   r?   	data_typeCopyFromr   
from_arrayr   astypenpfloat16r\   r   r`   r   r   r	   make_attributerm   r   typetensor_type	elem_typer   FLOATr]   rQ   	make_noder7   intFLOAT16r8   r"   rY   )r   r   initializersr?   r   r   input_value_info
cast_inputcast_output	cast_nodeoutput_value_infos              r    convert_model_float32_to_float16*OnnxModel.convert_model_float32_to_float16d  s   

  (('K$$)$$ ++L,A,A+,N,U,UVXV`V`,acncscstv (
 JJD||>>>>Cxx7*suu!/C"11 ')@)@AVAVWZW\W\A]AdAdegeoeoAp)qst *
 ||v%>>Cxx4'CEEQJV%:%:4%DE *  !&$$00::k>O>OO"223C3H3HI*BD$))55?!1!6!6J"2"7"7*"DK33JL & 0 0WbVc dI''..0E0EdCP[PcPcLd0e/fgMM), !, "' %%11;;{?P?PP.33j@
/4400I//H",,VZLS^R_`	##**F,A,A$KL]L]H^,_+`ai( ".r   c                 X   XR                   ;   a  U R                   U==   S-  ss'   OSU R                   U'   Ub  U[        U R                   U   5      -   nOUS-   [        U R                   U   5      -   nU R                  U5      nU H  nUR                  U:X  d  M  [	        SU5      e   U$ )Nr   _zNode name already taken:)r   rH   rb   r\   	Exception)r   r`   name_prefix	full_namer(   r   s         r   create_node_nameOnnxModel.create_node_name  s    ,,,""7+q0+./D""7+"#c$*@*@*I&JJI#D,B,B7,K(LLI ))'2DyyI% :IFF  r   c                 z    U R                   R                  R                   H  nUR                  U:X  d  M  Us  $    g r   )r   r   r   r\   )r   r   r   s      r   find_graph_inputOnnxModel.find_graph_input  s2    ZZ%%++EzzZ' , r   c                 z    U R                   R                  R                   H  nUR                  U:X  d  M  Us  $    g r   )r   r   r"   r\   )r   r$   r"   s      r   find_graph_outputOnnxModel.find_graph_output  s2    jj&&--F{{k) . r   c                 \   Uc  U R                  5       n/ nU R                  X5      n[        U5      n[        U5      S:  ak  UR	                  5       nXr;   a  M&  Xt;  a>  UR                  U5        UR                   H  nX;   d  M
  UR                  X8   5        M     [        U5      S:  a  Mk  U$ r   )r#   rj   r   rJ   r   r   r   r   )	r   r   r   r#   r   ri   r   r   r   s	            r   get_parent_subgraph_nodes#OnnxModel.get_parent_subgraph_nodes  s    &"&":":"<""4=7^"gk668L)/##L1)//E3&9&@A 0 "gk r   c                 Z   / nUR                    H3  nU R                  U5      (       d  M  XC;  d  M"  UR                  U5        M5     U(       a^  U R                  U/ 5      nU HF  nUR                    H3  nU R                  U5      (       d  M  XC;  d  M"  UR                  U5        M5     MH     U$ )z0
Find graph inputs that linked to current node.
)r   r   r   r   )r   r   r   graph_inputsr   parent_nodesr   s          r   get_graph_inputsOnnxModel.get_graph_inputs  s     !''E$$U++0I##E* ( 99,KL$!ZZE,,U338Q$++E2 ( % r   c                 J    SnUR                    H  nX0:X  a  Us  $ US-  nM     g)Nr   r   r   )r   )node_output
child_noder}   r   s       r   r{   OnnxModel.input_index  s0    %%E#QJE & r   c                 N   U R                  5       n/ nU R                  5       nU H;  nUR                  S:X  d  M  UR                  S   U;  d  M*  UR	                  U5        M=     U R                  U5        [        U5      S:  a"  [        R                  S[        U5       35        g g )Nr   r   zRemoved unused constant nodes: )	r   r(   r`   r"   r   r3   rJ   rs   rt   )r   r   unused_nodesr(   r   s        r   remove_unused_constant OnnxModel.remove_unused_constant  s    "668 

D||z)dkk!nDW.W##D)  	,'|q LL:3|;L:MNO !r   c           	         Uc9  U R                   R                  R                   Vs/ s H  o"R                  PM     nnU R	                  5       n/ nU HI  nX#;   d  M
  X2   nXT;   a  M  U R                  U/ 5      nUR                  U5        UR                  U5        MK     / nU R                   R                  R                   H  nX;  d  M
  UR                  U5        M     U R                  U5        / n	U R                   R                  R                   H&  nUR                  U;  d  M  U	R                  U5        M(     U	 H2  nU R                   R                  R                  R                  U5        M4     U R                  5       n
/ nU R                   R                  R                   H&  nUR                  U
;  d  M  UR                  U5        M(     U H2  nU R                   R                  R                  R                  U5        M4     [        R                  SR                  [!        U5      [!        U	5      [!        U5      5      5        U R#                  5         gs  snf )a  
Prune graph to keep only required outputs. It removes unnecessary inputs and nodes.
Nodes are not linked (directly or indirectly) to any required output will be removed.

Args:
    outputs (list): a list of graph outputs to retain. If it is None, all graph outputs will be kept.
Nz<Graph pruned: {} inputs, {} outputs and {} nodes are removed)r   r   r"   r\   r#   r   r   r7   r   r3   r-   r   r   rs   infoformatrJ   update_graph)r   r   r"   r#   	all_nodes	last_noder(   r2   r   output_to_remover   input_to_remover   s                r   prune_graphOnnxModel.prune_graph  s    ?151A1A1H1HI1Hv{{1HGI"668	F,/7	)66y"E  +  '  JJ$$))D$&&t, * 	/* jj&&--F{{') ''/ . 'FJJ##**62 ' #668ZZ%%++Ezz!44&&u- , %EJJ""))%0 % 	RYY #&6"7_9MO 	P 	Q Js   Ic                 *   U R                   R                  n/ nUR                   H@  nUR                  S:w  d  M  UR                   H  nXS;  d  M
  UR                  U5        M     MB     U(       a  [        R                  SU 35        / nUR                   H&  nUR                  U;  d  M  UR                  U5        M(     U H  nUR                  R                  U5        M      U Vs/ s H  owR                  PM     nn[        R                  S[        U5       SU 35        / n	/ n
UR                   HA  nUR                  U;  a  U	R                  U5        M&  U
R                  UR                  5        MC     U	 H  nUR                  R                  U5        M      U	 Vs/ s H  oR                  PM     nn[        R                  S[        U	5       SU 35        U(       a  [        R                  SU
 35        U R                  5         g s  snf s  snf )Nr   zremaining input names: zremove z unused inputs: z unused initializers: zremaining initializers:)r   r   r   r`   r   r   rs   rt   r\   r-   rJ   r?   r   )r   verboser   remaining_input_namesr   r   inputs_to_remover   names_to_removeweights_to_removeweights_to_keepr?   s               r   r   OnnxModel.update_graph"  s   

   "JJD||z)"&**J!>-44Z@ #- 
 LL23H2IJK [[Ezz!66 ''. ! &EKKu% & 4DD3C%::3CDws#3455EoEVWX  ,,K'<<!((5&&{'7'78	 -
 -K$$[1 - @QQ?P++?PQws#4566L_L]^_LL2?2CDE##%' E Rs   (H Hc           	          U HS  nUR                    H@  nXb;   a  M
  Xc;   d  M  X6    H'  nXq;  d  M
  [        R                  SU SU 35              g   MB     MU     g)Nz,it is not safe to remove nodes since output z is used by FT)r"   rs   rt   )r   r2   keep_outputsr   r#   node_to_remover  impacted_nodes           r   is_safe_to_fuse_nodesOnnxModel.is_safe_to_fuse_nodesK  sk    -N$2$9$9 #3#:)<)N(?"LL"NO_N``lmzl{ | $) *O %: . r   c                 b   [         R                  SU 35        UR                  S5      (       a[  [        U R                  [
        5      (       d   e[        US5       nUR                  [        U R                  5      5        S S S 5        g [        U R                  US S9  g ! , (       d  f       g = f)NzOutput model to z.jsonw)r   )
rs   r   endswithrG   r   r   openwriterH   r   )r   output_pathouts      r   save_model_to_fileOnnxModel.save_model_to_fileZ  s    &{m45((djj*5555k3'3		#djj/* (' tzz;t< ('s   %B  
B.c                     / nU R                   R                  R                   H2  nU R                  UR                  5      b  M!  UR                  U5        M4     U$ )zK
Returns real graph inputs (excluding initializers from older onnx model).
)r   r   r   r]   r\   r   )r   r   r   s      r   'get_graph_inputs_excluding_initializers1OnnxModel.get_graph_inputs_excluding_initializersg  sN     ZZ%%++E##EJJ/7##E* , r   r   r   rq   )NT)gư>)F)3__name__
__module____qualname____firstlineno__r   r   r#   r(   r   r/   r3   r8   r<   rA   rD   staticmethodrN   rQ   rV   rY   r]   rb   rf   rj   rn   rx   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   r   r  r   r  r  r  __static_attributes__ r   r   r   r      s7   $##% /#-36/ / /O 1 1RJ	* UW 4 "&)-#'-^ /3(,*X$
J2*)Z&,"  P1f'&R=r   r   )typingr   r   loggingsysargparsenumpyr   collectionsr   onnxr   r   r   r	   r
   r   	getLoggerr!  rs   r   r'  r   r   <module>r0     s;      
    ` `			8	$^	 ^	r   