
    6bi5                         S r SSKrSSKrSSKJs  Jr  SSKJr	  SSKJ
r
  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  S rSS jrS rSS jrSS jrS rSS jr S r!S r"S r#S r$S r%S r&g)z$Utils related to keras model saving.    N)backend)losses)
optimizers)base_layer_utils)optimizer_v1)serialization)version_utils)ask_to_proceed_with_overwrite)
tf_loggingc                     [        U SS5      (       a'  U R                   Vs0 s H  oR                  U_M     sn$ gs  snf )a:  Convert metrics from a TF-Keras model `compile` API to dictionary.

This is used for converting TF-Keras models to Estimators and SavedModels.

Args:
  model: A `tf.keras.Model` object.

Returns:
  Dictionary mapping metric names to metric instances. May return `None` if
  the model does not contain any metrics.
_compile_metricsN)getattr_compile_metric_functionsname)modelms     a/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/saving/legacy/saving_utils.pyextract_model_metricsr   $   sB     u($// $)#B#BC#Ba	#BCC Ds   ;c                 L    U R                  U(       + S9nUc  g[        U5      nU$ )a3  Inspect model to get its input signature.

The model's input signature is a list with a single (possibly-nested)
object. This is due to the Keras-enforced restriction that tensor inputs
must be passed in as the first argument.

For example, a model with input {'feature1': <Tensor>, 'feature2': <Tensor>}
will have input signature:
[{'feature1': TensorSpec, 'feature2': TensorSpec}]

Args:
  model: TF-Keras Model object.
  keep_original_batch_size: A boolean indicating whether we want to keep
    using the original batch size or set it to None. Default is `False`,
    which means that the batch dim of the returned input signature will
    always be set to `None`.

Returns:
  A tuple containing `(args, kwargs)` TensorSpecs of the model call function
  inputs.
  `kwargs` does not contain the `training` argument.
)dynamic_batch)NN)	save_spec_enforce_names_consistency)r   keep_original_batch_sizeinput_specss      r   model_call_inputsr   8   s1    . //4L0L/MK,[9K    c                     [        U [        R                  R                  5      (       a  [	        SU  S35      e[	        SU  S35      e)NzModel z cannot be saved because the input shape is not available. Please specify an input shape either by calling `build(input_shape)` directly, or by calling the model on actual data using `Model()`, `Model.fit()`, or `Model.predict()`.a   cannot be saved either because the input shape is not available or because the forward pass of the model is not defined.To define a forward pass, please override `Model.call()`. To specify an input shape, either call `build(input_shape)` directly, or call the model on actual data using `Model()`, `Model.fit()`, or `Model.predict()`. If you have a custom training step, please make sure to invoke the forward pass in train step through `Model.__call__`, i.e. `model(inputs)`, as opposed to `model.call()`.)
isinstancekerasmodels
Sequential
ValueErrorr   s    r   raise_model_input_errorr$   V   s[    %0011UG I I
 	
 
 P 	P	 	r   c                 T  ^  UcS  [        T R                  [        R                  R                  R
                  5      (       a  T R                  R                  nU(       a  Un0 nO[        T 5      u  p#Uc  [        T 5        [        R                  U 4S j5       nUR                  " U0 UD6$ )a{  Trace the model call to create a tf.function for exporting a TF-Keras
model.

Args:
  model: A TF-Keras model.
  input_signature: optional, a list of tf.TensorSpec objects specifying the
    inputs to the model.

Returns:
  A tf.function wrapping the model's call function with input signatures
  set.

Raises:
  ValueError: if input signature cannot be inferred from the model.
c                    > TR                   R                  SSXSS9u  p[        R                  " 5       R	                  TSSSSS9   T" U 0 UD6nSSS5        TR
                  nUc  SSKJn  UR                  W5      n[        R                  R                  W5      n[        X25       VVs0 s H  u  pVXV_M	     snn$ ! , (       d  f       Ns= fs  snnf )	z<A concrete tf.function that wraps the model's call function.trainingFT)inputs_in_argsN)inputsbuild_graphr'   savingr   )compile_utils)
_call_specset_arg_valuer   call_contextenteroutput_namestf_keras.src.enginer,   create_pseudo_output_namestfnestflattenzip)argskwargsoutputsr1   r,   r   outputr   s          r   _wrapped_model(trace_model_call.<locals>._wrapped_model   s      **88tD 9 
 **,22$EE$ 3 
 T,V,G
 ))9(CCGLL''//'*14\1KL1K1KLL
 
 Ms   	B<*C<
C
)
r   callr4   __internal__functionFunctioninput_signaturer   r$   get_concrete_function)r   rB   
model_argsmodel_kwargsr<   s   `    r   trace_model_callrF   m   s      ejj"//":":"C"CDD#jj88O$
#4U#; 
#E*[[M M( //L|LLr   c                 F   SSK Jn  SSKJn  SU R                  R
                  0n U R                  5       US'   [        [        U5      [        R                  " 5       US9nU R                  (       Ga  U(       Ga  [        U R                  [        R                  5      (       a  [        R                   " S5        U$ U R"                  (       a  U R%                  S	S
9nUR'                  SS5        [)        U5      US'   [        U R                  UR*                  5      (       a  [        S5      e[,        R.                  R1                  U R                  R                  5      U R                  R                  5       S.n	XS   S'   U$ ! [         a  nU(       a  Ue SnAGNbSnAff = f)z3Returns a dictionary containing the model metadata.r   )__version__)optimizer_v2
class_nameconfigN)keras_versionr   model_configa?  TensorFlow optimizers do not make it possible to access optimizer attributes or optimizer state after instantiation. As a result, we cannot save the optimizer as part of the model save file. You will have to compile your model again after loading it. Prefer using a TF-Keras optimizer instead (see keras.io/optimizers).F)user_metrics	optimizertraining_configzOptimizers loaded from a SavedModel cannot be saved. If you are calling `model.save` or `tf.keras.models.save_model`, please set the `include_optimizer` option to `False`. For `tf.saved_model.save`, delete the optimizer from the model.)rJ   rK   optimizer_config)tf_keras.srcrH   tf_keras.src.optimizers.legacyrI   	__class____name__
get_configNotImplementedErrordictstrr   rO   r   r   TFOptimizerloggingwarning_compile_was_called_get_compile_argspop_serialize_nested_configRestoredOptimizerr   utilsget_registered_name)
r   include_optimizerrequire_configrL   rI   rM   emetadatarP   rQ   s
             r   model_metadatarh      sq   9; %//":":;L!&!1!1!3X
 -(!!H
 ,eoo|'?'?@@OO-
D O/ &&#5555IOT2*B+H&' %//<+I+IJJ);  #(++"A"A11# $oo88:	$  ?O&'(:;O[  G s   F 
F 	FF c                 p    U(       d/  [         R                  R                  U 5      (       a  [        U 5      $ g)z3Returns whether the filepath should be overwritten.T)ospathisfiler
   )filepath	overwrites     r   should_overwritero      s'     11,X66r   c           	         Uc  0 n[         R                  R                  U5         U S   n[        R                  " U5      nSnU R                  SS5      nUb  [        [        R                  U5      nSnU R                  SS5      nUb  [        [        U5      nSnU R                  SS5      n	U	b  [        [        U	5      n[        U S5      (       a  U S   OSn
U S   nSSS5        [        WWWWWW
S9$ ! , (       d  f       N= f)	z4Return model.compile arguments from training config.NrQ   lossmetricsweighted_metricssample_weight_modeloss_weights)rO   rq   rr   rs   ru   rt   )r   rb   CustomObjectScoper   deserializeget_deserialize_nested_configr   _deserialize_metrichasattrrX   )rP   custom_objectsrQ   rO   rq   loss_configrr   metrics_configrs   weighted_metrics_configrt   ru   s               r   !compile_args_from_training_configr      s.   		&	&~	6*+=>**+;<	 %))&$7"-f.@.@+ND (,,Y=%0#^G
  "1"5"56H$"O".9#%<  (<== 01 	
 '~6? 
7B )!- C 
7	6s   B8C33
Dc           	      d   S nUc  gU" U5      (       a  U " U5      $ [        U[        5      (       a/  UR                  5        VVs0 s H  u  p4U[        X5      _M     snn$ [        U[        [
        45      (       a  U Vs/ s H  n[        X5      PM     sn$ [        SU S35      es  snnf s  snf )z@Deserializes arbitrary TF-Keras `config` using `deserialize_fn`.c                 h    [        U [        5      (       a  SU ;   a  g[        U [        5      (       a  gg)NrJ   TF)r   rX   rY   objs    r   _is_single_object5_deserialize_nested_config.<locals>._is_single_object  s,    c4  \S%8c3r   NzrSaved configuration not understood. Configuration should be a dictionary, string, tuple or list. Received: config=.)r   rX   itemsry   tuplelistr"   )deserialize_fnrK   r   kvr   s         r   ry   ry     s     ~  f%%	FD	!	! 
& ).<<&
 	
 
FUDM	*	*GM
GM&~;v
 	
 	??Eha	I 


s   B' B-c                 F    S n[         R                  R                  X5      $ )z2Serialized a nested structure of TF-Keras objects.c                 R    [        U 5      (       a  [        R                  " U 5      $ U $ N)callabler   serialize_keras_objectr   s    r   _serialize_fn/_serialize_nested_config.<locals>._serialize_fn3  s!    C== 77<<
r   )r4   r5   map_structure)rK   r   s     r   r`   r`   0  s    
 77  77r   c                 @    SSK Jn  U S;   a  U $ UR                  U 5      $ )z7Deserialize metrics, leaving special strings untouched.r   )rr   )accuracyacccrossentropyce)rR   rr   rw   )metric_configmetrics_modules     r   rz   rz   ;  s'    6AA %%m44r   c                 
  ^ S mS n[         R                  R                  U 5      n[        U4S jU 5       5      =(       a    [	        U4S jU 5       5      (       + nU(       a  [         R                  R                  X5      n U $ )z5Enforces that either all specs have names or none do.c                 Z    U S L =(       d!    [        U S5      =(       a    U R                  S L$ Nr   )r{   r   specs    r   	_has_name-_enforce_names_consistency.<locals>._has_nameJ  s&    t|Pf 5 O$))4:OPr   c                 b    [         R                  " U 5      n [        U S5      (       a  S U l        U $ r   )copydeepcopyr{   _namer   s    r   _clear_name/_enforce_names_consistency.<locals>._clear_nameM  s)    }}T"4  DJr   c              3   4   >#    U  H  nT" U5      v   M     g 7fr    .0sr   s     r   	<genexpr>-_enforce_names_consistency.<locals>.<genexpr>T  s     >:aYq\\:   c              3   4   >#    U  H  nT" U5      v   M     g 7fr   r   r   s     r   r   r   T  s      K(	!jr   )r4   r5   r6   anyallr   )specsr   
flat_specsname_inconsistencyr   s       @r   r   r   G  ss    Q 'J>:>> s K(K H D %%k9Lr   c                    [         R                  " U 5      (       d  U R                  b   U R                  R                  (       d%  U R                  R                  U R                  5        U R                  R                  (       d1  U R                  R                  U R                  U R                  5        g g g g !   [        R                  " S5         g = f)NzCompiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.)	r	   is_v1_layer_or_modelr:   compiled_lossbuiltbuildcompiled_metricsr[   r\   r#   s    r   try_build_compiled_argumentsr   ]  s    ..u55MM%
	&&,,##))%--8))//&&,,U]]EMMJ 0 & 6	OO9s   BB9 9Cc                     U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      $ )Nz.h5z.kerasz.hdf5)endswith)rm   s    r   is_hdf5_filepathr   o  s;    %  	&X&	&W%r   )Fr   )TT)'__doc__r   rj   tensorflow.compat.v2compatv2r4   rR   srcr   r   r   r   r2   r   tf_keras.src.optimizersr   tf_keras.src.saving.legacyr   tf_keras.src.utilsr	   tf_keras.src.utils.io_utilsr
   tensorflow.python.platformr   r[   r   r   r$   rF   rh   ro   r   ry   r`   rz   r   r   r   r   r   r   <module>r      s{    +  	 ! !     # 0 0 4 , E =(<.2Mj5p-`<8	5,$r   