o
    i es                     @   s  d 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 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddl#m%Z% ddl#m&Z& ddl#m'Z' dd Z(dd Z)dd Z*dd  Z+d!d" Z,d#d$ Z-d%d& Z.G d'd( d(ej/Z0d)d* Z1			d>d+d,Z2d-d. Z3d/d0 Z4d1d2 Z5d3d4 Z6d5d6 Z7d7d8 Z8d9d: Z9d;ej: Z;d<d= Z<dS )?z$Tools for deserializing `Function`s.    N)logging)
trace_type)function_type)saved_object_graph_pb2)def_function)function)function_type_utils)
func_graph)function_def_to_graph)op_def_registry)ops)tensor)	type_spec)	array_ops)custom_gradient)default_gradient)resource_variable_ops)nested_structure_coder)compat)nest)tf_decorator)
tf_inspectc                 C   s   t | tjtjfS N)
isinstancer   Tensorr   BaseResourceVariable)t r   e/var/www/myenv/lib/python3.10/site-packages/tensorflow/python/saved_model/function_deserialization.py
_is_tensor.   s   r   c           	      C   s   | j j}tj||dd}tj|dd}g }t||D ]"\}}t|tjr0|	t
j||jd qt|tjr<|	|j q| || j}t|t
jrLdS |S )a  Calls a restored Function with structured inputs.

  This differs from `function.__call__` in that inputs and outputs are
  structured and that it casts inputs to tensors if needed.

  Note: this does not checks that non-tensor inputs match. That should be
  done before via `_concrete_function_callable_with`.

  Args:
    function: ConcreteFunction to call.
    inputs: Structured inputs compatible with
      `function.graph.structured_input_signature`.

  Returns:
    The structured function output.
  T)expand_composites
dtype_hintN)graphstructured_input_signaturer   flatten_up_toflattenzipr   r   
TensorSpecappendr   convert_to_tensordtyper   VariableSpechandle
_call_flatcaptured_inputs	Operation)	r   inputsexpected_structureflatten_inputsflatten_expectedtensor_inputsargexpectedresultr   r   r   _call_concrete_function5   s$   r9   c              	   C   sr   z,t jdd  tj| |d}tj|j|jdW  d   W S 1 s%w   Y  W dS  t	t
fy8   Y dS w )zDReturns None or TensorSpec obtained if `arg` is converted to tensor.guess_conversionnamer!   )shaper+   N)func_graph_lib	FuncGraph
as_defaultr   r*   r   r(   r=   r+   	TypeError
ValueError)r6   r"   r8   r   r   r   _try_convert_to_tensor_specW   s   (rC   c              	   C   s   | j j}zt||}W n ttfy   Y dS w t|t|D ]Z\}}t|t	j
rU|r4t||jd}t|sAt|t	j
sA dS |j|jkrJ dS |j|jsT dS q!t|tjrd||sc dS q!t|rtt|t|krs dS q!||kr{ dS q!dS )z@Returns whether concrete `function` can be called with `inputs`.Fr!   T)r#   r$   r   r%   rA   rB   r'   r&   r   r   r(   rC   r+   r   r=   is_compatible_withr   TypeSpecid)r   r1   allow_conversionr2   r3   r6   r7   r   r   r    _concrete_function_callable_withb   s:   
rH   c              	   C   s   t | j}| js|jr"|jd dkr"|jstd|jdd }n|j}tj||j|j	|j
|j|j|jd}t | j}tjjjdtjjjdtjjjdi| j}tjj|||d	S )
z@Deserialize a FunctionSpec object from its proto representation.r   selfzECannot deserialize a method function without a named 'self' argument.   N)argsvarargsvarkwdefaults
kwonlyargskwonlydefaultsannotationsTF)fullargspecinput_signaturejit_compile)r   decode_protorR   	is_methodrK   NotImplementedErrorr   FullArgSpecrL   rM   rN   rO   rP   rQ   rS   r   FunctionSpec
JitCompileDEFAULTONOFFgetrT   r   from_fullargspec_and_signature)function_spec_prototypeless_fullargspecrK   rR   rS   rT   r   r   r   '_deserialize_function_spec_as_nonmethod   sH   


rb   c           	      C   s   |du r	d| _ dS tdd |jj D }| j\}}t|dd | D |j	i |\}}t
| jj}tj|j |d}|| _ dS )z@Set the FunctionType of the ConcreteFunction using FunctionSpec.Nc                 S   s"   g | ]}t |j|j|jd qS r   )function_type_lib	Parameterr<   kindoptional).0pr   r   r   
<listcomp>   s    z4set_preinitialized_function_spec.<locals>.<listcomp>c                 S   s   i | ]
\}}t ||qS r   )rc   sanitize_arg_name)rg   kvr   r   r   
<dictcomp>   s    
z4set_preinitialized_function_spec.<locals>.<dictcomp>)return_annotation)_function_typerc   FunctionTyper   
parametersvaluesr$   canonicalize_to_monomorphicitemsdefault_valuesr   
from_valuer#   structured_outputs)	concrete_fnspecunconstrained_type	arg_specskwarg_specsinput_function_type_output_typer   r   r   r    set_preinitialized_function_spec   s0   


r   c                 C   sD   || j  }| j|_| j|_| drt| j}t|| |	  |S )z1Makes a restored bare concrete function callable.function_spec)
concrete_function_nameargument_keywords_arg_keywordsallowed_positional_arguments_num_positional_argsHasFieldrb   r   r   add_to_graph)saved_bare_concrete_functionconcrete_functionsconcrete_functionr   r   r   r   setup_bare_concrete_function   s   

r   c                       s<   e Zd ZdZ fddZedd Zdd Zdd	 Z  Z	S )
RestoredFunctionzhWrapper class for a function that has been restored from saved state.

  See `def_function.Function`.
  c                    s:   t t| j||d|jd || _|j| _|j| _d| _	d S )NF)	autographrT   T)
superr   __init__rT   r   r   ro   ru   _default_values_omit_frequent_tracing_warning)rI   python_functionr<   r   r   	__class__r   r   r      s   

zRestoredFunction.__init__c                 C      dS )NFr   rI   r   r   r   _run_functions_eagerly   s   z'RestoredFunction._run_functions_eagerlyc                 C      | j S r   r   r   r   r   r   _list_all_concrete_functions     z-RestoredFunction._list_all_concrete_functionsc                 C   r   r   r   r   r   r   r   ._list_all_concrete_functions_for_serialization	  r   z?RestoredFunction._list_all_concrete_functions_for_serialization)
__name__
__module____qualname____doc__r   propertyr   r   r   __classcell__r   r   r   r   r      s    
r   c                    sl   t j} fdd}g }jD ]	}| |  q|D ]}t|| qt||j||}tj|||j	dS )aP  Creates a `Function` from a `SavedFunction`.

  Args:
    saved_function: `SavedFunction` proto.
    concrete_functions: map from function name to `ConcreteFunction`. As a side
      effect of this function, the `FunctionSpec` from `saved_function` is added
      to each `ConcreteFunction` in this map.

  Returns:
    A `Function`.
  c                     s   j std| |f}dD ])}j D ]#} | }tdd |jD r&tdt|||r5t||    S qqg }dd }tj D ]\}} | }	|	j\}
}|d	|d	 ||
| qBtd
||  d| dt
j  dtdtd | )zECalls a restored function or raises an error if no matching function.z2Found zero restored functions for caller function.)FTc                 S   s   g | ]}|d u qS r   r   rg   inpr   r   r   ri   8      zErecreate_function.<locals>.restored_function_body.<locals>.<listcomp>zLooks like you are trying to run a loaded non-Keras model that was trained using tf.distribute.experimental.ParameterServerStrategy with variable partitioning, which is not currently supported. Try using Keras to define your model if possible.c                 S   s    d t| ddd | D S )Nz)Positional arguments ({} total):
    * {}z
    * c                 s   s    | ]}t |V  qd S r   )pprintpformatrg   ar   r   r   	<genexpr>G      zgrecreate_function.<locals>.restored_function_body.<locals>._pretty_format_positional.<locals>.<genexpr>)formatlenjoin)
positionalr   r   r   _pretty_format_positionalD  s   zTrecreate_function.<locals>.restored_function_body.<locals>._pretty_format_positionalz'Option {}:
  {}
  Keyword arguments: {}rJ   zUCould not find matching concrete function to call loaded from the SavedModel. Got:
  z
  Keyword arguments: z:

 Expected these arguments to match one of the following z option(s):


   )r   rB   anyr/   rH   r9   	enumerater$   r)   r   r   chrr   )rK   kwargsr1   rG   function_namer   signature_descriptionsr   indexr   r   keywordr   saved_functionr   r   restored_function_body*  sB   

z1recreate_function.<locals>.restored_function_body)decorator_argspec)
rb   r   r   r)   r   r   r   r   make_decoratorrR   )r   r   r   r   concrete_function_objectsr   cfrestored_functionr   r   r   recreate_function  s$   ,
r   c              	   C   s<  t dd | jD }i }i }t rt }nt }|du r&dt }i }i }	i }
| jD ]}|j	rLt
 }t|j	}|j||< ||	|< ||
|j< q/i }| jD ]}t|||||jj< qRi }t| |D ]}t||||	}d}d}|dur||jv r|j| }t|j}t|j}|  tj|||d}W d   n1 sw   Y  t||| || D ]	}|| | qd|jv r|jd= t |j!|j"|j#j$}t%j&j'|||jd}|r||}|| |||< |||j< t(dd |) D r|t  ||
v r|
| }||t|< t*|t+| qf|S )	a  Load a set of functions as concrete functions without captured inputs.

  Functions names are manipulated during load such that they do not overlap
  with previously created ones.

  Gradients are re-registered under new names. Ops that reference the gradients
  are updated to reflect the new registered names.

  Args:
    library: FunctionDefLibrary proto message.
    saved_object_graph: SavedObjectGraph proto message. If not passed in,
      concrete function structured signatures and outputs will not be set.
    load_shared_name_suffix: If specified, used to uniquify shared names.
      Otherwise, a unique name is generated.
    wrapper_function: An object that will be wrapped on newly created functions.

  Returns:
    Map of original function names in the library to instances of
    `ConcreteFunction` without captured inputs.

  Raises:
    ValueError: if functions dependencies have a cycle.
  c                 s   s    | ]}|j jV  qd S r   	signaturer<   rg   fdefr   r   r   r     s    z,load_function_def_library.<locals>.<genexpr>Nz_load_{})r$   rw   _input_shapes)attrsc                 s   s    | ]}|j d kV  qdS )TRTEngineOpN)type)rg   opr   r   r   r     r   ),setr   r   #executing_eagerly_outside_functionsGraphget_default_graphr   uidregistered_gradientsregistered_op_typer   generate_namer   as_bytesgradient_func_list_function_depsr   r<   _sort_function_defs_fix_fdef_in_placer   r   rU   canonicalized_input_signatureoutput_signaturer@   function_def_libr
   _restore_gradient_functionsr   attrrc   from_structured_signaturer$   rw   function_capturescapture_typesfunction_libConcreteFunctionfrom_func_graphr   get_operationsRegisterGradient_gen_gradient_func)librarysaved_object_graphload_shared_name_suffixwrapper_functionlibrary_function_names	functionsrenamed_functionsr#   library_gradient_namesnew_gradient_op_typesgradients_to_registergdefnew_op_typeold_op_typefunction_depsr   loaded_gradients	orig_namer$   rw   protor	   depr   funcgradient_op_typer   r   r   load_function_def_libraryg  s   














r   c                    s    fdd}|S )zWraps a deserialized function.c                    s,   dd   fddt |jjD }| S )Nc                 S   sX   | d ur| S t |\}}| rt |S g }|jd ur&dd | D }t||S )Nc                 S   s   g | ]
}|d u r
dn|qS )NrJ   r   )rg   dr   r   r   ri     s    zS_gen_gradient_func.<locals>.gradient_func.<locals>.none_to_zero.<locals>.<listcomp>)r   shape_and_dtypeis_fully_defined
zeros_likerankas_listr   zeros)xr   r=   r+   dimsr   r   r   none_to_zero  s   

z?_gen_gradient_func.<locals>.gradient_func.<locals>.none_to_zeroc                    s   g | ]	\}} ||qS r   r   )rg   r  r   r  r   r   ri     s    z=_gen_gradient_func.<locals>.gradient_func.<locals>.<listcomp>)r'   r#   r1   )	unused_opresult_gradsr   r  r   r     s
   
z)_gen_gradient_func.<locals>.gradient_funcr   )r   r   r   r
  r   r     s   r   c              	   C   s   |   D ]A}|jdv r|t|jjd jj }| |_	z|
d}W n	 ty-   Y qw ||v rE|| }t|j|_dd |jD |_qdS )z@Populate function op's _gradient_function with default gradient.StatefulPartitionedCallPartitionedCallf_gradient_op_typec                 S   s   g | ]}|j qS r   r;   r   r   r   r   ri   ,  s    z/_restore_gradient_functions.<locals>.<listcomp>N)r   r   r   r   node_defr   r   r<   _get_gradient_function_gradient_functionget_attrrB   r   r1   r   r   )r	   r   r   r   r   r   grad_fnr   r   r   r     s"   

r   c                    s  t t}t dd  | D ]\}}|D ]}|| |  |  d7  < qq fdd| jD }g }|rZ| }|| || D ]}	 |	  d8  <  |	 sW||	 qD|s7t|t| jkrxtt	 
 t	| }
tdd|
 dd	d
 | jD fdd|D S )z5Return a topologic sort of FunctionDefs in a library.c                   S   r   )Nr   r   r   r   r   r   <lambda>2  s    z%_sort_function_defs.<locals>.<lambda>rJ   c                    s$   g | ]} |j j d kr|j jqS )r   r   r   )in_countr   r   ri   8  s
    z'_sort_function_defs.<locals>.<listcomp>z0There is a cyclic dependency between functions. zCould not resolve .c                 S   s   i | ]}|j j|qS r   r   r   r   r   r   rm   K  s    z'_sort_function_defs.<locals>.<dictcomp>c                    s   g | ]} | qS r   r   )rg   r  )reverser   r   ri   L  r   )collectionsdefaultdictlistrt   r)   r   popr   sortedr   keysrB   )r   r   edgesfnamedepsr   readyoutputnodedestfailed_to_resolver   )r  r  r   r   /  s6   




r   c                 C   s$   d| j v r| jdvr| j d jS dS )z$Returns the custom gradient op type.r  r  N)r   r   s)r  r   r   r   _get_gradient_op_typeO  s   

r(  c           	      C   sP  | j |v r|| j  j| _ | j D ]*\}}|ddkr&||jj j|j_q|ddkr;|jjD ]	}||j j|_q1q| j dkr[d| jvsL| jd js[d| jd _|dt	
 7 }t| j }|rtdd	 |jD d
}|rd
}d| jv r| jd jr| jd j}n|jjrt|jj}|st| j}|t| | jd _d
S d
S d
S )z7Replace functions calls and shared names in `node_def`.valuer   r  HashTableV2use_node_name_sharingTz_{}c                 s   s    | ]
}|j d kr|V  qdS )shared_nameNr;   r   r   r   r   r   q  s    zfix_node_def.<locals>.<genexpr>Nr,  )r   r<   r   rt   
WhichOneofr   r  br   r   r   r   r^   nextr'  default_valuer   r   )	r  r   shared_name_suffixr~   
attr_valuefnop_defr   r,  r   r   r   fix_node_defW  s<   



r5  c                 C   s   | j j}d}| jD ]"}t||| t|}|dur+||v r)t|| |jd _q	d}q	|r6t	
d| j j t| j j| j _|S )a  Fixes a FunctionDef proto to be loaded in current context.

  In particular, when loading a function library into an eager context, one
  must rename the functions to avoid conflicts with existent functions.

  Args:
    fdef: FunctionDef proto to fix. It is mutated in-place.
    functions: map from function name to a ConcreteFunction instance.
    shared_name_suffix: A unique string for this load which helps to avoid
      `shared_name` collisions across loads. Two functions from the same load
      using the same `shared_name` still need to share, but functions from
      different loads with the same `shared_name` should not.
    new_gradient_op_types: map from old gradient op type to newly generated op
      type.

  Returns:
    orig_name: original value of fdef.signature.name
  FNr  TznImporting a function (%s) with ops with unsaved custom gradients. Will likely fail if a gradient is requested.)r   r<   r  r5  r(  r   r   r   r'  r   warning_clean_function_name)r   r   r1  r   r   !contains_unsaved_custom_gradientsr  op_typer   r   r   r     s&   
r   c           	      C   s   t  }| jD ]M}t|}|j|v r||j q|r&||v r&|||  q|j D ]'\}}|ddkr>||jj	 q+|ddkrR|j
jD ]}||j	 qIq+q|S )z$Find functions referenced in `fdef`.r)  r   r  )r   r  r(  r   addr   rt   r-  r   r<   r  )	r   r   r   r!  r  grad_op_typer~   r2  r3  r   r   r   r     s    

r   z^%s(.*)_\d+$c                 C   s   t t| }|r|dS | S )z:Vanity function to keep the function names comprehensible.rJ   )research_FUNCTION_WRAPPER_NAME_REGEXgroup)r<   matchr   r   r   r7    s   
r7  )NNN)=r   r  r   r<  abslr   tensorflow.core.functionr   %tensorflow.core.function.polymorphismr   rc   tensorflow.core.protobufr   tensorflow.python.eagerr   r   r   ,tensorflow.python.eager.polymorphic_functionr   tensorflow.python.frameworkr	   r>   r
   r   r   r   r   r   tensorflow.python.opsr   r   r   r   tensorflow.python.saved_modelr   tensorflow.python.utilr   r   r   r   r   r9   rC   rH   rb   r   r   Functionr   r   r   r   r   r   r(  r5  r   r   _INFERENCE_PREFIXr>  r7  r   r   r   r   <module>   sb   "*&*[
 ! ()
