o
    2h3                     @   sl   d Z ddlmZ ddlmZ ddlmZ e Zdd Z	dd Z
d	d
 Zdd Zdd Zdd Zdd ZdS )aJ  Utilities for handling Keras model in graph plugin.

Two canonical types of Keras model are Functional and Sequential.
A model can be serialized as JSON and deserialized to reconstruct a model.
This utility helps with dealing with the serialized Keras model.

They have distinct structures to the configurations in shapes below:
Functional:
  config
    name: Name of the model. If not specified, it is 'model' with
          an optional suffix if there are more than one instance.
    input_layers: Keras.layers.Inputs in the model.
    output_layers: Layer names that are outputs of the model.
    layers: list of layer configurations.
      layer: [*]
        inbound_nodes: inputs to this layer.

Sequential:
  config
    name: Name of the model. If not specified, it is 'sequential' with
          an optional suffix if there are more than one instance.
    layers: list of layer configurations.
      layer: [*]

[*]: Note that a model can be a layer.
Please refer to https://github.com/tensorflow/tfjs-layers/blob/master/src/keras_format/model_serialization.ts
for more complete definition.
    )GraphDef)dtypes)
tb_loggingc                 c   sz    d| fV  |  d dr9|  d d}|  d dD ]}t|D ]\}}|r0d||f n|}||fV  q$qdS dS )aY  Walks the nested keras layer configuration in preorder.

    Args:
      keras_layer: Keras configuration from model.to_json.

    Yields:
      A tuple of (name_scope, layer_config).
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      layer_config: a dict representing a Keras layer configuration.
     configlayersname%s/%sN)get_walk_layers)keras_layer
name_scopelayersub_name_scopesublayer r   _/var/www/html/chatgem/venv/lib/python3.10/site-packages/tensorboard/plugins/graph/keras_util.pyr   4   s   
r   c                 C   s   | rd| |f S |S )a/  Returns scoped name for a node as a string in the form '<scope>/<node
    name>'.

    Args:
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      node_name: a string representing the current node name.

    Returns
      A string representing a scoped name.
    r	   r   )r   	node_namer   r   r   _scoped_nameL   s   r   c                 C   s   |  d dduS )zReturns True if layer is a model.

    Args:
      layer: a dict representing a Keras model configuration.

    Returns:
      bool: True if layer is a model.
    r   r   N)r
   )r   r   r   r   	_is_model\   s   	r   c                 C   s   t | d tfr
| S | gS )a  Normalizes to a list of layers.

    Args:
      maybe_layers: A list of data[1] or a list of list of data.

    Returns:
      List of list of data.

    [1]: A Functional model has fields 'inbound_nodes' and 'output_layers' which can
    look like below:
    - ['in_layer_name', 0, 0]
    - [['in_layer_is_model', 1, 0], ['in_layer_is_model', 1, 1]]
    The data inside the list seems to describe [name, size, index].
    r   )
isinstancelist)maybe_layersr   r   r   _norm_to_list_of_layersh   s   r   c                 C   s   g }|  ddurH|  dg D ]8}t|tsq| dg D ])}t|ts'|g}|D ]}| di  dg }t|dk r<q)||dd  q)qq|S )zOReturns a list of [name, size, index] for all inbound nodes of the given layer.inbound_nodesNargsr   keras_history   )r
   r   dictr   lenappend)r   r   maybe_inbound_nodeinbound_node_argsarghistoryr   r   r   _get_inbound_nodes|   s    


r%   c                    s`  | d}| dstdt| | d | d}| d}t|}t|o(|}	t|}
|
rM|	rMt||D ]\}}t |}t| |d }|||< q7n/|
r[|	s[t| |d d }n!|
s||r||	r|t|dksoJ d	t| |d }t |}|||< |	r|rt|} fd
d|D }|| < n| dd }| d d}t |}|g| < |||fS )a  Updates input_to_in_layer, model_name_to_output, and prev_node_name
    based on the model_layer.

    Args:
      name_scope: a string representing a scope name, similar to that of tf.name_scope.
      model_layer: a dict representing a Keras model configuration.
      input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
      model_name_to_output: a dict mapping Keras Model name to output layer of the model.
      prev_node_name: a string representing a previous, in sequential model layout,
                      node name.

    Returns:
      A tuple of (input_to_in_layer, model_name_to_output, prev_node_name).
      input_to_in_layer: a dict mapping Keras.layers.Input to inbound layer.
      model_name_to_output: a dict mapping Keras Model name to output layer of the model.
      prev_node_name: a string representing a previous, in sequential model layout,
                      node name.
    r   r   zlayer is not a model.r   input_layersoutput_layersr      zhCannot have multi-input Functional model when parent model is not Functional. Number of input layers: %dc                    s   g | ]	}t  |d  qS )r   )r   ).0r   r   r   r   
<listcomp>   s    z!_update_dicts.<locals>.<listcomp>)r
   
ValueErrorr   r%   boolzipr   r   )r   model_layerinput_to_in_layermodel_name_to_outputprev_node_namelayer_configr&   r'   r   is_functional_modelis_parent_functional_modelinput_layerinbound_nodeinput_layer_nameinbound_node_namer   layer_names
last_layerlast_layer_nameoutput_noder   r*   r   _update_dicts   sP   










r?   c              	   C   s  i }i }t  }d}t| D ]\}}t|r!t|||||\}}}q|d}t||d}|j }	||	_|ddurK|d	d}
|
|	j
d _|d}d}d}t|trfd|v rf|dd}n|durl|}|durzt|}|j|	j
d _W n ty   d	}Y nw |durd	}|rtd
| |ddurt|D ]%\}}}t||}|||g}|t|k r|| n|d }|	j| qn
|dur|	j| ||v r|	j|| |	j}q|S )a  Returns a GraphDef representation of the Keras model in a dict form.

    Note that it only supports models that implemented to_json().

    Args:
      keras_layer: A dict from Keras model.to_json().

    Returns:
      A GraphDef representation of the layers in the model.
    Nr   r   
class_nameasciikeras_classdtypeFTz8Unsupported dtype value in graph model config (json):
%sr   r,   )r   r   r   r?   r
   r   nodeaddr   encodeattrsr   r   r   as_dtypeas_datatype_enumtype	TypeErrorloggerwarningr%   r   inputr    )r   input_to_layerr2   gr3   r   r   r4   r   node_defkeras_cls_namedtype_or_policyrC   has_unsupported_valuetf_dtyper   sizeindexinbound_nameinbound_node_names
input_namer   r   r   keras_model_to_graph_def   s   




r\   N)__doc__"tensorboard.compat.proto.graph_pb2r   "tensorboard.compat.tensorflow_stubr   tensorboard.utilr   
get_loggerrM   r   r   r   r   r%   r?   r\   r   r   r   r   <module>   s   I