
    h<                       S SK Jr  S SKrS SKJr  S SKrSSKJrJr  SSK	J
r
  SSKJrJr  SS	KJr  SS
KJr  SSKJr  SSKJr            S                         SS jjr " S S5      r  S         SS jjrg)    )annotationsN)Path   )fix_output_shapesmake_input_shape_fixed)remove_initializer_from_input   )
FusionGeluFusionLayerNormalization)	ONNXModel)&save_and_reload_model_with_shape_infer   )FusionLpNormalization)FusionSpaceToDepthc           
        Sn[        U [        R                  5      (       a  U O[        R                  " U 5      n[	        U5      n[        U5      nU(       ah  U HK  u  nnUR                  S5       Vs/ s H  n[        U5      PM     nn[        UR                  5       UU5        MM     [        UR                  5        SnU(       a  U[        UR                  5      -  n[        U5      nUR                  5       (       a  Sn[        U5      nUR                  5       (       a  Sn[!        U5      nUR                  5       (       a  SnU(       as  [#        S UR$                   5       5      nUR&                  S:  a%  [(        R*                  " SUR&                   S35        O"[-        U5      nUR                  5       (       a  SnU	(       d  U
(       a/  SnUR/                  U5      S	-   n[1        UR                  U	U
UUS
9  SnSnUR/                  U5      S	-   nUR                  R                  R2                   Hd  nUR4                  S:w  d  M  UR6                  (       a  M(  U U< 3nUS	-  nUUl        Sn[(        R*                  " SUR4                   SU S35        Mf     U(       a*  UR9                  5         [        R:                  " UUUUUUUS9  U$ s  snf )a  
If necessary, this method creates a new "pre-processed" model in preparation for
quantization of a model to be used in QNN EP. Returns true if a new model was created.

This method perfoms the following operations:
- Fuse Erf sequence into a single Gelu node.
- Fuse ReduceL2 sequence into a single LpNormalization node (p == 2).
- (Optional) Fuse ReduceMean sequence into a single LayerNormalization node.

Args:
    model_input: Path to the input model file or ModelProto.
    model_output: Path the output model file, which is only created if this method returns True.
    exclude_initializer_from_input: A bool specifying whether to exclude initializer from input.
        Defaults to False.
    fuse_layernorm: True if ReduceMean sequences should be fused into LayerNormalization nodes.
        Defaults to False.
    save_as_external_data: True if output model should be saved with external data. Defaults to false.
    all_tensors_to_one_file: Effective only if save_as_external_data is true. Defaults to false.
        If true, save all tensors to one external file specified by external_data_location.
        If false, save each tensor to a file named with the tensor name.
    external_data_location: Effective only if save_as_external_data is true. Defaults to None.
        Specify the external file to which all tensors are saved. Path is relative
        to the model path. If not specified, the model's name is used.
    external_data_size_threshold: Effective only if save_as_external_data is true. Defaults to 1024.
        Tensors with a data size >= external_data_size_threshold are converted to external data.
        To convert every tensor with raw data to external data, set to 0.
    external_data_convert_attribute: Effective only if save_as_external_data is true. Defaults to false.
        If true, convert all tensors to external data.
        If false, convert only non-attribute tensors to external data.
    inputs_to_make_channel_last: List of graph input names to transpose to be "channel-last". For example,
        if "input0" originally has the shape (N, C, D1, D2, ..., Dn), the resulting model will change input0's
        shape to (N, D1, D2, ..., Dn, C) and add a transpose node after it.

        Original:
            input0 (N, C, D1, D2, ..., Dn) --> <Nodes>

        Updated:
            input0 (N, D1, D2, ..., Dn, C) --> Transpose --> input0_chanfirst (N, C, D1, D2, ..., Dn) --> <Nodes>

        This can potentially improve inference latency for QDQ models running on QNN EP because the
        additional transpose node may allow other transpose nodes inserted during ORT layout transformation
        to cancel out.
    outputs_to_make_channel_last: List of graph output names to transpose to be "channel-last". For example,
        if "output0" originally has the shape (N, C, D1, D2, ..., Dn), the resulting model will change output0's
        shape to (N, D1, D2, ..., Dn, C) and add a transpose node before it.

        Original:
            <Nodes> --> output0 (N, C, D1, D2, ..., Dn)

        Updated:
            <Nodes> --> output0_chanfirst (N, C, D1, D2, ..., Dn) --> Transpose --> output0 (N, D1, D2, ..., Dn, C)

        This can potentially improve inference latency for QDQ models running on QNN EP because the
        additional transpose node may allow other transpose nodes inserted during ORT layout transformation
        to cancel out.
    dynamic_input_shapes: A list of tuples specifying model input name to and its static shape in comma seprated
        format, for example: [('input', '1,3,256,256')]. Defaults to None.
F,Tc              3  h   #    U  H(  oR                   S :X  d  UR                   S:X  d  M$  Uv   M*     g7f) zai.onnxN)domain).0xs     u/var/www/fran/franai/venv/lib/python3.13/site-packages/onnxruntime/quantization/execution_providers/qnn/preprocess.py	<genexpr>'qnn_preprocess_model.<locals>.<genexpr>   s(     c%788r>QXXYbMb!!%7s   #2	2   zUnable to fuse ReduceMean sequence into a LayerNormalization node. ONNX model must use an opset >= 17 in order to use LayerNormalization, but found version z9. Please use onnx.version_converter to update your model.Transpose_channel_r   )transpose_node_name_prefix transpose_node_name_start_suffixqnn_preproc_node_ConstantzNode of type z" does not have a name. Renamed to .)save_as_external_dataall_tensors_to_one_filelocationsize_thresholdconvert_attribute)
isinstanceonnx
ModelProto
load_modelr   r   splitintr   graphr   modelr   r
   applyr   r   nextopset_importversionloggingwarningr   get_largest_node_name_suffixupdate_io_to_channel_lastnodeop_typenametopological_sort
save_model)model_inputmodel_outputexclude_initializer_from_inputfuse_layernormr"   r#   external_data_locationexternal_data_size_thresholdexternal_data_convert_attributeinputs_to_make_channel_lastoutputs_to_make_channel_lastdynamic_input_shapesmodifiedr.   
onnx_model
input_nameinput_shape_striinput_shapefusion_gelufusion_lpnorm
fusion_s2d
onnx_opsetfusion_layernormtranspose_node_prefixtranspose_node_suffixunnamed_node_prefixavailable_suffixr7   new_node_names                                 r   qnn_preprocess_modelrV      s   P H%k4??CCKYdIeE259E5!J +?'J+:+@+@+EF+Ea3q6+EKF":#3#3#5z;O ,@ 	***+ &1*2B2BCC Z(K **5M $J/J cU%7%7cc
 "OO%%/%7%7$88qs  8
C%%'' #&B 4%/%L%LMb%cfg%g!'('<-B	
  .!>>?RSVWW  &&++<<:%diii234D3GHM!%DIHOOmDLL>9[\i[jjklm , ##%"7$;+7=	
 OY Gs   2Kc                  4    \ rS rSr      SS jrSS jrSrg)InputOutputNameMap   c                D    Xl         X l        X0l        0 U l        / U l        g N)orig_tensor_namesorig_graph_inputsorig_graph_outputsupdated_io_namesnew_value_infos)selfr\   r]   r^   s       r   __init__InputOutputNameMap.__init__   s&     "3!2"4 "!    c                n   XR                   ;   a  U R                   U   $ U S3nSnU R                   H`  nUR                  U5      (       d  M  U[        U5      S  R	                  5       (       d  M>  [        U[        U5      S  5      n[        X55      nMb     US-  nU U< 3nU R                  R                  U5      =(       d    U R                  U   n[        R                  " 5       nUR                  U5        Xhl        U R                  R                  U5        X`R                   U'   U R                   U   $ )N_channel_first_r   )r_   r\   
startswithlenisdigitr,   maxr]   getr^   r(   ValueInfoProtoCopyFromr9   r`   append)	ra   	orig_nameprefixsuffixtensor_nameindexnew_nameorig_value_infovalue_info_protos	            r   get_new_nameInputOutputNameMap.get_new_name   s$   ---((33 #?311K%%f--+c&km2L2T2T2V2VKF67V+ 2
 	!XfZ( 0044Y?e4CZCZ[dCe..0!!/2 (##$45+3i($$Y//rd   )r`   r]   r^   r\   r_   N)r\   zset[str]r]   dict[str, onnx.ValueInfoProto]r^   rz   )rp   str)__name__
__module____qualname____firstlineno__rb   rx   __static_attributes__ rd   r   rX   rX      s(    
"#
" :
" ;	
"0rd   rX   c           	        [        U=(       d    / 5      n[        U=(       d    / 5      nU(       d  U(       d  g U R                  nUR                   Vs0 s H  ofR                  U_M     nnUR                   Vs0 s H  oR                  U_M     n	nU H  n
X;  d  M
  [        U
 S35      e   U H  nX;  d  M
  [        U S35      e   [        5       nUR                  [        U5      5        UR                  [        U	5      5        UR                  S UR                   5       5        [        XU	5      nUR                   GH8  n[        [        UR                  5      5       H  nUR                  U   (       a@  UR                  U   U;   a-  UR                  UR                  U   5      UR                  U'   MW  UR                  U   (       d  Mm  UR                  U   U;   d  M  UR                  UR                  U   5      UR                  U'   M     [        [        UR                  5      5       HC  nUR                  U   U;   d  M  UR                  UR                  U   5      UR                  U'   ME     GM;     U GH  nUU   nUR                  R                  S5      (       a*  UR                  R                  R                  S5      (       d  [        SUR                   S35      eUR                  R                  R                  n[        UR                   5      nUS:  a  [        SUR                   S	35      e["        R$                  R'                  5       nUR)                  UR                   S
   5        [        S
US
-
  5       H1  nUR                   U   R)                  UR                   US
-      5        M3     UR                   US
-
     R)                  U5        [+        [        U5      5      n[        U5       H  nUS
:  a  UOUS
-
  UU'   M     US
-
  US
'   ["        R,                  R/                  SU U< 3UR                  /UR                  UR                  5      /US9nUS
-  nUR                  R1                  U/5        GM     U GH  nU	U   nUR                  R                  S5      (       a*  UR                  R                  R                  S5      (       d  [        SUR                   S35      eUR                  R                  R                  n[        UR                   5      nUS:  a  [        SUR                   S	35      e["        R$                  R'                  5       nUR)                  UR                   S
   5        [        S
US
-
  5       H1  nUR                   U   R)                  UR                   US
-      5        M3     UR                   US
-
     R)                  U5        [+        [        U5      5      n[        U5       H  nUS:X  a  UOUS
-   UU'   M     S
UUS
-
  '   ["        R,                  R/                  SU U< 3UR                  UR                  5      /UR                  /US9nUS
-  nUR                  R1                  U/5        GM     UR2                  R1                  UR4                  5        g s  snf s  snf )Nz is not a graph inputz is not a graph outputc              3  \   #    U  H"  oR                     H  o"(       d  M  Uv   M     M$     g 7fr[   )input)r   r7   rH   s      r   r   ,update_io_to_channel_last.<locals>.<genexpr>   s"     jJDQ[Q[:_iZZQ[ZJs   ,,tensor_typeshapezExpected input z# to have a tensor_type with a shaper	   z to be of rank >= 3r   	Transpose)r9   inputsoutputspermzExpected output r   )setr-   r   r9   output
ValueErrorupdater7   rX   rangeri   rx   typeHasFieldr   r   dimr(   TensorShapeProto	Dimensionrn   listhelper	make_nodeextend
value_infor`   )r.   inputs_to_updateoutputs_to_updater   r   r-   ginputr]   goutputr^   rH   output_namer\   io_mapr7   rJ   g_input_nameg_inputrK   
input_rankchannel_dimtranspose_permtranspose_nodeg_output_nameg_outputoutput_shapeoutput_ranks                              r   r6   r6      s    +1r2-34$5KKE;@;;G;f,;G?D||L|G,,/|L '
.
|+@ABB ' )0},BCDD ) S!234S!345jEJJjj   1FXYF 

s4::'Azz!}A2B!B & 3 3DJJqM B

1A4::a=4E#E & 3 3DJJqM B

1	 ( s4;;'(A{{1~!22!'!4!4T[[^!DA )  )#L1||$$]337<<;S;S;\;\]d;e;ew||n<_`aall..44)
>w||n<OPQQ++557[__Q/0q*q.)AOOA''A(>? *
Q'00=eJ/0z"A%&UAN1 #&Nq.../0P/STLL>((67 / 
 	)A-(

>*+A )F +%m4}}%%m44HMM<U<U<^<^_f<g<g/>abcc}}0066,**+?/>QRSS++557\--a01q+/*AQ(()9)9!a%)@A +q)22;?eK01{#A%&!VQN1 $*+{Q'.../0P/ST''67]]O / 
 	)A-(

>*+? +B 
F223K HLs   [8[)
FFFFNi   FNNN)r<   zstr | Path | onnx.ModelProtor=   z
str | Pathr>   boolr?   r   r"   r   r#   r   r@   z
str | NonerA   r,   rB   r   rC   list[str] | NonerD   r   rE   zlist[tuple[str, str]] | Nonereturnr   )r   r   )
r.   zonnx.ModelProtor   r   r   r   r   r{   r   r,   )
__future__r   r3   pathlibr   r(   tools.onnx_model_utilsr   r   #tools.remove_initializer_from_inputr   fusionsr
   r   rG   r   quant_utilsr   rM   r   fusion_spacetodepthr   rV   rX   r6   r   rd   r   <module>r      s&   #    P Q ; # A 0 3 ,1 "'$))-(,,148599=\-\\ %)\ 	\
  \ "\ '\ #&\ &*\ "2\ #3\ 7\ 
\~$0 $0V ';,-s4s4&s4 (s4 !$	s4
 '*s4rd   