paddlex_cli.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. # copyright (c) 2024 PaddlePaddle Authors. All Rights Reserve.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import os
  15. import argparse
  16. import subprocess
  17. import sys
  18. from importlib_resources import files, as_file
  19. from . import create_pipeline
  20. from .inference.pipelines import create_pipeline_from_config, load_pipeline_config
  21. from .repo_manager import setup, get_all_supported_repo_names
  22. from .utils import logging
  23. from .utils.interactive_get_pipeline import interactive_get_pipeline
  24. from .utils.pipeline_arguments import PIPELINE_ARGUMENTS
  25. def _install_serving_deps():
  26. with as_file(files("paddlex").joinpath("serving_requirements.txt")) as req_file:
  27. return subprocess.check_call(
  28. [sys.executable, "-m", "pip", "install", "-r", str(req_file)]
  29. )
  30. def args_cfg():
  31. """parse cli arguments"""
  32. def parse_str(s):
  33. """convert str type value
  34. to None type if it is "None",
  35. to bool type if it means True or False.
  36. """
  37. if s in ("None", "none", "NONE"):
  38. return None
  39. elif s in ("TRUE", "True", "true", "T", "t"):
  40. return True
  41. elif s in ("FALSE", "False", "false", "F", "f"):
  42. return False
  43. return s
  44. parser = argparse.ArgumentParser(
  45. "Command-line interface for PaddleX. Use the options below to install plugins, run pipeline predictions, or start the serving application."
  46. )
  47. install_group = parser.add_argument_group("Install PaddleX Options")
  48. pipeline_group = parser.add_argument_group("Pipeline Predict Options")
  49. serving_group = parser.add_argument_group("Serving Options")
  50. ################# install pdx #################
  51. install_group.add_argument(
  52. "--install",
  53. action="store_true",
  54. default=False,
  55. help="Install specified PaddleX plugins.",
  56. )
  57. install_group.add_argument(
  58. "plugins",
  59. nargs="*",
  60. default=[],
  61. help="Names of custom development plugins to install (space-separated).",
  62. )
  63. install_group.add_argument(
  64. "--no_deps",
  65. action="store_true",
  66. help="Install custom development plugins without their dependencies.",
  67. )
  68. install_group.add_argument(
  69. "--platform",
  70. type=str,
  71. choices=["github.com", "gitee.com"],
  72. default="github.com",
  73. help="Platform to use for installation (default: github.com).",
  74. )
  75. install_group.add_argument(
  76. "-y",
  77. "--yes",
  78. dest="update_repos",
  79. action="store_true",
  80. help="Automatically confirm prompts and update repositories.",
  81. )
  82. install_group.add_argument(
  83. "--use_local_repos",
  84. action="store_true",
  85. default=False,
  86. help="Use local repositories if they exist.",
  87. )
  88. ################# pipeline predict #################
  89. pipeline_group.add_argument(
  90. "--pipeline", type=str, help="Name of the pipeline to execute for prediction."
  91. )
  92. pipeline_group.add_argument(
  93. "--input",
  94. type=str,
  95. default=None,
  96. help="Input data or path for the pipeline, supports specific file and directory.",
  97. )
  98. pipeline_group.add_argument(
  99. "--save_path",
  100. type=str,
  101. default=None,
  102. help="Path to save the prediction results.",
  103. )
  104. pipeline_group.add_argument(
  105. "--device",
  106. type=str,
  107. default=None,
  108. help="Device to run the pipeline on (e.g., 'cpu', 'gpu:0').",
  109. )
  110. pipeline_group.add_argument(
  111. "--use_hpip", action="store_true", help="Enable HPIP acceleration if available."
  112. )
  113. pipeline_group.add_argument(
  114. "--get_pipeline_config",
  115. type=str,
  116. default=None,
  117. help="Retrieve the configuration for a specified pipeline.",
  118. )
  119. ################# serving #################
  120. serving_group.add_argument(
  121. "--serve",
  122. action="store_true",
  123. help="Start the serving application to handle requests.",
  124. )
  125. serving_group.add_argument(
  126. "--host",
  127. type=str,
  128. default="0.0.0.0",
  129. help="Host address to serve on (default: 0.0.0.0).",
  130. )
  131. serving_group.add_argument(
  132. "--port",
  133. type=int,
  134. default=8080,
  135. help="Port number to serve on (default: 8080).",
  136. )
  137. # Parse known arguments to get the pipeline name
  138. args, remaining_args = parser.parse_known_args()
  139. pipeline_name = args.pipeline
  140. pipeline_args = []
  141. if not args.install and pipeline_name is not None:
  142. if pipeline_name not in PIPELINE_ARGUMENTS:
  143. support_pipelines = ", ".join(PIPELINE_ARGUMENTS.keys())
  144. logging.error(
  145. f"Unsupported pipeline: {pipeline_name}, CLI predict only supports these pipelines: {support_pipelines}\n"
  146. )
  147. sys.exit(1)
  148. pipeline_args = PIPELINE_ARGUMENTS[pipeline_name]
  149. if pipeline_args is None:
  150. pipeline_args = []
  151. pipeline_specific_group = parser.add_argument_group(
  152. f"{pipeline_name.capitalize()} Pipeline Options"
  153. )
  154. for arg in pipeline_args:
  155. pipeline_specific_group.add_argument(
  156. arg["name"],
  157. type=parse_str if arg["type"] is bool else arg["type"],
  158. help=arg.get("help", f"Argument for {pipeline_name} pipeline."),
  159. )
  160. return parser, pipeline_args
  161. def install(args):
  162. """install paddlex"""
  163. # Enable debug info
  164. os.environ["PADDLE_PDX_DEBUG"] = "True"
  165. # Disable eager initialization
  166. os.environ["PADDLE_PDX_EAGER_INIT"] = "False"
  167. plugins = args.plugins[:]
  168. if "serving" in plugins:
  169. plugins.remove("serving")
  170. _install_serving_deps()
  171. return
  172. if plugins:
  173. repo_names = plugins
  174. elif len(plugins) == 0:
  175. repo_names = get_all_supported_repo_names()
  176. setup(
  177. repo_names=repo_names,
  178. no_deps=args.no_deps,
  179. platform=args.platform,
  180. update_repos=args.update_repos,
  181. use_local_repos=args.use_local_repos,
  182. )
  183. return
  184. def pipeline_predict(
  185. pipeline,
  186. input,
  187. device,
  188. save_path,
  189. use_hpip,
  190. **pipeline_args,
  191. ):
  192. """pipeline predict"""
  193. pipeline = create_pipeline(pipeline, device=device, use_hpip=use_hpip)
  194. result = pipeline.predict(input, **pipeline_args)
  195. for res in result:
  196. res.print()
  197. if save_path:
  198. res.save_all(save_path=save_path)
  199. def serve(pipeline, *, device, use_hpip, host, port):
  200. from .inference.pipelines.serving import create_pipeline_app, run_server
  201. pipeline_config = load_pipeline_config(pipeline)
  202. pipeline = create_pipeline_from_config(
  203. pipeline_config, device=device, use_hpip=use_hpip
  204. )
  205. app = create_pipeline_app(pipeline, pipeline_config)
  206. run_server(app, host=host, port=port, debug=False)
  207. # for CLI
  208. def main():
  209. """API for commad line"""
  210. parser, pipeline_args = args_cfg()
  211. args = parser.parse_args()
  212. if len(sys.argv) == 1:
  213. logging.warning("No arguments provided. Displaying help information:")
  214. parser.print_help()
  215. return
  216. if args.install:
  217. install(args)
  218. elif args.serve:
  219. serve(
  220. args.pipeline,
  221. device=args.device,
  222. use_hpip=args.use_hpip,
  223. host=args.host,
  224. port=args.port,
  225. )
  226. else:
  227. if args.get_pipeline_config is not None:
  228. interactive_get_pipeline(args.get_pipeline_config, args.save_path)
  229. else:
  230. pipeline_args_dict = {}
  231. from .utils.flags import USE_NEW_INFERENCE
  232. if USE_NEW_INFERENCE:
  233. for arg in pipeline_args:
  234. arg_name = arg["name"].lstrip("-")
  235. if hasattr(args, arg_name):
  236. pipeline_args_dict[arg_name] = getattr(args, arg_name)
  237. else:
  238. logging.warning(f"Argument {arg_name} is missing in args")
  239. return pipeline_predict(
  240. args.pipeline,
  241. args.input,
  242. args.device,
  243. args.save_path,
  244. use_hpip=args.use_hpip,
  245. **pipeline_args_dict,
  246. )