U
    9%eB                    @  s  d Z ddlmZ 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	Z	ddl
Z
ddl	mZmZmZmZmZmZmZmZmZmZmZmZmZ ddlZddlm  mZ ddlZddlZddlmZ ddlm Z m!Z!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z, d	d
dddddddddddgZ-dddd	Z.i Z/ej0e(j1dddd
Z2ej0e(j1ddddZ3ej0e(j1ddd dZ4ej0e(j1ddd!d"dZ5e(j1d#d$ej6j7ddej8j9dd#dddd$d#fd%d&d'dddd(d(d)d*dd+d,d-d.d,d/d0d1dZ:e(j1d2d3 Z;e(j1d4d5 Z<e(j1dd6d)ddd7d8d9Z=e(j1d:d Z>e(j1d;d< Z?e(j1d,d)d=d>d?d@Z@e(j1dAdB ZAe(j1dCdD ZBe(j1dEddFdGZCe(j1dHdI ZDe(j1ddJdKZEe(j1dLdM ZFe(j1dNdO ZGe(j1dPdQ ZHddRdSdTdUdVZIe(j1dWdX ZJe(j1dYdZ ZKejLejMejNejOejPejQejRejOiZSe(j1dd[dZTe(j1d\d] ZUe(j1d$ddej8j9d#d$d$ej6j7df	d^dd_d`ZVe(j1ejWd#d$ej6j7ddej8j9dd$dddd#d#dfdadZXe(j1ej6j7dfdd*dbdcdddZYe(j1ded.dfdgdhdiZZe(j1djdk Z[e(j1dldm Z\e(j1d#d$ej6j7ddej8j9ddd#ddd$dd#d#d$d#fdndoZ]e(j1dpdq Z^e(j1drds Z_e(j1dtdu Z`e(j1dvdwdxdydzZae(j1dwd{d|d}Zbe(j1dwd~d=dddZce(j1dd=d)dddZde(j1dddddZee(j1dddddZfe(j1dvddddZge(j1ej8j9fd6dwdvddddddZhe(j1ddddZie(j1ddd=dddZje(j1dd=dddZke(j1dd ZlddEdddZmdS )zFunctions to export models into the ONNX IR format.

These models can be loaded with the ONNX library and then
converted to models which run on other deep learning frameworks.
    annotationsN)AnyCallablecast
CollectionDictListMappingOptionalSequenceSetTupleTypeUnion)_C)
_constants_exporter_stateserrorssymbolic_caffe2symbolic_helper)GLOBALS)	_beartypediagnostics	jit_utilsonnx_proto_utilsregistrationis_in_onnx_exportselect_model_mode_for_exportdisable_apex_o2_state_dict_hooksetup_onnx_loggingexporter_contextexportmodel_signaturewarn_on_static_input_changeunpack_quantized_tensorexport_to_pretty_stringunconvertible_opsregister_custom_op_symbolicunregister_custom_op_symbolicbool)returnc                   C  s   t jS )z3Returns whether it is in the middle of ONNX export.)r   in_onnx_export r-   r-   O/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/torch/onnx/utils.pyr   F   s    z_C_onnx.TrainingMode)modec              	   c  s   t |tjs tdt| dd}t| dr| j}|tjjksP|tjjkrv|rvdt	_
t	jdk r|tdt	j d ndt	_
|t	_|tjjkr| d n|tjjkr| d z
d	V  W 5 t| dr|tjjks| | X d	S )
a"  A context manager to temporarily set the training mode of ``model``
    to ``mode``, resetting it when we exit the with-block.

    Args:
        model: Same type and meaning as ``model`` arg to :func:`export`.
        mode: Same type and meaning as ``training`` arg to :func:`export`.
    z:'mode' should be a torch.onnx.TrainingMode enum, but got 'z'.FtrainingT   zEYou are exporting the model in training mode with onnx opset version zn. Opset versions lower than opset 12 will not be able to export nodes such as Dropout and BatchNorm correctly.N)
isinstance_C_onnxTrainingMode	TypeErrortypehasattrr0   ZTRAININGZPRESERVEr   Zexport_trainingexport_onnx_opset_versionwarningswarnZtraining_modetrainEVAL)modelr/   Zoriginally_trainingr-   r-   r.   r   P   s6    





z0Union[torch.nn.Module, torch.jit.ScriptFunction]r=   c                 c  s   t | tjjsi }|  D ]d}|j D ]2\}}t|jdkr(||krNi ||< ||| |< q(||kr|| D ]}|j	| qlqz
d V  W 5 | D ]$\}}| D ]\}}||j|< qqX nz
d V  W 5 X d S )NZO2StateDictHook)
r2   torchjitScriptFunctionmodulesZ_state_dict_hooksitemsr6   __name__pop)r=   Zmodel_hooksmodulekeyhookZm_mapr-   r-   r.   r      s&    	

verbosec                 c  s<   t j }|s| rt j  z
d V  W 5 |s6t j  X d S N)r?   onnxZis_onnx_log_enabledZ
enable_logZdisable_log)rJ   Zis_originally_enabledr-   r-   r.   r       s    


)r/   rJ   c                 c  sd   t | |P}t| <}t|(}t }||||fV  W 5 Q R X W 5 Q R X W 5 Q R X W 5 Q R X d S rK   )r   r   r    r   Z create_export_diagnostic_context)r=   r/   rJ   Zmode_ctxZapex_ctxZlog_ctxZdiagnostic_ctxr-   r-   r.   r!      s&        TFzHUnion[torch.nn.Module, torch.jit.ScriptModule, torch.jit.ScriptFunction]z$Union[Tuple[Any, ...], torch.Tensor]zUnion[str, io.BytesIO]zOptional[Sequence[str]]z_C_onnx.OperatorExportTypeszOptional[int]zMOptional[Union[Mapping[str, Mapping[int, str]], Mapping[str, Sequence[int]]]]zOptional[bool]zOptional[Mapping[str, int]]z.Union[bool, Collection[Type[torch.nn.Module]]]None)r=   argsfexport_paramsrJ   r0   input_namesoutput_namesoperator_export_typeopset_versiondo_constant_foldingdynamic_axeskeep_initializers_as_inputscustom_opsetsexport_modules_as_functionsautograd_inliningr+   c                 C  s,   t | |||||||||	|
|||||d dS )a9  Exports a model into ONNX format.

    If ``model`` is not a :class:`torch.jit.ScriptModule` nor a
    :class:`torch.jit.ScriptFunction`, this runs
    ``model`` once in order to convert it to a TorchScript graph to be exported
    (the equivalent of :func:`torch.jit.trace`). Thus this has the same limited support
    for dynamic control flow as :func:`torch.jit.trace`.

    Args:
        model (:class:`torch.nn.Module`, :class:`torch.jit.ScriptModule` or :class:`torch.jit.ScriptFunction`):
            the model to be exported.
        args (tuple or torch.Tensor):

            args can be structured either as:

            1. ONLY A TUPLE OF ARGUMENTS::

                args = (x, y, z)

            The tuple should contain model inputs such that ``model(*args)`` is a valid
            invocation of the model. Any non-Tensor arguments will be hard-coded into the
            exported model; any Tensor arguments will become inputs of the exported model,
            in the order they occur in the tuple.

            2. A TENSOR::

                args = torch.Tensor([1])

            This is equivalent to a 1-ary tuple of that Tensor.

            3. A TUPLE OF ARGUMENTS ENDING WITH A DICTIONARY OF NAMED ARGUMENTS::

                args = (
                    x,
                    {
                        "y": input_y,
                        "z": input_z
                    }
                )

            All but the last element of the tuple will be passed as non-keyword arguments,
            and named arguments will be set from the last element. If a named argument is
            not present in the dictionary, it is assigned the default value, or None if a
            default value is not provided.

            .. note::
                If a dictionary is the last element of the args tuple, it will be
                interpreted as containing named arguments. In order to pass a dict as the
                last non-keyword arg, provide an empty dict as the last element of the args
                tuple. For example, instead of::

                    torch.onnx.export(
                        model,
                        (
                            x,
                            # WRONG: will be interpreted as named arguments
                            {y: z}
                        ),
                        "test.onnx.pb"
                    )

                Write::

                    torch.onnx.export(
                        model,
                        (
                            x,
                            {y: z},
                            {}
                        ),
                        "test.onnx.pb"
                    )

        f: a file-like object (such that ``f.fileno()`` returns a file descriptor)
            or a string containing a file name.  A binary protocol buffer will be written
            to this file.
        export_params (bool, default True): if True, all parameters will
            be exported. Set this to False if you want to export an untrained model.
            In this case, the exported model will first take all of its parameters
            as arguments, with the ordering as specified by ``model.state_dict().values()``
        verbose (bool, default False): if True, prints a description of the
            model being exported to stdout. In addition, the final ONNX graph will include the
            field ``doc_string``` from the exported model which mentions the source code locations
            for ``model``. If True, ONNX exporter logging will be turned on.
        training (enum, default TrainingMode.EVAL):
            * ``TrainingMode.EVAL``: export the model in inference mode.
            * ``TrainingMode.PRESERVE``: export the model in inference mode if model.training is
                False and in training mode if model.training is True.
            * ``TrainingMode.TRAINING``: export the model in training mode. Disables optimizations
                which might interfere with training.
        input_names (list of str, default empty list): names to assign to the
            input nodes of the graph, in order.
        output_names (list of str, default empty list): names to assign to the
            output nodes of the graph, in order.
        operator_export_type (enum, default OperatorExportTypes.ONNX):

            * ``OperatorExportTypes.ONNX``: Export all ops as regular ONNX ops
                (in the default opset domain).
            * ``OperatorExportTypes.ONNX_FALLTHROUGH``: Try to convert all ops
                to standard ONNX ops in the default opset domain. If unable to do so
                (e.g. because support has not been added to convert a particular torch op to ONNX),
                fall back to exporting the op into a custom opset domain without conversion. Applies
                to `custom ops <https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html>`_
                as well as ATen ops. For the exported model to be usable, the runtime must support
                these non-standard ops.
            * ``OperatorExportTypes.ONNX_ATEN``: All ATen ops (in the TorchScript namespace "aten")
                are exported as ATen ops (in opset domain "org.pytorch.aten").
                `ATen <https://pytorch.org/cppdocs/#aten>`_ is PyTorch's built-in tensor library, so
                this instructs the runtime to use PyTorch's implementation of these ops.

                .. warning::

                    Models exported this way are probably runnable only by Caffe2.

                    This may be useful if the numeric differences in implementations of operators are
                    causing large differences in behavior between PyTorch and Caffe2 (which is more
                    common on untrained models).

            * ``OperatorExportTypes.ONNX_ATEN_FALLBACK``: Try to export each ATen op
                (in the TorchScript namespace "aten") as a regular ONNX op. If we are unable to do so
                (e.g. because support has not been added to convert a particular torch op to ONNX),
                fall back to exporting an ATen op. See documentation on OperatorExportTypes.ONNX_ATEN for
                context.
                For example::

                    graph(%0 : Float):
                    %3 : int = prim::Constant[value=0]()
                    # conversion unsupported
                    %4 : Float = aten::triu(%0, %3)
                    # conversion supported
                    %5 : Float = aten::mul(%4, %0)
                    return (%5)

                Assuming ``aten::triu`` is not supported in ONNX, this will be exported as::

                    graph(%0 : Float):
                    %1 : Long() = onnx::Constant[value={0}]()
                    # not converted
                    %2 : Float = aten::ATen[operator="triu"](%0, %1)
                    # converted
                    %3 : Float = onnx::Mul(%2, %0)
                    return (%3)

                If PyTorch was built with Caffe2 (i.e. with ``BUILD_CAFFE2=1``), then
                Caffe2-specific behavior will be enabled, including special support
                for ops are produced by the modules described in
                `Quantization <https://pytorch.org/docs/stable/quantization.html>`_.

                .. warning::

                    Models exported this way are probably runnable only by Caffe2.

        opset_version (int, default 17): The version of the
            `default (ai.onnx) opset <https://github.com/onnx/onnx/blob/master/docs/Operators.md>`_
            to target. Must be >= 7 and <= 17.
        do_constant_folding (bool, default True): Apply the constant-folding optimization.
            Constant-folding will replace some of the ops that have all constant inputs
            with pre-computed constant nodes.
        dynamic_axes (dict[string, dict[int, string]] or dict[string, list(int)], default empty dict):

            By default the exported model will have the shapes of all input and output tensors
            set to exactly match those given in ``args``. To specify axes of tensors as
            dynamic (i.e. known only at run-time), set ``dynamic_axes`` to a dict with schema:

            * KEY (str): an input or output name. Each name must also be provided in ``input_names`` or
                ``output_names``.
            * VALUE (dict or list): If a dict, keys are axis indices and values are axis names. If a
                list, each element is an axis index.

            For example::

                class SumModule(torch.nn.Module):
                    def forward(self, x):
                        return torch.sum(x, dim=1)

                torch.onnx.export(
                    SumModule(),
                    (torch.ones(2, 2),),
                    "onnx.pb",
                    input_names=["x"],
                    output_names=["sum"]
                )

            Produces::

                input {
                  name: "x"
                  ...
                      shape {
                        dim {
                          dim_value: 2  # axis 0
                        }
                        dim {
                          dim_value: 2  # axis 1
                ...
                output {
                  name: "sum"
                  ...
                      shape {
                        dim {
                          dim_value: 2  # axis 0
                ...

            While::

                torch.onnx.export(
                    SumModule(),
                    (torch.ones(2, 2),),
                    "onnx.pb",
                    input_names=["x"],
                    output_names=["sum"],
                    dynamic_axes={
                        # dict value: manually named axes
                        "x": {0: "my_custom_axis_name"},
                        # list value: automatic names
                        "sum": [0],
                    }
                )

            Produces::

                input {
                  name: "x"
                  ...
                      shape {
                        dim {
                          dim_param: "my_custom_axis_name"  # axis 0
                        }
                        dim {
                          dim_value: 2  # axis 1
                ...
                output {
                  name: "sum"
                  ...
                      shape {
                        dim {
                          dim_param: "sum_dynamic_axes_1"  # axis 0
                ...

        keep_initializers_as_inputs (bool, default None): If True, all the
            initializers (typically corresponding to parameters) in the
            exported graph will also be added as inputs to the graph. If False,
            then initializers are not added as inputs to the graph, and only
            the non-parameter inputs are added as inputs.
            This may allow for better optimizations (e.g. constant folding) by
            backends/runtimes.

            If True, `deduplicate_initializers` pass will not be executed. This means
            initializers with duplicated values will not be deduplicated and
            will be treated as distinct inputs to the graph. This allows different
            input initializers to be supplied at the runtime following export.

            If ``opset_version < 9``, initializers MUST be part of graph
            inputs and this argument will be ignored and the behavior will be
            equivalent to setting this argument to True.

            If None, then the behavior is chosen automatically as follows:

            * If ``operator_export_type=OperatorExportTypes.ONNX``, the behavior is equivalent
                to setting this argument to False.
            * Else, the behavior is equivalent to setting this argument to True.

        custom_opsets (dict[str, int], default empty dict): A dict with schema:

            * KEY (str): opset domain name
            * VALUE (int): opset version

            If a custom opset is referenced by ``model`` but not mentioned in this dictionary,
            the opset version is set to 1. Only custom opset domain name and version should be
            indicated through this argument.

        export_modules_as_functions (bool or set of type of nn.Module, default False): Flag to enable
            exporting all ``nn.Module`` forward calls as local functions in ONNX. Or a set to indicate the
            particular types of modules to export as local functions in ONNX.
            This feature requires ``opset_version`` >= 15, otherwise the export will fail. This is because
            ``opset_version`` < 15 implies IR version < 8, which means no local function support.
            Module variables will be exported as function attributes. There are two categories of function
            attributes.

            1. Annotated attributes: class variables that have type annotations via
            `PEP 526-style <https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations>`_
            will be exported as attributes.
            Annotated attributes are not used inside the subgraph of ONNX local function because
            they are not created by PyTorch JIT tracing, but they may be used by consumers
            to determine whether or not to replace the function with a particular fused kernel.

            2. Inferred attributes: variables that are used by operators inside the module. Attribute names
            will have prefix "inferred::". This is to differentiate from predefined attributes retrieved from
            python module annotations. Inferred attributes are used inside the subgraph of ONNX local function.

            * ``False`` (default): export ``nn.Module`` forward calls as fine grained nodes.
            * ``True``: export all ``nn.Module`` forward calls as local function nodes.
            * Set of type of nn.Module: export ``nn.Module`` forward calls as local function nodes,
                only if the type of the ``nn.Module`` is found in the set.

        autograd_inlining (bool, default True): Flag used to control whether to inline autograd functions.
            Refer to https://github.com/pytorch/pytorch/pull/74765 for more details.

    Raises:
        :class:`torch.onnx.errors.CheckerError`: If the ONNX checker detects an invalid ONNX graph.
        :class:`torch.onnx.errors.UnsupportedOperatorError`: If the ONNX graph cannot be exported because it
            uses an operator that is not supported by the exporter.
        :class:`torch.onnx.errors.OnnxExporterError`: Other errors that can occur during export.
            All errors are subclasses of :class:`errors.OnnxExporterError`.
    )rS   rT   rU   rV   rW   rX   rY   rZ   N)_export)r=   rN   rO   rP   rJ   r0   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r-   r-   r.   r"      s(      Ic                 C  sN   |   dkrdS |   }|tj r0dS |ttj rJdS d S )Nzprim::ConstantFT)	kindoutputr6   ZisSubtypeOfr   ListType	ofTensorsZOptionalTypeZofTensor)nodeoutput_typer-   r-   r.   _is_constant_tensor_list  s    rb   c                 C  s   |  D ]}| D ]}t| | qt|rg }|  D ]4}| |}| | | 	| |
| q<| d|| tj }| 	| | | qd S )Nzprim::ListConstruct)nodesblocks_split_tensor_list_constantsrb   r]   ZtoIValueZinsertConstantr`   Z
moveBeforeZcopyMetadataappendcreateZinsertBeforesetTyper   r^   r_   ZreplaceAllUsesWith)gblockr`   Zsubblockinputsvalinputlcr-   r-   r.   re   '  s$    
re   z_C.Graph)graphrS   _disable_torch_constant_propfixed_batch_sizec           	   
   C  s  |d kri }t |  t |  t |  tjr:t |  t |  |dkrVt |  t	| |  t 
|  t |  t | rt |  t |  t |  t | d t |  t |  t | d t |  t | | t |  t |  t |  t |  t |  tj  t | |t  t r\t | | t tdtd|  t |  tjr|d kr|g n|}|d kri n|}t  | || t |  t !| |} t |  t |  t "| dtj# t |  t $| tj#| t |  t %|  t |  t &| } t |  tjrzt '| |tj# W n< t(k
r~ } zt)j*rn|j+d dkrnW 5 d }~X Y nX | S )NFTz                graph(%Pi):
                    %Pq = quantized::nhwc2nchw(%Pi)
                    %Pr = quantized::nchw2nhwc(%Pq)
                    return (%Pr)z<                graph(%Ri):
                    return (%Ri)r   >ScalarType UNKNOWN_SCALAR is an unexpected tensor scalar type!),r   _jit_pass_inlineZ_jit_pass_inline_fork_waitZ_jit_pass_lintr   rZ   Z(_jit_pass_onnx_autograd_function_processZ_jit_pass_lower_all_tuplesZ_jit_pass_constant_propagationre   Z_jit_pass_dceZ_jit_pass_cse_jit_pass_onnx_lintZ&_jit_pass_canonicalize_graph_fuser_opsZ_jit_pass_peepholeZ_jit_pass_fuse_addmm*_jit_pass_onnx_remove_inplace_ops_for_onnxZ_jit_pass_onnx_preprocessZ#_jit_pass_prepare_division_for_onnxZ_jit_pass_onnx_remove_printZ _jit_pass_onnx_preprocess_caffe2r   Z_quantized_opsclearZ'_jit_pass_onnx_unpack_quantized_weightsis_caffe2_aten_fallbackZ+_jit_pass_onnx_quantization_insert_permutesZ,_jit_pass_custom_pattern_based_rewrite_graphtextwrapdedent_jit_pass_erase_number_typesonnx_shape_inferenceZ&_jit_pass_onnx_set_dynamic_input_shapeZ_jit_pass_onnxZ#_jit_pass_onnx_scalar_type_analysisr8   Z_jit_pass_onnx_peephole4_jit_pass_dce_allow_deleting_nodes_with_side_effectsZ_jit_pass_canonicalize)_jit_pass_onnx_graph_shape_type_inferenceRuntimeErrorr3   _CAFFE2_ATEN_FALLBACKrN   )	ro   rS   rp   rq   params_dictrV   rQ   rF   excr-   r-   r.   _optimize_graph>  s    





















  




  
  




  r   c                 C  sr   t | d | d D ]Z\}}t|trLt| t| krld}t| qt|tr||krd}t| qdS )aY  Warns that changes to input dictionaries and strings won't take effect in the traced ONNX graph.

    We accept dictionaries and strings as ONNX inputs, but they should be only for
    configuration use. we detect here if these inputs are modified, and if so we warn
    the user that the changes won't take effect in the traced ONNX graph.
    r      aQ  We detected that you are modifying a dictionary that is an input to your model. Note that dictionaries are allowed as inputs in ONNX but they should be handled with care. Usages of dictionaries is not recommended, and should not be used except for configuration use. Also note that the order and values of the keys must remain the same. zvThe model seems to have string inputs/outputs. Note that strings will not appear as inputs/outputs of the ONNX graph. N)zipr2   dictlistkeysr9   r:   str)Zinput_statesrm   Ztraced_inputwarningr-   r-   r.   r$     s    
	
c                 C  s8   ||j k	r4tjr4|dkr0td|  d|  d d}|S )zVResolves the arguments that are ignored when export_type != operator_export_type.ONNX.T'zu' can be set to True only when 'operator_export_type' is `ONNX`. Since 'operator_export_type' is not set to 'ONNX', 'z' argument will be ignored.F)ONNXr3   r   r9   r:   )Zarg_name	arg_valuerS   r-   r-   r.   _resolve_args_by_export_type  s    r   int)rW   rS   rT   c                 C  sJ   |dk r| dkrt d dS | dkr*dn| }| dkrF|tjjkrFd}|S )ae  Decides whether the initializers in the graph should be listed as ONNX graph inputs.

    This method encapsulates the logic to decide whether the initializers in the graph
    should be listed as ONNX graph inputs (i.e., whether to choose ONNX IR v3 or v4).
    If keep_initializers_as_inputs is not specified (None), then we decide whether to keep
    initializers as graph inputs (val_keep_init_as_ip) based on export type. If export type
    is ONNX, then do not keep initializers as input (val_keep_init_as_ip=False). For all other
    export types keep initializers as input (val_keep_init_as_ip=True).
    If keep_initializers_as_inputs is specified, then respect it. Unless opset version <= 8,
    in which case it must be ignored because for opset version <= 8, all initializers MUST be
    part of graph input (only ONNX IR v3 is allowed), i.e. val_keep_init_as_ip=True.

    Special handling is needed for opset version 8 or lower, because irrespective
    of user input for keep_initializers_as_inputs, the graph must follow ONNX IR v3
    semantics, i.e. all initializers must be listed as ONNX graph input.
    	   Fa  Setting 'keep_initializers_as_inputs=False' for opset version8 or lower would lead to an invalid ONNX graph. Therefore, 'keep_initializers_as_inputs=False' is ignored during export.Exported model will have initializers as graph inputs (compliant  to ONNX IR v3).TN)r9   r:   r3   OperatorExportTypesr   )rW   rS   rT   val_keep_init_as_ipr-   r-   r.   _decide_keep_init_as_input  s    
r   c                 C  s   t d| |S )Nadd_node_names)r   )r   rS   r-   r-   r.   _decide_add_node_names(  s
      r   c                 C  s2   t d| |} | r.|d k	r.|tjjk	r.td | S )NrU   a  It is recommended that constant folding be turned off ('do_constant_folding=False') when exporting the model in training-amenable mode, i.e. with 'training=TrainingMode.TRAIN' or 'training=TrainingMode.PRESERVE' (when model is in training mode). Otherwise, some learnable model parameters may not translate correctly in the exported ONNX model because constant folding mutates model parameters. Please consider turning off constant folding or setting the training=TrainingMode.EVAL.)r   r3   r4   r<   r9   r:   )rU   rS   r0   r-   r-   r.   _decide_constant_folding/  s      
r   zinspect.Signaturec                 C  s*   t | d| }t|rt|S tdd S )Nforwardz/model has no forward method and is not callable)getattrcallableinspect	signature
ValueError)r=   Zshould_be_callabler-   r-   r.   
_signatureB  s    
r   c           
   
   C  s  zt | }W n: tk
rF } zt| d | W Y S d }~X Y nX zt|j }|d dkrp|dd  }i }t|tr|}nt|trt|}n|g}t|d t	r|d }|d d }t
|}||d  D ]>}||kr|||  q|j| }	|	j|	jkr||	j qt|tr$|nt|}W nX tk
rN   td Y n: tk
r } ztd|jd   W 5 d }~X Y nX |S )Nz, skipping _decide_input_formatr   selfr   z,No input args, skipping _decide_input_formatzSkipping _decide_input_format
 )r   r   r9   r:   r   
parametersr   r2   tupler   lenrf   defaultempty
IndexError	ExceptionrN   )
r=   rN   sigeZordered_list_keysZ	args_dictZ	args_listZn_nonkeywordZoptional_argparamr-   r-   r.   _decide_input_formatJ  s>    



(r   c                 C  sT   t |tjr|f}tjj| |dddd\}}}t| t||i d}|rP||fS |S )NFTstrictZ_force_outplaceZ_return_inputs_states)r   )r2   r?   Tensorr@   _get_trace_graphr$   r   )funcrN   rS   Zreturn_outstrace_graph	torch_outinputs_statesr-   r-   r.   _tracer  s    r   c                 C  st   t j|  }t  }t d t jj| |dddd\}}}t | t| |t j|  krltd||fS )NFTr   zXstate_dict changed after running the tracer; something weird is happening in your model!)	r?   r@   _unique_state_dictr   Zis_autocast_cache_enabledZset_autocast_cache_enabledr   r$   r~   )r=   rN   Zorig_state_dict_keysZprev_autocast_cache_enabledr   r   r   r-   r-   r.   _trace_and_get_graph_from_model  s"    

r   c                 C  s^   g }t |  |D ]F\}}dt| krJtj|\}}|t| q||d k	 q|S )NZPackedParams)	r   rk   r   r6   r?   r@   _flattenrf   r   )method_graphargs_paramsparam_count_listZinput_Zarg_params_in_vars_r-   r-   r.   _get_param_count_list  s    r   c                   sR   t j fdd t | }t|t| }|dks:t|rNtd| ddS )zAtorch.jit._flatten removes None. Check if it did so in this case.c                 3  sZ   t | ttfr(| D ]} |E d H  qn.t | trP|  D ]} |E d H  q:n| V  d S rK   )r2   r   r   r   values)xinnerflattenr-   r.   r     s    
z._check_flatten_did_not_remove.<locals>.flattenr   zargs contained z None's after flattening. When exporting a ScriptModule or ScriptFunction, no args may be None because that breaks type propagation.N)r   beartyper   r   AssertionErrorr   )originalZjit_flattenedZflattened_with_noneZnum_noner-   r   r.   _check_flatten_did_not_remove  s    

r   zSequence[Any]zJTuple[_C.Graph, List[_C.IValue], Optional[Any], Optional[_C.ScriptModule]])r=   rN   r+   c              
   C  s  t | tjjtjjfrLttjt|d }t|| d }t | tjjrz| jj	}W n, t
k
r } ztd|W 5 d }~X Y nX t| tjttj| jdd}t|\}}|dj	}	t|t| }
t|	|
}tj|
\}}t|	t||dd}||||fS g }| j	}t| t||}t|||dd}|||d fS t| |\}}t| tj| }t| }t| }t|t| }t| }t|D ]&\}}||kr||||   qt| |||d fS )Nr   z('forward' method must be a script methodT)ZpreserveParametersr   F)r2   r?   r@   rA   ScriptModuler   r   r   r   ro   AttributeErrorr~   r   Z$_jit_pass_onnx_function_substitutionZ_freeze_moduler   Z_cZ_jit_onnx_list_model_parametersZ_get_methodr   Z"_propagate_and_assign_input_shapesr   rt   r   r   r   rk   r   r   	enumeratesetDebugName)r=   rN   Zflattened_argsr   ro   r   Zfreezed_modulerF   paramsr   r   r   r   r   Z
state_dictZgraph_inputsZuser_input_numparam_namesiZinpr-   r-   r.   _create_jit_graph  sf    

 
    

    


r   c                 C  s<   dd |   D }|t|t| d  }tt||}|S )Nc                 S  s   g | ]}|  qS r-   	debugName).0rl   r-   r-   r.   
<listcomp>  s     z)_get_named_param_dict.<locals>.<listcomp>)rk   r   r   r   )ro   r   Zinput_and_param_namesr   _params_dictr-   r-   r.   _get_named_param_dict  s    r   c                 C  sd   t |}i }|r4t|d tr4|d }|d d }| ||}t|trP|g}nt|ts`|f}|S )Nr   )copydeepcopyr2   r   r   r   )r=   rN   Z
input_argsZinput_kwargsexample_outputsr-   r-   r.   _get_example_outputs	  s    



r   c                 C  s   t | tjr| jtkr|  }|r6tj|  tjdntj|  tj	d}|rbtj| 
 tjdntj| 
 t| j d}|| | }|jt| j d}|||fS | fS d S )N)dtype)r2   r?   r   r   _qtype_vtype_mapZ
dequantizeZtensorq_scaledoubleZfloat32q_zero_pointZint64to)valueZcast_onnx_acceptedZq_value_dequantizer   r   Zq_valuer-   r-   r.   r%   "  s    
c                 C  s@   t dd t| dt D s.t dd |D r<tj| |S | S )zReturns `torch.jit.trace(model, args)` if model is quantized. Otherwise do nothing and return
    original model.

    This is due to https://github.com/pytorch/pytorch/issues/75761.
    c                 s  s   | ]}t |d V  qdS )Z_packed_paramsN)r7   )r   mr-   r-   r.   	<genexpr>>  s    z)_pre_trace_quant_model.<locals>.<genexpr>rB   c                 s  s   | ]}t |d dV  qdS Zis_quantizedFNr   )r   argr-   r-   r.   r   @  s     )anyr   r   r?   r@   trace)r=   rN   r-   r-   r.   _pre_trace_quant_model7  s    r   zTuple[_C.Graph, Dict[str, torch.Tensor], Optional[Union[torch.Tensor, Tuple[torch.Tensor, ...], List[torch.Tensor], Dict[str, torch.Tensor], Any]]]c              
   C  s`  t |tjtttfr|f}t| |} t| |\}}}}t||}zt	||||||
||d}W n2 t
k
r } ztjd|  W 5 d}~X Y nX t | tjjtjjf}|rt| |}d}|D ]}|t|7 }qtj|\}}t|||tj|tj n\t |ttfs|g}n|}tjt|\}}tdd |D sTt|||tj|tj t||| t||}|rtjtjkr|	dks|	tjj krt!||}t"||tj}t#| tjrzt$||tj W n< t%k
r } ztj&r|j'd dkrW 5 d}~X Y nX t(||}tjd	k r8t)| t*|}t+| t,|| |||fS )
a  Converts model into an ONNX graph.

    Returns:
        graph: A TorchScript IR Graph with ONNX nodes.
        params_dict: Dict from input param name to param value.
        torch_out: The output tensors resulting from the trace of ``model``.
            If ``model`` is a :class:`torch.jit.ScriptModule` or :class:`torch.jit.ScriptFunction`,
            this will be None, since we are not doing any tracing.
    )rp   rq   r   rV   rQ   rF   zTorch IR graph at exception: Nr-   c                 s  s   | ]}t |d dV  qdS r   r   )r   outr-   r-   r.   r     s     z"_model_to_graph.<locals>.<genexpr>r   rr   r   )-r2   r?   r   r   floatr*   r   r   r   r   r   rL   logr@   rA   r   r   r%   r   r   Z"_jit_pass_onnx_assign_output_shaper   r{   r8   r   r   r   _set_input_and_output_namesr   ZONNX_CONSTANT_FOLDING_MIN_OPSETr3   r4   r<   Z_jit_pass_onnx_eval_peepholeZ_jit_pass_onnx_constant_foldr|   r}   r~   r   rN   Z%_jit_pass_onnx_eliminate_unused_itemsZ,_jit_pass_onnx_cast_all_constant_to_floatingZ%_jit_pass_filter_non_tensor_argumentsZ#_jit_decay_packed_param_input_types_apply_friendly_debug_names)r=   rN   rJ   rQ   rR   rS   rU   rp   rq   r0   rV   ro   r   r   rF   r   r   Z	is_scriptr   Zexample_outputs_finalZexample_outputZout_varsdescZoutput_wrappedZoutput_tensorsZout_descr   r-   r-   r.   _model_to_graphE  s    &




	
  
  



r   c                 C  s   |
dkrt j}
|dkri }|
t_|t_t| ||r t|||
}t||}t|||}t	| |}t
| ||||||||d	\}}}|||
d||	|||W  5 Q R  S Q R X dS )a  
    Similar to :func:`export`, but returns a text representation of the ONNX
    model. Only differences in args listed below. All other args are the same
    as :func:`export`.

    Args:
        add_node_names (bool, default True): Whether or not to set
            NodeProto.name. This makes no difference unless
            ``google_printer=True``.
        google_printer (bool, default False): If False, will return a custom,
            compact representation of the model. If True will return the
            protobuf's `Message::DebugString()`, which is more verbose.

    Returns:
        A UTF-8 str containing a human-readable representation of the ONNX model.
    N)r0   rV   F)r   ONNX_DEFAULT_OPSETr   r8   rS   r!   r   r   r   r   r   Z_pretty_print_onnx)r=   rN   rP   rJ   r0   rQ   rR   rS   export_typeZgoogle_printerrT   rW   rX   r   rU   rV   r   val_add_node_namesval_do_constant_foldingro   r   r   r-   r-   r.   r&     sV    $     
zTuple[_C.Graph, List[str]])r0   rT   r+   c              
   C  s   |pt j}|t_znt| |ddV t| |}t| |} t| |\}}}}t	| t
|| t| t| W 5 Q R X W n. tk
r } ztd|W 5 d}~X Y nX g }| D ]6}	|	 }
|
drqtj|
d|s||
 q||fS )a  Returns an approximated list of all ops that are yet supported by :mod:`torch.onnx`.

    The list is approximated because some ops may be removed during the conversion
    process and don't need to be converted. Some other ops may have partial support
    that will fail conversion with particular inputs. Please open a Github Issue
    for op support requests.

    Args:
        model: Same as the `model` parameter in :func:`torch.onnx.export`.
        args: Same as the `args` parameter in :func:`torch.onnx.export`.
        training: Same as the `training` parameter in :func:`torch.onnx.export`.
        opset_version: Same as the `opset_version` parameter in :func:`torch.onnx.export`.

    Returns:
        The JIT graph and a list of unconvertible ops in the format of "domain::op".
    FrI   z_Failed to discover unconvertible ops because of errors during the JIT graph generation process.N)zonnx::zprim::r   )r   r   r   r8   r!   r   r   r   r   rs   ru   rz   r|   r   r   OnnxExporterErrorrc   r\   
startswithr   registryis_registered_oprstriprf   )r=   rN   r0   rT   ro   r   rF   r   Zunsupported_opsr`   Z	domain_opr-   r-   r.   r'   $  s8    





 z.Union[torch.nn.Module, torch.jit.ScriptModule]zSet[str])r=   rY   r+   c                   s   fdd}dddddfdd  D }|tjj_t|trZ|rZd	d
 |D }n0t|tr|rdd   fdd
|D }nt }|r|  |S )Nc                    sB   d  fdd}  fdd}  D ]}|| ||  q$d S )NZ_onnx_attrsc                   s   t |  t|  d S rK   )setattr_get_module_attributes)rF   rm   	attr_namer-   r.   )_track_module_attributes_forward_pre_hookq  s    zm_setup_trace_module_map.<locals>.__register_attribute_hook.<locals>._track_module_attributes_forward_pre_hookc                   sJ   t  }|sd S | }i }t|  r:t|  }t|   t || d S rK   )r   Z_get_tracing_statero   r7   r   delattrZ%_jit_pass_onnx_track_scope_attributes)rF   rm   r]   Ztracing_statero   Z
onnx_attrsr   r-   r.   %_track_module_attributes_forward_hookt  s    


zi_setup_trace_module_map.<locals>.__register_attribute_hook.<locals>._track_module_attributes_forward_hook)rB   Zregister_forward_hookZregister_forward_pre_hook)r   r   r   r>   r   r.   __register_attribute_hookn  s    
z:_setup_trace_module_map.<locals>.__register_attribute_hookr   )qualified_namer+   c                 S  sF   |  d}ttt|D ]&\}}| sd||d   S q| S )a  
        Parse qualified variable name and return the unqualified version.

        Pure numeric atoms are considered inadequate, so this function will look past them,
        and start from the first non-numeric atom.

        Example:
            >>> _unqualified_variable_name('__main__.Foo.bar')
            'bar'
            >>> _unqualified_variable_name('__main__.Foo.bar.0')
            'bar.0'
        .N)splitreversedr   r   	isnumericjoin)r   Z
name_atomsr   Zatomr-   r-   r.   _unqualified_variable_name  s
    
z;_setup_trace_module_map.<locals>._unqualified_variable_namec              	     s.   i | ]&\}}|t jt t| |qS r-   )r?   r   Z _jit_onnx_create_full_scope_nametypenamer6   )r   Z_n_m)r  r-   r.   
<dictcomp>  s     z+_setup_trace_module_map.<locals>.<dictcomp>c                 S  s   h | ]}t t|qS r-   )r?   r  r6   )r   rF   r-   r-   r.   	<setcomp>  s     z*_setup_trace_module_map.<locals>.<setcomp>c                 S  s*   t | trt| S tdt| j d S )NznOnly type of the `nn.Module` should be passed in the set for argument `export_modules_as_functions`. Got `%s`.)r2   r6   r?   r  r~   rD   )vr-   r-   r.   _find_typename  s    

z/_setup_trace_module_map.<locals>._find_typenamec                   s   h | ]} |qS r-   r-   )r   r	  )r
  r-   r.   r    s     )Znamed_modulesr?   r@   r   _trace_module_mapr2   r*   set)r=   rY   r   Ztrace_module_mapZmodule_typenamesr-   )r
  r  r=   r.   _setup_trace_module_mapi  s    


r  c                   C  s   d t jj_t  d S rK   )r?   r@   r   r  r   Z"_jit_pass_onnx_clear_scope_recordsr-   r-   r-   r.   _reset_trace_module_map  s    
r  c                   s@   t t t tjj} fdd|D  fdd D S )Nc                   s   g | ]}  |d qS rK   )rE   r   kr   r-   r.   r     s     z*_get_module_attributes.<locals>.<listcomp>c                   s   i | ]}|t  |qS r-   r   r  )rF   r-   r.   r    s      z*_get_module_attributes.<locals>.<dictcomp>)typingget_type_hintsr6   r?   nnModule)rF   Zbase_m_annotationsr-   )r   rF   r.   r     s    r   c           $      C  s  t jdkst|	d krtjj}	tjr4tj	dt
dd t| tjjrJtd|t _|
d kr^tj}
|
tjkrtj	d|
 dtj dtjd	 |r|
d
k rtd|stjrtjj}ntjj}|
t _|t _z"dt _t j}|t _t }t| tjjtjj frt!| |}t"| || t#|||
}t$||}t%|||}t|t&rF|}nd}t'| |}|d krbi }t(|| || t)| |||||||||d
\}}}|	tjjk	}|d kri }t*+| i }|rt*,||t-|. }|dk	rt*/||t0| dd}t*1| |r0|2||
|||| |||||\}} }!}"n(|2i |
|d|| |||||\}} }!}"t34||}|rxtj56d| t37|||	|  |tjjkr|!szt*8| W n0 t9k
r }# zt:|#|#W 5 d }#~#X Y nX W 5 Q R X W 5 t jstdt _|t _t  X |S )NFzCaffe2 ONNX exporter is deprecated in version 2.0 and will be removed in 2.2. Please use PyTorch 2.1 or older for this capability.   )category
stacklevelztorch.nn.DataParallel is not supported by ONNX exporter, please use 'attribute' module to unwrap model from torch.nn.DataParallel. Try torch.onnx.export(model.module, ...)z Exporting to ONNX opset version zT is not supported. by 'torch.onnx.export()'. The highest opset version supported is z. To use a newer opset version, consider 'torch.onnx.dynamo_export()'. Note that dynamo_export() is in preview. Please report errors with dynamo_export() as Github issues to https://github.com/pytorch/pytorch/issues.r     z`export_modules_as_functions` is not supported for `opset_version` < 15.This is because `opset_version` < 15 implies IR version < 8, which means no local function support. T )rq   r0   rV   r0   zExported graph: );r   r,   r   r   ZExportTypesZPROTOBUF_FILEr3   r   r9   r:   FutureWarningr2   r?   r  ZDataParallelr   r{   r   r   Z#ONNX_TORCHSCRIPT_EXPORTER_MAX_OPSETr   ZOnnxExporterWarningr   ONNX_ATEN_FALLBACKr   r8   rS   rZ   r  r  r  r@   r   r  r!   r   r   r   r   r   _validate_dynamic_axesr   r   r|   Z"_jit_pass_onnx_function_extractionr   r   Z'_jit_pass_onnx_deduplicate_initializersr   Z5_jit_pass_onnx_assign_scoped_names_for_node_and_valueZ_export_onnxr   Z_add_onnxscript_fnrL   r   Z_export_fileZ_check_onnx_protor~   ZCheckerError)$r=   rN   rO   rP   rJ   r0   rQ   rR   rS   r   rT   rU   rV   rW   rq   rX   r   r{   rY   rZ   Z_autograd_inlining_previousZ'module_typenames_to_export_as_functionsr   r   r   Zmodel_file_locationro   r   r   Zdefer_weight_exportZnode_attr_to_nameprotoZ
export_mapZval_use_external_data_formatZ
node_namesr   r-   r-   r.   r[     s.   


    






  

,r[   c                 C  sp   |   D ]b}| D ]T}| }|t| kr2q|  d|  }|| ||kr||||< qqd S )Nr   )rc   rk   r   r   uniquer\   r   rE   )ro   r   nr	  Zold_namenew_namer-   r-   r.   r     s    
r   c                   s>   t j fdd}|t  |d |t  |d d S )Nc                   s   |d krd S t |t | kr8td|t ||t | f t }tt|| D ]\}\}}|dkr||kr d}||  || |	 
|    ||	  |	 }|| | |krL|| qLd S )Nz<number of %s names provided (%d) exceeded number of %ss (%d)r]   zonnx::Identity)r   r~   r  r   r   rg   ZinsertAfterr`   ZaddInputr]   rh   r6   Zreturn_nodeZreplaceInputaddr   r   )Z	node_list	name_listZ
descriptorZoutput_node_setr   namer`   Zidentity_nodero   r-   r.   	set_names  s*    


z._set_input_and_output_names.<locals>.set_namesrm   r]   )r   r   r   rk   outputs)ro   rQ   rR   r&  r-   r%  r.   r     s    r   c              
   C  sp   z,t j| |  tjdti d}||f| W S  tk
rj } z |jd  d| df|_ W 5 d}~X Y nX dS )z\
    This trampoline function gets invoked for every symbolic method
    call from C++.
    Nro   rj   Zopsetoriginal_noder   envr   z (occurred when translating ))r   GraphContextrj   r   r8   r   r5   rN   )ri   op_namesymbolic_fnrN   graph_contextr   r-   r-   r.   _run_symbolic_method  s    r0  z_C.Nodez_C.Block)r`   r+   c                 C  s   |   S rK   )ZaddBlockr`   r-   r-   r.   
_add_block  s    r2  rj   c                 C  s   |   S rK   )ZaddInputToBlockr3  r-   r-   r.   _add_input_to_block  s    r4  z_C.Value)rj   r   r+   c                 C  s
   |  |S rK   )ZregisterOutput)rj   r   r-   r-   r.   _add_output_to_block  s    r5  r   )r$  rT   rS   c                 C  sd   t j| |}|tjjk}|tjjk}tj}| ds:dS |rP|sF|r`|s`dS n|s\|r`|s`dS dS )Naten::FT)	r   r   r   r3   r   Z	ONNX_ATENr  r   r   )r$  rT   rS   Zis_exportable_aten_opZis_onnx_aten_exportZis_aten_fallback_exportZis_caffe2_buildr-   r-   r.   _should_aten_fallback  s,    

r7  r   )r.  r+   c                 C  sP   t t| j }|sdS |d j}t| }||kr<dS || }t|t	j
S )z^Checks if the first argument to symbolic_fn is annotated as type `torch.onnx.SymbolicContext`.Fr   )r   r   r   r   r   r$  r  r  
issubclassr   SymbolicContext)r.  r   Zfirst_param_nameZ
type_hintsZ
param_typer-   r-   r.   _need_symbolic_context  s    

r:  c                   s0   t  r,tjdtd dd fdd}|S  S )zPDecorator that provides the symbolic context to the symbolic function if needed.zThe first argument to symbolic functions is deprecated in 1.13 and will be removed in the future. Please annotate treat the first argument (g) as GraphContext and use context information from the object instead.r  zjit_utils.GraphContext)r/  c                   s,   t j| j| j| j| jd} || f||S )N)r   r*  Zcur_nodeZ
onnx_block)r   r9  r   r*  r)  rj   )r/  rN   kwargsZsymbolic_contextr.  r-   r.   wrapper3  s    z*_symbolic_context_handler.<locals>.wrapper)r:  r9   r:   r  )r.  r=  r-   r<  r.   _symbolic_context_handler'  s    	r>  )r   r+   c                 C  s*   |   }|drt rdS t|jS )Nr6  r  )schemar   r   rw   r   Zparse_schemaoverload_name)r   r?  r-   r-   r.   _get_aten_op_overload_name@  s    rA  r   zDict[_C.Value, _C.Value]z7Optional[Union[_C.Value, Sequence[Optional[_C.Value]]]])ro   rj   r`   rk   r*  r+   c              
     sT  t j}  }|dr&|dd }n|}t|\}	}
tj| || t|d}t|||r fdd 	 D } 
 }||d< |j|
f|dt i|S zt r|d	krtd
| |	dkrt rd
}n|	}| d|
 }tj|}|dk	r6||}|dk	r6 fdd 	 D }||f||W S  fdd 	 D }|	dkrv|j|
f||d 
 iW S t|||r| ndW n tk
r   |tjjkrY dS |tjjkr
t s
 fdd 	 D }|j|
f|dt i| Y S  Y n@ tk
rN } z |jd  d|
 df|_ W 5 d}~X Y nX dS )zRuns a symbolic function.

    The function is used in C++ to export the node to ONNX.

    Returns:
        A single or a tuple of Values.
        None when the node gets cloned as is into the new graph.
    r   Nr   r(  c                   s,   i | ]$}|d    |d  t |qS r   r   ZkindOfr   	_node_getr  r1  r-   r.   r  r  s    z*_run_symbolic_function.<locals>.<dictcomp>r'  r@  r   Zcaffe2Z	quantized::c                   s   i | ]}|t  |qS r-   )r   rD  r  r1  r-   r.   r    s     c                   s,   i | ]$}|d    |d  t |qS rB  rC  r  r1  r-   r.   r    s    rL   c                   s,   i | ]$}|d    |d  t |qS rB  rC  r  r1  r-   r.   r    s    r   z 
(Occurred when translating z).) r   r8   r\   endswithr   parse_node_kindr,  r   r7  ZattributeNamesZoutputsSizeZaten_oprA  r   rw   r   Zregister_quantized_opsr   r   Zget_function_groupgetopr   ZUnsupportedOperatorErrorZget_min_supportedr~   r3   r   ZONNX_FALLTHROUGHr  r5   rN   )ro   rj   r`   rk   r*  rS   rT   Z	node_kindZ
ns_op_name	namespacer-  r/  attrsr'  domainZsymbolic_function_nameZsymbolic_function_groupr.  r   r-   r1  r.   _run_symbolic_functionI  s    








 


rM  )symbolic_namec                 C  sN   t d| std|  dt| \}}|dkrJtd|  d| dd S )Nz+^[a-zA-Z0-9-_]+::[a-zA-Z-_]+[a-zA-Z0-9-_]*$zFailed to register operator z. The symbolic name must match the format domain::name, and should start with a letter and contain only alphanumerical charactersrL   z. z domain cannot be modified.)rematchr   r   r   rG  r   )rN  nsr   r-   r-   r.   _verify_custom_op_name  s    
rR  rN  r.  rT   c                 C  s6   |  drd|  } t|  tj| |tgd| dS )aC  Registers a symbolic function for a custom operator.

    When the user registers symbolic for custom/contrib ops,
    it is highly recommended to add shape inference for that operator via setType API,
    otherwise the exported graph may have incorrect shape inference in some extreme cases.
    An example of setType is `test_aten_embedding_2` in `test_operators.py`.

    See "Custom Operators" in the module documentation for an example usage.

    Args:
        symbolic_name (str): The name of the custom operator in "<domain>::<op>"
            format.
        symbolic_fn (Callable): A function that takes in the ONNX graph and
            the input arguments to the current operator, and returns new
            operator nodes to add to the graph.
        opset_version (int): The ONNX opset version in which to register.
    rE  aten)ZdecorateN)r   rR  r   Zcustom_onnx_symbolicr>  rS  r-   r-   r.   r(     s    

rN  rT   c                 C  s.   |  drd|  } t|  tj| | dS )a-  Unregisters ``symbolic_name``.

    See "Custom Operators" in the module documentation for an example usage.

    Args:
        symbolic_name (str): The name of the custom operator in "<domain>::<op>"
            format.
        opset_version (int): The ONNX opset version in which to unregister.
    rE  rT  N)r   rR  r   r   
unregisterrU  r-   r-   r.   r)     s    

c           
   	   C  s8  t | dkrdS t|drj|dks.t |dkrBdd |j D }|dksVt |dkrjdd |j D }t|prg |pxg  }|  D ]\}}||krtd| d t	|t
rtd	|  i }t|D ]Z\}}	t	|	tstd
|	|krtd|	 d| d qt|d t|d  ||	< q|| |< qdS )z=Ensures dynamic axes argument is follows the expected format.r   Nro   c                 S  s   g | ]}|  qS r-   r   )r   r   r-   r-   r.   r     s     z*_validate_dynamic_axes.<locals>.<listcomp>c                 S  s   g | ]}|  qS r-   r   )r   yr-   r-   r.   r     s     zProvided key z2 for dynamic axes is not a valid input/output namezNo names were found for specified dynamic axes of provided input.Automatically generated names will be applied to each dynamic axes of input z3The type of axis index is expected to be an integerzDuplicate dynamic axis index z was provided for input r   Z_dynamic_axes_r   )r   r7   ro   rk   r'  r  rC   r9   r:   r2   r   r   r   r   r   )
rV   r=   rQ   rR   Zvalid_namesrG   r   Z
value_dictr   r   r-   r-   r.   r  	  s:    




r  z Union[torch.nn.Module, Callable])r=   r+   c                 C  s   t t| tjjr| jn| S rK   )r   r   r2   r?   r  r  r   r>   r-   r-   r.   r#   6  s    )FFNNNN)F)T)n__doc__
__future__r   
contextlibr   r   iorO  rx   r  r9   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r?   Ztorch._C._onnxr   Z_onnxr3   Ztorch.jit._traceZtorch.serializationZ
torch.onnxr   r   r   r   r   Ztorch.onnx._globalsr   Ztorch.onnx._internalr   r   r   r   r   __all__r   r   contextmanagerr   r   r   r    r!   r4   r<   r   r   r"   rb   re   r   r$   r   r   r   r   r   r   r   r   r   r   r   r   r   Zquint8Zuint8Zqint8Zint8Zqint32Zint32Zquint4x2r   r%   r   r   Z_disable_dynamor&   r'   r  r  r   r[   r   r   r0  r2  r4  r5  r7  r:  r>  rA  rM  rR  r(   r)   r  r#   r-   r-   r-   r.   <module>   s  <	/ 2  \

       

+


'


3

    
 LDM

 ]

 
v$
,