o
    * i:t                     @  s  d dl mZ d dlZd dlZd dlZd dl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 g ZdZd	d
lmZmZmZ dd Zedd Zedd Zd dlmZ dd ZG dd dZdd Zd#ddZd#ddZ dd Z!dd Z"dd  Z#G d!d" d"ej$Z%dS )$    )annotationsN)core	frameworkunique_name)switch_to_static_graph)in_dynamic_mode)layers)datatype_to_vartypez.json   )BUFFER_NAME_PREFIXINFER_PARAMS_SUFFIXPARAMETER_NAME_PREFIXc                 C  s"   t j }t jj| |}||fS N)paddlestaticZProgrambaser   Zdeserialize_pir_program)model_file_pathprogram	trainable r   k/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/paddle/jit/pir_translated_layer.py_load_pir_program'   s
   
r   c                 C  
   t | S r   )r   Zgenerate_with_ignorable_keyprefixr   r   r   _generate_unique_var_name0      
r   c                 C  r   r   )r   generater   r   r   r   r   5   r   )get_pir_parametersc           	      C  sf   g }g }i }t | \}}|| }|D ]}|| |j}t|j|_|||j< ||j q|||fS r   )r   appendnamer   )	r   persistable_varspersistable_namesZrename_new_old_dictparamoptvarsvarZorigin_namer   r   r   _get_pir_parameters_var_names=   s   

r'   c                      s`   e Zd Z fddZdd Zedd Zedd Zed	d
 Zedd Z	edd Z
  ZS )_PirProgramHolderc                   s@   t    g | _g | _g | _g | _|| _d | _|| _| 	  d S r   )
super__init___input_vars_output_vars_parameter_vars_parameter_namessupport_train_suffix_varname_dict_infer_program_preprocess)selfr   r   	__class__r   r   r*   R   s   
z_PirProgramHolder.__init__c              	   C  sJ  t | j\| _| _| _| j }|jD ]}| dkr%| j	|
d nD| dkri| d }|
d}|$ tjj||j|jtjj d}|| | | W d    n1 s_w   Y  || | dkr| j	|d | tj|ddtt| jd   W d    n1 sw   Y  || qd S )	Nz
pd_op.datar   z
pd_op.feedr    )r    shapedtypeplacezpd_op.fetchZoutput_r
   )r'   r1   r-   r.   r0   global_blockopsr    r+   r   resultattrr   Z_pir_opsdatar6   r7   r   r   ZPlaceZreplace_all_uses_withZget_defining_opZmove_beforeZ	remove_opr,   Zoperand_sourceZset_persistable_valuestrlen)r3   blockopvar_nameZ	org_valuevaluer   r   r   r2   b   sD   





	
z_PirProgramHolder._preprocessc                 C     | j S r   )r1   r3   r   r   r   infer_program      z_PirProgramHolder.infer_programc                 C  rD   r   )r+   rE   r   r   r   
input_vars   rG   z_PirProgramHolder.input_varsc                 C  rD   r   )r,   rE   r   r   r   output_vars   rG   z_PirProgramHolder.output_varsc                 C  rD   r   )r.   rE   r   r   r   r"      rG   z#_PirProgramHolder.persistable_namesc                 C  rD   r   )r-   rE   r   r   r   r!      rG   z"_PirProgramHolder.persistable_vars)__name__
__module____qualname__r*   r2   propertyrF   rH   rI   r"   r!   __classcell__r   r   r4   r   r(   Q   s     



r(   c              	     s.  i }g }i }g } j } j} fdd|D }	tt|	|D ]D\}
}|jrHtj|jtj	j
j|jdd}|j|_|||
< || ||  qtjjt|j |j|jtj	j
jt dd}|||
< q|d uskJ dtj| |}tj|rt|t| |dt  ntd| d	|| |S )
Nc                      g | ]} j | qS r   r0   .0rB   program_holderr   r   
<listcomp>       z,_load_pir_parameter_vars.<locals>.<listcomp>T)r6   r7   r    persistableF)r7   dimsr    typer8   rW   z#params_filename should not be None.z	The file z- does not exist. Please check the model path.)r!   r"   sortedziprW   r   EagerParamBaser6   r   ZVarDescZVarTypeZFP32r    Zstop_gradientr   Z
get_tensoreagerTensorr	   r7   ZDENSE_TENSOR_current_expected_placeospathjoinexistsZload_combine_funclistkeys
ValueErrorupdate)
model_pathrT   params_filenameZload_var_dictZload_var_listZother_var_dictZload_densetensor_listZpersistable_varZpersistable_var_nameorigin_persistable_var_namer    r&   Znew_varZvar_file_pathr   rS   r   _load_pir_parameter_vars   sZ   





rk   c                 C  sf  i }|d urwt j|}t j| |}|d tt  }t | D ]S}||kr1d}t j| |}n6|trf||rf|t|tt d  	d}t|dkret|d dkre|d }t j| |}nq!q!t
|\}}	t||	||< q!|S t | D ]4\}
}
}|D ],}d|v rt j| |}|d}|dkrd}n|dd t
|\}}	t||	||< qq||S )	Nforwardr
   .   r   model_ )r`   ra   basenamerb   r?   PIR_INFER_MODEL_SUFFIXlistdirendswith
startswithsplitr   r(   walkstripreplace)rh   model_filenameZprogram_holder_dictr   
model_namefilename	func_nameparsing_namesr   r   rp   Z
file_namesr    method_namer   r   r   _construct_program_holders   sX   

r   c           	      C  s   t j| t|}|d urt j|si S t| |d |}|d tt  }t | D ]<}|	|r[|
tr[|t|tt d  d}t|dkrZt|d dkrZ|d }nq+q+|t| || | q+|S )Nrl   r
   rm   rn   r   )r`   ra   rb   r>   rc   rk   r?   r   rt   rv   ru   rw   rg   )	rh   programsri   Zparams_pathZvar_dictr|   	file_namer   r~   r   r   r   _construct_params_and_buffers!  s4   


r   c                   s  g }g }t |D ]D\}}t|tjtjjfs tdt| dt|tjr8tjj| j	| j
dt dd}n	|} j	| j
|_
||j
 || q| |d u rg }	 fdd jD }
|
D ]*}| j| }|| jv rw|	| j|  qb|| jv r|	| j|  qbtd| d	d
dlm}  j	} j}|	 jf}| j|||}| || | |}| jrd|_||S  jstdd|_||S )Nz^The type of input in PirTranslatedLayer must be numpy array or Variable(Tensor), but received rm   FT)rC   r    rW   r8   Z	zero_copyc                   rO   r   rP   rQ   rS   r   r   rU   a  rV   z _run_dygraph.<locals>.<listcomp>zThe persistable variable z. does not exist in current PirTranslatedLayer.r   )PartialProgramLayerz@The model is not trainable, please check model_file of jit.save.)	enumerate
isinstancenpZndarrayr   r]   r^   	TypeErrorrY   rH   r    r   r_   r   _get_partial_program_layerr"   _persistable_var_name_dict_parameters_buffersrf   Z(paddle.jit.dy2static.pir_partial_programr   rI   r!   rF   _set_partial_program_layer_is_testtrainingr/   )instanceinputrT   r   Zinput_tensorsZinput_tensor_namesirC   ZtensorZpersistable_tensorsrj   rB   Zdy_var_namer   inputsZoutputs
parameterslayerr   rS   r   _run_dygraphD  sl   







	r   c              	     sF  t j }t j  t| j}| jD ]=}| dkrS| jd| D ]+}| | krR|	dj|	djkrRt
| D ]} |	||	| qCq'q|j}t|t| krntdt| dt|  dt|| D ]
\}	}
 |	|
 qst j }| }| |  fdd|jD }t|d	kr|d S |S )
zg
    This function is used when the pirTranslatedLayer is
    applied for dy_to_static conversion.
    zbuiltin.parameterNr   z)The number of input is invalid, expected z, but received rm   c                   s   g | ]}  |qS r   )Zlook_up)rR   vZ	value_mapr   r   rU     s    z%_run_static_graph.<locals>.<listcomp>r
   )r   r   Zdefault_main_programZpirZ	IrMappingr?   r9   r:   r    r;   rangeZnum_resultsaddrH   rf   r[   Zget_current_insertion_pointr@   Zcopy_to_blockrI   )r   rT   Zsrc_programZdst_programZ
len_dst_opZdst_opZsrc_opr   Z
src_inputsZ	src_inputZinput_Zcurrent_insert_pointZcurrent_blockoutputr   r   r   _run_static_graph  s.   


r   c                 C  sR   g }|dk r|S |  |jD ]}|| q|  |j}|dkr'|t| |7 }|S )z
    Get variables in current block and its parent block.

    Args:
        program(Program): The program containing the current block.
        block_idx(int): index of current block.

    Returns:
        List: list of variables.
    r   )r@   r%   r   
parent_idx_collect_current_and_parent_var)r   Z	block_idxr%   r&   r   r   r   r   r     s   r   c                      s   e Zd ZdZd fddZeejdd	d
Ze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 Zdd Z  ZS )!PirTranslatedLayeraX  
    PirTranslatedLayer is a ``paddle.nn.Layer`` for holding the model
    loaded by :ref:`api_paddle_jit_load` . It can be used like a
    general Layer object in eval or train mode.

    .. note:
        The PirTranslatedLayer objects should not be created by constructor, it only can be loaded and constructed by :ref:`api_paddle_jit_load` .

    Examples:
        .. code-block:: python

            >>> # doctest: +SKIP('`paddle.jit.to_static` can not run in xdoctest')
            >>> import numpy as np
            >>> import paddle
            >>> import paddle.nn as nn
            >>> import paddle.optimizer as opt

            >>> BATCH_SIZE = 16
            >>> BATCH_NUM = 4
            >>> EPOCH_NUM = 4

            >>> IMAGE_SIZE = 784
            >>> CLASS_NUM = 10

            >>> # define a random dataset
            >>> class RandomDataset(paddle.io.Dataset): # type: ignore[type-arg]
            ...     def __init__(self, num_samples):
            ...         self.num_samples = num_samples
            ...
            ...     def __getitem__(self, idx):
            ...         image = np.random.random([IMAGE_SIZE]).astype('float32')
            ...         label = np.random.randint(0, CLASS_NUM - 1, (1, )).astype('int64')
            ...         return image, label
            ...
            ...     def __len__(self):
            ...         return self.num_samples
            ...
            >>> class LinearNet(nn.Layer):
            ...     def __init__(self):
            ...         super().__init__()
            ...         self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
            ...
            ...     @paddle.jit.to_static
            ...     def forward(self, x):
            ...         return self._linear(x)
            ...
            >>> def train(layer, loader, loss_fn, opt):
            ...     for epoch_id in range(EPOCH_NUM):
            ...         for batch_id, (image, label) in enumerate(loader()):
            ...             out = layer(image)
            ...             loss = loss_fn(out, label)
            ...             loss.backward()
            ...             opt.step()
            ...             opt.clear_grad()
            ...             print("Epoch {} batch {}: loss = {}".format(
            ...                 epoch_id, batch_id, np.mean(loss.numpy())))
            ...
            >>> # 1. train & save model.
            >>> # create network
            >>> layer = LinearNet()
            >>> loss_fn = nn.CrossEntropyLoss()
            >>> adam = opt.Adam(learning_rate=0.001, parameters=layer.parameters())

            >>> # create data loader
            >>> dataset = RandomDataset(BATCH_NUM * BATCH_SIZE)
            >>> loader = paddle.io.DataLoader(dataset,
            ...     batch_size=BATCH_SIZE,
            ...     shuffle=True,
            ...     drop_last=True,
            ...     num_workers=2
            ... )
            >>> # train
            >>> train(layer, loader, loss_fn, adam)

            >>> # save
            >>> model_path = "linear.example.model"
            >>> paddle.jit.save(layer, model_path)

            >>> # 2. load model as PirTranslatedLayer
            >>> # load
            >>> translated_layer = paddle.jit.load(model_path)

            >>> # inference
            >>> translated_layer.eval()
            >>> x = paddle.randn([1, IMAGE_SIZE], 'float32')
            >>> pred = translated_layer(x)

            >>> # fine-tune
            >>> translated_layer.train()
            >>> adam = opt.Adam(learning_rate=0.001, parameters=translated_layer.parameters())
            >>> train(translated_layer, loader, loss_fn, adam)

    r    dict[str, paddle.static.Program]r!   dict[str, paddle.Tensor]c                   s   t    t|tstdt|tstd|| _i | _t A |	 D ]4\}}t|t
jr@tt}|| j|< | || q&t|tjjrWtt}|| j|< | || q&tdW d    n1 sew   Y  d| _d | _i | _d S )NzHPirTranslatedLayer need to use _ProgramHolder's dict for initialization.zLPirTranslatedLayer need to use persistable variable dict for initialization.z?Adding persistent variable which  to layer is not supported nowT)r)   r*   r   dictr   _program_holder_dictr   r   guarditemsr   r\   r   r   Zadd_parameterr   r]   r^   r   Zregister_bufferr   _input_args_names_partial_program_layers)r3   r   r!   r    r&   Zdy_namer4   r   r   r*   &  s:   


	



zPirTranslatedLayer.__init__Nc           	      C  s   t j| } t j| std|  dd }d }|d ur"|j}|j}t| |}t| ||}t	||}|
 D ]\}}|jd u rHdd |jD |_tt	|t	|| q6|  |S )NzThere is no directory named ''c                 S  s   g | ]}|j qS r   )r    )rR   Zinsr   r   r   rU   o  s    z1PirTranslatedLayer._construct.<locals>.<listcomp>)r`   ra   normpathisdirrf   r{   ri   r   r   r   r   r   rH   setattr_execution_method_creatoreval)	rh   Zconfigsr{   ri   r   r!   translated_layerr   rT   r   r   r   
_constructT  s6   


	zPirTranslatedLayer._constructc                   s    fdd  _  S )Nc                   s.   | j  j }t rt| ||S t|||jS r   )r   rJ   r   r   r   rF   )r3   r   rT   __i_m_p_l__r   r   r   r     s   zAPirTranslatedLayer._execution_method_creator.<locals>.__i_m_p_l__)rJ   )r   rT   r   r   r   r     s   z,PirTranslatedLayer._execution_method_creatorc                 C     d| _ d| _d S )NFTr   r   rE   r   r   r   train     
zPirTranslatedLayer.trainc                 C  r   )NTFr   rE   r   r   r   r     r   zPirTranslatedLayer.evalrl   c                 C  s   |  |}|j}|S )aX  
        Gets translated program of specified method.

        Args:
            - method_name (string): method name corresponding to the program
                to be obtained. Default: 'forward'.

        Returns:
            Program

        Examples:
            .. code-block:: python

                >>> # doctest: +SKIP('`paddle.jit.to_static` can not run in xdoctest')
                >>> import numpy as np
                >>> import paddle
                >>> from paddle import nn
                >>> import paddle.optimizer as opt

                >>> BATCH_SIZE = 16
                >>> BATCH_NUM = 4
                >>> EPOCH_NUM = 4

                >>> IMAGE_SIZE = 784
                >>> CLASS_NUM = 10

                >>> # define a random dataset
                >>> class RandomDataset(paddle.io.Dataset): # type: ignore[type-arg]
                ...     def __init__(self, num_samples):
                ...         self.num_samples = num_samples
                ...
                ...     def __getitem__(self, idx):
                ...         image = np.random.random([IMAGE_SIZE]).astype('float32')
                ...         label = np.random.randint(0, CLASS_NUM - 1, (1, )).astype('int64')
                ...         return image, label
                ...
                ...     def __len__(self):
                ...         return self.num_samples
                ...
                >>> class LinearNet(nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...         self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
                ...
                ...     @paddle.jit.to_static
                ...     def forward(self, x):
                ...         return self._linear(x)
                ...
                >>> def train(layer, loader, loss_fn, opt):
                ...     for epoch_id in range(EPOCH_NUM):
                ...         for batch_id, (image, label) in enumerate(loader()):
                ...             out = layer(image)
                ...             loss = loss_fn(out, label)
                ...             loss.backward()
                ...             opt.step()
                ...             opt.clear_grad()
                ...             print("Epoch {} batch {}: loss = {}".format(
                ...                 epoch_id, batch_id, np.mean(loss.numpy())))
                ...
                >>> # create network
                >>> layer = LinearNet()
                >>> loss_fn = nn.CrossEntropyLoss()
                >>> adam = opt.Adam(learning_rate=0.001, parameters=layer.parameters())
                >>> # create data loader
                >>> dataset = RandomDataset(BATCH_NUM * BATCH_SIZE)
                >>> loader = paddle.io.DataLoader(dataset,
                ...     batch_size=BATCH_SIZE,
                ...     shuffle=True,
                ...     drop_last=True,
                ...     num_workers=2
                ... )
                >>> # train
                >>> train(layer, loader, loss_fn, adam)

                >>> # save
                >>> model_path = "linear.example.model"
                >>> paddle.jit.save(layer, model_path)

                >>> # load
                >>> translated_layer = paddle.jit.load(model_path)

                >>> # get program
                >>> program = translated_layer.program()
        )_get_program_holderrF   )r3   r   rT   r   r   r   r   r     s   
VzPirTranslatedLayer.programc                 C  s*   | j |d }|d u rtd| d|S )NzThe method `z.` does not exist in loaded PirTranslatedLayer.)r   getrf   )r3   r   rT   r   r   r   r     s   
z&PirTranslatedLayer._get_program_holderc                 C  @   |  |}g }|jD ]}tjj|j|j|jd}|| q
|S N)r6   r7   r    )	r   rH   r   r   	InputSpecr6   r7   r    r   )r3   r   rT   Z
input_specr&   specr   r   r   _input_spec  s   

zPirTranslatedLayer._input_specc                 C  r   r   )	r   rI   r   r   r   r6   r7   r    r   )r3   r   rT   Zoutput_specr&   r   r   r   r   _output_spec  s   

zPirTranslatedLayer._output_specc                 C  s   | j |d S r   )r   r   )r3   r   r   r   r   r        z-PirTranslatedLayer._get_partial_program_layerc                 C  s   || j |< d S r   )r   )r3   r   r   r   r   r   r   "  r   z-PirTranslatedLayer._set_partial_program_layer)r   r   r!   r   r   )rl   )rJ   rK   rL   __doc__r*   staticmethodr   Zdygraph_onlyr   r   r   r   r   r   r   r   r   r   rN   r   r   r4   r   r     s     ^.)


]

r   r   )&
__future__r   r`   numpyr   r   Zpaddle.baser   r   r   Zpaddle.base.dygraph.baser   Zpaddle.frameworkr   Zpaddle.nn.layerr   Zpaddle.pir.corer	   __all__rs   r   r   r   r   r   r   Zpaddle.static.pir_ior   r'   r(   rk   r   r   r   r   r   ZLayerr   r   r   r   r   <module>   s6   	

e
:
1#G&