o
    2h0q                     @   s   d dl Z d dl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 d dlmZ d dlmZ d dlmZ d dlmZ zd dlZW n eyQ   dZY nw dd	 Zed
G dd dZdddZdd Zdd Zdd Zdd ZdddZdS )    N)backend)keras_export)
saving_lib)	H5IOStore)naming)summary_utilsc                  C   s8   zddl m}  |  durW dS W dS  ty   Y dS w )z3Checks if the code is being executed in a notebook.r   get_ipythonNTF)IPythonr	   ImportErrorr    r   W/var/www/html/chatgem/venv/lib/python3.10/site-packages/keras/src/saving/file_editor.pyis_ipython_notebook   s   
r   zkeras.saving.KerasFileEditorc                   @   s   e Zd Z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d Zd,ddZd-ddZd-dd Zd-d!d"Z	d.d%d&Zd'd( Zd)d* ZdS )/KerasFileEditora  Utility to inspect, edit, and resave Keras weights files.

    You will find this class useful when adapting
    an old saved weights file after having made
    architecture changes to a model.

    Args:
        filepath: The path to a local file to inspect and edit.

    Examples:

    ```python
    editor = KerasFileEditor("my_model.weights.h5")

    # Displays current contents
    editor.summary()

    # Remove the weights of an existing layer
    editor.delete_object("layers/dense_2")

    # Add the weights of a new layer
    editor.add_object("layers/einsum_dense", weights={"0": ..., "1": ...})

    # Save the weights of the edited model
    editor.resave_weights("edited_model.weights.h5")
    ```
    c           	      C   s\  || _ d | _d | _d | _tjjdd| _|drlt	|d}t
tjd |dd}|tjd}| }W d    n1 s?w   Y  |tjd}| }W d    n1 sZw   Y  t|| _t|| _n|drxt
|dd}ntd	| | |j\}}|  || _|| _| j| jd
d | jd ur| j| jd
d d S d S )NF)	highlightz.kerasrz.h5)archivemode.weights.h5r   zRInvalid filename: expected a `.keras` `.weights.h5` extension. Received: filepath=T)
rich_style)filepathmetadataconfigmodelrichconsoleConsoleendswithzipfileZipFiler   r   _VARS_FNAMEopen_CONFIG_FILENAMEread_METADATA_FILENAMEjsonloads
ValueError_extract_weights_from_storeh5_filecloseweights_dictobject_metadataprint_generate_filepath_info_generate_metadata_info)	selfr   zfweights_storefconfig_jsonmetadata_jsonr,   r-   r   r   r   __init__B   sJ   




zKerasFileEditor.__init__c                 C   s   |    dS )z/Prints the weight structure of the opened file.N)_weights_summary_clir1   r   r   r   summaryn      zKerasFileEditor.summaryc           
   
      s   j d i }t||  fdd t } j|ddddd|d\}} |jddddd|d\}}||7 }j d	 |dkrad
}j d |dkrRd}	nd}	j d| d|	  nd}|dkrjd}	nd}	j d| d|	 d |||dS )a)  Compares the opened file to a reference model.

        This method will list all mismatches between the
        currently opened file and the provided reference model.

        Args:
            reference_model: Model instance to compare to.

        Returns:
            Dict with the following keys:
            `'status'`, `'error_count'`, `'match_count'`.
            Status can be `'success'` or `'error'`.
            `'error_count'` is the number of mismatches found.
            `'match_count'` is the number of matching weights found.
        zRunning comparisonc                    s`  |}|  D ]\}	}
|d |	 }||v rq|	| vr\|d7 }|| t|
trKjd| d| d| d jd| d| d	t|
   qjd
| d| d| d qt|
tr| | |	 ||	 ||||||d\}}||7 }||7 }q| |	 j|
jkr|d7 }|| jd| d| d|
j d| d| |	 j 
 q|d7 }q||fS )N/   z[color(160)]...Object [bold]z[/] present in z, missing from z[/]z    In , z contains the following keys: z[color(160)]...Weight [bold])error_countmatch_countchecked_pathsz/[color(160)]...Weight shape mismatch for [bold]z[/][/]
    In z: shape=z
    In )	itemsadd
isinstancedictr   r.   listkeysshape)targetref_spec
inner_pathtarget_nameref_namer?   r@   rA   base_inner_pathref_keyref_val_error_count_match_count_comparer1   r   r   rT      sv   









	z)KerasFileEditor.compare.<locals>._compare z
saved filezreference modelr   )rK   rL   rM   r?   r@   rA   u?   ─────────────────────successz_[color(28)][bold]Comparison successful:[/] saved file is compatible with the reference model[/]r=   sz
    Found z matching weighterrorz[color(160)][bold]Found z errorz=:[/] saved file is not compatible with the reference model[/])statusr?   r@   )r   r.   get_weight_spec_of_saveablesetr,   )
r1   reference_modelrJ   rA   r?   r@   rQ   _rY   pluralr   rS   r   comparer   sb   
@



zKerasFileEditor.compareNc                    s  d urdv rt d ddv rNd}| j}|d d D ]}||vr0t d d|| }q"|d |vrCt d d||d d d S dfd	d
	| j}|dkrgt d d|dkrst d d fdd  | j d S )Nr<   z[Argument `target_name` should be a leaf name, not a full path name. Received: target_name=''Path '' not found in model.source_namerL   r   c                    s@   | D ]}t | | tr| | | ||7 }q|| v r|d7 }|S Nr=   rD   rE   )dnamecountk)count_occurencesr   r   rl     s   z6KerasFileEditor._edit_object.<locals>.count_occurencesr=   zName 'zA' occurs more than once in the model; try passing a complete pathzSource name 'zS' does not appear in the model. Use `editor.weights_summary()` to list all objects.c                    sB   | D ]}t | | tr | |  q| v r| d d S d S )Nrd   rg   )rh   rk   )_editedit_fnre   rL   r   r   rm   '  s   z+KerasFileEditor._edit_object.<locals>._edit)r   )r(   splitr,   )r1   rn   re   rL   elementsr,   eoccurrencesr   )rm   rl   rn   re   rL   r   _edit_object   s@   






zKerasFileEditor._edit_objectc                 C   s   dd }|  ||| dS )a
  Rename an object in the file (e.g. a layer).

        Args:
            object_name: String, name or path of the
                object to rename (e.g. `"dense_2"` or
                `"layers/dense_2"`).
            new_name: String, new name of the object.
        c                 S   s   | | | |< |  | d S Npopr,   re   rL   r   r   r   	rename_fn:  s   z0KerasFileEditor.rename_object.<locals>.rename_fnNrs   )r1   object_namenew_namerx   r   r   r   rename_object0  s   
zKerasFileEditor.rename_objectc                 C   s   ddd}|  || dS )zRemoves an object from the file (e.g. a layer).

        Args:
            object_name: String, name or path of the
                object to delete (e.g. `"dense_2"` or
                `"layers/dense_2"`).
        Nc                 S      |  | d S rt   ru   rw   r   r   r   	delete_fnI     z0KerasFileEditor.delete_object.<locals>.delete_fnrt   ry   )r1   rz   r~   r   r   r   delete_object@  s   
	zKerasFileEditor.delete_objectc                 C   s   t |tstdt| d|v rD|d}d|dd }| j}|dd D ]}||vr7td| d|| }q)|||d < dS || j|< dS )aF  Add a new object to the file (e.g. a layer).

        Args:
            object_path: String, full path of the
                object to add (e.g. `"layers/dense_2"`).
            weights: Dict mapping weight names to weight
                values (arrays),
                e.g. `{"0": kernel_value, "1": bias_value}`.
        Argument `weights` should be a dict where keys are weight names (usually '0', '1', etc.) and values are NumPy arrays. Received: type(weights)=r<   Nra   rb   rc   )rD   rE   r(   typero   joinr,   )r1   object_pathweightsrp   partial_pathr,   rq   r   r   r   
add_objectN  s$   




zKerasFileEditor.add_objectc                    s    d fdd	}|  |  dS )aC  Removes a weight from an existing object.

        Args:
            object_name: String, name or path of the
                object from which to remove the weight
                (e.g. `"dense_2"` or `"layers/dense_2"`).
            weight_name: String, name of the weight to
                delete (e.g. `"0"`).
        Nc              	      sD   | | vrt d d  dt| |   | |  d S )NzWeight z not found in object z. Weights found: )r(   rF   rG   rv   rw   rz   weight_namer   r   delete_weight_fnz  s   z7KerasFileEditor.delete_weight.<locals>.delete_weight_fnrt   ry   )r1   rz   r   r   r   r   r   delete_weighto  s   
zKerasFileEditor.delete_weightc                    s:   t  tstdt  d fdd	}| || dS )a}  Add one or more new weights to an existing object.

        Args:
            object_name: String, name or path of the
                object to add the weights to
                (e.g. `"dense_2"` or `"layers/dense_2"`).
            weights: Dict mapping weight names to weight
                values (arrays),
                e.g. `{"0": kernel_value, "1": bias_value}`.
        r   Nc                    s   | |    d S rt   )updaterw   r   r   r   add_weight_fn  s   z2KerasFileEditor.add_weights.<locals>.add_weight_fnrt   )rD   rE   r(   r   rs   )r1   rz   r   r   r   r   r   add_weights  s   
zKerasFileEditor.add_weightsc                    sT   t |}|dstd| t|dd} fdd  | j|dd |  d	S )
zSave the edited weights file.

        Args:
            filepath: Path to save the file to.
                Must be a `.weights.h5` file.
        r   zTInvalid `filepath` argument: expected a `.weights.h5` extension. Received: filepath=wr   c                    sx   i }|   D ]\}}t|tr|r | | ||d | d q|||< q|r8||}|  D ]
\}}|||< q/d S d S )Nr<   rK   )rB   rD   rE   make)r,   r3   rK   vars_to_createri   value	var_store_saver   r   r     s"   




z#KerasFileEditor.save.<locals>._saverU   r   N)strr   r(   r   r,   r+   )r1   r   r3   r   r   r   save  s   
zKerasFileEditor.savec                 C   r}   rt   )r   )r1   r   r   r   r   resave_weights  r   zKerasFileEditor.resave_weightsrU   c           
      C   s   |pi }i }|j  D ]\}}|||< q|r|||< t }| D ]U}|d | }|| }	t|	tjrJt|	dkr;q"d|	 v rJt|	d dkrJq"t	|	drqd|	 v rd| j
|	d ||d\||< }q"| j
|	||d\||< }q"|	d ||< q"||fS )Nr<   r   varsrG   )r   rK   r   )attrsrB   collectionsOrderedDictrG   rD   h5pyGrouplenhasattrr)   )
r1   datar   rK   r-   rk   vresultkeyr   r   r   r   r)     s2   


z+KerasFileEditor._extract_weights_from_storeFc                 C   s8   |rd| j  d}t| }nd| j  d}d| S )Nr`   zKeras model file )r   r   highlight_symbol)r1   r   r   r   r   r   r/     s
   
z'KerasFileEditor._generate_filepath_infoc                 C   s   t | jS rt   )pprintpformatr   )r1   r   r   r   r   _generate_config_info  s   z%KerasFileEditor._generate_config_infoc                 C   s@   | j d }| j d }|rt| }t| }d| d| S )Nkeras_version
date_savedzSaved with Keras z	 - date: )r   r   r   )r1   r   versiondater   r   r   r0     s   

z'KerasFileEditor._generate_metadata_infor   Tc                 C   sL  t | D ]\}\}}|d | }|t|d k}	|r!d}d}
n|	r&d}
nd}
t|trrt|}| |
 | }|| jv rT| j| }d|v rT|d }|d| d	7 }| j	| |	r_d
}nd}|| }| j
||d |||d qt|drt|}| j	| |
 | dd|j d|j   q| j	| |
 | d|  qd S )Nr<   r=   Fz> u   └─ u   ├─ ri   z ('z')z    u   │   )is_firstprefixrK   rH   :z shape=, dtype=z: )	enumeraterB   r   rD   rE   r   	bold_textr-   r   r.   _print_weights_structurer   rH   dtype)r1   r,   indentr   r   rK   idxr   r   is_last	connectorbold_keyobject_labelr   ri   appended
new_prefixr   r   r   r     sL   





 z(KerasFileEditor._print_weights_structurec                 C   s    | j d | j| jdd d S )NWeights structurez  )r   )r   r.   r   r,   r9   r   r   r   r8   &  s   z$KerasFileEditor._weights_summary_clic                    s>   d fdd	 d}t   | | j7 }tjtj| d S )Nr   r=   c                    s   d}|   D ]_\}}t|tr6|r6|d| dd d| d d d| d	  ||d
 |d  d 7 }q|d| dd| d | d|j  d|j d	 d| d| d t|  d d 7 }q|S )NrU   z<details style="margin-left: zpx;">z<summary style="zfont-size: zem; zfont-weight: bold;z">z
</summary>   r=   z
</details>z<summary style="font-size: zem;">z	 : shape=r   z<div style="margin-left: zpx;"margin-top: z</div>)rB   rD   rE   rH   r   display_weight)
dictionarymargin_left	font_sizehtmlr   r   _generate_html_weightsr   r   r   +  sT   




	zLKerasFileEditor._weights_summary_interactive.<locals>._generate_html_weightsr   )r   r=   )initialize_id_counterr,   ipythondisplayHTML)r1   outputr   r   r   _weights_summary_interactive*  s
   z,KerasFileEditor._weights_summary_interactivert   )NrU   )F)r   TrU   rU   )__name__
__module____qualname____doc__r7   r:   r_   rs   r|   r   r   r   r   r   r   r)   r/   r   r0   r   r8   r   r   r   r   r   r   $   s,    , 
	6!%

 

	
-r   c                 C   s   ddl m} |p
t }t| |v rd S t| dr;i }| | |r;t| }|D ]}|| }tj	|j
|jd||< q)|t|  t| D ]1\}}	t|	|r`i }
t|	|
|d |
r_|
||< qGt|	ttttfrxi }
t|	|
|d |
rx|
||< qGd S )Nr   KerasSaveablesave_own_variables)rH   r   visited_saveables)keras.src.saving.keras_saveabler   r[   idr   r   sortedrG   r   KerasTensorrH   r   rC   r   _walk_saveablerD   rZ   rF   rE   tupleget_weight_spec_of_container)saveablespecr   r   storerG   rk   val
child_attr	child_objsub_specr   r   r   rZ   P  sF   



rZ   c                 C   s   ddl m} i }t| trt|  } | D ]7}t||rLt|jj	}||v r9||  d7  < | d||  }nd||< i }t
|||d |rL|||< qd S )Nr   r   r=   r]   r   )r   r   rD   rE   rF   valuesr   to_snake_case	__class__r   rZ   )	containerr   r   r   
used_namesr   ri   r   r   r   r   r   y  s*   

r   c                   C   s   da d S )Nr   div_id_counterr   r   r   r   r     s   r   c                   C   s   t d7 a d S rf   r   r   r   r   r   increment_id_counter  r;   r   c                   C   s   t S rt   r   r   r   r   r   get_id_counter  s   r   ra      c           	         s   dd dd  dd }d fdd		}| j d
kr | dtjf } t| |d} | d| jd } | jd \}}| ||| jd } dD ]}| j| |krZ|| | j| | |d} qE| |   |  |   d  } || }|S )Nc                 S   s\   t t| }t|ddD ]}| | dkr+|}| | }||kr%||f  S ||f  S qd S )Nr   ra   )intnpsqrtrange)numsqrt_numiMNr   r   r   _find_factors_closest_to_sqrt  s   z5display_weight.<locals>._find_factors_closest_to_sqrtc                 S   s$   d| d  d| d  d| d  dS )Nzrgba(r   r>   r=      z, 1)r   )r   r   r   r   _color_from_rbg  s   $z'display_weight.<locals>._color_from_rbgc                 S   s@  |dkr4| d d d d d | j d | j d |  f }t|| j d | j d d|f}tj|dd}|S |dkrh| d d d | j d | j d |  d d f }t|| j d d|| j d f}tj|dd}|S |dkr| d | j d | j d |  d d d d f }t|d|| j d | j d f}tj|dd}|S td)Nr   r   r=   ra      axiszAxis must be 0, 1, or 2.)rH   r   reshapemeanr(   )arrnr   trimmed_arrreshapedmean_valuesr   r   r   _reduce_3d_array_by_mean  s,   ...z0display_weight.<locals>._reduce_3d_array_by_meanH  c                    sp  | j \}}}|\}}zddlm} W n ty   d }Y nw |r(|| }n| t|  t| t|   }tj|||gdd}|dd df d 	d}d	}	t
|D ])}
d	}|d|
d d f D ]}|D ]} |}|d
| d7 }qgqc|	d| d7 }	qV|||  }t  t }d| d| d| d| d| d| d| d| d| d| d| d| d|	 d}|S )Nr   )cmra   r   .r      uint8rU   z+<div class="cell" style="background-color: z	;"></div>zH
                        <div class="matrix">
                          z8
                        </div>
                        z*
            <div class="unique-container_zE">
                  <style>
                      .unique-container_zm .subplots {
                      display: inline-grid;
                      grid-template-columns: repeat(a  , 1fr);
                      column-gap: 5px;  /* Minimal horizontal gap */
                      row-gap: 5px;     /* Small vertical gap */
                      margin: 0;
                      padding: 0;
                    }
                    .unique-container_zk .matrix {
                      display: inline-grid;
                      grid-template-columns: repeat(r>   z6px);
                      grid-template-rows: repeat(zpx);
                      gap: 1px;
                      margin: 0;
                      padding: 0;
                    }
                    .unique-container_z& .cell {
                      width: z"px;
                      height: a3  px;
                      display: flex;
                      justify-content: center;
                      align-items: center;
                      font-size: 5px;
                      font-weight: bold;
                      color: white;
                    }
                     .unique-container_z {
                      margin-top: 20px;
                      margin-bottom: 20px;
                    }
                  </style>
                  <div class="subplots">
                    zC
                  </div>
                  </div>
                )rH   
matplotlibr  r   jetr   minmaxstackastyper   r   r   )matrixsubplot_sizerowscols
num_slicesr   r   r  
rgb_matrixsubplot_htmlr   	cell_htmlrowrgbcolor	cell_sizediv_id	html_coder   r   r   r   _create_matrix_html  sx   #(z+display_weight.<locals>._create_matrix_htmlr=   .ra   r   )r   r=   r   r   gh㈵>)r  )ndimr   newaxisswapaxesr   rH   r  r  )	weightr   	thresholdr  r  r   r   reduce_axisr  r   r  r   r     s*   
R r   rt   )ra   r   )r   r&   r   r   r   numpyr   rich.consoler   	keras.srcr   keras.src.api_exportr   keras.src.savingr   keras.src.saving.saving_libr   keras.src.utilsr   r   r
   r   r   r   r   rZ   r   r   r   r   r   r   r   r   r   <module>   s>        
/)