
    g;                        d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dlmZmZ d dlZd dlZd dlmZmZmZ d dlmZ d dlZ ej.                  e      ZdZd	Z G d
 de      Zd Zd Zd Zedk(  r e        yy)    N)deque)datetime)Path)ListOptional)
ModelProtoTensorProtonumpy_helper)	OnnxModelconstant_shape_opt__reshape_input_shape__c                        e Zd ZdZ fdZd Zd Zd Zd Zd Z	ddZ
	 dd	Zd
 Zd ZdefdZdee   fdZ	 	 	 	 ddededededededeee      fdZ xZS )BertOnnxModelShapeOptimizerz
    This optimizer will replace Shape output or the shape input of Reshape node by initializer. Currently, it requires
    model inputs to have static shape.
    c                 8    t         |   |j                         y )N)super__init__model)self
onnx_model	__class__s     ]/var/www/openai/venv/lib/python3.12/site-packages/onnxruntime/transformers/shape_optimizer.pyr   z$BertOnnxModelShapeOptimizer.__init__(   s    ))*    c                    t        j                  |t         j                        }| j                  dt              }t
        j                  j                  |t        j                  |j                  |      }| j                  |       |S )z8
        Add an initializer for constant shape.
        dtypeConstant)name	data_typedimsvals)npasarrayint64create_node_nameCONSTANT_SHAPE_NAME_PREFIXonnxhelpermake_tensorr	   INT64shapeadd_initializer)r   r*   shape_valueconstant_shape_nametensors        r   add_shape_initializerz1BertOnnxModelShapeOptimizer.add_shape_initializer+   sr     jjbhh7"33J@Z[(($!''""	 ) 
 	V$r   c                     | j                         }g }| j                  j                  j                  D ]B  }|j                  dk(  s|j
                  d   |v s%|j                  |j
                  d          D |S )zD
        Returns a list of output names of all Shape nodes.
        Shaper   )input_name_to_nodesr   graphnodeop_typeoutputappend)r   r2   outputsr4   s       r   get_shape_outputsz-BertOnnxModelShapeOptimizer.get_shape_outputs:   sj     #668JJ$$))D||w&;;q>%88NN4;;q>2 *
 r   c                     | j                          g }| j                  j                  j                  D ]0  }|j                  dk(  s|j                  |j                  d          2 |S )zG
        Returns a list of shape input names of Reshape nodes.
        Reshape   )output_name_to_noder   r3   r4   r5   r7   input)r   shape_inputsr4   s      r   get_reshape_shape_inputsz4BertOnnxModelShapeOptimizer.get_reshape_shape_inputsH   sY     	  "JJ$$))D||y(##DJJqM2 * r   c                 p   g }g }| j                   j                  j                  D ]}  }|j                  dk(  s|j                  d   }| j                  dt              }t        j                  j                  d|g|g      }|j                  |       |j                  |        | j                  |       |S )z
        For each Reshape node, create a Shape node for its first input.
        Returns the output names of these Shape nodes.
        r;   r   Reshape_Inputr1   )inputsr8   )r   r3   r4   r5   r>   r$   RESHAPE_INPUT_SHAPE_PREFIXr&   r'   	make_noder7   	add_nodes)r   output_namesnodes_to_addr4   r>   output_name
shape_nodes          r   add_shape_for_reshape_inputz7BertOnnxModelShapeOptimizer.add_shape_for_reshape_inputU   s    
 JJ$$))D||y(

1"33OE_`![[227E7U`Ta2b
##J/##K0 * 	|$r   c                    g }| j                   j                  j                  D cg c]  }|j                   }}|D ]  }| j	                  |      |j                  |       ||vs+t        j                  j                         }||_        | j                   j                  j                  j                  |g       |j                  |        |S c c}w )z=
        Add a list of output names to graph output.
        )
r   r3   r6   r   get_initializerr7   r&   r'   ValueInfoProtoextend)r   extra_outputsnames_to_evaluater6   rG   r   output_infos          r   add_extra_graph_outputz2BertOnnxModelShapeOptimizer.add_extra_graph_outputg   s     26**2B2B2I2IJ2I2IJ!D##D)5$$T*<'"kk88:#' 

  ''..}=##D) " !  Ks   Cc                    | j                   j                  j                  D ]  }|j                  |v s|j                  j
                  j                  j                  d   }||_        |j                  j
                  j                  j                  d   }|j                  d      r||_        |j                  d      s|j                  |k7  st        d| dd d|j                   d|j                   d		       y
)z_
        Update the model to use static axes instead of dynamic axes for graph inputs.
        r   r<   	dim_param	dim_valuez!Unable to set dimension value to z
 for axis z of z'. Contradicts existing dimension value .N)r   r3   r>   r   typetensor_typer*   dimrV   HasField
ValueError)r   rC   
batch_sizemax_seq_lenr>   	dim_protos         r   use_static_inputz,BertOnnxModelShapeOptimizer.use_static_input{   s     ZZ%%++EzzV#!JJ2288<<Q?	&0	#!JJ2288<<Q?	%%k2*5I'''49L9LP[9[$;K=
STRUUYZ_ZdZdYe  fM  NW  Na  Na  Mb  bc  d  ,r   c                 4   |dv sJ t         j                  j                  |||ft         j                        }t        j                  ||ft         j                        }	t        j
                  ||ft         j                        }
|dk(  r@t        j                  |      }t        j                  |	      }	t        j                  |
      }
nD|dk(  r?t        j                  |      }t        j                  |	      }	t        j                  |
      }
||||	||
i}|S )z
        Create dummy data for model inputs. If the model has more than 3 inputs, please update this function accordingly before running the tool.
        )r<         )sizer   r   r<   rc   )r!   randomrandintint32oneszerosfloat32r#   )r   	input_idssegment_ids
input_maskr]   sequence_length	elem_typedictionary_sizeinput_1input_2input_3rC   s               r   create_dummy_inputsz/BertOnnxModelShapeOptimizer.create_dummy_inputs   s     I%%% ))##O::W_a_g_g#h'':7rxxH((J8I >jj)Gjj)Gjj)G!^hhw'Ghhw'Ghhw'GWj';Pr   c                     |||g| _         g }|r|j                  | j                                |	rB| j                         }| j	                         }|j                  |       |j                  |       t        |      dk(  ry | j                  |      }| j                  | j                   ||       t        |d      5 }|j                  | j                  j                                d d d        t        j                         }t        j                  j                  |_        t        j"                  ||ddg      }d}| j                  j$                  j&                  D ]2  }|j(                  |k(  s|j*                  j,                  j.                  }4 | j1                  ||||||      }|j3                  ||      }i }t5        |      D ]  \  }}||   ||<    t6        j9                  d|        |	r,t5              D ]  \  }}|   }| j;                  ||||
         |j=                         D ]2  \  }}| j?                  |      }| jA                  ||j(                         4 | jC                  |       y # 1 sw Y   xY w)Nr   wbCUDAExecutionProviderCPUExecutionProvider)	providersrc   zshapes=)"bert_inputsrO   r9   r@   rK   lenrS   r`   openwriter   SerializeToStringonnxruntimeSessionOptionsGraphOptimizationLevelORT_DISABLE_ALLgraph_optimization_levelInferenceSessionr3   r>   r   rX   rY   ro   rt   run	enumerateloggerdebugupdate_target_shapeitemsr/   replace_input_of_all_nodesprune_graph)r   temp_model_pathrk   rl   rm   rG   r]   rn   enable_shape_optenable_reshape_optverboserP   reshape_shape_inputsreshape_input_shapesrQ   outsess_optionssessionro   r>   rC   r8   shapesir   shape_inputinput_shaper*   r.   s                                r   shape_optimizationz.BertOnnxModelShapeOptimizer.shape_optimization   sM    &{J?  !7!7!9:#'#@#@#B #'#C#C#E   !56  !56}" 77F 	d..
OL/4(CIIdjj2245 )"1130;0R0R0b0b-...0FG
 	ZZ%%++EzzY&!JJ22<<	 , )))[*jZiktu++/8 !23GAt"1:F4L 4 	wvh'("+,@"A;215((k7S #B "<<>KD%//6F++D&++> *
 	&C )(s   ;*I33I=c                    ||v r||   }n*| j                  |      }|J t        j                  |      }||v r||   }n*| j                  |      }|J t        j                  |      }g }t        |      D ]>  \  }	}
|	t	        |      k  r||	   |
k(  r|j                  d       .|j                  |
       @ |||<   t        j                  d| d| d|        y)z
        Update the target shape to use 0 to represent that dimension value does not change.
        For example, shape of source data is (2, 5, 8) and target shape is (2, 5, 4, 2), the target shape will be updated to (0, 0, 4, 2).
        Nr   zsource_shape=z, target_shape=z, new_target_shape=)rM   r
   to_arrayr   r{   r7   r   r   )r   r   r   r   r   target_shapeinitializersource_shapenew_target_shaper   rV   s              r   r   z/BertOnnxModelShapeOptimizer.update_target_shape   s    
 & !+.L..{;K***'00=L& !+.L..{;K***'00=L%l3LAy3|$$aI)E ''* ''	2	 4
 /{}\N/,Obcsbtuvr   r>   c                     | j                  |      sH| j                  j                  j                  D cg c]  }|j                   }}t        d d|       y c c}w )NzInput z% does not exist in the graph inputs: )find_graph_inputr   r3   r>   r   	Exception)r   r>   valid_namess      r   validate_inputz*BertOnnxModelShapeOptimizer.validate_input  s]    $$U+37::3C3C3I3IJ3I%5::3IKJfUG+PQ\P]^__ ,Js   ArG   c                     | j                   j                  j                  D cg c]  }|j                   }}|D ]  }||vst	        d| d|        y c c}w )NzOutput z& does not exist in the graph outputs: )r   r3   r6   r   r   )r   rG   r6   r   r   s        r   validate_outputsz,BertOnnxModelShapeOptimizer.validate_outputs  s_    151A1A1H1HI1Hvv{{1HI D;&'$/UVaUb cdd ! Js   Aoutput_pathrk   rl   rm   r   r   c                    | j                   j                  j                  D ]8  }|j                  j	                  t
              s#t        j                  d        y  | j                  |       | j                  |       | j                  |       |"| j                  |       | j                  |       | j                   j                  j                  D cg c]  }|j                   }}|s|rt        | j                               dk7  rt        j                  d       y t        j                         5 }dj!                  t#        j$                         j'                  d            }|
rdn|}t(        j*                  j-                  ||      }| j/                  |||||||	|||

       d d d        t        j1                  d        t        j3                  d| d	|	        |?t5        |d
      5 }|j7                  | j                   j9                                d d d        y y c c}w # 1 sw Y   xY w# 1 sw Y   y xY w)Nz5Skip shape optimization since it has been done before   z9Skip shape optimization since graph input number is not 3ztemp_{}.onnxz%m_%d-%H_%M_%SrW   z$Temp model with additional outputs: zZShape optimization is done. The optimized model might only work for input with batch_size=z sequence_length=rv   )r   r3   r   r   
startswithr%   r   infor   r   r   r6   r{   'get_graph_inputs_excluding_initializerstempfileTemporaryDirectoryformatr   nowstrftimeospathjoinr   r   warningr|   r}   r~   )r   r   rk   rl   rm   r   r   rG   r]   rn   r   r.   r6   remaining_outputstemp_dirtemp_file_namedir	temp_filer   s                      r   optimizez$BertOnnxModelShapeOptimizer.optimize  s    jj&&22F{{%%&@AST 3
 	I&K(J'#!!,/\*7;zz7G7G7N7NO7NVV[[7NO14??ABaGWX,,.(!/!6!6x||~7N7NO_7`!a$c(GGLLn=	''%#$&	 /  LL?	{KLNNlmwlx  yJ  KZ  J[  \ "k4(C		$**6689 )( #9 P /., )(s   H$4A3H)0*H5)H25H>)r<      )   )Nr<   r   F)__name__
__module____qualname____doc__r   r/   r9   r@   rK   rS   r`   rt   r   r   strr   r   r   boolr   r   __classcell__)r   s   @r   r   r   "   s    
+$!(0 BB'Hw:`C `
eT#Y e -19:9: 9: 	9:
 9: 9: !9: tCy)9:r   r   c                     t        j                         } | j                  ddt               | j                  ddt               | j                  ddt               | j                  ddt               | j                  ddt               | j                  dd	t        d 
       | j                  dd	t        d
       | j                  dd	t        d
       | j                  dd	d       | j                  d	       | j                  dd	d       | j                  d	       | j                  dd	d       | j                  d	       | j                         }|S )Nz--inputT)requiredrX   z--outputz--input_idsz--segment_idsz--input_maskz--output_namesF)r   rX   defaultz--batch_sizer<   z--sequence_lengthr   z--enable_shape_opt
store_true)r   action)r   z--enable_reshape_opt)r   z	--verbose)r   )argparseArgumentParseradd_argumentr   intset_defaults
parse_args)parserargss     r   parse_argumentsr   T  sG   $$&F
	Ds;

T<
3?
$SA
C@
(5sDQ
S!L
+e#sS
,u\R
/
.|T
51
eLI
&DKr   c                    t        j                  t        j                        }| r5|j	                  t        j
                  d             t         j                  }n4|j	                  t        j
                  d             t         j                  }|j                  |       t        j                  |       t        j                  |       y )Nz8[%(filename)s:%(lineno)s - %(funcName)20s()] %(message)sz%(filename)20s: %(message)s)loggingStreamHandlersysstdoutsetFormatter	FormatterDEBUGINFOsetLevelr   
addHandler)r   log_handlerlogging_levels      r   setup_loggingr   h  s    ''

3K  !2!23m!no  !2!23P!QR'
k"
OOM"r   c                  P   t               } t        | j                         | j                  d n| j                  j	                  d      }t               }t        | j                  d      5 }|j                  |j                                d d d        t        |      }t        |      }|j                  | j                  | j                  | j                  | j                   | j"                  | j$                  || j&                  | j(                  | j                  
       y # 1 sw Y   xY w)N;rb)r   r   r   rG   splitr   r|   r>   ParseFromStringreadr   r   r   r6   rk   rl   rm   r   r   r]   rn   )r   rG   r   
input_filer   	optimizers         r   mainr   u  s    D$,,,,44$:K:K:Q:QRU:VLLE	djj$	:joo/0 
 5!J+J7I 
 	s   ) DD%__main__) r   r   r   rer   r   collectionsr   r   pathlibr   typingr   r   numpyr!   r&   r   r	   r
   r   r   r   	getLoggerr   r   r%   rD   r   r   r   r    r   r   <module>r      s      	 	 
     !   6 6   			8	$3 4 o:) o:d	(
#6 zF r   