o
    2h                     @   sv  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 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# G dd deeZ$d.ddZ%dd Z&dd Z'dd Z(d/d d!Z)d"d# Z*d$d% Z+d&d' Z,d(d) Z-d*d+ Z.d,d- Z/dS )0    N)backend)ops)tree)global_state)Input)
InputLayer)	InputSpec)Layer)saving_utils)serialization)Model)Function
_build_map)make_node_key)KerasHistory)Node)	Operation)serialization_lib)trackingc                       s  e Zd ZdZ fddZejd0ddZdd Zd	d
 Z	e
dd Zejdd Zd1ddZd1 fdd	Z fddZdd Ze
dd Ze
dd Z fddZd2ddZdd  Zd!d" Zd#d$ Ze
d%d& Ze
d'd( Zd)d* Ze
d+d, Zejd-d, Zd.d/ Z  ZS )3
Functionala?
  A `Functional` model is a `Model` defined as a directed graph of layers.

    Three types of `Model` exist: subclassed `Model`, `Functional` model,
    and `Sequential` (a special case of `Functional`).

    A `Functional` model can be instantiated by passing two arguments to
    `__init__()`. The first argument is the `keras.Input` objects
    that represent the inputs to the model.
    The second argument specifies the output tensors that represent
    the outputs of this model. Both arguments can be a nested structure
    of tensors.

    Example:

    ```
    inputs = {'x1': keras.Input(shape=(10,), name='x1'),
              'x2': keras.Input(shape=(1,), name='x2')}
    t = keras.layers.Dense(1, activation='relu')(inputs['x1'])
    outputs = keras.layers.Add()([t, inputs['x2']])
    model = keras.Model(inputs, outputs)
    ```

    A `Functional` model constructed using the Functional API can also
    include raw Keras 3 ops.

    Example:

    ```python
    inputs = keras.Input(shape=(10,))
    x = keras.layers.Dense(1)(inputs)
    outputs = ops.nn.relu(x)
    model = keras.Model(inputs, outputs)
    ```

    A new `Functional` model can also be created by using the
    intermediate tensors. This enables you to quickly extract sub-components
    of the model.

    Example:

    ```python
    inputs = keras.Input(shape=(None, None, 3))
    processed = keras.layers.RandomCrop(width=32, height=32)(inputs)
    conv = keras.layers.Conv2D(filters=2, kernel_size=3)(processed)
    pooling = keras.layers.GlobalAveragePooling2D()(conv)
    feature = keras.layers.Dense(10)(pooling)

    full_model = keras.Model(inputs, feature)
    backbone = keras.Model(processed, conv)
    activations = keras.Model(conv, feature)
    ```

    Note that the `backbone` and `activations` models are not
    created with `keras.Input` objects, but with the tensors
    that are originated from `keras.Input` objects.
    Under the hood, the layers and weights will
    be shared across these models, so that user can train the `full_model`, and
    use `backbone` or `activations` to do feature extraction.
    The inputs and outputs of the model can be nested structures of tensors as
    well, and the created models are standard `Functional` model that support
    all the existing API.

    Args:
        inputs: List of input tensors (must be created via `keras.Input()`
            or originated from `keras.Input()`).
        outputs: List of output tensors.
        name: String, optional. Name of the model.
        trainable: Boolean, optional. If the model's variables should be
            trainable.
    c                    s   t | t | S N)typingcastsuper__new__)clsargskwargs	__class__ V/var/www/html/chatgem/venv/lib/python3.10/site-packages/keras/src/models/functional.pyr   c   s   zFunctional.__new__Nc                 K   sh  t |tr/| D ]%\}}t |tjr.||jkr.td| d| d|j d| d| d q	|dd }t	
|}t	
|}	|D ]}
t |
tjsXtd| d	|
 d
t|
 qA|	D ]}
t |
tjsrtd| d	|
 d
t|
 q[tdd |D st||\}}tj| |||d |d ur|| _| j| _| d  d| _d| _dd | jD }dd |D | _d S )NzyWhen providing `inputs` as a dict, all keys in the dict must match the names of the corresponding tensors. Received key 'z' mapping to value z which has name 'z'. Change the tensor name to 'z' (via `Input(..., name='z')`)	trainablez;All `inputs` values must be KerasTensors. Received: inputs=z including invalid value z	 of type z=All `outputs` values must be KerasTensors. Received: outputs=c                 s   s    | ]}t |V  qd S r   )is_input_keras_tensor).0tr!   r!   r"   	<genexpr>   s    z&Functional.__init__.<locals>.<genexpr>nameFTc                 S   s   g | ]}|j d  qS )r   )_keras_historyr%   xr!   r!   r"   
<listcomp>       z'Functional.__init__.<locals>.<listcomp>c                 S      g | ]}|j qS r!   r(   r+   r!   r!   r"   r-          )
isinstancedictitemsr   KerasTensorr)   warningswarnpopr   flatten
ValueErrortypeallclone_graph_nodesr   __init__r#   layers_layersbuild_convert_input_args!_allow_non_tensor_positional_argsoutputsoutput_names)selfinputsrC   r)   r   kvr#   flat_inputsflat_outputsr,   output_layersr!   r!   r"   r=   f   sn   



zFunctional.__init__c                 C   s   d S r   r!   rE   r!   r!   r"   _lock_state   s   zFunctional._lock_statec                 C   s   dS )Nr   r!   rL   r!   r!   r"   	_obj_type   s   zFunctional._obj_typec                 C   s(   g }| j D ]}t|tr|| q|S r   )_operationsr1   r	   append)rE   r>   	operationr!   r!   r"   r>      s   


zFunctional.layersc                 C   s   t d)NzU`Model.layers` attribute is reserved and should not be used. Please use another name.)AttributeError)rE   _r!   r!   r"   r>      s   c                    st   |  |}|d u rd gt| }nt|}t||D ]\}}|d ur)t|| q| j| fddd}t|S )Nc                    s   t | fdi S )Ntrainingoperation_fn)opr   rT   r!   r"   <lambda>   s    z!Functional.call.<locals>.<lambda>rU   )	_standardize_inputslenr   r8   zipr   set_keras_mask_run_through_graphunpack_singleton)rE   rF   rT   maskr   masksr,   rC   r!   rX   r"   call   s   

zFunctional.callc                       t  |S r   )r   compute_output_spec)rE   rF   rT   r`   r   r!   r"   rd         zFunctional.compute_output_specc                    rc   r   )r   compute_output_shaperE   input_shaper   r!   r"   rf      re   zFunctional.compute_output_shapec                 C   s
   d| _ d S )NT)builtrg   r!   r!   r"   r@      s   
zFunctional.buildc                 C   4   t dd | j}t|trt|dkr|d S |S )Nc                 S      | j S r   shaper,   r!   r!   r"   rY          z(Functional.input_shape.<locals>.<lambda>   r   )r   map_structurerF   r1   listr[   )rE   input_shapesr!   r!   r"   rh         zFunctional.input_shapec                 C   rj   )Nc                 S   rk   r   rl   rn   r!   r!   r"   rY      ro   z)Functional.output_shape.<locals>.<lambda>rp   r   )r   rq   rC   r1   rr   r[   )rE   output_shapesr!   r!   r"   output_shape   rt   zFunctional.output_shapec                    s   t t| j| S r   )r   r   _assert_input_compatibility)rE   r   r   r!   r"   rw      s   z&Functional._assert_input_compatibilityFc                 C   sv   zt t |t | j W d S    t dd | j}t dd |}d| d| }|r3t|t| Y d S )Nc                 S   rk   r   r(   rn   r!   r!   r"   rY      ro   z?Functional._maybe_warn_inputs_struct_mismatch.<locals>.<lambda>c                 S   s   d| j  dS )NzTensor(shape=)rl   rn   r!   r!   r"   rY      s    zJThe structure of `inputs` doesn't match the expected structure.
Expected: z
Received: inputs=)r   assert_same_structurelists_to_tuples_inputs_structrq   r9   r5   r6   )rE   rF   raise_exceptionmodel_inputs_structinputs_structmsgr!   r!   r"   "_maybe_warn_inputs_struct_mismatch   s*   


z-Functional._maybe_warn_inputs_struct_mismatchc                 C   sL   g }t || jD ]\}}|d u r|| q|tj||j|jd q|S )N)dtypesparse)r\   _inputsrP   r   convert_to_tensorr   r   )rE   rI   	convertedr,   inputr!   r!   r"   _convert_inputs_to_tensors   s   
z%Functional._convert_inputs_to_tensorsc           
      C   s4  dd | j D }g }t||D ]]\}}|d u r|| qt|j}t|}||kr0|| q||d krH|jd dkrH|tj|dd q||d kr_|d dkr_|tj|dd qtd| d| d|j t	t|D ]$}t
|| d	r|| j|| _t|| }	|	d urt|| |	 qs|S )
Nc                 S   r/   r!   rl   r+   r!   r!   r"   r-     r0   z1Functional._adjust_input_rank.<locals>.<listcomp>rp   )axiszInvalid input shape for input z. Expected shape z#, but input has incompatible shape r*   )r   r\   rP   r[   rm   r   squeezeexpand_dimsr9   rangehasattrr*   r   get_keras_maskr]   )
rE   rI   flat_ref_shapesadjustedr,   	ref_shapex_rankref_rankir`   r!   r!   r"   _adjust_input_rank   sD   


zFunctional._adjust_input_rankc                    sB  d}t | jtrt| jdkrt r g nXt  trpt | jtspt| jdrVtdd | jD rVt	dd | jD }t	 
 }||rS fdd| jD  nd	}nt | jtjrn| jj v rk | jj g nd	}nd	}t | jtrt  tst| j
 t| j
 krd	}| j |d
 t }| |}| |S )NFrp   __len__c                 s       | ]	}t |tjV  qd S r   r1   r   r4   r%   r   r!   r!   r"   r'   .  s    
z1Functional._standardize_inputs.<locals>.<genexpr>c                 s   s    | ]}|j V  qd S r   r(   r   r!   r!   r"   r'   1  s    c                    s   g | ]} |j  qS r!   r(   r   rF   r!   r"   r-   4  r.   z2Functional._standardize_inputs.<locals>.<listcomp>T)r|   )r1   r{   rr   r[   r   	is_tensorr2   r   r;   setkeysissubsetr   r4   r)   sortedr   r   r8   r   r   )rE   rF   r|   expected_keysr   rI   r!   r   r"   rZ   !  sJ   





zFunctional._standardize_inputsc                 C   rk   r   r{   rL   r!   r!   r"   r   M  s   zFunctional.inputc                 C   rk   r   )_outputs_structrL   r!   r!   r"   outputT  s   zFunctional.outputc                 C   s   t r   )NotImplementedError)rE   lossr!   r!   r"   add_lossX  s   zFunctional.add_lossc                    s   t drjS dd dfdd	 tjtr8tdd j D r6tj } fdd	|D S d S  fd
d	j	D S )N_manual_input_specc                 S   s   t | } | r
d | d< t| S )Nr   )rr   tuplern   r!   r!   r"   shape_with_no_batch_sizea  s   z7Functional.input_spec.<locals>.shape_with_no_batch_sizec                    sT   d}t | jd tr| jd jrd}t | jd|d u r%| jd j|dS ||dS )NFr   T)rm   allow_last_axis_squeezer)   optional)r1   r*   r   r   r   rm   r)   )r,   r)   r   )r   r!   r"   make_spec_for_tensorg  s   z3Functional.input_spec.<locals>.make_spec_for_tensorc                 s   r   r   r   r+   r!   r!   r"   r'   t  s
    

z(Functional.input_spec.<locals>.<genexpr>c                    s   g | ]} j | |d qS )r(   r   )r%   r)   )r   rE   r!   r"   r-   z  s    z)Functional.input_spec.<locals>.<listcomp>c                       g | ]} |qS r!   r!   r+   )r   r!   r"   r-         r   )
r   r   r1   r{   r2   r;   valuesr   r   rF   )rE   namesr!   )r   rE   r   r"   
input_spec\  s   
zFunctional.input_specc                 C   s
   || _ d S r   )r   )rE   valuer!   r!   r"   r     s   
c                    s`  t js
tS jjd}i jD ])}t|jtr!d}nd}t	|j
D ]\}}t||}|jv r>||< |d7 }q(qg }jD ]F}g }t	|j
D ]\}}t||}|jv rlt|jd}	|	d url||	 qNtj}
tddrytj}
|
|}|j|d< ||d< || qE||d	< fd
d  fdd}|j|d< |j|d< t|S )Nr)   r#   rp   r   	own_nodesuse_legacy_configFr)   inbound_nodesr>   c                    sJ   | j d }| j d }| j d }t||}|jv sJ  | }|j||gS )Nr   rp      )r*   r   _nodesr)   )tensorrQ   
node_indextensor_indexnode_keynew_node_index)node_reindexing_maprE   r!   r"   get_tensor_config  s   



z0Functional.get_config.<locals>.get_tensor_configc                    s   t  | S r   r   rq   tensors)r   r!   r"   map_tensors  s   z*Functional.get_config.<locals>.map_tensorsinput_layersrK   )functional_like_constructorr    r   
get_configr)   r#   
operations
issubclassr   	enumerate_inbound_nodesr   r   serialize_noderP   r   serialize_keras_objectr   get_global_attributelegacy_serializationr{   r   copydeepcopy)rE   configrQ   
kept_nodesoriginal_node_indexnoder   layer_configsfiltered_inbound_nodes	node_dataserialize_obj_fnlayer_configr   r!   )r   r   rE   r"   r     sX   










	
zFunctional.get_configr   )NN)F)__name__
__module____qualname____doc__r   r    no_automatic_dependency_trackingr=   rM   rN   propertyr>   setterrb   rd   rf   r@   rh   rv   rw   r   r   r   rZ   r   r   r   r   r   __classcell__r!   r!   r   r"   r      sD    G.





!,


$
r   c              	      s  i i fdd fdd} fdd}i }dD ]	}| |||< qdD ]}||v r6| |||< q(d	||< q(|d
 D ]}|| q?r|d
 D ]I}|d  }|v r| }	d}
|
t|	k r|	|
 }z||| W n	 tyx   Y nw |
d7 }
|
t|	k sd|
t|	k r|	|
d	 |< qL|= qLsH|d }|d }fddfdd|d }|d }| d||||d|S )aI  Instantiates a Functional model from its config (from `get_config()`).

    Args:
        cls: Class of the model, e.g. a custom subclass of `Model`.
        config: Output of `get_config()` for the original model instance.
        custom_objects: Optional dict of custom objects.

    Returns:
        An instance of `cls`.
    c                    s(   |  vr|g | < dS  |   | dS )zAdd node to layer list

        Arg:
            layer: layer object
            node_data: Node data specifying layer call
        N)rP   )layerr   )unprocessed_nodesr!   r"   add_unprocessed_node  s   z4functional_from_config.<locals>.add_unprocessed_nodec                    s    t | \}}| |i | dS )zReconstruct node by linking to inbound layers

        Args:
            layer: Layer to process
            node_data: List of layer configs
        N)deserialize_node)r   r   r   r   created_layersr!   r"   process_node  s   z,functional_from_config.<locals>.process_nodec                    sr   | d }d| vrt j| d}ntj| d}t|ts%tdt| ||< | d }|D ]} || q/dS )ztDeserializes a layer and index its inbound nodes.

        Args:
            layer_data: layer config dict.
        r)   module)custom_objectszMUnexpected object from deserialization, expected a layer or operation, got a r   N)r
   model_from_configr   deserialize_keras_objectr1   r   r9   r:   )
layer_data
layer_namer   inbound_nodes_datar   )r   r   r   r!   r"   process_layer  s&   
z-functional_from_config.<locals>.process_layer)r>   r   rK   r   Nr>   r)   r   rp   r#   c                    s:   |  v sJ  |  }t |tr|d8 }|j| j}|| S )Nrp   )r1   r   r   output_tensors)r   r   r   r   layer_output_tensorsr   r!   r"   
get_tensorU  s   
z*functional_from_config.<locals>.get_tensorc                    s~   t | trt| dkrt | d tr |  S t | tr&fdd|  D S t | tr6tfdd| D S fdd| D S )N   r   c                    s   i | ]	\}}| |qS r!   r!   )r%   rG   rH   r   r!   r"   
<dictcomp>g  s    z?functional_from_config.<locals>.map_tensors.<locals>.<dictcomp>c                    r   r!   r!   r%   rH   r   r!   r"   r-   i  r   z?functional_from_config.<locals>.map_tensors.<locals>.<listcomp>c                    r   r!   r!   r   r   r!   r"   r-   j  r   )r1   rr   r[   strr2   r3   r   r   )r   r   r!   r"   r   ^  s   

z+functional_from_config.<locals>.map_tensorsr   rK   )rF   rC   r)   r#   r!   )r7   r[   
IndexError)r   r   r   r   r   functional_configkeyr   r   node_data_listr   r   r)   r#   input_tensorsr   r!   )r   r   r   r   r   r   r"   functional_from_config  s`   &

	r   c                    s    fdd}|S )z.Wraps each op to inject the call-context args.c                     s@      D ]\}}|tdi v r|d ur|||< q| i |S )N_call_context_args)r3   getattr)r   r   r)   r   call_context_argsrQ   r!   r"   rb   {  s   zoperation_fn.<locals>.callr!   )rQ   r  rb   r!   r  r"   rV   x  s   rV   c                 C   s<   t | jjdd  }t tjjdd  }||krdS dS )Nrp   TF)inspectgetfullargspecr=   r   r   )r   	init_argsfunctional_init_argsr!   r!   r"   r     s
   r   c                 C   s&   t | ttfrt| dkr| d S | S )Nrp   r   )r1   rr   r   r[   rn   r!   r!   r"   r_     s   r_   r!   c                    sT   | j sd S  fdd}| jj}| jj}t||}t||}t|t|dS )Nc           	         s   t | tjr@| j\}}}d}t|jd | D ]\}}t||}| vr(|d7 }qt||| || _t	| }t|||| _|S | S )Nr   rp   )
r1   r   r4   r*   r   r   r   r   r   r   )	r,   rQ   r   r   irrelevant_node_countr   r   r   
serializedr   r!   r"   serialize_keras_tensor  s   


z.serialize_node.<locals>.serialize_keras_tensor)r   r   )r   	argumentsr   r   r   rq   r   r   )r   r   r
  r   r   r!   r   r"   r     s   r   c                    s  | sg i fS t | trcg }| D ]L}|d }|d }|d }t|dkr&i }nt|dkr1|d }ntd | }t|j|krNtd| d|j d	| |j| }	||	j|  qt|g|fS t	
| d
 }
t	
| d } fdd}t||
}
t||}|
|fS )z1Return (args, kwargs) for calling the node layer.r   rp   r   r      z3Cannot deserialize the model (invalid config data?)0Layer node index out of bounds.
inbound_layer =  
inbound_layer._inbound_nodes = 
inbound_node_index = r   r   c                    s   t | tjrK| j}|d u r| S  |d d }|d u r$td|d  |d }|d }t|j|krAtd| d|j d| |j| }|j	| S | S )Nr   zUnknown layer: rp   r   r  r  r  )
r1   r   r4    _pre_serialization_keras_historygetr9   r[   r   r   r   )r,   historyr   inbound_node_indexinbound_tensor_indexinbound_noder   r!   r"   convert_revived_tensor  s,   

z0deserialize_node.<locals>.convert_revived_tensor)r1   rr   r[   r9   r   r   rP   r   r_   r   r   r   rq   )r   r   r   
input_datainbound_layer_namer  r  r   inbound_layerr  r   r  r!   r   r"   r     sJ   


r   c                 C   s   | j \}}}|j| }|jS r   )r*   r   is_input)r,   rQ   r   rS   r   r!   r!   r"   r$     s   
r$   c                 C   s   t j| j| j| j| jd dS )N_clone)rm   r   r   r)   )r   r4   rm   r   r   r)   rn   r!   r!   r"   clone_single_keras_tensor  s   r  c                    s    fdd}t || S )Nc                    s@   t | tjs| S t|  v r t|  S t| }| t| < |S r   )r1   r   r4   idr  )r,   new_xkt_id_mappingr!   r"   swap  s   z!clone_keras_tensors.<locals>.swapr   )r   r   r!  r!   r  r"   clone_keras_tensors  s   	r"  c                 C   s   t | |\}}|S r   r   )rF   rC   nodesrS   r!   r!   r"    find_nodes_by_inputs_and_outputs  s   r$  c                 C   sd  t | |}g }g }i }i }t| D ]7}t|r$|| ||t|< qt|j|j|j	|j
d d}|| ||t|< |jd |t|jd < qt| |}t|D ]}	t|	}
|	j|
_||
 |
|t|	< qUt||}|D ]:}t|j|v r|t|j }n|j}t|j|}t|tst|jj|}t|jj|}nd}i }t||||d qs||fS )a  Clone the `Node` between the inputs and output tensors.

    This function is used to create a new functional model from any intermediate
    Keras tensors. The clone of the nodes mimic the behavior of reconstructing
    the functional graph network by re-executing all the `__call__()` methods.
    The cloned nodes will be appended to the layers.

    Note that a new `keras.Input` will be created for any items in the
    `inputs`

    Args:
    inputs: A nested structure of `KerasTensor` instances.
    outputs: A nested structure of `KerasTensor` instances.

    Returns:
        A pair of inputs and outputs, with cloned `KerasTensor` instances.
        They can be used to create a new functional model.
    CLONE)batch_shaper   r   r)   r   r!   )	call_argscall_kwargsrC   )r$  r   r8   r$   rP   r  r   rm   r   r   r)   r*   pack_sequence_asr  rQ   r"  r   r1   r   r  r   r   r   )rF   rC   nodes_to_clonecloned_inputscloned_outputsr   op_id_mappingkt_inputcloned_input	kt_outputcpyr   rQ   output_copycall_args_copycall_kwargs_copyr!   r!   r"   r<     s^   




r<   r   )r!   )0r   r  r   r5   	keras.srcr   r   r   keras.src.backend.commonr   !keras.src.layers.core.input_layerr   r   keras.src.layers.input_specr   keras.src.layers.layerr	   keras.src.legacy.savingr
   r   r   keras.src.models.modelr   keras.src.ops.functionr   r   r   keras.src.ops.noder   r   keras.src.ops.operationr   keras.src.savingr   keras.src.utilsr   r   r   rV   r   r_   r   r   r$   r  r"  r$  r<   r!   r!   r!   r"   <module>   sN       
7 *
"C
