U
    Mh,                  
   @  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m	Z	 d dl
Z
d dlmZ d dlmZ erhd dlZeeZejddddddd	d
ddZdd ZejdddddddddddZdS )    )annotationsN)OptionalTupleTYPE_CHECKINGUnion)_type_utils)	_beartypeztorch.TensorstrzOptional['onnx.TypeProto']zonnx.TensorProto)tensornamelocationbasepathdtype_overridereturnc              	   C  s:  ddl }|dk	r tj|jjntj| j}|dk	rR| | jkrR| | } |	 }||_
| |_|j| j |j	j|_|d|   d}| D ]"\}	}
|j }|	|_t|
|_qtj||}tj|rt| tj|}tj|s
t | t!|d}|"| j#dd$  W 5 Q R X |S )a  Create a TensorProto with external data from a PyTorch tensor.
    The external data is saved to os.path.join(basepath, location).

    Args:
        tensor: Tensor to be saved.
        name: Name of the tensor (i.e., initializer name in ONNX graph).
        location: Relative location of the external data file
            (e.g., "/tmp/initializers/weight_0" when model is "/tmp/model_name.onnx").
        basepath: Base path of the external data file (e.g., "/tmp/external_data" while model must be in "/tmp").


    Reference for ONNX's external data format:
        How to load?
        https://github.com/onnx/onnx/blob/5dac81ac0707bdf88f56c35c0a5e8855d3534673/onnx/external_data_helper.py#L187
        How to save?
        https://github.com/onnx/onnx/blob/5dac81ac0707bdf88f56c35c0a5e8855d3534673/onnx/external_data_helper.py#L43
        How to set ONNX fields?
        https://github.com/onnx/onnx/blob/5dac81ac0707bdf88f56c35c0a5e8855d3534673/onnx/external_data_helper.py#L88
    r   N)r   offsetlengthxbT)force)%onnxjit_type_utilsZJitScalarTypeZfrom_onnx_typeZtensor_typeZ	elem_typeZ
from_dtypeZdtypetoZTensorProtor   Z	onnx_typeZ	data_typeZdimsextendshapeZEXTERNALZdata_locationZuntyped_storagenbytesitemsZexternal_dataaddkeyr	   valueospathjoinexistsremovedirnamemakedirsopenwritenumpytobytes)r
   r   r   r   r   r   Zscalar_typetensor_protoZkey_value_pairskventryZexternal_data_file_pathZexternal_data_dir_pathZ	data_file r-   W/var/www/html/venv/lib/python3.8/site-packages/torch/onnx/_internal/fx/serialization.py'_create_tensor_proto_with_external_data   s>    





 r/   c              	   C  sN   ddl m} i }|| ddd&}| D ]}|| ||< q(W 5 Q R X |S )Nr   )	safe_openptcpu)Z	frameworkZdevice)Zsafetensorsr0   keysZ
get_tensorr2   )Zsafetensors_filer0   Ztensorsfr*   r-   r-   r.   $_convert_safetensors_to_torch_formath   s    r5   Fz(Tuple[Union[dict, str, io.BytesIO], ...]zonnx.ModelProtoboolNone)r   model_locationinitializer_locationtorch_state_dicts
onnx_modelrename_initializerr   c                 C  s  ddl }i }dd t|jjD }dd |jjD }	|D ]}
t|
trN|
}nt|
trl|
drlt	|
}nzt
j|
dd	d
}W nr ttfk
r } zPdt|kst|
tjrtd t|
tjr|
d t
j|
dd}n|W 5 d}~X Y nX | D ]\}}|r|dd}||	kr,|	| n8|	D ]2}||sL||r0|}|	|  qdq0tj||}dd |jjD }||kr|||| < t|||| ||d}|jj| qq8tt| d	d}| D ]}|jj|= q||tj| | dS )a  Load PyTorch tensors from files and add to "onnx_model" as external initializers.

    Output files:
        ONNX model file path:
        ONNX initializer folder: os.path.join(basepath, initializer_location)

    After running this function, you can do
        ort_sess = onnxruntime.InferenceSession(os.path.join(basepath, model_location))
    to execute the model.

    Arguments:
        basepath: Base path of the ONNX external data file (e.g., "/path/to/large_model/").
        model_location: Relative location of the ONNX model file.
            E.g., "model.onnx" so that the model file is saved to
            "<basepath>/model.onnx".
        initializer_location: Relative location of the ONNX initializer folder.
            E.g., "initializers" so that the initializers are saved to
            "<basepath>/initializers/".
            Note: When initializers are >2GB, must be the same as `model_location`.
        torch_state_dicts: Dictionaries or files which contain PyTorch tensors to be saved
            as ONNX initializers. For non-dict arguments, `torch.load` will be used to load them from file-like objects.
        onnx_model: ONNX model to be saved with external initializers.
            If an input name matches a tensor loaded from "torch_state_dicts",
            the tensor will be saved as that input's external initializer.
        rename_initializer: Replaces "." by "_" for all ONNX initializer names.
            Not needed by the official torch.onnx.dynamo_export. This is a hack
            for supporting `FXSymbolicTracer` tracer with fake tensor mode.
            In short, `FXSymbolicTracer` lifts FX parameters (self.linear_weight)
            as inputs (`def forward(self, linear_weight)`) and therefore, `.` cannot be used.
    r   Nc                 S  s   i | ]\}}|j |qS r-   r   ).0idxr*   r-   r-   r.   
<dictcomp>   s     z1save_model_with_external_data.<locals>.<dictcomp>c                 S  s   h | ]
}|j qS r-   r=   )r>   inputr-   r-   r.   	<setcomp>   s     z0save_model_with_external_data.<locals>.<setcomp>z.safetensorsr2   T)map_locationmmapz+mmap can only be used with files saved withzFailed to load the checkpoint with memory-map enabled, retrying without memory-map.Consider updating the checkpoint with mmap by using torch.save() on PyTorch version >= 1.6.)rC   ._c                 S  s   i | ]}|j |jqS r-   )r   type)r>   r*   r-   r-   r.   r@      s      )reverse)r   	enumerategraphZinitializerrA   
isinstancedictr	   endswithr5   torchloadRuntimeError
ValueErrorioBytesIOlogwarningseekr   replacer"   r   r   r    r/   popappendsortedr3   save)r   r8   r9   r:   r;   r<   r   Zinitializers_to_be_deletedZexisting_initializersZonnx_input_nameselZ
state_dicter   r
   Zonnx_input_nameZrelative_tensor_file_pathZmodel_input_typesr)   r?   r-   r-   r.   save_model_with_external_datau   sl    (










r^   )N)F)
__future__r   rR   loggingr   typingr   r   r   r   rN   Z
torch.onnxr   r   Ztorch.onnx._internalr   r   	getLogger__name__rT   Zbeartyper/   r5   r^   r-   r-   r-   r.   <module>   s"   
 T 