
    #Zj                        U 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	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZ d dlZddlmZmZmZmZmZ ddlmZ ddl m!Z! dd	l"m#Z# dd
l$m%Z%m&Z&m'Z'm(Z(m)Z)  ed          Z* ed          Z+ edd          Z, edi           Z-ee.         e/d<   d$dZ0 G d dee*e+f                   Z1ej2        de	de	de3de1de4f
d            Z5ej2        de	de	de3de1de	f
d            Z6 ede1          Z7de7dee3ee3e	f         f         de7fdZ8dgfde7de9de7fd Z:de1d!e
e1ge7f         de7fd"Z;g d#Z<dS )%    N)
ContextVar)Path)AnyCallableDictGenericIterableIteratorListOptionalSequenceSetTupleTypeVarUnioncast   )CupyOpsNumpyOpsOpsParamServerget_current_ops)	Optimizer)Shim)FloatsXd)DATA_VALIDATIONconvert_recursiveis_xp_arraypartialvalidate_fwd_input_outputInTOutTSelfTModel)boundcontext_operators)defaultmodelreturnc                     | S N )r(   argskwargss      W/Users/jameslopez/projects/MentorCore/.venv/lib/python3.11/site-packages/thinc/model.py
empty_initr0   -   s    L    c                   	   e Zd ZU dZdZeed<    ej                    Z	ej        ed<   e
Zeed<   eed<   eed<   eed<   eed	<   eed
<   eeee         f         ed<   ed          ed<   ee         ed<   eeef         ed<   eeee         f         ed<   g dZdi i g g i i dddeded	ee         deeee         f         deeee         f         ded          dee         deeef         deeed          f         deeeef                  fdZeded          fd            Zedee         fd            Zedeeef         fd            Z ede!edf         fd             Z"ede!edf         fd!            Z#ede!edf         fd"            Z$ede!edf         fd#            Z%e&e'j(        d$eeef         fd%                        Z)dedee         fd&Z*dedefd'Z+d(d)ded*ed+eddfd,Z,dedee         fd-Z-dedee         fd.Z.dedefd/Z/dedee         fd0Z0ded*ee         ddfd1Z1dedefd2Z2dedefd3Z3ded*eddfd4Z4dedee         fd5Z5ded*eddfd6Z6dedee         fd7Z7dedd fd8Z8deded          fd9Z9ded*ed          ddfd:Z:d;e;d<ede!e<ef         fd=Z=dzd;ee;         d>ee<         dd fd?Z>d;e;de!e<ee<ge;f         f         fd@Z?d;e;de<fdAZ@dBeAddfdCZBe'j(        dee!eef         ef         fdD            ZCdEdFdGedeDd          fdHZEdeDd          fdIZFd{dJedeDd          fdKZGd|dMZHddNded	ee         ddfdOZIdPd dQd defdRZJdee!eef         e!eef         f         fdSZKdTeLdeLfdUZM	 d}dTeLdVeeeed ef         f                  deLfdWZNdXeddfdYZOd~dZZPdeddfd[ZQdeRfd\ZSd]eeTef         ddfd^ZUdefd_ZVd`eRdd fdaZWd]eeTef         dd fdbZXdcedd fddZYdedfd]eeTef         dgedefdhZZdedfd`eRdgedefdiZ[dedfdcedgedefdjZ\dkedd fdlZ]dkedd fdmZ^dkedd fdnZ_dkedd fdoZ`dkedd fdpZadkedd fdqZbdkedd fdrZcdkedd fdsZddkedd fdtZedkedd fduZfdkedd fdvZgdkedd fdwZhdkedd fdxZidkedd fdyZjdS )r$   z/Class for implementing Thinc models and layers.r   	global_idglobal_id_locknameopsid_funcinit_params_dims_layers_shims_attrs_has_params)r5   r7   r6   r8   r9   r:   r;   r>   _refsr<   r=   r?   N)r9   dimsparamslayersshimsattrsrefsr6   forwardrA   rB   rC   rD   rE   rF   c                   || _         |t          t          |           }t          | d|           t          | d|           |
|
nt	                      | _        t                      | _        t          |          | _	        t          |          | _
        t          |	          | _        t          |          | _        t          |          | _        t          j        5  t          xj        dz  c_        t          j        | _        ddd           n# 1 swxY w Y   i | _        |                                D ]'\  }}d| j        |<   ||                     ||           (dS )zInitialize a new model.Nr8   r9   r   )r5   r   r0   setattrr   r6   r   r:   dictr;   r>   r@   listr<   r=   r$   r4   r3   r7   r?   items	set_param)selfr5   rG   r9   rA   rB   rC   rD   rE   rF   r6   values               r/   __init__zModel.__init__U   st    	<:t,,Dgw'''fd###/33/@/@"}}$ZZ
5kk$ZZ
F||5kk ! 	& 	&OOq OOoDG	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& !<<>> 	, 	,KD%%)DT" tU+++	, 	,s   'DDDr)   c                     | j         S )zmA list of child layers of the model. You can append to it to add
        layers but not reassign it.
        )r<   rN   s    r/   rC   zModel.layers|   s    
 |r1   c                     | j         S r+   )r=   rR   s    r/   rD   zModel.shims   s
    {r1   c                     | j         S )zfA dict of the model's attrs. You can write to it to update attrs but
        not reassign it.
        )r>   rR   s    r/   rE   zModel.attrs   s    
 {r1   .c                 N    t          | j                                                  S )z8Get the names of registered parameter (including unset).)tupler?   keysrR   s    r/   param_nameszModel.param_names   s!     T%**,,---r1   c                 D     t           fd j        D                       S )zHGet the names of parameters with registered gradients (including unset).c                 >    g | ]}                     |          |S r,   )has_grad).0r5   rN   s     r/   
<listcomp>z$Model.grad_names.<locals>.<listcomp>   s*    OOOt4==;N;NOdOOOr1   )rV   rX   rR   s   `r/   
grad_nameszModel.grad_names   s+     OOOOt'7OOOPPPr1   c                 N    t          | j                                                  S )z9Get the names of registered dimensions (including unset).)rV   r;   rW   rR   s    r/   	dim_nameszModel.dim_names        TZ__&&'''r1   c                 N    t          | j                                                  S )z>Get the names of registered node references (including unset).)rV   r@   rW   rR   s    r/   	ref_nameszModel.ref_names   ra   r1   	operatorsc              #      K   | j                             t          |                    }dV  | j                             |           dS )a  Bind arbitrary binary functions to Python operators, for use in any
        `Model` instance. Can (and should) be used as a contextmanager.

        EXAMPLE:
            with Model.define_operators({">>": chain}):
                model = Relu(512) >> Relu(512) >> Softmax()
        N)_context_operatorssetrJ   reset)clsrd   tokens      r/   define_operatorszModel.define_operators   sJ       &**4	??;;$$U+++++r1   c                 :    || j         vrdS | j         |         dS dS )zCheck whether the model has a dimension of a given name. If the
        dimension is registered but the value is unset, returns None.
        FNT)r;   rN   r5   s     r/   has_dimzModel.has_dim   -     tz!!5Z)44r1   c                     || j         vrt          d| d| j         d          | j         |         }|d| d| j         d}t          |          |S )z4Retrieve the value of a dimension of the given name.zCannot get dimension '' for model ''Nz': value unset)r;   KeyErrorr5   
ValueErrorrN   r5   rO   errs       r/   get_dimzModel.get_dim   so    tz!!SDSStySSSTTT
4 =W4WWdiWWWCS//!Lr1   F)forcerO   rx   c                F   || j         vrt          d| d| j         d          | j         |         }t          d | j                                        D                       }|duo||k    o| p|o|}|r"d| d| j         d| d| }t          |          || j         |<   dS )	zSet a value for a dimension.zCannot set unknown dimension 'rq   '.c              3   :   K   | ]\  }}t          |          V  d S r+   )bool)r\   xys      r/   	<genexpr>z Model.set_dim.<locals>.<genexpr>   s,      FFTQaFFFFFFr1   NzAttempt to change dimension 'z' from z to )r;   rs   r5   anyr?   rL   rt   )rN   r5   rO   rx   	old_value
has_paramsinvalid_changerv   s           r/   set_dimzModel.set_dim   s    tz!!QQQDIQQQ   Jt$	FFT-=-C-C-E-EFFFFF
#4/FI4F 
I--: 	  	"m$mmTYmmW`mmfkmmCS//! 
4r1   c                 Z    |                      |          r|                     |          ndS )z=Retrieve the value of a dimension of the given name, or None.N)rn   rw   rm   s     r/   maybe_get_dimzModel.maybe_get_dim   *    %)\\$%7%7At||D!!!TAr1   c                 :    || j         vrdS | j         |         dS dS )zCheck whether the model has a weights parameter of the given name.

        Returns None if the parameter is registered but currently unset.
        FNT)r?   rm   s     r/   	has_paramzModel.has_param   s/    
 t'''5d#/44r1   c                     || j         vrt          d| d| j         d          | j                            | j        |          st          d| d| j         d          | j                            | j        |          S )z%Retrieve a weights parameter by name.zUnknown param: 'rq   rz   zParameter 'z' has not been allocated yet.)r?   rs   r5   r:   r   r7   	get_paramrm   s     r/   r   zModel.get_param   s    t'''NdNNNNNOOO|%%dgt44 	YdYYYYY   |%%dgt444r1   c                 Z    |                      |          r|                     |          ndS )z.Retrieve a weights parameter by name, or None.N)r   r   rm   s     r/   maybe_get_paramzModel.maybe_get_param   s*    '+~~d';';Et~~d###Er1   c                 x    |d| j         |<   dS | j                            | j        ||           d| j         |<   dS )z Set a weights parameter's value.NT)r?   r:   rM   r7   rN   r5   rO   s      r/   rM   zModel.set_param   sI    =%)DT"""L""47D%888%)DT"""r1   c                 B    | j                             | j        |          S )z@Check whether the model has a non-zero gradient for a parameter.)r:   r[   r7   rm   s     r/   r[   zModel.has_grad       |$$TWd333r1   c                 B    | j                             | j        |          S )zGet a gradient from the model.)r:   get_gradr7   rm   s     r/   r   zModel.get_grad   r   r1   c                 H    | j                             | j        ||           dS )z#Set a gradient value for the model.N)r:   set_gradr7   r   s      r/   r   zModel.set_grad  $    dgtU33333r1   c                 Z    |                      |          r|                     |          ndS )z%Retrieve a gradient by name, or None.N)r[   r   rm   s     r/   maybe_get_gradzModel.maybe_get_grad  s*    &*mmD&9&9Ct}}T"""tCr1   c                 H    | j                             | j        ||           dS )z1Increment the gradient of a parameter by a value.N)r:   inc_gradr7   r   s      r/   r   zModel.inc_grad  r   r1   c                 :    || j         vrdS | j         |         dS dS )zCheck whether the model has a reference of a given name. If the
        reference is registered but the value is unset, returns None.
        FNT)r@   rm   s     r/   has_refzModel.has_ref  ro   r1   c                     || j         vrt          d| d| j         d          | j         |         }|d| d| j         d}t          |          |S )z4Retrieve the value of a reference of the given name.zCannot get reference 'rq   rz   Nz': value unset.)r@   rs   r5   rt   ru   s       r/   get_refzModel.get_ref  so    tz!!TDTTtyTTTUUU
4 =X4XXdiXXXCS//!Lr1   c                 Z    |                      |          r|                     |          ndS )z8Retrieve the value of a reference if it exists, or None.N)r   r   rm   s     r/   maybe_get_refzModel.maybe_get_ref&  r   r1   c                     ||| j         |<   dS ||                                 v r|| j         |<   dS t          d          )zSet a value for a reference.Nz)Cannot add reference to node not in tree.)r@   walkrt   r   s      r/   set_refzModel.set_ref*  sM    =$DJtdiikk!!$DJtHIIIr1   Xis_trainc                 2    |                      | ||          S )z~Call the model's `forward` function, returning the output and a
        callback to compute the gradients via backpropagation.r   r8   )rN   r   r   s      r/   __call__zModel.__call__3  s     zz$Hz555r1   Yc                     t          j                    rt          | j        | j        ||           | j        |                     | ||           | S )zFinish initialization of the model, optionally providing a batch of
        example input and output data to perform shape inference.N)r   r   )r   getr    r5   r8   r9   )rN   r   r   s      r/   
initializezModel.initialize8  sS        	C%diQBBB9 IIda1I%%%r1   c                 2    |                      | |d          S )ap  Run the model over a batch of data, returning the output and a
        callback to complete the backward pass. A tuple (Y, finish_update),
        where Y is a batch of output data, and finish_update is a callback that
        takes the gradient with respect to the output and an optimizer function,
        and returns the gradient with respect to the input.
        Tr   r   rN   r   s     r/   begin_updatezModel.begin_updateA  s     zz$Dz111r1   c                 >    |                      | |d          d         S )zCall the model's `forward` function with `is_train=False`, and return
        only the output, instead of the `(output, callback)` tuple.
        Fr   r   r   r   s     r/   predictzModel.predictJ  s!     zz$Ez22155r1   	optimizerc           	         |                                  D ]!}|j        D ]}|                    |           "|                                  D ]t}|j        D ]j}|                    |          rS ||j        |f|                    |          |                    |                    \  }}|                    ||           kudS )zUpdate parameters with current gradients. The optimizer is called
        with each parameter and gradient of the model.
        N)	r   rD   finish_updaterX   r[   r7   r   r   rM   )rN   r   nodeshimr5   paramgrads          r/   r   zModel.finish_updateP  s     IIKK 	. 	.D
 . .""9----.IIKK 	0 	0D( 0 0==&& 0"+)$)=)=t}}T?R?R# #KE4 NN4///0	0 	0r1   c              #   2  K   i }| j         D ]C}| j        |f}||v r4|                     |          ||<   |                     |||                    Dt	          j                    5 }| j        D ]*}|                    |                    |                     +| j	        D ]*}|                    |                    |                     +dV  ddd           n# 1 swxY w Y   |r0|
                                D ]\  }}|                     ||           dS dS )zContext manager to temporarily set the model's parameters to
        specified values. The params are a dictionary keyed by model IDs, whose
        values are arrays of weight values.
        N)rX   r7   r   rM   
contextlib	ExitStackrC   enter_context
use_paramsrD   rL   )	rN   rB   backupr5   keystacklayerr   r   s	            r/   r   zModel.use_params_  s      $ 	2 	2D7D/Cf}}#~~d33ttVC[111!## 	u > >##E$4$4V$<$<====
 = =##DOOF$;$;<<<<EEE	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  	,%||~~ , ,etU++++	, 	,, ,s   #A)CCCbfsorderr   c                    |dk    r|                                  S |dk    r|                     d          S |dk    r|                     d          S t          d          )zIterate out layers of the model.

        Nodes are returned in breadth-first order by default. Other possible
        orders are "dfs_pre" (depth-first search in preorder) and "dfs_post"
        (depth-first search in postorder).r   dfs_preF)
post_orderdfs_postTz5Invalid order, must be one of: bfs, dfs_pre, dfs_post)	_walk_bfs	_walk_dfsrt   )rN   r   s     r/   r   z
Model.walkv  sj     E>>>>###i>>U>333j  >>T>222TUUUr1   c              #      K   | g}t                      }|D ]T}t          |          |v r|                    t          |                     |V  |                    |j                   UdS )z/Iterate out layers of the model, breadth-first.N)rg   r7   addextendrC   )rN   queueseenr   s       r/   r   zModel._walk_bfs  s{       	& 	&D$xx4HHRXXJJJLL%%%%	& 	&r1   r   c              #     K   t                      }| g}t          | j                  |t          |           <   |s| V  |r	 t	          |t          |d                                      }t          |          |vr?|s|V  |                    |           t          |j                  |t          |          <   n0# t          $ r# |r
|d         V  |                                 Y nw xY w|dS dS )z-Iterate out layers of the model, depth-first.N)rJ   iterrC   r7   nextappendStopIterationpop)rN   r   r   r   
next_childs        r/   r   zModel._walk_dfs  s     -1VVdk**RXX 	JJJ 	!$r%)}}"566
*~~--% )((((LL,,,+/
0A+B+BDJ(     $)OOO		  	 	 	 	 	s   A8B: :*C'&C'r   c                 h   t          |                                           D ].}||j        v r#|j                            |           ||j        v #/t	          |                                           }|D ]=}|j        D ]3}|                    |          }|||vr|                    |d           4>dS )a]  Remove a node from all layers lists, and then update references.
        References that no longer point to a node within the tree will be set
        to `None`. For instance, let's say a node has its grandchild as a reference.
        If the child is removed, the grandchild reference will be left dangling,
        so will be set to None.
        N)rK   r   rC   removerg   rc   r   r   )rN   r   childtreer5   refs         r/   remove_nodezModel.remove_node  s     $))++&& 	* 	*E%,&&##D))) %,&&499;; 	- 	-D - -ll4((?s$LLt,,,-	- 	-r1   )r9   c                J    t          | d|           t          | d|           d S )Nr8   r9   )rI   )rN   rG   r9   s      r/   replace_callbackszModel.replace_callbacks  s.     	gw'''fd#####r1   oldnewc                    d}t          |                     d                    D ]Y}|u rd}	fd|j        D             |_        |j        D ]/}|                    |          u r|                    |           0Z|S )zzReplace a node anywhere it occurs within the model. Returns a boolean
        indicating whether the replacement was made.Fr   r   Tc                      g | ]
}|u rn|S r,   r,   )r\   r   r   r   s     r/   r]   z&Model.replace_node.<locals>.<listcomp>  s2          7<5C<<CCU     r1   )rK   r   r<   rc   r   r   )rN   r   r   r   r   r5   s    ``   r/   replace_nodezModel.replace_node  s     
 4455 		0 		0Ds{{         @D      !N 0 0D||D))S00T3///0 r1   c                     i }|                                  D ]D}|j        D ]:}|                    |          }|                    |          }||f||j        |f<   ;E|S )zGet non-zero gradients of the model's parameters, as a dictionary
        keyed by the parameter ID. The values are (weights, gradients) tuples.
        )r   r^   r   r   r7   )rN   	gradientsr   r5   r   r   s         r/   get_gradientszModel.get_gradients  sw     	IIKK 	; 	;D ; ;t,,}}T**.3T]	47D/**; r1   rN   c                 *    |                                  S )z
        Create a copy of the model, its attributes, and its parameters. Any child
        layers will also be deep-copied. The copy will receive a distinct `model.id`
        value.
        )_copyrR   s    r/   copyz
Model.copy  s     zz||r1   r   c           
      R   |i }i }| j         D ]1}|                     |          r|                     |          nd ||<   2g }| j        D ]}t	          |          |v r<|                    t          t          |t	          |                                        O|                    |          }||t	          |          <   |                    |           g }| j	        D ]}t	          |          |v r<|                    t          t          |t	          |                                        O|                                }	|	|t	          |          <   |                    |	           t          | j        | j        | j        t          j        |          t          j        | j                  t          j        | j                  ||          }
| j        D ]=}|
                    ||                     |                                                     >t          t*          |
          S )N)r9   rB   rA   rE   rC   rD   )rX   r   r   rC   r7   r   r   r$   r   rD   r   r   r5   r8   r9   deepcopyr;   r>   r^   r   r   r#   )rN   r   rB   r5   copied_layersr   copied_layercopied_shimsr   copied_shimcopieds              r/   r   zModel._copy  s    <D$ 	R 	RD37>>$3G3GQ4>>$///TF4LL%'[ 	3 	3E%yyD  $$T%bii%A%ABBBB${{400".RYY$$\2222J 	1 	1D$xx4##DtBtHH~$>$>????"iikk!,RXX##K0000#(IJ=((tz**-,, 	$
 	$
 	$
 O 	> 	>DOOD$--"5"5":":"<"<====E6"""r1   gpu_idc                     ddl }|j        j                            |          5  |                     t                                 ddd           dS # 1 swxY w Y   dS )z)Transfer the model to a given GPU device.r   N)cupy.cuda.devicecudadeviceDevice_to_opsr   )rN   r   cupys      r/   to_gpuzModel.to_gpu  s    Y$$V,, 	$ 	$LL###	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$s   "AAAc                 H    |                      t                                 dS )zTransfer the model to CPU.N)r   r   rR   s    r/   to_cpuzModel.to_cpu  s    XZZ     r1   c           
         |                                  D ]}||_        |j        D ]}|                    |          r<|                    ||                    |                    |                               |                    |          r<|                    ||                    |	                    |                               |j
        D ]"}|                    |j        |j                   #dS )z Common method for to_cpu/to_gpu.N)r   r6   rX   r   rM   	asarray_fr   r[   r   r   rD   	to_devicedevice_type	device_id)rN   r6   r   r5   r   s        r/   r   zModel._to_ops  s    IIKK 	? 	?DDH( L L>>$'' NNN4t~~d7K7K)L)LMMM==&& LMM$dmmD6I6I(J(JKKK
 ? ?s>>>>?	? 	?r1   c                     |                                  }t          | j        j        d          }t	          t
          ||          }t          j        |          S )aa  Serialize the model to a bytes representation. Models are usually
        serialized using msgpack, so you should be able to call msgpack.loads()
        on the data and get back a dictionary with the contents.

        Serialization should round-trip identically, i.e. the same bytes should
        result from loading and serializing a model.
        <)
byte_order)to_dictr   r6   to_numpyr   r   srslymsgpack_dumps)rN   msgto_numpy_les      r/   to_byteszModel.to_bytes&  sJ     llnndh/C@@@[#>>"3'''r1   pathc                     t          |t                    rt          |          n|}|                    d          5 }|                    |                                            ddd           dS # 1 swxY w Y   dS )zSerialize the model to disk. Most models will serialize to a single
        file, which should just be the bytes contents of model.to_bytes().
        wbN)
isinstancestrr   openwriter  )rN   r  file_s      r/   to_diskzModel.to_disk3  s     (c22<tDzzzYYt__ 	)KK(((	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)s   (A11A58A5c                    g g g g d}t          |                                           }d t          |          D             }t          |          D ]\  }}i }g }|j        D ]a}|                    |          sd||<   |                    |          }	|	j        |v r||	j                 ||<   L|                    |           b|rt          d|           i }
|j	        D ]1}|
                    |          r|                    |          nd|
|<   2|d                             ||j        |
|d           |D ]d}i }|j                                        D ]+\  }}	 t          ||||          ||<   # t           $ r Y (w xY w|d                             |           e|D ],}|d                             d	 |j        D                        -|D ]z}i }|j        D ]S}|                    |          r7t)          t*          t,                   |                    |                    ||<   Nd||<   T|d
                             |           {|S )zSerialize the model to a dict representation.

        Serialization should round-trip identically, i.e. the same dict should
        result from loading and serializing a model.
        )nodesrE   rB   rD   c                 $    i | ]\  }}|j         |S r,   )r7   )r\   ir   s      r/   
<dictcomp>z!Model.to_dict.<locals>.<dictcomp>K  s     @@@GAtTWa@@@r1   NzCannot get references: r  )indexr5   rA   rF   rE   rD   c                 6    g | ]}|                                 S r,   )r  )r\   r   s     r/   r]   z!Model.to_dict.<locals>.<listcomp>i  s      H H HT H H Hr1   rB   )rK   r   	enumeraterc   r   r   r7   r   rt   r`   rn   rw   r5   rE   rL   serialize_attr	TypeErrorrD   rX   r   r   r   r   r   )rN   r
  r  	node_to_ir  r   rF   invalid_refsr5   r   rA   dimrE   rO   rB   s                  r/   r  zModel.to_dict;  s    *,bBQSTTTYY[[!!
 A@y/?/?@@@	 '' 	 	GAt-/D&(L 2 2||D)) 2!%DJJ,,t,,Cv**%.sv%6T

$++D1111 K !I<!I!IJJJD~ M M15c1B1BLDLL---S		LTYdKK     	' 	'DE#z//11  e"0tT"J"JE$KK    HL&&&& 	J 	JDL H HTZ H H HIIII 	) 	)D46F( ( (>>$'' (#'(:DNN4<P<P#Q#QF4LL#'F4LLM  ((((
s   E33
F ?F 
bytes_datac                     t          j        |          }t          t          | j        j        |          }|                     |          S )ae  Deserialize the model from a bytes representation. Models are usually
        serialized using msgpack, so you should be able to call msgpack.loads()
        on the data and get back a dictionary with the contents.

        Serialization should round-trip identically, i.e. the same bytes should
        result from loading and serializing a model.
        )r  msgpack_loadsr   r   r6   asarray	from_dict)rN   r#  r
  s      r/   
from_byteszModel.from_bytest  s<     !*--TX-=sCC~~c"""r1   c                     t          |t                    rt          |          n|}|                    d          5 }|                                }ddd           n# 1 swxY w Y   |                     |          S )a  Deserialize the model from disk. Most models will serialize to a single
        file, which should just be the bytes contents of model.to_bytes().

        The model instance must have the same architecture (layers, dimensions)
        as the model that was serialized. For example, if a chain(Relu(10),
        Relu(1), Logistic()) model was saved, load it into a model created with
        the same chain(...) call, not a bare Model().
        rbN)r  r  r   r  readr(  )rN   r  r  r#  s       r/   	from_diskzModel.from_disk  s     (c22<tDzzzYYt__ 	&J	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&z***s   AA!$A!r
  c                    d|                                 vrd}t          |          t          |                                           }t	          |d                   t	          |          k    rt          d          t          |          D ]\  }}|d         |         }|d         |_        |d                                         D ]\  }}||                    ||           |d                                         D ]:\  }	}
|
|	                    |	d            |	                    |	||
                    ;|d         |                                         D ];\  }}|j
                            |          }t          ||||          }||j
        |<   <|d         |                                         D ]I\  }}|,|j                            |                                          }|                    ||           Jt          |d	         |                   D ]%\  }}|j        |                             |           &| S )
Nr  zMTrying to read a Model that was created with an incompatible version of Thincz.Cannot deserialize model: mismatched structurer5   rA   rF   rE   rB   rD   )rW   rt   rK   r   lenr  r5   rL   r   r   rE   r   deserialize_attrr6   r&  r   rM   rD   r(  )rN   r
  rv   r  r  r   infor"  rO   r   	ref_indexattrdefault_valueloaded_value
param_name
shim_bytess                   r/   r'  zModel.from_dict  sA   #((**$$aCS//!TYY[[!!s7|E

**MNNN '' 	5 	5GAtw<?DVDI"6l0022 - -
U$LLe,,,"&v,"4"4"6"6 8 8Y$LLd++++LLeI&67777"7|A4466 0 0e $
t 4 4/udDQQ#/
4  %(]1%5%;%;%=%= 2 2!
E$ H,,U3388::Ez51111!*3w<?!;!; 5 5:
1((44445r1   Tstrictr8  c                R   t          |t                    rt          |          n|}|                                s|                                sdS |                    d          5 }|                                }ddd           n# 1 swxY w Y   |                     ||          S )zCheck whether serialized data on disk is compatible with the model.
        If 'strict', the function returns False if the model has an attribute
        already loaded that would be changed.
        Fr*  Nr7  )r  r  r   is_direxistsr  r+  can_from_bytes)rN   r  r8  r  r#  s        r/   can_from_diskzModel.can_from_disk  s    
 (c22<tDzzz;;== 	 	5YYt__ 	&J	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&"":f"===s   &BBBc                ~    	 t          j        |          }n# t          $ r Y dS w xY w|                     ||          S )zCheck whether the bytes data is compatible with the model. If 'strict',
        the function returns False if the model has an attribute already loaded
        that would be changed.
        Fr7  )r  r%  rt   can_from_dict)rN   r#  r8  r
  s       r/   r<  zModel.can_from_bytes  sT    
	%j11CC 	 	 	55	!!#f!555s    
%%c                (   d|                                 vrdS t          |                                           }t          |d                   t          |          k    rdS t	          |          D ]\  }}|d         |         }|r|d         |j        k    r dS t          |d         |                   t          |j                  k    r dS |d                                         D ]A\  }}|                    |          }	|	du r  dS |	r|	                    |          |k    r  dS B|d         |                                         D ]O\  }
}|
                    |
          }|du r  dS |r+|)|                    |
          }|j        |j        k    r  dS P|rs|d         |                                         D ]R\  }}||j        v rD	 t          |j        |         |j        |         ||          }n# t          $ r Y Dw xY w||k    r  dS Sd	S )
zCheck whether a dictionary is compatible with the model.
        If 'strict', the function returns False if the model has an attribute
        already loaded that would be changed.
        r  Fr5   rD   rA   rB   NrE   T)rW   rK   r   r.  r  r5   rD   rL   rn   rw   r   r   shaperE   r  r  )rN   r
  r8  r  r  r   r0  r"  rO   rn   r5  r   r   r2  
serializeds                  r/   r?  zModel.can_from_dict  sa   
 #((**$$5TYY[[!!s7|E

**5 '' !	) !	)GAtw<?D $v,$)33uu3w<?##s4:66 uu"6l0022 ! !
U,,s++e## 555 !c!2!2e!;!; 555%(]1%5%;%;%=%= % %!
E NN:66	%% 555 %5#4 NN:66E{ek11$uuu )#&w<?#8#8#:#: 
) 
)KD%tz))%)7 $
4 0$*T2BD$* *JJ  ) % % %$H%%..#(555ts   (G55
HHotherc                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '+' operator.+zUndefined operator: +rf   r   r  rN   rC  s     r/   __add__zModel.__add__  Q    d-11333334441t&**,,S1$>>>r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '-' operator.-zUndefined operator: -rF  rG  s     r/   __sub__zModel.__sub__  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '*' operator.*zUndefined operator: *rF  rG  s     r/   __mul__zModel.__mul__  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '@' operator.@zUndefined operator: @rF  rG  s     r/   
__matmul__zModel.__matmul__  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S z-Apply the function bound to the '/' operator./zUndefined operator: /rF  rG  s     r/   __div__zModel.__div__
  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S rT  rF  rG  s     r/   __truediv__zModel.__truediv__  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z.Apply the function bound to the '//' operator.z//zUndefined operator: //rF  rG  s     r/   __floordiv__zModel.__floordiv__  Q    t.22444445552t&**,,T24???r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '%' operator.%zUndefined operator: %rF  rG  s     r/   __mod__zModel.__mod__  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z.Apply the function bound to the '**' operator.z**zUndefined operator: **rF  )rN   rC  r.   s      r/   __pow__zModel.__pow__"  r[  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z.Apply the function bound to the '<<' operator.z<<zUndefined operator: <<rF  rG  s     r/   
__lshift__zModel.__lshift__(  r[  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z.Apply the function bound to the '>>' operator.z>>zUndefined operator: >>rF  rG  s     r/   
__rshift__zModel.__rshift__.  r[  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '&' operator.&zUndefined operator: &rF  rG  s     r/   __and__zModel.__and__4  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '^' operator.^zUndefined operator: ^rF  rG  s     r/   __xor__zModel.__xor__:  rI  r1   c                     d| j                                         vrt          d           | j                                         d         | |          S )z-Apply the function bound to the '|' operator.|zUndefined operator: |rF  rG  s     r/   __or__zModel.__or__@  rI  r1   )NN)F)r   r$   r)   Nr+   )r)   N)k__name__
__module____qualname____doc__r3   int__annotations__	threadingLockr4   r&   rf   r  r   r   r   r   r   r   r   r   r|   	__slots__r   r   r   r   r   rP   propertyrC   rD   rE   r   rX   r^   r`   rc   classmethodr   contextmanagerrk   rn   rw   r   r   r   r   r   rM   r[   r   r   r   r   r   r   r   r   r!   r"   r   r   r   r   r   r   r   r	   r   r   r   r   r   r   r   r#   r   r   r   r   r   bytesr  r   r  r  r(  r,  r'  r=  r<  r?  rH  rL  rO  rR  rV  rX  rZ  r^  r`  rb  rd  rg  rj  rm  r,   r1   r/   r$   r$   1   s        99Is%3Y^%5%5NIN555*
III	HHHGGGOOO
NNNXc]"####']JcNc8D>)****  I( $()+02$& "-/26%, %, %,%, %,
 x %, 3%&%, S(8,,-%, !%, Dz%, CH~%, 3))*%, eHg-./%, %, %, %,N W    X tDz    X tCH~    X .U38_ . . . X. QE#s(O Q Q Q XQ (5c? ( ( ( X( (5c? ( ( ( X( 
,c8m)< 
, 
, 
,  [
,	C 	HTN 	 	 	 		C 	C 	 	 	 	 ?D ! ! !C ! !t ! ! ! ! ! B# B(3- B B B B
c 
htn 
 
 
 
5c 5h 5 5 5 5FC FHX,> F F F F*c *(8*< * * * * *4S 4T 4 4 4 44S 4X 4 4 4 44S 4 4d 4 4 4 4D3 D8H+= D D D D4S 4 4d 4 4 4 4	C 	HTN 	 	 	 		C 	G 	 	 	 	B# B(7*; B B B BJC J(9 Jd J J J J6# 6 6%h2G 6 6 6 6
 HSM Xd^ w    2c 2eD(D63;2G,G&H 2 2 2 26 6 6 6 6 60y 0T 0 0 0 0 ,eCHox&?!@ , , , ,, $) V V VS VXg-> V V V V	&8G, 	& 	& 	& 	& D Xg5F    ,- - - -$ @D$ $ $$*28*<$	$ $ $ $ g $    *
tE#s(OU8X;M5N$NO 
 
 
 
5 U     HL'# '#'##DeGTM.B)B$CD'#	'# '# '# '#R$S $T $ $ $ $! ! ! !
?3 
?4 
? 
? 
? 
?(% ( ( ( ()E$), ) ) ) ) )7 7 7 7 7r
#U 
#w 
# 
# 
# 
#+eD#I. +7 + + + +T g    < GK 
> 
> 
>%c	"2 
>t 
>t 
> 
> 
> 
> CG 	6 	6 	6 	64 	64 	6 	6 	6 	6 :> - - - -$ -$ - - - -^?S ?W ? ? ? ??S ?W ? ? ? ??S ?W ? ? ? ?? ? ? ? ? ??S ?W ? ? ? ?? ? ? ? ? ?@# @' @ @ @ @?S ?W ? ? ? ?@S @w @ @ @ @@ @ @ @ @ @@ @ @ @ @ @?S ?W ? ? ? ??S ?W ? ? ? ??C ?G ? ? ? ? ? ?r1   _rO   r5   c                 *    t          j        |          S )zSerialize an attribute value (defaults to msgpack). You can register
    custom serializers using the @serialize_attr.register decorator with the
    type to serialize, e.g.: @serialize_attr.register(MyCustomObject).
    )r  r	  r{  rO   r5   r(   s       r/   r  r  G       u%%%r1   c                 *    t          j        |          S )zDeserialize an attribute value (defaults to msgpack). You can register
    custom deserializers using the @deserialize_attr.register decorator with the
    type to deserialize, e.g.: @deserialize_attr.register(MyCustomObject).
    )r  r%  r}  s       r/   r/  r/  P  r~  r1   _ModelTmappingc                     |                                  D ]E}|j        |v r:||j                 }|                                D ]\  }}||j        v r
||j        |<   F| S )zWalk over the model's nodes, changing the value of attributes using the
    provided mapping, which maps node names to attr names to attr values.
    )r   r5   rL   rE   )r(   r  r   rE   r2  rO   s         r/   change_attr_valuesr  \  so     

 - -9DI&E${{}} - -e4:%%',DJt$Lr1   dropout_ratedropc                 d    |                                  D ]}|D ]}||j        v r
||j        |<   | S )zWalk over the model's nodes, setting the dropout rate. You can specify
    one or more attribute names, by default it looks for ["dropout_rate"].
    )r   rE   )r(   r  rE   r   r2  s        r/   set_dropout_rater  i  sP     

 ( ( 	( 	(Dtz!!#'
4 	( Lr1   wrapperc                     t          |                                           D ]!}|                     | ||                     " ||           S )zORecursively wrap a model and its submodules. The model is updated
    in-place.)rK   r   r   )r(   r  r   s      r/   wrap_model_recursiver  t  sR     UZZ\\"" 0 04////75>>r1   )r$   r  r/  r  r  r  )r(   r$   r)   r$   )=r   r   	functoolsrt  contextvarsr   pathlibr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r  backendsr   r   r   r   r   
optimizersr   rD   r   typesr   utilr   r   r   r   r    r!   r"   r#   r&   rJ   rs  r0   r$   singledispatchr  rz  r  r/  r  r  floatr  r  __all__r,   r1   r/   <module>r     s                 " " " " " "                                     "  J J J J J J J J J J J J J J ! ! ! ! ! !                          gennwvw'''&0j1Db&Q&Q&Q :d# Q Q Q   S? S? S? S? S?GCI S? S? S?l &c &# &S & &5 & & & & & &C &s &5 &S & & & & ')5
)
)
)
g 
S$sCx.5H0I 
g 
 
 
 
 :H8H  G 5 W     %'9I0J w      r1   