Selaa lähdekoodia

[Fix] Let HPIP not automatically choose pptrt when it is not available (#3782)

* Fix

* Revert

* Revert

* Revert

* Fix bug
Lin Manhui 7 kuukautta sitten
vanhempi
commit
3685fd2843

+ 23 - 60
paddlex/inference/models/common/static_infer.py

@@ -20,11 +20,7 @@ from typing import List, Sequence
 import numpy as np
 
 from ....utils import logging
-from ....utils.deps import (
-    class_requires_deps,
-    function_requires_deps,
-    is_paddle2onnx_plugin_available,
-)
+from ....utils.deps import class_requires_deps, function_requires_deps
 from ....utils.device import constr_device
 from ....utils.flags import DEBUG, INFER_BENCHMARK_USE_NEW_INFER_API, USE_PIR_TRT
 from ...utils.benchmark import benchmark, set_inference_operations
@@ -602,7 +598,7 @@ class MultiBackendInfer(object):
 
 # TODO: It would be better to refactor the code to make `HPInfer` a higher-level
 # class that uses `PaddleInfer`.
-@class_requires_deps("ultra-infer", "paddlepaddle")
+@class_requires_deps("ultra-infer")
 class HPInfer(StaticInfer):
     def __init__(
         self,
@@ -659,54 +655,13 @@ class HPInfer(StaticInfer):
         return self._multi_backend_infer(inputs)
 
     def _determine_backend_and_config(self):
-        from ultra_infer import (
-            is_built_with_om,
-            is_built_with_openvino,
-            is_built_with_ort,
-            is_built_with_trt,
-        )
-
-        model_paths = get_model_paths(self._model_dir, self._model_file_prefix)
-        is_onnx_model_available = "onnx" in model_paths
-        # TODO: Give a warning if the Paddle2ONNX plugin is not available but
-        # can be used to select a better backend.
-        if self._config.auto_paddle2onnx:
-            if is_paddle2onnx_plugin_available():
-                is_onnx_model_available = (
-                    is_onnx_model_available or "paddle" in model_paths
-                )
-            else:
-                logging.debug(
-                    "The Paddle2ONNX plugin is not available. Automatic model conversion will not be performed."
-                )
-        available_backends = []
-        if "paddle" in model_paths:
-            available_backends.append("paddle")
-        if is_built_with_openvino() and is_onnx_model_available:
-            available_backends.append("openvino")
-        if is_built_with_ort() and is_onnx_model_available:
-            available_backends.append("onnxruntime")
-        if is_built_with_trt() and is_onnx_model_available:
-            available_backends.append("tensorrt")
-        if is_built_with_om() and "om" in model_paths:
-            available_backends.append("om")
-
-        if not available_backends:
-            raise RuntimeError("No inference backend is available")
-
-        if (
-            self._config.backend is not None
-            and self._config.backend not in available_backends
-        ):
-            raise RuntimeError(
-                f"Inference backend {repr(self._config.backend)} is unavailable"
-            )
-
         if self._config.auto_config:
             # Should we use the strategy pattern here to allow extensible
             # strategies?
+            model_paths = get_model_paths(self._model_dir, self._model_file_prefix)
             ret = suggest_inference_backend_and_config(
-                self._config, available_backends=available_backends
+                self._config,
+                model_paths,
             )
             if ret[0] is None:
                 # Should I use a custom exception?
@@ -789,16 +744,24 @@ class HPInfer(StaticInfer):
                     logging.info(
                         "Automatically converting PaddlePaddle model to ONNX format"
                     )
-                    subprocess.check_call(
-                        [
-                            "paddlex",
-                            "--paddle2onnx",
-                            "--paddle_model_dir",
-                            self._model_dir,
-                            "--onnx_model_dir",
-                            self._model_dir,
-                        ]
-                    )
+                    try:
+                        subprocess.run(
+                            [
+                                "paddlex",
+                                "--paddle2onnx",
+                                "--paddle_model_dir",
+                                self._model_dir,
+                                "--onnx_model_dir",
+                                self._model_dir,
+                            ],
+                            capture_output=True,
+                            check=True,
+                            text=True,
+                        )
+                    except subprocess.CalledProcessError as e:
+                        raise RuntimeError(
+                            f"PaddlePaddle-to-ONNX conversion failed:\n{e.stderr}"
+                        ) from e
                     model_paths = get_model_paths(
                         self.model_dir, self.model_file_prefix
                     )

+ 44 - 5
paddlex/inference/utils/hpi.py

@@ -12,7 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import ctypes.util
 import importlib.resources
+import importlib.util
 import json
 import platform
 from functools import lru_cache
@@ -23,7 +25,8 @@ from typing import Any, Dict, List, Literal, Optional, Tuple, TypedDict, Union
 from pydantic import BaseModel, Field
 from typing_extensions import Annotated, TypeAlias
 
-from ...utils.flags import FLAGS_json_format_model
+from ...utils.deps import function_requires_deps, is_paddle2onnx_plugin_available
+from ...utils.flags import USE_PIR_TRT, FLAGS_json_format_model
 
 
 class PaddleInferenceInfo(BaseModel):
@@ -131,21 +134,48 @@ def _get_hpi_model_info_collection():
     return hpi_model_info_collection
 
 
+@function_requires_deps("paddlepaddle", "ultra-infer")
 def suggest_inference_backend_and_config(
     hpi_config: HPIConfig,
-    available_backends: Optional[List[InferenceBackend]] = None,
+    model_paths: ModelPaths,
 ) -> Union[Tuple[InferenceBackend, Dict[str, Any]], Tuple[None, str]]:
     # TODO: The current strategy is naive. It would be better to consider
     # additional important factors, such as NVIDIA GPU compute capability and
     # device manufacturers. We should also allow users to provide hints.
 
     import paddle
-
-    if available_backends is not None and not available_backends:
+    from ultra_infer import (
+        is_built_with_om,
+        is_built_with_openvino,
+        is_built_with_ort,
+        is_built_with_trt,
+    )
+
+    is_onnx_model_available = "onnx" in model_paths
+    # TODO: Give a warning if the Paddle2ONNX plugin is not available but
+    # can be used to select a better backend.
+    if hpi_config.auto_paddle2onnx and is_paddle2onnx_plugin_available():
+        is_onnx_model_available = is_onnx_model_available or "paddle" in model_paths
+    available_backends = []
+    if "paddle" in model_paths:
+        available_backends.append("paddle")
+    if is_built_with_openvino() and is_onnx_model_available:
+        available_backends.append("openvino")
+    if is_built_with_ort() and is_onnx_model_available:
+        available_backends.append("onnxruntime")
+    if is_built_with_trt() and is_onnx_model_available:
+        available_backends.append("tensorrt")
+    if is_built_with_om() and "om" in model_paths:
+        available_backends.append("om")
+
+    if not available_backends:
         return None, "No inference backends are available."
 
+    if hpi_config.backend is not None and hpi_config.backend not in available_backends:
+        return None, f"Inference backend {repr(hpi_config.backend)} is unavailable."
+
     paddle_version = paddle.__version__
-    if paddle_version != "3.0.0-rc0":
+    if paddle_version != "3.0.0":
         return None, f"{repr(paddle_version)} is not a supported Paddle version."
 
     if hpi_config.device_type == "cpu":
@@ -181,6 +211,15 @@ def suggest_inference_backend_and_config(
         hpi_config.pdx_model_name
     ]
 
+    # XXX
+    if not ctypes.util.find_library("nvinfer") or (
+        USE_PIR_TRT and importlib.util.find_spec("tensorrt") is None
+    ):
+        if "paddle_tensorrt" in supported_pseudo_backends:
+            supported_pseudo_backends.remove("paddle_tensorrt")
+        if "paddle_tensorrt_fp16" in supported_pseudo_backends:
+            supported_pseudo_backends.remove("paddle_tensorrt_fp16")
+
     candidate_backends = []
     backend_to_pseudo_backend = {}
     for pb in supported_pseudo_backends:

+ 2 - 1
paddlex/utils/deps.py

@@ -80,6 +80,7 @@ def get_dep_version(dep):
 
 @lru_cache()
 def is_dep_available(dep, /):
+    # Currently for several special deps we check if the import packages exist.
     if dep == "paddlepaddle":
         return importlib.util.find_spec("paddle") is not None
     elif dep == "paddle-custom-device":
@@ -221,4 +222,4 @@ def require_paddle2onnx_plugin():
 
 
 def get_paddle2onnx_spec():
-    return "paddle2onnx"
+    return "paddle2onnx == 2.0.0a2"