o
    Xi2X                     @  sD  U d dl m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 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mZ d dlmZmZmZmZ d dl m!Z! ee	ej" ed f Z#d	e$d< ee	d
 ed f Z%d	e$d< ee	d
 ed ej"e&e'e(e)f Z*d	e$d< edZ+dOddZ,dPddZ-dQddZ.eG dd de
Z/G dd de/ej0Z1G dd  d e2Z3d!d" Z4dRd(d)Z5d*d+ Z6dSd.d/Z7dTd2d3Z8dTd4d5Z9dUd9d:Z:G d;d< d<e1Z;G d=d> d>e1Z<e; Z=G d?d@ d@e;Z>e> Z?e?j@ejAdAdVdCdDZBe=aCde$dE< dWdFdGZDdXdJdKZEejFdYdMdNZGdS )Z    )annotationsN)	AnyCallableMappingOptionalProtocolSequenceTypeVarUnionruntime_checkable)	TypeAlias)
onnx_opsettensor)autocastparam_manipulationutilsvalues)_schemasUserModeValuer   ztensor.TensorEagerModeValueExtendedModeValue_Tinputsreturntuple[EagerModeValue, bool]c                   s$   dd	 fdd  | }|fS )
a  Adapts inputs into representation used by onnxscript eager mode.

    This does the following transformations:
    * It adds an onnxscript Tensor wrapper around numpy arrays, which
    allows the use of overloaded operators like + to be controlled by onnxscript.
    * It also provides a promotion of scalars into tensors as a convenience.
    This is needed to complement the similar promotion supported by the
    onnxscript converter (for example, when an attribute is promoted and used
    as an input argument).

    Args:
        inputs: a list/tuple of inputs to an ONNX function

    Returns:
        a pair (wrapped_inputs, flag) where flag indicates whether any numpy array
        was wrapped into a Tensor.
    Finputr   r   r   c                   s   t | tjrdt| S t | tjr| S t | ttfr$tt| S t | tr4ttj| tj	dS | d u r:d S t | t
rH fdd| D S t | trXt fdd| D S tdt|  d)	NTdtypec                   s   g | ]} |qS  r   .0eltadaptr   R/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/_internal/evaluator.py
<listcomp>R       z7_adapt_to_eager_mode.<locals>.adapt.<locals>.<listcomp>c                 3  s    | ]} |V  qd S Nr   r   r"   r   r$   	<genexpr>T       z6_adapt_to_eager_mode.<locals>.adapt.<locals>.<genexpr>zUnexpected input type .)
isinstancenpndarrayr   Tensorboolfloatarrayintint64listtuple	TypeErrortyper   r#   	has_arrayr   r$   r#   D   s    



z#_adapt_to_eager_mode.<locals>.adaptN)r   r   r   r   r   )r   resultr   r9   r$   _adapt_to_eager_mode0   s   r<   outputc                 C  sv   t | tjr	| jS | du rdS t | trdd | D S t | tr)tdd | D S t | tjr1| S tdt	|  d)zUnwraps Tensor wrapper around numpy arrays.

    Args:
        output: output of an ONNX function, which can be either a single
            onnx value or a list/tuple of onnx values.

    Returns:
        unwrapped output
    Nc                 S     g | ]}t |qS r   _adapt_to_user_moder   r   r   r$   r%   j   r&   z'_adapt_to_user_mode.<locals>.<listcomp>c                 s  s    | ]}t |V  qd S r'   r?   r   r   r   r$   r(   l   r)   z&_adapt_to_user_mode.<locals>.<genexpr>zUnexpected type r*   )
r+   r   r.   valuer4   r5   r,   r-   r6   r7   r=   r   r   r$   r@   [   s   


r@   kwargsMapping[str, Any]dict[str, Any]c                 C  s8   i }|   D ]\}}|||< t|tjr|j||< q|S )z,Unwrap tensors in a mapping to numpy arrays.)itemsr+   r   r.   rA   )rC   
new_kwargskvr   r   r$   _unwrap_tensors_in_kwargsr   s   
rJ   c                   @  s$   e Zd ZdZddd	ZdddZdS )	EvaluatorzProtocol for evaluating ONNX ops.

    NOTE: The ``eval`` method was deprecated and removed. Implement ``eval_op``
    and ``eval_function`` instead.
    op	values.OpargsSequence[ExtendedModeValue]rC   Mapping[str, ExtendedModeValue]c                 C     dS )zEvaluates an Op.

        Args:
            op: The Op to evaluate.
            args: The positional arguments to the op.
            kwargs: The keyword arguments to the op.
        Nr   )selfrL   rN   rC   r   r   r$   eval_op       zEvaluator.eval_opfunctionvalues.OnnxFunctionc                 C  rQ   )zEvaluates an OnnxFunction.

        Args:
            function: The OnnxFunction to evaluate.
            args: The positional arguments to the function.
            kwargs: The keyword arguments to the function.
        Nr   )rR   rU   rN   rC   r   r   r$   eval_function   rT   zEvaluator.eval_functionNrL   rM   rN   rO   rC   rP   rU   rV   rN   rO   rC   rP   )__name__
__module____qualname____doc__rS   rW   r   r   r   r$   rK   }   s    
rK   c                   @  sh   e Zd ZdZd*d+ddZd,ddZd-ddZd.ddZd/ddZe	j
d0ddZd1d#d$Zd2d'd(Zd)S )3BaseEvaluatorao  Base class for evaluation of ONNX ops.

    The execution of onnxscript functions in eager-mode is dispatched to an Evaluator
    instance (or, more precisely, to the eval method of the Evaluator instance).
    The evaluator is expected to transform the input/output/attribute representation
    supported by onnxscript to those expected by a particular backend.
    Fignore_unknown_function_kwargsr/   c                 C  s
   || _ dS )a  Initializes a BaseEvaluator.

        Args:
            ignore_unknown_function_kwargs: Whether to ignore unknown keyword arguments
                when evaluating an OnnxFunction. This is useful when using the
                evaluator to validate operators programmatically, where
                additional keyword arguments that is not part of the signature
                may be provided to the function.
        N)_ignore_unknown_function_kwargs)rR   r_   r   r   r$   __init__   s   

zBaseEvaluator.__init__op_signature_schemas.OpSignaturer   rO   c                 C  s   t ||S )zTransform inputs to the expected format for the evaluator.

        Enables some syntactic sugar, such as the use of Python scalars,
        in a manner consistent with the translator. See autocast.py for details.
        )r   dynamic_cast_inputs)rR   rb   r   r   r   r$   _adapt_inputs   s   zBaseEvaluator._adapt_inputs
attributesrP   r   Atuple[dict[str, ExtendedModeValue], dict[str, ExtendedModeValue]]c           
      C  s   |  |}i }i }| D ]>\}}t|tjr:|r4|j ||< |jjD ]\}}	|jj	| ||	j
j< q$q|j||< qt|rGtd|j d|||< q||fS )zTransform attributes to the expected format for the evaluator.

        Returns:
            A closure that can be used to evaluate graph-valued attributes.
        z!Error: function-valued attribute zH has no graph_protoattribute. Did you forget to decorate it with @graph?)use_graph_attributerF   r+   r   OnnxClosurefunction_irto_graph_protoouter_scope_variablesframef_localsrA   namerU   callabler6   rZ   )
rR   rb   rf   rh   closureadapted_attributesrH   rI   pyvaronnxvarr   r   r$   _adapt_attributes   s"   

zBaseEvaluator._adapt_attributesoutputsSequence[EagerModeValue]c                 C  s   t |dkr
|d S |S )zAdapt evaluator's output to convention used in onnxscript.

        Onnxscript uses a tuple/sequence only when number of outputs > 1.
           r   )len)rR   rv   r   r   r$   _adapt_outputs   s   zBaseEvaluator._adapt_outputsc                 C  s   ~dS )NTr   rR   rb   r   r   r$   rh      s   z!BaseEvaluator.use_graph_attributeschemaonnx.defs.OpSchemarq   r   c                 C  rQ   )aA  Evaluates an ONNX op given its schema and inputs/attributes.

        Args:
            schema: The schema of the op to evaluate.
            inputs: The ONNX inputs to the op.
            attributes: The ONNX attributes to the op.
            closure: The closure to use when evaluating graph-valued attributes.
        Nr   rR   r|   r   rf   rq   r   r   r$   _eval   rT   zBaseEvaluator._evalrL   rM   rN   rC   c           	      C  s`   |j }|d usJ d|j dt|}| ||\}}| ||}| |j|||}| |S )NzOp  has no signature.)rb   ro   rJ   ru   re   r   	op_schemarz   )	rR   rL   rN   rC   rb   rf   rq   r   rv   r   r   r$   rS      s   
zBaseEvaluator.eval_oprU   rV   c                 C  s   |j }|du rtd|j dtj|||d| jd\}}g }i }d}	|D ]\}
}t|tjr?t	|
\}}|	p8|}	|
| q%|
|
 q%| D ]\}\}
}t|tjrdt	|
\}}|	p^|}	|||< qI|
||< qI|j|i |}|	rwt|S |S )a8  Evaluates a function in eager mode.

        Override this function to change the evaluator's behavior for functions.

        Args:
            function: The OnnxFunction to evaluate.
            args: The positional arguments to the function.
            kwargs: The keyword arguments to the function.
        Nz	Function r   F)fill_defaultsallow_extra_kwargs)rb   RuntimeErrorro   r   tag_arguments_with_signaturer`   r+   r   	Parameterr<   appendrF   rU   r@   )rR   rU   rN   rC   rb   tagged_argstagged_kwargsadapted_argsadapted_kwargsr:   argparamadapted_arg
has_array_keyr;   r   r   r$   rW     s6   


	zBaseEvaluator.eval_functionN)F)r_   r/   )rb   rc   r   rO   )rf   rP   r   rg   )rv   rw   rb   rc   r   r/   )
r|   r}   r   rO   rf   rP   rq   rP   r   r   rX   rY   )rZ   r[   r\   r]   ra   re   ru   rz   rh   abcabstractmethodr   rS   rW   r   r   r   r$   r^      s    





r^   c                   @  s   e Zd ZdS )EagerModeErrorN)rZ   r[   r\   r   r   r   r$   r   E  s    r   c                 C  s   |d u rdS |  | S )N r   )prefixir   r   r   r$   
_rename_ioI  s   r   r|   r}   rN   Sequence[Any]r2   c                 C  s   | j dkrZ| jdkr|ddsdS | jdkrdS | jdkr<t|dkr,d	|vr,td
t|dkr8t|d S |d	 S | jdkrJ|d }t|jS | jdkrZ|d }t|jd S t| jS )z'Returns the number of outputs expected.r   BatchNormalizationtraining_moder   rx   LSTM   Splitnum_outputszcOperator Split: the number of expected outputs defines the split. This information is unknown here.   ScanbodyLoop)domainro   getry   r   r=   rv   )r|   rN   rC   	scan_body	loop_bodyr   r   r$   compute_num_outputsO  s*   







r   c                 C  s   t | tjr	| jS t | trdd | D S t | tr5t| dkr0t| d tu r0t	j
| t	jdS t	
| S | du r;| S t | t	jrC| S tdt|  d)zZConverts an onnxscript encoding of an ONNX value into the numpy encoding used by runtimes.c                 S  r>   r   _onnxscript_to_numpy_valuer    xr   r   r$   r%   s  r&   z._onnxscript_to_numpy_value.<locals>.<listcomp>r   r   Nz"Unexpected onnxscript value type 'zV'.Valid value types are 'Tensor | list[Tensor] | None | np.ndarray | list[np.ndarray]')r+   r   r.   rA   r4   r5   ry   r7   r2   r,   r1   r3   r-   r6   rI   r   r   r$   r   n  s   


r   rI   =np.ndarray | np.generic | list[np.ndarray] | list[np.generic]c                 C  sv   t | tjrt|  S tt| tjrtt	| S t | t
r)dd | D S | du r1tdtdt|  d)zOConverts an ORT encoding of an ONNX value into the encoding used by onnxscript.c                 S  r>   r   _numpy_to_onnxscript_valuer   r   r   r$   r%     r&   z._numpy_to_onnxscript_value.<locals>.<listcomp>Nz*Dynamic optional values not yet supported.zUnexpected runtime value type 'zR'.Valid types are: 'np.ndarray | np.generic | list[np.ndarray] | list[np.generic]')r+   r,   r-   r   r.   copy
issubclassr7   genericr1   r4   r6   r   r   r   r$   r     s   
r   implicit_argsOptional[Mapping[str, Any]]c                   sH  |pi }dd |D }dd |  D }dfdd dd t|D }t||}dd t|D }tjjj||jd}|j	
 fdd|  D  tt||}t|  }	dd |D }
tj|gd||	 |
}tjjj}tjj||gtjjjdd}tj|}dd t||D }|| |||fS )Nc                 S  r>   r   r   r   r   r   r$   r%     r&   z7_prepare_model_and_inputs_for_eager.<locals>.<listcomp>c                 S     i | ]	\}}|t |qS r   r   r    rH   rI   r   r   r$   
<dictcomp>      z7_prepare_model_and_inputs_for_eager.<locals>.<dictcomp>r   strrA   r   r   onnx.AttributeProtoc              
     s0   d fdd}t t ||tj  jS )Nr   r   c                     s
   d  S )Nattr_r   r   r   r   r$   make_tensor_name  s   
zP_prepare_model_and_inputs_for_eager.<locals>.make_attr.<locals>.make_tensor_name)r   r   )irto_protor   pyvalue_to_onnx_attributer2   rf   r7   )r   rA   r   )r|   r   r$   	make_attr  s   z6_prepare_model_and_inputs_for_eager.<locals>.make_attrc                 S  s   g | ]
\}}t d ||qS r8   )r   )r    r   r   r   r   r$   r%     s    c                 S  s   g | ]}d | qS rB   r   r    r   r   r   r$   r%         )r   c                 3  s&    | ]\}}|d ur ||V  qd S r'   r   )r    r   rA   )r   r   r$   r(     s    z6_prepare_model_and_inputs_for_eager.<locals>.<genexpr>c                 S  s   g | ]}t j|t  qS r   )onnxhelpermake_value_info	TypeProto)r    ro   r   r   r$   r%     s    
node_graph)opset_imports
ir_versionc                 S  s   i | ]\}}|d kr||qS )r   r   )r    ro   r   r   r   r$   r     s    )r   r   rA   r   r   r   )rF   	enumerater   ranger   r   	make_nodero   r   	attributeextendr   values_to_value_infoszip
make_graphmake_opsetidsince_version
make_modelr   select_ir_versionshape_inferenceinfer_shapesupdate)r|   rN   rC   r   r   r   rv   nodeinput_value_infosimplicit_value_infosoutput_value_infosgraphopset_idmodelsession_run_inputr   )r   r|   r$   #_prepare_model_and_inputs_for_eager  s:   

r   c                 C  s*  dd l }ddlm}m}m} t| |||\}}	}
z|j| dd}W n# |||fyF } ztd| j	 d| j
 dtj| |d }~ww z|d |	}W n> t|fy } z0td| j
d	|d
tdd t|
|D  dtdd |	 D  dt|	 d| |d }~ww dd |D S )Nr   )FailInvalidArgumentInvalidGraph)CPUExecutionProvider)	providersz<Unable to create onnxruntime InferenceSession for executing r*   z op with onnx model
!Unable to execute model operator  due to 
input types:
c                 S  r   r   r7   r   r   r   r$   r     r   z_call_ort.<locals>.<dictcomp>
modified input types:
c                 S  r   r   r   r   r   r   r$   r     r   	
inputs:

c                 S  r>   r   r   r   r   r   r$   r%     r&   z_call_ort.<locals>.<listcomp>)onnxruntime+onnxruntime.capi.onnxruntime_pybind11_stater   r   r   r   InferenceSessionSerializeToStringr   r   ro   r   printerto_textrunr   pprintpformatr   rF   )r|   rN   rC   r   ortr   r   r   r   r   r   sessioner;   r   r   r$   	_call_ort  sT   


r   op_schema_or_signature)onnx.defs.OpSchema | _schemas.OpSignaturetuple[str, str, int]c                 C  s   | j | j| jfS r'   )ro   r   r   )r   r   r   r$   _op_identifier  s   r   c                   @     e Zd ZdZdd ZdS )ORTEvaluator&Evaluates ONNX ops using ONNX Runtime.c                 C  s   t ||||S r'   )r   r~   r   r   r$   r        zORTEvaluator._evalNrZ   r[   r\   r]   r   r   r   r   r$   r        r  c                   @  r  )OnnxReferenceRuntimeEvaluatorr  c                 C  s   t ||||\}}}tj|}z|d |}	W n< tyT }
 z0td|jd|
dt	dd t
||D  dt	dd | D  dt	| d	| |
d }
~
ww d
d |	D S )Nr   r   r   c                 S  r   r   r   r   r   r   r$   r      r   z7OnnxReferenceRuntimeEvaluator._eval.<locals>.<dictcomp>r   c                 S  r   r   r   r   r   r   r$   r   "  r   r   r   c                 S  r>   r   r   r   r   r   r$   r%   &  r&   z7OnnxReferenceRuntimeEvaluator._eval.<locals>.<listcomp>)r   r   	referenceReferenceEvaluatorr   r   r   ro   r   r   r   rF   )rR   r|   r   rf   rq   r   r   adapted_inputsr   r;   r   r   r   r$   r     s.   

z#OnnxReferenceRuntimeEvaluator._evalNr  r   r   r   r$   r    r  r  c                      sB   e Zd ZdZd fddZdd	d
Z fddZdddZ  ZS )ORTMixedEvaluatorzEvaluates ONNX ops using ONNX Runtime, unless an overriding python implementation is registered.

    This is useful for higher-order ops such as Scan and SequenceMap, allowing for
    python-based debugging.
    r   Nonec                   s   t    i | _d S r'   )superra   _python_ops)rR   	__class__r   r$   ra   3  s   

zORTMixedEvaluator.__init__rb   rc   r/   c                 C  s   t || jvS r'   )r   r  r{   r   r   r$   rh   7  r  z%ORTMixedEvaluator.use_graph_attributec                   s4   t |}|| jv r| j| ||S t ||||S r'   )r   r  r  r   )rR   r|   r   rf   rq   
identifierr  r   r$   r   :  s   
zORTMixedEvaluator._evalopsetvalues.OpsetCallable[[_T], _T]c                   s     d usJ d fdd}|S )NrU   r   r   c                   s    | j  j}| jt|< | S r'   )rZ   rb   r  r   )rU   rb   r  rR   r   r$   	decoratorD  s   z-ORTMixedEvaluator.register.<locals>.decorator)rU   r   r   r   r   )rR   r  r  r   r  r$   registerA  s   zORTMixedEvaluator.register)r   r  r   )r  r  r   r  )	rZ   r[   r\   r]   ra   rh   r   r  __classcell__r   r   r  r$   r  ,  s    
r  )r  rf   c                   sB   |d  fddfdd fddt td D S )	zEvaluates a SequenceMap op.r   c                   s    |  }t |tr|| S |S r'   )r+   r4   )input_indexiter_numr   )r   r   r$   get_input_ofT  s   
z!SequenceMap.<locals>.get_input_ofc                   s    fddt tD S )Nc                   s   g | ]} |qS r   r   )r    r  )r  r  r   r$   r%   [  r   z2SequenceMap.<locals>.get_input.<locals>.<listcomp>r   ry   r  )r  r   r  r$   	get_inputZ  s   zSequenceMap.<locals>.get_inputc                   s   g | ]} | qS r   r   r   )funr  r   r$   r%   ]  s    zSequenceMap.<locals>.<listcomp>r   r  )r   rf   r   )r  r  r  r   r$   SequenceMapO  s    r   _default_evaluatorc                   C  s   t S )z&Returns the default Evaluator default.r!  r   r   r   r$   defaulte  s   r#  new_defaultr  c                 C  s   | a dS )z#Sets the current Evaluator default.Nr"  )r$  r   r   r$   set_defaultj  s   r%  temp_defaultc                 c  s.    t }t|  z
dV  W t| dS t| w )z@Context manager that temporarily switches the default evaluator.N)r!  r%  )r&  old_defaultr   r   r$   
default_asp  s   r(  )r   r   r   r   )r=   r   r   r   )rC   rD   r   rE   )r|   r}   rN   r   rC   rD   r   r2   )rI   r   )r|   r}   rN   r   rC   rD   r   r   )r   r   r   r   )r   r   rf   rD   )r   rK   )r$  rK   r   r  )r&  rK   )H
__future__r   r   
contextlibr   typingr   r   r   r   r   r   r	   r
   r   numpyr,   r   	onnx.defsonnx.referenceonnx_irr   typing_extensionsr   
onnxscriptr   r   onnxscript._internalr   r   r   r   onnxscript.irr   r-   r   __annotations__r   r2   r0   r/   r   r   r   r<   r@   rJ   rK   ABCr^   r   r   r   r   r   r   r   r   r   r  r  ort_evaluatorr  ort_mixed_evaluatorr  opset18r   r!  r#  r%  contextmanagerr(  r   r   r   r$   <module>   sl   ,


+
$ $



9
.
 

