| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import os |
| import shutil |
| from pathlib import Path |
| from typing import Optional, Union |
|
|
| import numpy as np |
|
|
| from .download_utils import ppdiffusers_bos_download |
| from .utils import ( |
| FASTDEPLOY_MODEL_NAME, |
| FASTDEPLOY_WEIGHTS_NAME, |
| is_fastdeploy_available, |
| is_paddle_available, |
| logging, |
| ) |
|
|
| if is_paddle_available(): |
| import paddle |
|
|
|
|
| if is_fastdeploy_available(): |
| import fastdeploy as fd |
|
|
| def fdtensor2pdtensor(fdtensor: fd.C.FDTensor): |
| dltensor = fdtensor.to_dlpack() |
| pdtensor = paddle.utils.dlpack.from_dlpack(dltensor) |
| return pdtensor |
|
|
| def pdtensor2fdtensor(pdtensor: paddle.Tensor, name: str = "", share_with_raw_ptr=False): |
| if not share_with_raw_ptr: |
| dltensor = paddle.utils.dlpack.to_dlpack(pdtensor) |
| return fd.C.FDTensor.from_dlpack(name, dltensor) |
| else: |
| return fd.C.FDTensor.from_external_data( |
| name, |
| pdtensor.data_ptr(), |
| pdtensor.shape, |
| pdtensor.dtype.name, |
| str(pdtensor.place), |
| int(pdtensor.place.gpu_device_id()), |
| ) |
|
|
|
|
| logger = logging.get_logger(__name__) |
|
|
|
|
| class FastDeployRuntimeModel: |
| def __init__(self, model=None, **kwargs): |
| logger.info("`ppdiffusers.FastDeployRuntimeModel` is experimental and might change in the future.") |
| self.model = model |
| self.model_save_dir = kwargs.get("model_save_dir", None) |
| self.latest_model_name = kwargs.get("latest_model_name", "inference.pdmodel") |
| self.latest_params_name = kwargs.get("latest_params_name", "inference.pdiparams") |
|
|
| def zero_copy_infer(self, prebinded_inputs: dict, prebinded_outputs: dict, share_with_raw_ptr=True, **kwargs): |
| """ |
| Execute inference without copying data from cpu to gpu. |
| |
| Arguments: |
| kwargs (`dict(name, paddle.Tensor)`): |
| An input map from name to tensor. |
| Return: |
| List of output tensor. |
| """ |
| for inputs_name, inputs_tensor in prebinded_inputs.items(): |
| input_fdtensor = pdtensor2fdtensor(inputs_tensor, inputs_name, share_with_raw_ptr=share_with_raw_ptr) |
| self.model.bind_input_tensor(inputs_name, input_fdtensor) |
|
|
| for outputs_name, outputs_tensor in prebinded_outputs.items(): |
| output_fdtensor = pdtensor2fdtensor(outputs_tensor, outputs_name, share_with_raw_ptr=share_with_raw_ptr) |
| self.model.bind_output_tensor(outputs_name, output_fdtensor) |
|
|
| self.model.zero_copy_infer() |
|
|
| def __call__(self, **kwargs): |
| inputs = {k: np.array(v) for k, v in kwargs.items()} |
| return self.model.infer(inputs) |
|
|
| @staticmethod |
| def load_model( |
| model_path: Union[str, Path], |
| params_path: Union[str, Path], |
| runtime_options: Optional["fd.RuntimeOption"] = None, |
| ): |
| """ |
| Loads an FastDeploy Inference Model with fastdeploy.RuntimeOption |
| |
| Arguments: |
| model_path (`str` or `Path`): |
| Model path from which to load |
| params_path (`str` or `Path`): |
| Params path from which to load |
| runtime_options (fd.RuntimeOption, *optional*): |
| The RuntimeOption of fastdeploy to initialize the fastdeploy runtime. Default setting |
| the device to cpu and the backend to paddle inference |
| """ |
| option = runtime_options |
| if option is None or not isinstance(runtime_options, fd.RuntimeOption): |
| logger.info("No fastdeploy.RuntimeOption specified, using CPU device and paddle inference backend.") |
| option = fd.RuntimeOption() |
| option.use_paddle_backend() |
| option.use_cpu() |
| option.set_model_path(model_path, params_path) |
| return fd.Runtime(option) |
|
|
| def _save_pretrained( |
| self, |
| save_directory: Union[str, Path], |
| model_file_name: Optional[str] = None, |
| params_file_name: Optional[str] = None, |
| **kwargs |
| ): |
| """ |
| Save a model and its configuration file to a directory, so that it can be re-loaded using the |
| [`~FastDeployRuntimeModel.from_pretrained`] class method. It will always save the |
| latest_model_name. |
| |
| Arguments: |
| save_directory (`str` or `Path`): |
| Directory where to save the model file. |
| model_file_name(`str`, *optional*): |
| Overwrites the default model file name from `"inference.pdmodel"` to `model_file_name`. This allows you to save the |
| model with a different name. |
| params_file_name(`str`, *optional*): |
| Overwrites the default model file name from `"inference.pdiparams"` to `params_file_name`. This allows you to save the |
| model with a different name. |
| """ |
|
|
| model_file_name = model_file_name if model_file_name is not None else FASTDEPLOY_MODEL_NAME |
| params_file_name = params_file_name if params_file_name is not None else FASTDEPLOY_WEIGHTS_NAME |
|
|
| src_model_path = self.model_save_dir.joinpath(self.latest_model_name) |
| dst_model_path = Path(save_directory).joinpath(model_file_name) |
|
|
| src_params_path = self.model_save_dir.joinpath(self.latest_params_name) |
| dst_params_path = Path(save_directory).joinpath(params_file_name) |
| try: |
| shutil.copyfile(src_model_path, dst_model_path) |
| shutil.copyfile(src_params_path, dst_params_path) |
| except shutil.SameFileError: |
| pass |
|
|
| def save_pretrained( |
| self, |
| save_directory: Union[str, os.PathLike], |
| **kwargs, |
| ): |
| """ |
| Save a model to a directory, so that it can be re-loaded using the [`~FastDeployRuntimeModel.from_pretrained`] class |
| method.: |
| |
| Arguments: |
| save_directory (`str` or `os.PathLike`): |
| Directory to which to save. Will be created if it doesn't exist. |
| """ |
| if os.path.isfile(save_directory): |
| logger.error(f"Provided path ({save_directory}) should be a directory, not a file") |
| return |
|
|
| os.makedirs(save_directory, exist_ok=True) |
|
|
| |
| self._save_pretrained(save_directory, **kwargs) |
|
|
| @classmethod |
| def _from_pretrained( |
| cls, |
| pretrained_model_name_or_path: Union[str, Path], |
| cache_dir: Optional[str] = None, |
| model_file_name: Optional[str] = None, |
| params_file_name: Optional[str] = None, |
| runtime_options: Optional["fd.RuntimeOption"] = None, |
| **kwargs, |
| ): |
| """ |
| Load a model from a directory or the BOS. |
| |
| Arguments: |
| pretrained_model_name_or_path (`str` or `Path`): |
| Directory from which to load |
| cache_dir (`Union[str, Path]`, *optional*): |
| Path to a directory in which a downloaded pretrained model configuration should be cached if the |
| standard cache should not be used. |
| model_file_name (`str`): |
| Overwrites the default model file name from `"inference.pdmodel"` to `file_name`. This allows you to load |
| different model files from the same repository or directory. |
| params_file_name (`str`): |
| Overwrites the default params file name from `"inference.pdiparams"` to `file_name`. This allows you to load |
| different model files from the same repository or directory. |
| runtime_options (`fastdeploy.RuntimeOption`, *optional*): |
| The RuntimeOption of fastdeploy. |
| kwargs (`Dict`, *optional*): |
| kwargs will be passed to the model during initialization |
| """ |
| model_file_name = model_file_name if model_file_name is not None else FASTDEPLOY_MODEL_NAME |
| params_file_name = params_file_name if params_file_name is not None else FASTDEPLOY_WEIGHTS_NAME |
| |
| if os.path.isdir(pretrained_model_name_or_path): |
| model = FastDeployRuntimeModel.load_model( |
| os.path.join(pretrained_model_name_or_path, model_file_name), |
| os.path.join(pretrained_model_name_or_path, params_file_name), |
| runtime_options=runtime_options, |
| ) |
| kwargs["model_save_dir"] = Path(pretrained_model_name_or_path) |
| |
| else: |
| |
| model_cache_path = ppdiffusers_bos_download( |
| pretrained_model_name_or_path=pretrained_model_name_or_path, |
| filename=model_file_name, |
| cache_dir=cache_dir, |
| ) |
| |
| params_cache_path = ppdiffusers_bos_download( |
| pretrained_model_name_or_path=pretrained_model_name_or_path, |
| filename=params_file_name, |
| cache_dir=cache_dir, |
| ) |
| kwargs["model_save_dir"] = Path(model_cache_path).parent |
| kwargs["latest_model_name"] = Path(model_cache_path).name |
| kwargs["latest_params_name"] = Path(params_cache_path).name |
| model = FastDeployRuntimeModel.load_model( |
| model_cache_path, params_cache_path, runtime_options=runtime_options |
| ) |
| return cls(model=model, **kwargs) |
|
|
| @classmethod |
| def from_pretrained( |
| cls, |
| pretrained_model_name_or_path: Union[str, Path], |
| cache_dir: Optional[str] = None, |
| model_file_name: Optional[str] = None, |
| params_file_name: Optional[str] = None, |
| runtime_options: Optional["fd.RuntimeOption"] = None, |
| **model_kwargs, |
| ): |
| return cls._from_pretrained( |
| pretrained_model_name_or_path=pretrained_model_name_or_path, |
| cache_dir=cache_dir, |
| model_file_name=model_file_name, |
| params_file_name=params_file_name, |
| runtime_options=runtime_options, |
| **model_kwargs, |
| ) |
|
|