oracle-ads 2.13.9rc0__py3-none-any.whl → 2.13.9rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (857) hide show
  1. ads/aqua/__init__.py +40 -0
  2. ads/aqua/app.py +506 -0
  3. ads/aqua/cli.py +96 -0
  4. ads/aqua/client/__init__.py +3 -0
  5. ads/aqua/client/client.py +836 -0
  6. ads/aqua/client/openai_client.py +305 -0
  7. ads/aqua/common/__init__.py +5 -0
  8. ads/aqua/common/decorator.py +125 -0
  9. ads/aqua/common/entities.py +269 -0
  10. ads/aqua/common/enums.py +122 -0
  11. ads/aqua/common/errors.py +109 -0
  12. ads/aqua/common/utils.py +1285 -0
  13. ads/aqua/config/__init__.py +4 -0
  14. ads/aqua/config/container_config.py +248 -0
  15. ads/aqua/config/evaluation/__init__.py +4 -0
  16. ads/aqua/config/evaluation/evaluation_service_config.py +147 -0
  17. ads/aqua/config/utils/__init__.py +4 -0
  18. ads/aqua/config/utils/serializer.py +339 -0
  19. ads/aqua/constants.py +116 -0
  20. ads/aqua/data.py +14 -0
  21. ads/aqua/dummy_data/icon.txt +1 -0
  22. ads/aqua/dummy_data/oci_model_deployments.json +56 -0
  23. ads/aqua/dummy_data/oci_models.json +1 -0
  24. ads/aqua/dummy_data/readme.md +26 -0
  25. ads/aqua/evaluation/__init__.py +8 -0
  26. ads/aqua/evaluation/constants.py +53 -0
  27. ads/aqua/evaluation/entities.py +186 -0
  28. ads/aqua/evaluation/errors.py +70 -0
  29. ads/aqua/evaluation/evaluation.py +1814 -0
  30. ads/aqua/extension/__init__.py +42 -0
  31. ads/aqua/extension/aqua_ws_msg_handler.py +76 -0
  32. ads/aqua/extension/base_handler.py +90 -0
  33. ads/aqua/extension/common_handler.py +121 -0
  34. ads/aqua/extension/common_ws_msg_handler.py +36 -0
  35. ads/aqua/extension/deployment_handler.py +298 -0
  36. ads/aqua/extension/deployment_ws_msg_handler.py +54 -0
  37. ads/aqua/extension/errors.py +30 -0
  38. ads/aqua/extension/evaluation_handler.py +129 -0
  39. ads/aqua/extension/evaluation_ws_msg_handler.py +61 -0
  40. ads/aqua/extension/finetune_handler.py +96 -0
  41. ads/aqua/extension/model_handler.py +390 -0
  42. ads/aqua/extension/models/__init__.py +0 -0
  43. ads/aqua/extension/models/ws_models.py +145 -0
  44. ads/aqua/extension/models_ws_msg_handler.py +50 -0
  45. ads/aqua/extension/ui_handler.py +282 -0
  46. ads/aqua/extension/ui_websocket_handler.py +130 -0
  47. ads/aqua/extension/utils.py +133 -0
  48. ads/aqua/finetuning/__init__.py +7 -0
  49. ads/aqua/finetuning/constants.py +23 -0
  50. ads/aqua/finetuning/entities.py +181 -0
  51. ads/aqua/finetuning/finetuning.py +749 -0
  52. ads/aqua/model/__init__.py +8 -0
  53. ads/aqua/model/constants.py +60 -0
  54. ads/aqua/model/entities.py +385 -0
  55. ads/aqua/model/enums.py +32 -0
  56. ads/aqua/model/model.py +2114 -0
  57. ads/aqua/modeldeployment/__init__.py +8 -0
  58. ads/aqua/modeldeployment/constants.py +10 -0
  59. ads/aqua/modeldeployment/deployment.py +1326 -0
  60. ads/aqua/modeldeployment/entities.py +653 -0
  61. ads/aqua/modeldeployment/inference.py +74 -0
  62. ads/aqua/modeldeployment/utils.py +543 -0
  63. ads/aqua/resources/gpu_shapes_index.json +94 -0
  64. ads/aqua/server/__init__.py +4 -0
  65. ads/aqua/server/__main__.py +24 -0
  66. ads/aqua/server/app.py +47 -0
  67. ads/aqua/server/aqua_spec.yml +1291 -0
  68. ads/aqua/training/__init__.py +4 -0
  69. ads/aqua/training/exceptions.py +476 -0
  70. ads/aqua/ui.py +499 -0
  71. ads/automl/__init__.py +9 -0
  72. ads/automl/driver.py +330 -0
  73. ads/automl/provider.py +975 -0
  74. ads/bds/__init__.py +5 -0
  75. ads/bds/auth.py +127 -0
  76. ads/bds/big_data_service.py +255 -0
  77. ads/catalog/__init__.py +19 -0
  78. ads/catalog/model.py +1576 -0
  79. ads/catalog/notebook.py +461 -0
  80. ads/catalog/project.py +468 -0
  81. ads/catalog/summary.py +178 -0
  82. ads/common/__init__.py +11 -0
  83. ads/common/analyzer.py +65 -0
  84. ads/common/artifact/.model-ignore +63 -0
  85. ads/common/artifact/__init__.py +10 -0
  86. ads/common/auth.py +1122 -0
  87. ads/common/card_identifier.py +83 -0
  88. ads/common/config.py +647 -0
  89. ads/common/data.py +165 -0
  90. ads/common/decorator/__init__.py +9 -0
  91. ads/common/decorator/argument_to_case.py +88 -0
  92. ads/common/decorator/deprecate.py +69 -0
  93. ads/common/decorator/require_nonempty_arg.py +65 -0
  94. ads/common/decorator/runtime_dependency.py +178 -0
  95. ads/common/decorator/threaded.py +97 -0
  96. ads/common/decorator/utils.py +35 -0
  97. ads/common/dsc_file_system.py +303 -0
  98. ads/common/error.py +14 -0
  99. ads/common/extended_enum.py +81 -0
  100. ads/common/function/__init__.py +5 -0
  101. ads/common/function/fn_util.py +142 -0
  102. ads/common/function/func_conf.yaml +25 -0
  103. ads/common/ipython.py +76 -0
  104. ads/common/model.py +679 -0
  105. ads/common/model_artifact.py +1759 -0
  106. ads/common/model_artifact_schema.json +107 -0
  107. ads/common/model_export_util.py +664 -0
  108. ads/common/model_metadata.py +24 -0
  109. ads/common/object_storage_details.py +296 -0
  110. ads/common/oci_client.py +175 -0
  111. ads/common/oci_datascience.py +46 -0
  112. ads/common/oci_logging.py +1144 -0
  113. ads/common/oci_mixin.py +957 -0
  114. ads/common/oci_resource.py +136 -0
  115. ads/common/serializer.py +559 -0
  116. ads/common/utils.py +1852 -0
  117. ads/common/word_lists.py +1491 -0
  118. ads/common/work_request.py +189 -0
  119. ads/data_labeling/__init__.py +13 -0
  120. ads/data_labeling/boundingbox.py +253 -0
  121. ads/data_labeling/constants.py +47 -0
  122. ads/data_labeling/data_labeling_service.py +244 -0
  123. ads/data_labeling/interface/__init__.py +5 -0
  124. ads/data_labeling/interface/loader.py +16 -0
  125. ads/data_labeling/interface/parser.py +16 -0
  126. ads/data_labeling/interface/reader.py +23 -0
  127. ads/data_labeling/loader/__init__.py +5 -0
  128. ads/data_labeling/loader/file_loader.py +241 -0
  129. ads/data_labeling/metadata.py +110 -0
  130. ads/data_labeling/mixin/__init__.py +5 -0
  131. ads/data_labeling/mixin/data_labeling.py +232 -0
  132. ads/data_labeling/ner.py +129 -0
  133. ads/data_labeling/parser/__init__.py +5 -0
  134. ads/data_labeling/parser/dls_record_parser.py +388 -0
  135. ads/data_labeling/parser/export_metadata_parser.py +94 -0
  136. ads/data_labeling/parser/export_record_parser.py +473 -0
  137. ads/data_labeling/reader/__init__.py +5 -0
  138. ads/data_labeling/reader/dataset_reader.py +574 -0
  139. ads/data_labeling/reader/dls_record_reader.py +121 -0
  140. ads/data_labeling/reader/export_record_reader.py +62 -0
  141. ads/data_labeling/reader/jsonl_reader.py +75 -0
  142. ads/data_labeling/reader/metadata_reader.py +203 -0
  143. ads/data_labeling/reader/record_reader.py +263 -0
  144. ads/data_labeling/record.py +52 -0
  145. ads/data_labeling/visualizer/__init__.py +5 -0
  146. ads/data_labeling/visualizer/image_visualizer.py +525 -0
  147. ads/data_labeling/visualizer/text_visualizer.py +357 -0
  148. ads/database/__init__.py +5 -0
  149. ads/database/connection.py +338 -0
  150. ads/dataset/__init__.py +10 -0
  151. ads/dataset/capabilities.md +51 -0
  152. ads/dataset/classification_dataset.py +339 -0
  153. ads/dataset/correlation.py +226 -0
  154. ads/dataset/correlation_plot.py +563 -0
  155. ads/dataset/dask_series.py +173 -0
  156. ads/dataset/dataframe_transformer.py +110 -0
  157. ads/dataset/dataset.py +1979 -0
  158. ads/dataset/dataset_browser.py +360 -0
  159. ads/dataset/dataset_with_target.py +995 -0
  160. ads/dataset/exception.py +25 -0
  161. ads/dataset/factory.py +987 -0
  162. ads/dataset/feature_engineering_transformer.py +35 -0
  163. ads/dataset/feature_selection.py +107 -0
  164. ads/dataset/forecasting_dataset.py +26 -0
  165. ads/dataset/helper.py +1450 -0
  166. ads/dataset/label_encoder.py +99 -0
  167. ads/dataset/mixin/__init__.py +5 -0
  168. ads/dataset/mixin/dataset_accessor.py +134 -0
  169. ads/dataset/pipeline.py +58 -0
  170. ads/dataset/plot.py +710 -0
  171. ads/dataset/progress.py +86 -0
  172. ads/dataset/recommendation.py +297 -0
  173. ads/dataset/recommendation_transformer.py +502 -0
  174. ads/dataset/regression_dataset.py +14 -0
  175. ads/dataset/sampled_dataset.py +1050 -0
  176. ads/dataset/target.py +98 -0
  177. ads/dataset/timeseries.py +18 -0
  178. ads/dbmixin/__init__.py +5 -0
  179. ads/dbmixin/db_pandas_accessor.py +153 -0
  180. ads/environment/__init__.py +9 -0
  181. ads/environment/ml_runtime.py +66 -0
  182. ads/evaluations/README.md +14 -0
  183. ads/evaluations/__init__.py +109 -0
  184. ads/evaluations/evaluation_plot.py +983 -0
  185. ads/evaluations/evaluator.py +1334 -0
  186. ads/evaluations/statistical_metrics.py +543 -0
  187. ads/experiments/__init__.py +9 -0
  188. ads/experiments/capabilities.md +0 -0
  189. ads/explanations/__init__.py +21 -0
  190. ads/explanations/base_explainer.py +142 -0
  191. ads/explanations/capabilities.md +83 -0
  192. ads/explanations/explainer.py +190 -0
  193. ads/explanations/mlx_global_explainer.py +1050 -0
  194. ads/explanations/mlx_interface.py +386 -0
  195. ads/explanations/mlx_local_explainer.py +287 -0
  196. ads/explanations/mlx_whatif_explainer.py +201 -0
  197. ads/feature_engineering/__init__.py +20 -0
  198. ads/feature_engineering/accessor/__init__.py +5 -0
  199. ads/feature_engineering/accessor/dataframe_accessor.py +535 -0
  200. ads/feature_engineering/accessor/mixin/__init__.py +5 -0
  201. ads/feature_engineering/accessor/mixin/correlation.py +166 -0
  202. ads/feature_engineering/accessor/mixin/eda_mixin.py +266 -0
  203. ads/feature_engineering/accessor/mixin/eda_mixin_series.py +85 -0
  204. ads/feature_engineering/accessor/mixin/feature_types_mixin.py +211 -0
  205. ads/feature_engineering/accessor/mixin/utils.py +65 -0
  206. ads/feature_engineering/accessor/series_accessor.py +431 -0
  207. ads/feature_engineering/adsimage/__init__.py +5 -0
  208. ads/feature_engineering/adsimage/image.py +192 -0
  209. ads/feature_engineering/adsimage/image_reader.py +170 -0
  210. ads/feature_engineering/adsimage/interface/__init__.py +5 -0
  211. ads/feature_engineering/adsimage/interface/reader.py +19 -0
  212. ads/feature_engineering/adsstring/__init__.py +7 -0
  213. ads/feature_engineering/adsstring/oci_language/__init__.py +8 -0
  214. ads/feature_engineering/adsstring/string/__init__.py +8 -0
  215. ads/feature_engineering/data_schema.json +57 -0
  216. ads/feature_engineering/dataset/__init__.py +5 -0
  217. ads/feature_engineering/dataset/zip_code_data.py +42062 -0
  218. ads/feature_engineering/exceptions.py +40 -0
  219. ads/feature_engineering/feature_type/__init__.py +133 -0
  220. ads/feature_engineering/feature_type/address.py +184 -0
  221. ads/feature_engineering/feature_type/adsstring/__init__.py +5 -0
  222. ads/feature_engineering/feature_type/adsstring/common_regex_mixin.py +164 -0
  223. ads/feature_engineering/feature_type/adsstring/oci_language.py +93 -0
  224. ads/feature_engineering/feature_type/adsstring/parsers/__init__.py +5 -0
  225. ads/feature_engineering/feature_type/adsstring/parsers/base.py +47 -0
  226. ads/feature_engineering/feature_type/adsstring/parsers/nltk_parser.py +96 -0
  227. ads/feature_engineering/feature_type/adsstring/parsers/spacy_parser.py +221 -0
  228. ads/feature_engineering/feature_type/adsstring/string.py +258 -0
  229. ads/feature_engineering/feature_type/base.py +58 -0
  230. ads/feature_engineering/feature_type/boolean.py +183 -0
  231. ads/feature_engineering/feature_type/category.py +146 -0
  232. ads/feature_engineering/feature_type/constant.py +137 -0
  233. ads/feature_engineering/feature_type/continuous.py +151 -0
  234. ads/feature_engineering/feature_type/creditcard.py +314 -0
  235. ads/feature_engineering/feature_type/datetime.py +190 -0
  236. ads/feature_engineering/feature_type/discrete.py +134 -0
  237. ads/feature_engineering/feature_type/document.py +43 -0
  238. ads/feature_engineering/feature_type/gis.py +251 -0
  239. ads/feature_engineering/feature_type/handler/__init__.py +5 -0
  240. ads/feature_engineering/feature_type/handler/feature_validator.py +524 -0
  241. ads/feature_engineering/feature_type/handler/feature_warning.py +319 -0
  242. ads/feature_engineering/feature_type/handler/warnings.py +128 -0
  243. ads/feature_engineering/feature_type/integer.py +142 -0
  244. ads/feature_engineering/feature_type/ip_address.py +144 -0
  245. ads/feature_engineering/feature_type/ip_address_v4.py +138 -0
  246. ads/feature_engineering/feature_type/ip_address_v6.py +138 -0
  247. ads/feature_engineering/feature_type/lat_long.py +256 -0
  248. ads/feature_engineering/feature_type/object.py +43 -0
  249. ads/feature_engineering/feature_type/ordinal.py +132 -0
  250. ads/feature_engineering/feature_type/phone_number.py +135 -0
  251. ads/feature_engineering/feature_type/string.py +171 -0
  252. ads/feature_engineering/feature_type/text.py +93 -0
  253. ads/feature_engineering/feature_type/unknown.py +43 -0
  254. ads/feature_engineering/feature_type/zip_code.py +164 -0
  255. ads/feature_engineering/feature_type_manager.py +406 -0
  256. ads/feature_engineering/schema.py +795 -0
  257. ads/feature_engineering/utils.py +245 -0
  258. ads/feature_store/.readthedocs.yaml +19 -0
  259. ads/feature_store/README.md +65 -0
  260. ads/feature_store/__init__.py +9 -0
  261. ads/feature_store/common/__init__.py +0 -0
  262. ads/feature_store/common/enums.py +339 -0
  263. ads/feature_store/common/exceptions.py +18 -0
  264. ads/feature_store/common/spark_session_singleton.py +125 -0
  265. ads/feature_store/common/utils/__init__.py +0 -0
  266. ads/feature_store/common/utils/base64_encoder_decoder.py +72 -0
  267. ads/feature_store/common/utils/feature_schema_mapper.py +283 -0
  268. ads/feature_store/common/utils/transformation_utils.py +82 -0
  269. ads/feature_store/common/utils/utility.py +403 -0
  270. ads/feature_store/data_validation/__init__.py +0 -0
  271. ads/feature_store/data_validation/great_expectation.py +129 -0
  272. ads/feature_store/dataset.py +1230 -0
  273. ads/feature_store/dataset_job.py +530 -0
  274. ads/feature_store/docs/Dockerfile +7 -0
  275. ads/feature_store/docs/Makefile +44 -0
  276. ads/feature_store/docs/conf.py +28 -0
  277. ads/feature_store/docs/requirements.txt +14 -0
  278. ads/feature_store/docs/source/ads.feature_store.query.rst +20 -0
  279. ads/feature_store/docs/source/cicd.rst +137 -0
  280. ads/feature_store/docs/source/conf.py +86 -0
  281. ads/feature_store/docs/source/data_versioning.rst +33 -0
  282. ads/feature_store/docs/source/dataset.rst +388 -0
  283. ads/feature_store/docs/source/dataset_job.rst +27 -0
  284. ads/feature_store/docs/source/demo.rst +70 -0
  285. ads/feature_store/docs/source/entity.rst +78 -0
  286. ads/feature_store/docs/source/feature_group.rst +624 -0
  287. ads/feature_store/docs/source/feature_group_job.rst +29 -0
  288. ads/feature_store/docs/source/feature_store.rst +122 -0
  289. ads/feature_store/docs/source/feature_store_class.rst +123 -0
  290. ads/feature_store/docs/source/feature_validation.rst +66 -0
  291. ads/feature_store/docs/source/figures/cicd.png +0 -0
  292. ads/feature_store/docs/source/figures/data_validation.png +0 -0
  293. ads/feature_store/docs/source/figures/data_versioning.png +0 -0
  294. ads/feature_store/docs/source/figures/dataset.gif +0 -0
  295. ads/feature_store/docs/source/figures/dataset.png +0 -0
  296. ads/feature_store/docs/source/figures/dataset_lineage.png +0 -0
  297. ads/feature_store/docs/source/figures/dataset_statistics.png +0 -0
  298. ads/feature_store/docs/source/figures/dataset_statistics_viz.png +0 -0
  299. ads/feature_store/docs/source/figures/dataset_validation_results.png +0 -0
  300. ads/feature_store/docs/source/figures/dataset_validation_summary.png +0 -0
  301. ads/feature_store/docs/source/figures/drift_monitoring.png +0 -0
  302. ads/feature_store/docs/source/figures/entity.png +0 -0
  303. ads/feature_store/docs/source/figures/feature_group.png +0 -0
  304. ads/feature_store/docs/source/figures/feature_group_lineage.png +0 -0
  305. ads/feature_store/docs/source/figures/feature_group_statistics_viz.png +0 -0
  306. ads/feature_store/docs/source/figures/feature_store_deployment.png +0 -0
  307. ads/feature_store/docs/source/figures/feature_store_overview.png +0 -0
  308. ads/feature_store/docs/source/figures/featuregroup.gif +0 -0
  309. ads/feature_store/docs/source/figures/lineage_d1.png +0 -0
  310. ads/feature_store/docs/source/figures/lineage_d2.png +0 -0
  311. ads/feature_store/docs/source/figures/lineage_fg.png +0 -0
  312. ads/feature_store/docs/source/figures/logo-dark-mode.png +0 -0
  313. ads/feature_store/docs/source/figures/logo-light-mode.png +0 -0
  314. ads/feature_store/docs/source/figures/overview.png +0 -0
  315. ads/feature_store/docs/source/figures/resource_manager.png +0 -0
  316. ads/feature_store/docs/source/figures/resource_manager_feature_store_stack.png +0 -0
  317. ads/feature_store/docs/source/figures/resource_manager_home.png +0 -0
  318. ads/feature_store/docs/source/figures/stats_1.png +0 -0
  319. ads/feature_store/docs/source/figures/stats_2.png +0 -0
  320. ads/feature_store/docs/source/figures/stats_d.png +0 -0
  321. ads/feature_store/docs/source/figures/stats_fg.png +0 -0
  322. ads/feature_store/docs/source/figures/transformation.png +0 -0
  323. ads/feature_store/docs/source/figures/transformations.gif +0 -0
  324. ads/feature_store/docs/source/figures/validation.png +0 -0
  325. ads/feature_store/docs/source/figures/validation_fg.png +0 -0
  326. ads/feature_store/docs/source/figures/validation_results.png +0 -0
  327. ads/feature_store/docs/source/figures/validation_summary.png +0 -0
  328. ads/feature_store/docs/source/index.rst +81 -0
  329. ads/feature_store/docs/source/module.rst +8 -0
  330. ads/feature_store/docs/source/notebook.rst +94 -0
  331. ads/feature_store/docs/source/overview.rst +47 -0
  332. ads/feature_store/docs/source/quickstart.rst +176 -0
  333. ads/feature_store/docs/source/release_notes.rst +194 -0
  334. ads/feature_store/docs/source/setup_feature_store.rst +81 -0
  335. ads/feature_store/docs/source/statistics.rst +58 -0
  336. ads/feature_store/docs/source/transformation.rst +199 -0
  337. ads/feature_store/docs/source/ui.rst +65 -0
  338. ads/feature_store/docs/source/user_guides.setup.feature_store_operator.rst +66 -0
  339. ads/feature_store/docs/source/user_guides.setup.helm_chart.rst +192 -0
  340. ads/feature_store/docs/source/user_guides.setup.terraform.rst +338 -0
  341. ads/feature_store/entity.py +718 -0
  342. ads/feature_store/execution_strategy/__init__.py +0 -0
  343. ads/feature_store/execution_strategy/delta_lake/__init__.py +0 -0
  344. ads/feature_store/execution_strategy/delta_lake/delta_lake_service.py +375 -0
  345. ads/feature_store/execution_strategy/engine/__init__.py +0 -0
  346. ads/feature_store/execution_strategy/engine/spark_engine.py +316 -0
  347. ads/feature_store/execution_strategy/execution_strategy.py +113 -0
  348. ads/feature_store/execution_strategy/execution_strategy_provider.py +47 -0
  349. ads/feature_store/execution_strategy/spark/__init__.py +0 -0
  350. ads/feature_store/execution_strategy/spark/spark_execution.py +618 -0
  351. ads/feature_store/feature.py +192 -0
  352. ads/feature_store/feature_group.py +1494 -0
  353. ads/feature_store/feature_group_expectation.py +346 -0
  354. ads/feature_store/feature_group_job.py +602 -0
  355. ads/feature_store/feature_lineage/__init__.py +0 -0
  356. ads/feature_store/feature_lineage/graphviz_service.py +180 -0
  357. ads/feature_store/feature_option_details.py +50 -0
  358. ads/feature_store/feature_statistics/__init__.py +0 -0
  359. ads/feature_store/feature_statistics/statistics_service.py +99 -0
  360. ads/feature_store/feature_store.py +699 -0
  361. ads/feature_store/feature_store_registrar.py +518 -0
  362. ads/feature_store/input_feature_detail.py +149 -0
  363. ads/feature_store/mixin/__init__.py +4 -0
  364. ads/feature_store/mixin/oci_feature_store.py +145 -0
  365. ads/feature_store/model_details.py +73 -0
  366. ads/feature_store/query/__init__.py +0 -0
  367. ads/feature_store/query/filter.py +266 -0
  368. ads/feature_store/query/generator/__init__.py +0 -0
  369. ads/feature_store/query/generator/query_generator.py +298 -0
  370. ads/feature_store/query/join.py +161 -0
  371. ads/feature_store/query/query.py +403 -0
  372. ads/feature_store/query/validator/__init__.py +0 -0
  373. ads/feature_store/query/validator/query_validator.py +57 -0
  374. ads/feature_store/response/__init__.py +0 -0
  375. ads/feature_store/response/response_builder.py +68 -0
  376. ads/feature_store/service/__init__.py +0 -0
  377. ads/feature_store/service/oci_dataset.py +139 -0
  378. ads/feature_store/service/oci_dataset_job.py +199 -0
  379. ads/feature_store/service/oci_entity.py +125 -0
  380. ads/feature_store/service/oci_feature_group.py +164 -0
  381. ads/feature_store/service/oci_feature_group_job.py +214 -0
  382. ads/feature_store/service/oci_feature_store.py +182 -0
  383. ads/feature_store/service/oci_lineage.py +87 -0
  384. ads/feature_store/service/oci_transformation.py +104 -0
  385. ads/feature_store/statistics/__init__.py +0 -0
  386. ads/feature_store/statistics/abs_feature_value.py +49 -0
  387. ads/feature_store/statistics/charts/__init__.py +0 -0
  388. ads/feature_store/statistics/charts/abstract_feature_plot.py +37 -0
  389. ads/feature_store/statistics/charts/box_plot.py +148 -0
  390. ads/feature_store/statistics/charts/frequency_distribution.py +65 -0
  391. ads/feature_store/statistics/charts/probability_distribution.py +68 -0
  392. ads/feature_store/statistics/charts/top_k_frequent_elements.py +98 -0
  393. ads/feature_store/statistics/feature_stat.py +126 -0
  394. ads/feature_store/statistics/generic_feature_value.py +33 -0
  395. ads/feature_store/statistics/statistics.py +41 -0
  396. ads/feature_store/statistics_config.py +101 -0
  397. ads/feature_store/templates/feature_store_template.yaml +45 -0
  398. ads/feature_store/transformation.py +499 -0
  399. ads/feature_store/validation_output.py +57 -0
  400. ads/hpo/__init__.py +9 -0
  401. ads/hpo/_imports.py +91 -0
  402. ads/hpo/ads_search_space.py +439 -0
  403. ads/hpo/distributions.py +325 -0
  404. ads/hpo/objective.py +280 -0
  405. ads/hpo/search_cv.py +1657 -0
  406. ads/hpo/stopping_criterion.py +75 -0
  407. ads/hpo/tuner_artifact.py +413 -0
  408. ads/hpo/utils.py +91 -0
  409. ads/hpo/validation.py +140 -0
  410. ads/hpo/visualization/__init__.py +5 -0
  411. ads/hpo/visualization/_contour.py +23 -0
  412. ads/hpo/visualization/_edf.py +20 -0
  413. ads/hpo/visualization/_intermediate_values.py +21 -0
  414. ads/hpo/visualization/_optimization_history.py +25 -0
  415. ads/hpo/visualization/_parallel_coordinate.py +169 -0
  416. ads/hpo/visualization/_param_importances.py +26 -0
  417. ads/jobs/__init__.py +53 -0
  418. ads/jobs/ads_job.py +663 -0
  419. ads/jobs/builders/__init__.py +5 -0
  420. ads/jobs/builders/base.py +156 -0
  421. ads/jobs/builders/infrastructure/__init__.py +6 -0
  422. ads/jobs/builders/infrastructure/base.py +165 -0
  423. ads/jobs/builders/infrastructure/dataflow.py +1252 -0
  424. ads/jobs/builders/infrastructure/dsc_job.py +1894 -0
  425. ads/jobs/builders/infrastructure/dsc_job_runtime.py +1233 -0
  426. ads/jobs/builders/infrastructure/utils.py +65 -0
  427. ads/jobs/builders/runtimes/__init__.py +5 -0
  428. ads/jobs/builders/runtimes/artifact.py +338 -0
  429. ads/jobs/builders/runtimes/base.py +325 -0
  430. ads/jobs/builders/runtimes/container_runtime.py +242 -0
  431. ads/jobs/builders/runtimes/python_runtime.py +1016 -0
  432. ads/jobs/builders/runtimes/pytorch_runtime.py +204 -0
  433. ads/jobs/cli.py +104 -0
  434. ads/jobs/env_var_parser.py +131 -0
  435. ads/jobs/extension.py +160 -0
  436. ads/jobs/schema/__init__.py +5 -0
  437. ads/jobs/schema/infrastructure_schema.json +116 -0
  438. ads/jobs/schema/job_schema.json +42 -0
  439. ads/jobs/schema/runtime_schema.json +183 -0
  440. ads/jobs/schema/validator.py +141 -0
  441. ads/jobs/serializer.py +296 -0
  442. ads/jobs/templates/__init__.py +5 -0
  443. ads/jobs/templates/container.py +6 -0
  444. ads/jobs/templates/driver_notebook.py +177 -0
  445. ads/jobs/templates/driver_oci.py +500 -0
  446. ads/jobs/templates/driver_python.py +48 -0
  447. ads/jobs/templates/driver_pytorch.py +852 -0
  448. ads/jobs/templates/driver_utils.py +615 -0
  449. ads/jobs/templates/hostname_from_env.c +55 -0
  450. ads/jobs/templates/oci_metrics.py +181 -0
  451. ads/jobs/utils.py +104 -0
  452. ads/llm/__init__.py +28 -0
  453. ads/llm/autogen/__init__.py +2 -0
  454. ads/llm/autogen/constants.py +15 -0
  455. ads/llm/autogen/reports/__init__.py +2 -0
  456. ads/llm/autogen/reports/base.py +67 -0
  457. ads/llm/autogen/reports/data.py +103 -0
  458. ads/llm/autogen/reports/session.py +526 -0
  459. ads/llm/autogen/reports/templates/chat_box.html +13 -0
  460. ads/llm/autogen/reports/templates/chat_box_lt.html +5 -0
  461. ads/llm/autogen/reports/templates/chat_box_rt.html +6 -0
  462. ads/llm/autogen/reports/utils.py +56 -0
  463. ads/llm/autogen/v02/__init__.py +4 -0
  464. ads/llm/autogen/v02/client.py +295 -0
  465. ads/llm/autogen/v02/log_handlers/__init__.py +2 -0
  466. ads/llm/autogen/v02/log_handlers/oci_file_handler.py +83 -0
  467. ads/llm/autogen/v02/loggers/__init__.py +6 -0
  468. ads/llm/autogen/v02/loggers/metric_logger.py +320 -0
  469. ads/llm/autogen/v02/loggers/session_logger.py +580 -0
  470. ads/llm/autogen/v02/loggers/utils.py +86 -0
  471. ads/llm/autogen/v02/runtime_logging.py +163 -0
  472. ads/llm/chain.py +268 -0
  473. ads/llm/chat_template.py +31 -0
  474. ads/llm/deploy.py +63 -0
  475. ads/llm/guardrails/__init__.py +5 -0
  476. ads/llm/guardrails/base.py +442 -0
  477. ads/llm/guardrails/huggingface.py +44 -0
  478. ads/llm/langchain/__init__.py +5 -0
  479. ads/llm/langchain/plugins/__init__.py +5 -0
  480. ads/llm/langchain/plugins/chat_models/__init__.py +5 -0
  481. ads/llm/langchain/plugins/chat_models/oci_data_science.py +1027 -0
  482. ads/llm/langchain/plugins/embeddings/__init__.py +4 -0
  483. ads/llm/langchain/plugins/embeddings/oci_data_science_model_deployment_endpoint.py +184 -0
  484. ads/llm/langchain/plugins/llms/__init__.py +5 -0
  485. ads/llm/langchain/plugins/llms/oci_data_science_model_deployment_endpoint.py +979 -0
  486. ads/llm/requirements.txt +3 -0
  487. ads/llm/serialize.py +219 -0
  488. ads/llm/serializers/__init__.py +0 -0
  489. ads/llm/serializers/retrieval_qa.py +153 -0
  490. ads/llm/serializers/runnable_parallel.py +27 -0
  491. ads/llm/templates/score_chain.jinja2 +155 -0
  492. ads/llm/templates/tool_chat_template_hermes.jinja +130 -0
  493. ads/llm/templates/tool_chat_template_mistral_parallel.jinja +94 -0
  494. ads/model/__init__.py +52 -0
  495. ads/model/artifact.py +573 -0
  496. ads/model/artifact_downloader.py +254 -0
  497. ads/model/artifact_uploader.py +267 -0
  498. ads/model/base_properties.py +238 -0
  499. ads/model/common/.model-ignore +66 -0
  500. ads/model/common/__init__.py +5 -0
  501. ads/model/common/utils.py +142 -0
  502. ads/model/datascience_model.py +2635 -0
  503. ads/model/deployment/__init__.py +20 -0
  504. ads/model/deployment/common/__init__.py +5 -0
  505. ads/model/deployment/common/utils.py +308 -0
  506. ads/model/deployment/model_deployer.py +466 -0
  507. ads/model/deployment/model_deployment.py +1846 -0
  508. ads/model/deployment/model_deployment_infrastructure.py +671 -0
  509. ads/model/deployment/model_deployment_properties.py +493 -0
  510. ads/model/deployment/model_deployment_runtime.py +838 -0
  511. ads/model/extractor/__init__.py +5 -0
  512. ads/model/extractor/automl_extractor.py +74 -0
  513. ads/model/extractor/embedding_onnx_extractor.py +80 -0
  514. ads/model/extractor/huggingface_extractor.py +88 -0
  515. ads/model/extractor/keras_extractor.py +84 -0
  516. ads/model/extractor/lightgbm_extractor.py +93 -0
  517. ads/model/extractor/model_info_extractor.py +114 -0
  518. ads/model/extractor/model_info_extractor_factory.py +105 -0
  519. ads/model/extractor/pytorch_extractor.py +87 -0
  520. ads/model/extractor/sklearn_extractor.py +112 -0
  521. ads/model/extractor/spark_extractor.py +89 -0
  522. ads/model/extractor/tensorflow_extractor.py +85 -0
  523. ads/model/extractor/xgboost_extractor.py +94 -0
  524. ads/model/framework/__init__.py +5 -0
  525. ads/model/framework/automl_model.py +178 -0
  526. ads/model/framework/embedding_onnx_model.py +438 -0
  527. ads/model/framework/huggingface_model.py +399 -0
  528. ads/model/framework/lightgbm_model.py +266 -0
  529. ads/model/framework/pytorch_model.py +266 -0
  530. ads/model/framework/sklearn_model.py +250 -0
  531. ads/model/framework/spark_model.py +326 -0
  532. ads/model/framework/tensorflow_model.py +254 -0
  533. ads/model/framework/xgboost_model.py +258 -0
  534. ads/model/generic_model.py +3518 -0
  535. ads/model/model_artifact_boilerplate/README.md +381 -0
  536. ads/model/model_artifact_boilerplate/__init__.py +5 -0
  537. ads/model/model_artifact_boilerplate/artifact_introspection_test/__init__.py +5 -0
  538. ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py +427 -0
  539. ads/model/model_artifact_boilerplate/artifact_introspection_test/requirements.txt +2 -0
  540. ads/model/model_artifact_boilerplate/runtime.yaml +7 -0
  541. ads/model/model_artifact_boilerplate/score.py +61 -0
  542. ads/model/model_file_description_schema.json +68 -0
  543. ads/model/model_introspect.py +331 -0
  544. ads/model/model_metadata.py +1810 -0
  545. ads/model/model_metadata_mixin.py +460 -0
  546. ads/model/model_properties.py +63 -0
  547. ads/model/model_version_set.py +739 -0
  548. ads/model/runtime/__init__.py +5 -0
  549. ads/model/runtime/env_info.py +306 -0
  550. ads/model/runtime/model_deployment_details.py +37 -0
  551. ads/model/runtime/model_provenance_details.py +58 -0
  552. ads/model/runtime/runtime_info.py +81 -0
  553. ads/model/runtime/schemas/inference_env_info_schema.yaml +16 -0
  554. ads/model/runtime/schemas/model_provenance_schema.yaml +36 -0
  555. ads/model/runtime/schemas/training_env_info_schema.yaml +16 -0
  556. ads/model/runtime/utils.py +201 -0
  557. ads/model/serde/__init__.py +5 -0
  558. ads/model/serde/common.py +40 -0
  559. ads/model/serde/model_input.py +547 -0
  560. ads/model/serde/model_serializer.py +1184 -0
  561. ads/model/service/__init__.py +5 -0
  562. ads/model/service/oci_datascience_model.py +1076 -0
  563. ads/model/service/oci_datascience_model_deployment.py +500 -0
  564. ads/model/service/oci_datascience_model_version_set.py +176 -0
  565. ads/model/transformer/__init__.py +5 -0
  566. ads/model/transformer/onnx_transformer.py +324 -0
  567. ads/mysqldb/__init__.py +5 -0
  568. ads/mysqldb/mysql_db.py +227 -0
  569. ads/opctl/__init__.py +18 -0
  570. ads/opctl/anomaly_detection.py +11 -0
  571. ads/opctl/backend/__init__.py +5 -0
  572. ads/opctl/backend/ads_dataflow.py +353 -0
  573. ads/opctl/backend/ads_ml_job.py +710 -0
  574. ads/opctl/backend/ads_ml_pipeline.py +164 -0
  575. ads/opctl/backend/ads_model_deployment.py +209 -0
  576. ads/opctl/backend/base.py +146 -0
  577. ads/opctl/backend/local.py +1053 -0
  578. ads/opctl/backend/marketplace/__init__.py +9 -0
  579. ads/opctl/backend/marketplace/helm_helper.py +173 -0
  580. ads/opctl/backend/marketplace/local_marketplace.py +271 -0
  581. ads/opctl/backend/marketplace/marketplace_backend_runner.py +71 -0
  582. ads/opctl/backend/marketplace/marketplace_operator_interface.py +44 -0
  583. ads/opctl/backend/marketplace/marketplace_operator_runner.py +24 -0
  584. ads/opctl/backend/marketplace/marketplace_utils.py +212 -0
  585. ads/opctl/backend/marketplace/models/__init__.py +5 -0
  586. ads/opctl/backend/marketplace/models/bearer_token.py +94 -0
  587. ads/opctl/backend/marketplace/models/marketplace_type.py +70 -0
  588. ads/opctl/backend/marketplace/models/ocir_details.py +56 -0
  589. ads/opctl/backend/marketplace/prerequisite_checker.py +238 -0
  590. ads/opctl/cli.py +707 -0
  591. ads/opctl/cmds.py +869 -0
  592. ads/opctl/conda/__init__.py +5 -0
  593. ads/opctl/conda/cli.py +193 -0
  594. ads/opctl/conda/cmds.py +749 -0
  595. ads/opctl/conda/config.yaml +34 -0
  596. ads/opctl/conda/manifest_template.yaml +13 -0
  597. ads/opctl/conda/multipart_uploader.py +188 -0
  598. ads/opctl/conda/pack.py +89 -0
  599. ads/opctl/config/__init__.py +5 -0
  600. ads/opctl/config/base.py +57 -0
  601. ads/opctl/config/diagnostics/__init__.py +5 -0
  602. ads/opctl/config/diagnostics/distributed/default_requirements_config.yaml +62 -0
  603. ads/opctl/config/merger.py +255 -0
  604. ads/opctl/config/resolver.py +297 -0
  605. ads/opctl/config/utils.py +79 -0
  606. ads/opctl/config/validator.py +17 -0
  607. ads/opctl/config/versioner.py +68 -0
  608. ads/opctl/config/yaml_parsers/__init__.py +7 -0
  609. ads/opctl/config/yaml_parsers/base.py +58 -0
  610. ads/opctl/config/yaml_parsers/distributed/__init__.py +7 -0
  611. ads/opctl/config/yaml_parsers/distributed/yaml_parser.py +201 -0
  612. ads/opctl/constants.py +66 -0
  613. ads/opctl/decorator/__init__.py +5 -0
  614. ads/opctl/decorator/common.py +129 -0
  615. ads/opctl/diagnostics/__init__.py +5 -0
  616. ads/opctl/diagnostics/__main__.py +25 -0
  617. ads/opctl/diagnostics/check_distributed_job_requirements.py +212 -0
  618. ads/opctl/diagnostics/check_requirements.py +144 -0
  619. ads/opctl/diagnostics/requirement_exception.py +9 -0
  620. ads/opctl/distributed/README.md +109 -0
  621. ads/opctl/distributed/__init__.py +5 -0
  622. ads/opctl/distributed/certificates.py +32 -0
  623. ads/opctl/distributed/cli.py +207 -0
  624. ads/opctl/distributed/cmds.py +731 -0
  625. ads/opctl/distributed/common/__init__.py +5 -0
  626. ads/opctl/distributed/common/abstract_cluster_provider.py +449 -0
  627. ads/opctl/distributed/common/abstract_framework_spec_builder.py +88 -0
  628. ads/opctl/distributed/common/cluster_config_helper.py +103 -0
  629. ads/opctl/distributed/common/cluster_provider_factory.py +21 -0
  630. ads/opctl/distributed/common/cluster_runner.py +54 -0
  631. ads/opctl/distributed/common/framework_factory.py +29 -0
  632. ads/opctl/docker/Dockerfile.job +103 -0
  633. ads/opctl/docker/Dockerfile.job.arm +107 -0
  634. ads/opctl/docker/Dockerfile.job.gpu +175 -0
  635. ads/opctl/docker/base-env.yaml +13 -0
  636. ads/opctl/docker/cuda.repo +6 -0
  637. ads/opctl/docker/operator/.dockerignore +0 -0
  638. ads/opctl/docker/operator/Dockerfile +41 -0
  639. ads/opctl/docker/operator/Dockerfile.gpu +85 -0
  640. ads/opctl/docker/operator/cuda.repo +6 -0
  641. ads/opctl/docker/operator/environment.yaml +8 -0
  642. ads/opctl/forecast.py +11 -0
  643. ads/opctl/index.yaml +3 -0
  644. ads/opctl/model/__init__.py +5 -0
  645. ads/opctl/model/cli.py +65 -0
  646. ads/opctl/model/cmds.py +73 -0
  647. ads/opctl/operator/README.md +4 -0
  648. ads/opctl/operator/__init__.py +31 -0
  649. ads/opctl/operator/cli.py +344 -0
  650. ads/opctl/operator/cmd.py +596 -0
  651. ads/opctl/operator/common/__init__.py +5 -0
  652. ads/opctl/operator/common/backend_factory.py +460 -0
  653. ads/opctl/operator/common/const.py +27 -0
  654. ads/opctl/operator/common/data/synthetic.csv +16001 -0
  655. ads/opctl/operator/common/dictionary_merger.py +148 -0
  656. ads/opctl/operator/common/errors.py +42 -0
  657. ads/opctl/operator/common/operator_config.py +99 -0
  658. ads/opctl/operator/common/operator_loader.py +811 -0
  659. ads/opctl/operator/common/operator_schema.yaml +130 -0
  660. ads/opctl/operator/common/operator_yaml_generator.py +152 -0
  661. ads/opctl/operator/common/utils.py +208 -0
  662. ads/opctl/operator/lowcode/__init__.py +5 -0
  663. ads/opctl/operator/lowcode/anomaly/MLoperator +16 -0
  664. ads/opctl/operator/lowcode/anomaly/README.md +207 -0
  665. ads/opctl/operator/lowcode/anomaly/__init__.py +5 -0
  666. ads/opctl/operator/lowcode/anomaly/__main__.py +103 -0
  667. ads/opctl/operator/lowcode/anomaly/cmd.py +35 -0
  668. ads/opctl/operator/lowcode/anomaly/const.py +167 -0
  669. ads/opctl/operator/lowcode/anomaly/environment.yaml +10 -0
  670. ads/opctl/operator/lowcode/anomaly/model/__init__.py +5 -0
  671. ads/opctl/operator/lowcode/anomaly/model/anomaly_dataset.py +146 -0
  672. ads/opctl/operator/lowcode/anomaly/model/anomaly_merlion.py +162 -0
  673. ads/opctl/operator/lowcode/anomaly/model/automlx.py +99 -0
  674. ads/opctl/operator/lowcode/anomaly/model/autots.py +115 -0
  675. ads/opctl/operator/lowcode/anomaly/model/base_model.py +404 -0
  676. ads/opctl/operator/lowcode/anomaly/model/factory.py +110 -0
  677. ads/opctl/operator/lowcode/anomaly/model/isolationforest.py +78 -0
  678. ads/opctl/operator/lowcode/anomaly/model/oneclasssvm.py +78 -0
  679. ads/opctl/operator/lowcode/anomaly/model/randomcutforest.py +120 -0
  680. ads/opctl/operator/lowcode/anomaly/model/tods.py +119 -0
  681. ads/opctl/operator/lowcode/anomaly/operator_config.py +127 -0
  682. ads/opctl/operator/lowcode/anomaly/schema.yaml +401 -0
  683. ads/opctl/operator/lowcode/anomaly/utils.py +88 -0
  684. ads/opctl/operator/lowcode/common/__init__.py +5 -0
  685. ads/opctl/operator/lowcode/common/const.py +10 -0
  686. ads/opctl/operator/lowcode/common/data.py +116 -0
  687. ads/opctl/operator/lowcode/common/errors.py +47 -0
  688. ads/opctl/operator/lowcode/common/transformations.py +296 -0
  689. ads/opctl/operator/lowcode/common/utils.py +384 -0
  690. ads/opctl/operator/lowcode/feature_store_marketplace/MLoperator +13 -0
  691. ads/opctl/operator/lowcode/feature_store_marketplace/README.md +30 -0
  692. ads/opctl/operator/lowcode/feature_store_marketplace/__init__.py +5 -0
  693. ads/opctl/operator/lowcode/feature_store_marketplace/__main__.py +116 -0
  694. ads/opctl/operator/lowcode/feature_store_marketplace/cmd.py +85 -0
  695. ads/opctl/operator/lowcode/feature_store_marketplace/const.py +15 -0
  696. ads/opctl/operator/lowcode/feature_store_marketplace/environment.yaml +0 -0
  697. ads/opctl/operator/lowcode/feature_store_marketplace/models/__init__.py +4 -0
  698. ads/opctl/operator/lowcode/feature_store_marketplace/models/apigw_config.py +32 -0
  699. ads/opctl/operator/lowcode/feature_store_marketplace/models/db_config.py +43 -0
  700. ads/opctl/operator/lowcode/feature_store_marketplace/models/mysql_config.py +120 -0
  701. ads/opctl/operator/lowcode/feature_store_marketplace/models/serializable_yaml_model.py +34 -0
  702. ads/opctl/operator/lowcode/feature_store_marketplace/operator_utils.py +386 -0
  703. ads/opctl/operator/lowcode/feature_store_marketplace/schema.yaml +160 -0
  704. ads/opctl/operator/lowcode/forecast/MLoperator +25 -0
  705. ads/opctl/operator/lowcode/forecast/README.md +209 -0
  706. ads/opctl/operator/lowcode/forecast/__init__.py +5 -0
  707. ads/opctl/operator/lowcode/forecast/__main__.py +89 -0
  708. ads/opctl/operator/lowcode/forecast/cmd.py +40 -0
  709. ads/opctl/operator/lowcode/forecast/const.py +92 -0
  710. ads/opctl/operator/lowcode/forecast/environment.yaml +20 -0
  711. ads/opctl/operator/lowcode/forecast/errors.py +26 -0
  712. ads/opctl/operator/lowcode/forecast/model/__init__.py +5 -0
  713. ads/opctl/operator/lowcode/forecast/model/arima.py +279 -0
  714. ads/opctl/operator/lowcode/forecast/model/automlx.py +553 -0
  715. ads/opctl/operator/lowcode/forecast/model/autots.py +312 -0
  716. ads/opctl/operator/lowcode/forecast/model/base_model.py +875 -0
  717. ads/opctl/operator/lowcode/forecast/model/factory.py +106 -0
  718. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +492 -0
  719. ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +243 -0
  720. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +482 -0
  721. ads/opctl/operator/lowcode/forecast/model/prophet.py +445 -0
  722. ads/opctl/operator/lowcode/forecast/model_evaluator.py +244 -0
  723. ads/opctl/operator/lowcode/forecast/operator_config.py +234 -0
  724. ads/opctl/operator/lowcode/forecast/schema.yaml +506 -0
  725. ads/opctl/operator/lowcode/forecast/utils.py +397 -0
  726. ads/opctl/operator/lowcode/forecast/whatifserve/__init__.py +7 -0
  727. ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +285 -0
  728. ads/opctl/operator/lowcode/forecast/whatifserve/score.py +246 -0
  729. ads/opctl/operator/lowcode/pii/MLoperator +17 -0
  730. ads/opctl/operator/lowcode/pii/README.md +208 -0
  731. ads/opctl/operator/lowcode/pii/__init__.py +5 -0
  732. ads/opctl/operator/lowcode/pii/__main__.py +78 -0
  733. ads/opctl/operator/lowcode/pii/cmd.py +39 -0
  734. ads/opctl/operator/lowcode/pii/constant.py +84 -0
  735. ads/opctl/operator/lowcode/pii/environment.yaml +17 -0
  736. ads/opctl/operator/lowcode/pii/errors.py +27 -0
  737. ads/opctl/operator/lowcode/pii/model/__init__.py +5 -0
  738. ads/opctl/operator/lowcode/pii/model/factory.py +82 -0
  739. ads/opctl/operator/lowcode/pii/model/guardrails.py +167 -0
  740. ads/opctl/operator/lowcode/pii/model/pii.py +145 -0
  741. ads/opctl/operator/lowcode/pii/model/processor/__init__.py +34 -0
  742. ads/opctl/operator/lowcode/pii/model/processor/email_replacer.py +34 -0
  743. ads/opctl/operator/lowcode/pii/model/processor/mbi_replacer.py +35 -0
  744. ads/opctl/operator/lowcode/pii/model/processor/name_replacer.py +225 -0
  745. ads/opctl/operator/lowcode/pii/model/processor/number_replacer.py +73 -0
  746. ads/opctl/operator/lowcode/pii/model/processor/remover.py +26 -0
  747. ads/opctl/operator/lowcode/pii/model/report.py +487 -0
  748. ads/opctl/operator/lowcode/pii/operator_config.py +95 -0
  749. ads/opctl/operator/lowcode/pii/schema.yaml +108 -0
  750. ads/opctl/operator/lowcode/pii/utils.py +43 -0
  751. ads/opctl/operator/lowcode/recommender/MLoperator +16 -0
  752. ads/opctl/operator/lowcode/recommender/README.md +206 -0
  753. ads/opctl/operator/lowcode/recommender/__init__.py +5 -0
  754. ads/opctl/operator/lowcode/recommender/__main__.py +82 -0
  755. ads/opctl/operator/lowcode/recommender/cmd.py +33 -0
  756. ads/opctl/operator/lowcode/recommender/constant.py +30 -0
  757. ads/opctl/operator/lowcode/recommender/environment.yaml +11 -0
  758. ads/opctl/operator/lowcode/recommender/model/base_model.py +212 -0
  759. ads/opctl/operator/lowcode/recommender/model/factory.py +56 -0
  760. ads/opctl/operator/lowcode/recommender/model/recommender_dataset.py +25 -0
  761. ads/opctl/operator/lowcode/recommender/model/svd.py +106 -0
  762. ads/opctl/operator/lowcode/recommender/operator_config.py +81 -0
  763. ads/opctl/operator/lowcode/recommender/schema.yaml +265 -0
  764. ads/opctl/operator/lowcode/recommender/utils.py +13 -0
  765. ads/opctl/operator/runtime/__init__.py +5 -0
  766. ads/opctl/operator/runtime/const.py +17 -0
  767. ads/opctl/operator/runtime/container_runtime_schema.yaml +50 -0
  768. ads/opctl/operator/runtime/marketplace_runtime.py +50 -0
  769. ads/opctl/operator/runtime/python_marketplace_runtime_schema.yaml +21 -0
  770. ads/opctl/operator/runtime/python_runtime_schema.yaml +21 -0
  771. ads/opctl/operator/runtime/runtime.py +115 -0
  772. ads/opctl/schema.yaml.yml +36 -0
  773. ads/opctl/script.py +40 -0
  774. ads/opctl/spark/__init__.py +5 -0
  775. ads/opctl/spark/cli.py +43 -0
  776. ads/opctl/spark/cmds.py +147 -0
  777. ads/opctl/templates/diagnostic_report_template.jinja2 +102 -0
  778. ads/opctl/utils.py +344 -0
  779. ads/oracledb/__init__.py +5 -0
  780. ads/oracledb/oracle_db.py +346 -0
  781. ads/pipeline/__init__.py +39 -0
  782. ads/pipeline/ads_pipeline.py +2279 -0
  783. ads/pipeline/ads_pipeline_run.py +772 -0
  784. ads/pipeline/ads_pipeline_step.py +605 -0
  785. ads/pipeline/builders/__init__.py +5 -0
  786. ads/pipeline/builders/infrastructure/__init__.py +5 -0
  787. ads/pipeline/builders/infrastructure/custom_script.py +32 -0
  788. ads/pipeline/cli.py +119 -0
  789. ads/pipeline/extension.py +291 -0
  790. ads/pipeline/schema/__init__.py +5 -0
  791. ads/pipeline/schema/cs_step_schema.json +35 -0
  792. ads/pipeline/schema/ml_step_schema.json +31 -0
  793. ads/pipeline/schema/pipeline_schema.json +71 -0
  794. ads/pipeline/visualizer/__init__.py +5 -0
  795. ads/pipeline/visualizer/base.py +570 -0
  796. ads/pipeline/visualizer/graph_renderer.py +272 -0
  797. ads/pipeline/visualizer/text_renderer.py +84 -0
  798. ads/secrets/__init__.py +11 -0
  799. ads/secrets/adb.py +386 -0
  800. ads/secrets/auth_token.py +86 -0
  801. ads/secrets/big_data_service.py +365 -0
  802. ads/secrets/mysqldb.py +149 -0
  803. ads/secrets/oracledb.py +160 -0
  804. ads/secrets/secrets.py +407 -0
  805. ads/telemetry/__init__.py +7 -0
  806. ads/telemetry/base.py +69 -0
  807. ads/telemetry/client.py +125 -0
  808. ads/telemetry/telemetry.py +257 -0
  809. ads/templates/dataflow_pyspark.jinja2 +13 -0
  810. ads/templates/dataflow_sparksql.jinja2 +22 -0
  811. ads/templates/func.jinja2 +20 -0
  812. ads/templates/schemas/openapi.json +1740 -0
  813. ads/templates/score-pkl.jinja2 +173 -0
  814. ads/templates/score.jinja2 +322 -0
  815. ads/templates/score_embedding_onnx.jinja2 +202 -0
  816. ads/templates/score_generic.jinja2 +165 -0
  817. ads/templates/score_huggingface_pipeline.jinja2 +217 -0
  818. ads/templates/score_lightgbm.jinja2 +185 -0
  819. ads/templates/score_onnx.jinja2 +407 -0
  820. ads/templates/score_onnx_new.jinja2 +473 -0
  821. ads/templates/score_oracle_automl.jinja2 +185 -0
  822. ads/templates/score_pyspark.jinja2 +154 -0
  823. ads/templates/score_pytorch.jinja2 +219 -0
  824. ads/templates/score_scikit-learn.jinja2 +184 -0
  825. ads/templates/score_tensorflow.jinja2 +184 -0
  826. ads/templates/score_xgboost.jinja2 +178 -0
  827. ads/text_dataset/__init__.py +5 -0
  828. ads/text_dataset/backends.py +211 -0
  829. ads/text_dataset/dataset.py +445 -0
  830. ads/text_dataset/extractor.py +207 -0
  831. ads/text_dataset/options.py +53 -0
  832. ads/text_dataset/udfs.py +22 -0
  833. ads/text_dataset/utils.py +49 -0
  834. ads/type_discovery/__init__.py +9 -0
  835. ads/type_discovery/abstract_detector.py +21 -0
  836. ads/type_discovery/constant_detector.py +41 -0
  837. ads/type_discovery/continuous_detector.py +54 -0
  838. ads/type_discovery/credit_card_detector.py +99 -0
  839. ads/type_discovery/datetime_detector.py +92 -0
  840. ads/type_discovery/discrete_detector.py +118 -0
  841. ads/type_discovery/document_detector.py +146 -0
  842. ads/type_discovery/ip_detector.py +68 -0
  843. ads/type_discovery/latlon_detector.py +90 -0
  844. ads/type_discovery/phone_number_detector.py +63 -0
  845. ads/type_discovery/type_discovery_driver.py +87 -0
  846. ads/type_discovery/typed_feature.py +594 -0
  847. ads/type_discovery/unknown_detector.py +41 -0
  848. ads/type_discovery/zipcode_detector.py +48 -0
  849. ads/vault/__init__.py +7 -0
  850. ads/vault/vault.py +237 -0
  851. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.9rc1.dist-info}/METADATA +150 -150
  852. oracle_ads-2.13.9rc1.dist-info/RECORD +858 -0
  853. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.9rc1.dist-info}/WHEEL +1 -2
  854. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.9rc1.dist-info}/entry_points.txt +2 -1
  855. oracle_ads-2.13.9rc0.dist-info/RECORD +0 -9
  856. oracle_ads-2.13.9rc0.dist-info/top_level.txt +0 -1
  857. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.9rc1.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,3518 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) 2022, 2025 Oracle and/or its affiliates.
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5
+
6
+ import inspect
7
+ import os
8
+ import shutil
9
+ import tempfile
10
+ import warnings
11
+ from enum import Enum
12
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union
13
+
14
+ import numpy as np
15
+ import pandas as pd
16
+ import requests
17
+ import yaml
18
+ from PIL import Image
19
+
20
+ from ads.common import auth as authutil
21
+ from ads.common import logger, utils
22
+ from ads.common.decorator.utils import class_or_instance_method
23
+ from ads.common.object_storage_details import ObjectStorageDetails
24
+ from ads.common.utils import DATA_SCHEMA_MAX_COL_NUM, get_files
25
+ from ads.config import (
26
+ CONDA_BUCKET_NS,
27
+ JOB_RUN_COMPARTMENT_OCID,
28
+ JOB_RUN_OCID,
29
+ NB_SESSION_COMPARTMENT_OCID,
30
+ NB_SESSION_OCID,
31
+ PIPELINE_RUN_COMPARTMENT_OCID,
32
+ PROJECT_OCID,
33
+ TMPDIR,
34
+ )
35
+ from ads.evaluations import EvaluatorMixin
36
+ from ads.feature_engineering import ADSImage
37
+ from ads.feature_engineering.schema import Schema
38
+ from ads.feature_store.model_details import ModelDetails
39
+ from ads.model.artifact import ModelArtifact
40
+ from ads.model.common.utils import (
41
+ _extract_locals,
42
+ _is_json_serializable,
43
+ fetch_manifest_from_conda_location,
44
+ zip_artifact,
45
+ )
46
+ from ads.model.datascience_model import DataScienceModel
47
+ from ads.model.deployment import (
48
+ DEFAULT_POLL_INTERVAL,
49
+ DEFAULT_WAIT_TIME,
50
+ ModelDeployment,
51
+ ModelDeploymentCondaRuntime,
52
+ ModelDeploymentContainerRuntime,
53
+ ModelDeploymentInfrastructure,
54
+ ModelDeploymentMode,
55
+ ModelDeploymentProperties,
56
+ )
57
+ from ads.model.deployment.common.utils import State as ModelDeploymentState
58
+ from ads.model.deployment.common.utils import send_request
59
+ from ads.model.model_introspect import (
60
+ TEST_STATUS,
61
+ Introspectable,
62
+ IntrospectionNotPassed,
63
+ ModelIntrospect,
64
+ )
65
+ from ads.model.model_metadata import (
66
+ ExtendedEnum,
67
+ Framework,
68
+ MetadataCustomCategory,
69
+ ModelCustomMetadata,
70
+ ModelProvenanceMetadata,
71
+ ModelTaxonomyMetadata,
72
+ )
73
+ from ads.model.model_metadata_mixin import MetadataMixin
74
+ from ads.model.model_properties import ModelProperties
75
+ from ads.model.model_version_set import ModelVersionSet, _extract_model_version_set_id
76
+ from ads.model.runtime.env_info import DEFAULT_CONDA_BUCKET_NAME
77
+ from ads.model.runtime.runtime_info import RuntimeInfo
78
+ from ads.model.serde.common import SERDE
79
+ from ads.model.serde.model_input import (
80
+ SUPPORTED_MODEL_INPUT_SERIALIZERS,
81
+ ModelInputSerializerFactory,
82
+ ModelInputSerializerType,
83
+ )
84
+ from ads.model.serde.model_serializer import (
85
+ SUPPORTED_MODEL_SERIALIZERS,
86
+ ModelSerializerFactory,
87
+ ModelSerializerType,
88
+ )
89
+ from ads.model.transformer.onnx_transformer import ONNXTransformer
90
+
91
+ _TRAINING_RESOURCE_ID = JOB_RUN_OCID or NB_SESSION_OCID
92
+ _COMPARTMENT_OCID = (
93
+ NB_SESSION_COMPARTMENT_OCID
94
+ or JOB_RUN_COMPARTMENT_OCID
95
+ or PIPELINE_RUN_COMPARTMENT_OCID
96
+ )
97
+
98
+ MODEL_DEPLOYMENT_INSTANCE_SHAPE = "VM.Standard.E4.Flex"
99
+ MODEL_DEPLOYMENT_INSTANCE_OCPUS = 1
100
+ MODEL_DEPLOYMENT_INSTANCE_MEMORY_IN_GBS = 16
101
+ MODEL_DEPLOYMENT_INSTANCE_COUNT = 1
102
+ MODEL_DEPLOYMENT_BANDWIDTH_MBPS = 10
103
+
104
+
105
+ DEFAULT_MODEL_FOLDER_NAME = "model"
106
+
107
+ ONNX_DATA_TRANSFORMER = "onnx_data_transformer.json"
108
+ _ATTRIBUTES_TO_SHOW_ = [
109
+ "artifact_dir",
110
+ "framework",
111
+ "algorithm",
112
+ "model_id",
113
+ "model_deployment_id",
114
+ ]
115
+ FRAMEWORKS_WITHOUT_ONNX_DATA_TRANSFORM = [
116
+ Framework.TENSORFLOW,
117
+ Framework.PYTORCH,
118
+ Framework.SPARK,
119
+ ]
120
+
121
+ VERIFY_STATUS_NAME = "verify()"
122
+ PREPARE_STATUS_NAME = "prepare()"
123
+ INITIATE_STATUS_NAME = "initiate"
124
+ SAVE_STATUS_NAME = "save()"
125
+ DEPLOY_STATUS_NAME = "deploy()"
126
+ PREDICT_STATUS_NAME = "predict()"
127
+
128
+ INITIATE_STATUS_DETAIL = "Initiated the model"
129
+ PREPARE_STATUS_GEN_RUNTIME_DETAIL = "Generated runtime.yaml"
130
+ PREPARE_STATUS_GEN_SCORE_DETAIL = "Generated score.py"
131
+ PREPARE_STATUS_SERIALIZE_MODEL_DETAIL = "Serialized model"
132
+ PREPARE_STATUS_POPULATE_METADATA_DETAIL = (
133
+ "Populated metadata(Custom, Taxonomy and Provenance)"
134
+ )
135
+ VERIFY_STATUS_LOCAL_TEST_DETAIL = "Local tested .predict from score.py"
136
+ SAVE_STATUS_INTROSPECT_TEST_DETAIL = "Conducted Introspect Test"
137
+ SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL = "Uploaded artifact to model catalog"
138
+ DEPLOY_STATUS_DETAIL = "Deployed the model"
139
+ PREDICT_STATUS_CALL_ENDPOINT_DETAIL = "Called deployment predict endpoint"
140
+
141
+ Self = TypeVar("Self", bound="GenericModel")
142
+
143
+
144
+ class ModelDeploymentRuntimeType:
145
+ CONDA = "conda"
146
+ CONTAINER = "container"
147
+
148
+
149
+ class DataScienceModelType(ExtendedEnum):
150
+ MODEL_DEPLOYMENT = "datasciencemodeldeployment"
151
+ MODEL = "datasciencemodel"
152
+
153
+
154
+ class NotActiveDeploymentError(Exception): # pragma: no cover
155
+ def __init__(self, state: str):
156
+ msg = (
157
+ "To perform a prediction the deployed model needs to be in an active state. "
158
+ f"The current state is: {state}."
159
+ )
160
+ super().__init__(msg)
161
+
162
+
163
+ class ArtifactsNotAvailableError(Exception):
164
+ def __init__(
165
+ self, msg="Model artifacts are either not generated or not available locally."
166
+ ):
167
+ super().__init__(msg)
168
+
169
+
170
+ class SerializeModelNotImplementedError(NotImplementedError): # pragma: no cover
171
+ pass
172
+
173
+
174
+ class SerializeInputNotImplementedError(NotImplementedError): # pragma: no cover
175
+ pass
176
+
177
+
178
+ class RuntimeInfoInconsistencyError(Exception): # pragma: no cover
179
+ pass
180
+
181
+
182
+ def _prepare_artifact_dir(artifact_dir: str = None) -> str:
183
+ """Prepares artifact dir for the model.
184
+
185
+ Parameters
186
+ ----------
187
+ artifact_dir: (str, optional). Defaults to `None`.
188
+ The artifact dir that needs to be normalized.
189
+
190
+ Returns
191
+ -------
192
+ str
193
+ The artifact dir.
194
+ """
195
+ if artifact_dir and ObjectStorageDetails.is_oci_path(artifact_dir):
196
+ return artifact_dir
197
+
198
+ if artifact_dir and isinstance(artifact_dir, str):
199
+ return os.path.abspath(os.path.expanduser(artifact_dir))
200
+
201
+ artifact_dir = TMPDIR or tempfile.mkdtemp()
202
+ logger.info(
203
+ f"The `artifact_dir` was not provided and "
204
+ f"automatically set to: {artifact_dir}"
205
+ )
206
+
207
+ return artifact_dir
208
+
209
+
210
+ class GenericModel(MetadataMixin, Introspectable, EvaluatorMixin):
211
+ """Generic Model class which is the base class for all the frameworks including
212
+ the unsupported frameworks.
213
+
214
+ Attributes
215
+ ----------
216
+ algorithm: str
217
+ The algorithm of the model.
218
+ artifact_dir: str
219
+ Artifact directory to store the files needed for deployment.
220
+ auth: Dict
221
+ Default authentication is set using the `ads.set_auth` API. To override the
222
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create
223
+ an authentication signer to instantiate an IdentityClient object.
224
+ estimator: Callable
225
+ Any model object generated by sklearn framework
226
+ framework: str
227
+ The framework of the model.
228
+ hyperparameter: dict
229
+ The hyperparameters of the estimator.
230
+ metadata_custom: ModelCustomMetadata
231
+ The model custom metadata.
232
+ metadata_provenance: ModelProvenanceMetadata
233
+ The model provenance metadata.
234
+ metadata_taxonomy: ModelTaxonomyMetadata
235
+ The model taxonomy metadata.
236
+ model_artifact: ModelArtifact
237
+ This is built by calling prepare.
238
+ model_deployment: ModelDeployment
239
+ A ModelDeployment instance.
240
+ model_file_name: str
241
+ Name of the serialized model.
242
+ model_id: str
243
+ The model ID.
244
+ model_input_serializer: SERDE
245
+ Instance of ads.model.SERDE. Used for serialize/deserialize data.
246
+ properties: ModelProperties
247
+ ModelProperties object required to save and deploy model.
248
+ runtime_info: RuntimeInfo
249
+ A RuntimeInfo instance.
250
+ schema_input: Schema
251
+ Schema describes the structure of the input data.
252
+ schema_output: Schema
253
+ Schema describes the structure of the output data.
254
+ serialize: bool
255
+ Whether to serialize the model to pkl file by default. If False, you need to serialize the model manually,
256
+ save it under artifact_dir and update the score.py manually.
257
+ version: str
258
+ The framework version of the model.
259
+
260
+ Methods
261
+ -------
262
+ delete_deployment(...)
263
+ Deletes the current model deployment.
264
+ deploy(..., **kwargs)
265
+ Deploys a model.
266
+ from_model_artifact(uri, ..., **kwargs)
267
+ Loads model from the specified folder, or zip/tar archive.
268
+ from_model_catalog(model_id, ..., **kwargs)
269
+ Loads model from model catalog.
270
+ from_model_deployment(model_deployment_id, ..., **kwargs)
271
+ Loads model from model deployment.
272
+ update_deployment(model_deployment_id, ..., **kwargs)
273
+ Updates a model deployment.
274
+ from_id(ocid, ..., **kwargs)
275
+ Loads model from model OCID or model deployment OCID.
276
+ introspect(...)
277
+ Runs model introspection.
278
+ predict(data, ...)
279
+ Returns prediction of input data run against the model deployment endpoint.
280
+ prepare(..., **kwargs)
281
+ Prepare and save the score.py, serialized model and runtime.yaml file.
282
+ prepare_save_deploy(..., **kwargs)
283
+ Shortcut for prepare, save and deploy steps.
284
+ reload(...)
285
+ Reloads the model artifact files: `score.py` and the `runtime.yaml`.
286
+ restart_deployment(...)
287
+ Restarts the model deployment.
288
+ save(..., **kwargs)
289
+ Saves model artifacts to the model catalog.
290
+ set_model_input_serializer(serde)
291
+ Registers serializer used for serializing data passed in verify/predict.
292
+ summary_status(...)
293
+ Gets a summary table of the current status.
294
+ verify(data, ...)
295
+ Tests if deployment works in local environment.
296
+ upload_artifact(...)
297
+ Uploads model artifacts to the provided `uri`.
298
+ download_artifact(...)
299
+ Downloads model artifacts from the model catalog.
300
+ update_summary_status(...)
301
+ Update the status in the summary table.
302
+ update_summary_action(...)
303
+ Update the actions needed from the user in the summary table.
304
+
305
+
306
+ Examples
307
+ --------
308
+ >>> import tempfile
309
+ >>> from ads.model.generic_model import GenericModel
310
+
311
+ >>> class Toy:
312
+ ... def predict(self, x):
313
+ ... return x ** 2
314
+ >>> estimator = Toy()
315
+
316
+ >>> model = GenericModel(estimator=estimator, artifact_dir=tempfile.mkdtemp())
317
+ >>> model.summary_status()
318
+ >>> model.prepare(
319
+ ... inference_conda_env="dbexp_p38_cpu_v1",
320
+ ... inference_python_version="3.8",
321
+ ... model_file_name="toy_model.pkl",
322
+ ... training_id=None,
323
+ ... force_overwrite=True
324
+ ... )
325
+ >>> model.verify(2)
326
+ >>> model.save()
327
+ >>> model.deploy()
328
+ >>> # Update access log id, freeform tags and description for the model deployment
329
+ >>> model.update_deployment(
330
+ ... access_log={
331
+ ... log_id=<log_ocid>
332
+ ... },
333
+ ... description="Description for Custom Model",
334
+ ... freeform_tags={"key": "value"},
335
+ ... )
336
+ >>> model.predict(2)
337
+ >>> # Uncomment the line below to delete the model and the associated model deployment
338
+ >>> # model.delete(delete_associated_model_deployment = True)
339
+ """
340
+
341
+ _summary_status = None
342
+ _PREFIX = "generic"
343
+ model_input_serializer_type = ModelInputSerializerType
344
+ model_save_serializer_type = ModelSerializerType
345
+
346
+ def __init__(
347
+ self,
348
+ estimator: Callable = None,
349
+ artifact_dir: Optional[str] = None,
350
+ properties: Optional[ModelProperties] = None,
351
+ auth: Optional[Dict] = None,
352
+ serialize: bool = True,
353
+ model_save_serializer: Optional[SERDE] = None,
354
+ model_input_serializer: Optional[SERDE] = None,
355
+ **kwargs: dict,
356
+ ) -> Self:
357
+ """GenericModel Constructor.
358
+
359
+ Parameters
360
+ ----------
361
+ estimator: (Callable).
362
+ Trained model.
363
+ artifact_dir: (str, optional). Defaults to None.
364
+ Artifact directory to store the files needed for deployment.
365
+ properties: (ModelProperties, optional). Defaults to None.
366
+ ModelProperties object required to save and deploy model.
367
+ auth :(Dict, optional). Defaults to None.
368
+ The default authetication is set using `ads.set_auth` API. If you need to override the
369
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
370
+ authentication signer and kwargs required to instantiate IdentityClient object.
371
+ serialize: (bool, optional). Defaults to True.
372
+ Whether to serialize the model to pkl file by default. If False, you need to serialize the model manually,
373
+ save it under artifact_dir and update the score.py manually.
374
+ model_save_serializer: (SERDE or str, optional). Defaults to None.
375
+ Instance of ads.model.SERDE. Used for serialize/deserialize model.
376
+ model_input_serializer: (SERDE or str, optional). Defaults to None.
377
+ Instance of ads.model.SERDE. Used for serialize/deserialize model input.
378
+ """
379
+ if (
380
+ artifact_dir
381
+ and ObjectStorageDetails.is_oci_path(artifact_dir)
382
+ and not self._PREFIX == "spark"
383
+ ):
384
+ raise ValueError(
385
+ f"Unsupported value of `artifact_dir`: {artifact_dir}. "
386
+ "Only SparkPipelineModel framework supports object storage path as `artifact_dir`."
387
+ )
388
+
389
+ self.estimator = estimator
390
+ self.auth = auth or authutil.default_signer()
391
+ self.dsc_model = (
392
+ DataScienceModel()
393
+ .with_custom_metadata_list(ModelCustomMetadata())
394
+ .with_provenance_metadata(ModelProvenanceMetadata())
395
+ .with_defined_metadata_list(ModelTaxonomyMetadata())
396
+ .with_input_schema(Schema())
397
+ .with_output_schema(Schema())
398
+ )
399
+
400
+ self.model_file_name = None
401
+ self.artifact_dir = (
402
+ artifact_dir
403
+ if ObjectStorageDetails.is_oci_path(artifact_dir)
404
+ else _prepare_artifact_dir(artifact_dir)
405
+ )
406
+ self.local_copy_dir = (
407
+ _prepare_artifact_dir()
408
+ if ObjectStorageDetails.is_oci_path(artifact_dir)
409
+ else self.artifact_dir
410
+ )
411
+ if ObjectStorageDetails.is_oci_path(self.artifact_dir):
412
+ os.environ["OCI_DEPLOYMENT_PATH"] = self.artifact_dir
413
+
414
+ self.model_artifact = None
415
+ self.framework = None
416
+ self.algorithm = None
417
+ self.version = None
418
+ self.hyperparameter = None
419
+ self._introspect = ModelIntrospect(self)
420
+ self.model_deployment = (
421
+ ModelDeployment()
422
+ .with_infrastructure(ModelDeploymentInfrastructure())
423
+ .with_runtime(ModelDeploymentContainerRuntime())
424
+ )
425
+ self.runtime_info = None
426
+ self._as_onnx = kwargs.pop("as_onnx", False)
427
+ self._score_args = {}
428
+
429
+ if properties:
430
+ self.properties = (
431
+ properties
432
+ if isinstance(properties, ModelProperties)
433
+ else ModelProperties.from_dict(properties)
434
+ )
435
+ else:
436
+ self.properties = ModelProperties().with_env()
437
+
438
+ self._serialize = serialize
439
+ self._summary_status = SummaryStatus()
440
+ self._init_serde(
441
+ model_input_serde=model_input_serializer,
442
+ model_save_serializer=model_save_serializer,
443
+ )
444
+ self.ignore_conda_error = False
445
+
446
+ def _init_serde(
447
+ self,
448
+ model_input_serde: Union[SERDE, str] = None,
449
+ model_save_serializer: Union[SERDE, str] = None,
450
+ ):
451
+ """Initializes serde.
452
+
453
+ Parameters
454
+ ----------
455
+ model_save_serializer: (SERDE or str). Defaults to None.
456
+ Instance of ads.model.SERDE. Used for serialize/deserialize model.
457
+ model_input_serializer: (SERDE or str). Defaults to None.
458
+ Instance of ads.model.SERDE. Used for serialize/deserialize model input.
459
+ """
460
+ if model_input_serde is None:
461
+ logger.warning(
462
+ "In the future model input will be serialized by `cloudpickle` by "
463
+ "default. Currently, model input are serialized into a dictionary "
464
+ "containing serialized input data and original data type information."
465
+ 'Set `model_input_serializer="cloudpickle"` to use cloudpickle model input serializer.'
466
+ )
467
+ self.set_model_input_serializer(
468
+ model_input_serializer=model_input_serde
469
+ or self.model_input_serializer_type.JSON
470
+ )
471
+ self.set_model_save_serializer(
472
+ model_save_serializer or self.model_save_serializer_type.CLOUDPICKLE
473
+ )
474
+
475
+ @property
476
+ def metadata_custom(self):
477
+ return self.dsc_model.custom_metadata_list
478
+
479
+ @metadata_custom.setter
480
+ def metadata_custom(self, value: ModelCustomMetadata):
481
+ self.dsc_model.with_custom_metadata_list(value)
482
+
483
+ @property
484
+ def metadata_taxonomy(self):
485
+ return self.dsc_model.defined_metadata_list
486
+
487
+ @metadata_taxonomy.setter
488
+ def metadata_taxonomy(self, value: ModelTaxonomyMetadata):
489
+ self.dsc_model.with_defined_metadata_list(value)
490
+
491
+ @property
492
+ def metadata_provenance(self):
493
+ return self.dsc_model.provenance_metadata
494
+
495
+ @metadata_provenance.setter
496
+ def metadata_provenance(self, value: ModelProvenanceMetadata):
497
+ self.dsc_model.with_provenance_metadata(value)
498
+
499
+ @property
500
+ def schema_input(self):
501
+ return self.dsc_model.input_schema
502
+
503
+ @schema_input.setter
504
+ def schema_input(self, value: Schema):
505
+ self.dsc_model.with_input_schema(value)
506
+
507
+ @property
508
+ def schema_output(self):
509
+ return self.dsc_model.output_schema
510
+
511
+ @schema_output.setter
512
+ def schema_output(self, value: Schema):
513
+ self.dsc_model.with_output_schema(value)
514
+
515
+ @property
516
+ def model_id(self):
517
+ return self.dsc_model.id
518
+
519
+ @property
520
+ def model_deployment_id(self):
521
+ if self.model_deployment:
522
+ return self.model_deployment.model_deployment_id
523
+ return None
524
+
525
+ def __repr__(self) -> str:
526
+ """Representation of the model."""
527
+ return self._to_yaml()
528
+
529
+ def _to_dict(self):
530
+ """Converts the model attributes to dictionary format."""
531
+ attributes = {}
532
+ for key in _ATTRIBUTES_TO_SHOW_:
533
+ if key == "artifact_dir":
534
+ attributes[key] = {getattr(self, key): [self._get_files()]}
535
+ else:
536
+ attributes[key] = getattr(self, key, None)
537
+ return attributes
538
+
539
+ def _to_yaml(self):
540
+ """Converts the model attributes to yaml format."""
541
+ return yaml.safe_dump(self._to_dict())
542
+
543
+ def set_model_input_serializer(
544
+ self,
545
+ model_input_serializer: Union[str, SERDE],
546
+ ):
547
+ """Registers serializer used for serializing data passed in verify/predict.
548
+
549
+ Examples
550
+ --------
551
+ >>> generic_model.set_model_input_serializer(GenericModel.model_input_serializer_type.CLOUDPICKLE)
552
+
553
+ >>> # Register serializer by passing the name of it.
554
+ >>> generic_model.set_model_input_serializer("cloudpickle")
555
+
556
+ >>> # Example of creating customized model input serializer and registering it.
557
+ >>> from ads.model import SERDE
558
+ >>> from ads.model.generic_model import GenericModel
559
+
560
+ >>> class MySERDE(SERDE):
561
+ ... def __init__(self):
562
+ ... super().__init__()
563
+ ... def serialize(self, data):
564
+ ... serialized_data = 1
565
+ ... return serialized_data
566
+ ... def deserialize(self, data):
567
+ ... deserialized_data = 2
568
+ ... return deserialized_data
569
+
570
+ >>> class Toy:
571
+ ... def predict(self, x):
572
+ ... return x ** 2
573
+
574
+ >>> generic_model = GenericModel(
575
+ ... estimator=Toy(),
576
+ ... artifact_dir=tempfile.mkdtemp(),
577
+ ... model_input_serializer=MySERDE()
578
+ ... )
579
+
580
+ >>> # Or register the serializer after creating model instance.
581
+ >>> generic_model.set_model_input_serializer(MySERDE())
582
+
583
+ Parameters
584
+ ----------
585
+ model_input_serializer: (str, or ads.model.SERDE)
586
+ name of the serializer, or instance of SERDE.
587
+ """
588
+ if isinstance(model_input_serializer, str):
589
+ self.model_input_serializer = ModelInputSerializerFactory.get(
590
+ model_input_serializer
591
+ )
592
+ else:
593
+ self.model_input_serializer = model_input_serializer
594
+
595
+ try:
596
+ serializer_name = self.model_input_serializer.name
597
+ if serializer_name not in SUPPORTED_MODEL_INPUT_SERIALIZERS:
598
+ logger.warn(
599
+ "Replace the code of `deserialize()` in `score.py` with "
600
+ "the your own implementation of `deserialize()`."
601
+ )
602
+ except AttributeError:
603
+ self.model_input_serializer.name = "customized"
604
+ logger.warn(
605
+ "Model input will be serialized by `serialize()` "
606
+ "defined in your provided `model_input_serializer`. "
607
+ "Replace the code of `deserialize()` in `score.py` with "
608
+ "the your own implementation of `deserialize()`."
609
+ )
610
+
611
+ def set_model_save_serializer(self, model_save_serializer: Union[str, SERDE]):
612
+ """Registers serializer used for saving model.
613
+
614
+ Examples
615
+ --------
616
+ >>> generic_model.set_model_save_serializer(GenericModel.model_save_serializer_type.CLOUDPICKLE)
617
+
618
+ >>> # Register serializer by passing the name of it.
619
+ >>> generic_model.set_model_save_serializer("cloudpickle")
620
+
621
+ >>> # Example of creating customized model save serializer and registing it.
622
+ >>> from ads.model import SERDE
623
+ >>> from ads.model.generic_model import GenericModel
624
+
625
+ >>> class MySERDE(SERDE):
626
+ ... def __init__(self):
627
+ ... super().__init__()
628
+ ... def serialize(self, data):
629
+ ... serialized_data = 1
630
+ ... return serialized_data
631
+ ... def deserialize(self, data):
632
+ ... deserialized_data = 2
633
+ ... return deserialized_data
634
+
635
+ >>> class Toy:
636
+ ... def predict(self, x):
637
+ ... return x ** 2
638
+
639
+ >>> generic_model = GenericModel(
640
+ ... estimator=Toy(),
641
+ ... artifact_dir=tempfile.mkdtemp(),
642
+ ... model_save_serializer=MySERDE()
643
+ ... )
644
+
645
+ >>> # Or register the serializer after creating model instance.
646
+ >>> generic_model.set_model_save_serializer(MySERDE())
647
+
648
+ Parameters
649
+ ----------
650
+ model_save_serializer: (ads.model.SERDE or str)
651
+ name of the serializer or instance of SERDE.
652
+ """
653
+ if isinstance(model_save_serializer, str):
654
+ self.model_save_serializer = ModelSerializerFactory.get(
655
+ model_save_serializer
656
+ )
657
+ else:
658
+ self.model_save_serializer = model_save_serializer
659
+
660
+ try:
661
+ serializer_name = self.model_save_serializer.name
662
+ if serializer_name not in SUPPORTED_MODEL_SERIALIZERS:
663
+ logger.warn(
664
+ "Replace the code of `load_model()` in `score.py` with "
665
+ "the your own implementation of `deserialize()`."
666
+ )
667
+ except AttributeError:
668
+ self.model_save_serializer.name = "customized"
669
+ logger.warn(
670
+ "Model will be saved by `serialize()` "
671
+ "defined in your provided `model_save_serializer`. "
672
+ "Replace the code of `load_model()` in `score.py` with "
673
+ "the your own implementation of `deserialize()`."
674
+ )
675
+
676
+ def serialize_model(
677
+ self,
678
+ as_onnx: bool = False,
679
+ initial_types: List[Tuple] = None,
680
+ force_overwrite: bool = False,
681
+ X_sample: any = None,
682
+ **kwargs,
683
+ ):
684
+ """
685
+ Serialize and save model using ONNX or model specific method.
686
+
687
+ Parameters
688
+ ----------
689
+ as_onnx: (boolean, optional)
690
+ If set as True, convert into ONNX model.
691
+ initial_types: (List[Tuple], optional)
692
+ a python list. Each element is a tuple of a variable name and a data type.
693
+ force_overwrite: (boolean, optional)
694
+ If set as True, overwrite serialized model if exists.
695
+ X_sample: (any, optional). Defaults to None.
696
+ Contains model inputs such that model(X_sample) is a valid
697
+ invocation of the model, used to valid model input type.
698
+
699
+ Returns
700
+ -------
701
+ None
702
+ Nothing
703
+ """
704
+ if self._serialize:
705
+ if not self.model_file_name:
706
+ self.model_file_name = self._handle_model_file_name(as_onnx=as_onnx)
707
+ if not self.estimator:
708
+ raise ValueError(
709
+ "Parameter `estimator` has to be provided when `serialize=True`, or you can set `serialize=False`."
710
+ )
711
+ self._serialize_model_helper(
712
+ initial_types, force_overwrite, X_sample, **kwargs
713
+ )
714
+ else:
715
+ raise SerializeModelNotImplementedError(
716
+ "`serialize_model` is not implemented."
717
+ )
718
+
719
+ def _serialize_model_helper(
720
+ self,
721
+ initial_types: List[Tuple] = None,
722
+ force_overwrite: bool = False,
723
+ X_sample: any = None,
724
+ **kwargs,
725
+ ):
726
+ model_path = self._check_model_file(
727
+ self.model_file_name, force_overwrite=force_overwrite
728
+ )
729
+ self.get_model_serializer().serialize(
730
+ estimator=self.estimator,
731
+ model_path=model_path,
732
+ X_sample=X_sample,
733
+ initial_types=initial_types,
734
+ **kwargs,
735
+ )
736
+
737
+ def _check_model_file(self, model_file_name, force_overwrite):
738
+ model_path = os.path.join(self.artifact_dir, model_file_name)
739
+ if utils.is_path_exists(uri=model_path, auth=self.auth) and not force_overwrite:
740
+ raise ValueError(
741
+ f"The {model_path} already exists, set force_overwrite to True if you wish to overwrite."
742
+ )
743
+ if not ObjectStorageDetails.is_oci_path(self.artifact_dir):
744
+ os.makedirs(self.artifact_dir, exist_ok=True)
745
+ return model_path
746
+
747
+ def _handle_model_file_name(self, as_onnx: bool, model_file_name: str = None):
748
+ if as_onnx:
749
+ self._set_model_save_serializer_to_onnx()
750
+
751
+ if not model_file_name:
752
+ if not self._serialize:
753
+ raise NotImplementedError("`model_file_name` has to be provided.")
754
+ else:
755
+ model_file_name = f"model.{self._get_model_file_suffix()}"
756
+
757
+ if as_onnx:
758
+ assert model_file_name.endswith(
759
+ ".onnx"
760
+ ), "Wrong file extension. Expecting `.onnx` suffix."
761
+
762
+ return model_file_name
763
+
764
+ def _get_model_file_suffix(self):
765
+ try:
766
+ suffix = self.model_save_serializer.model_file_suffix
767
+ return suffix
768
+ except AttributeError as e:
769
+ logger.error(
770
+ "Please specify `model_file_suffix` in `model_save_serializer`. "
771
+ )
772
+ raise e
773
+
774
+ def _set_model_save_serializer_to_onnx(self):
775
+ try:
776
+ self.set_model_save_serializer(self.model_save_serializer_type.ONNX)
777
+ except AttributeError as e:
778
+ logger.error(
779
+ f"This framework {self._PREFIX} to Onnx Conversion is not supported. Please set `as_onnx=False` (default) to perform other model serialization."
780
+ )
781
+ raise e
782
+
783
+ def _onnx_data_transformer(
784
+ self,
785
+ X: Union[pd.DataFrame, pd.Series],
786
+ impute_values: Dict = None,
787
+ force_overwrite: bool = False,
788
+ ):
789
+ """Apply onnx data transformer to data."""
790
+ if self.framework in FRAMEWORKS_WITHOUT_ONNX_DATA_TRANSFORM or X is None:
791
+ return X
792
+ try:
793
+ if hasattr(self, "onnx_data_preprocessor") and isinstance(
794
+ self.onnx_data_preprocessor, ONNXTransformer
795
+ ):
796
+ X = self.onnx_data_preprocessor.transform(X=X)
797
+
798
+ self.onnx_data_preprocessor = ONNXTransformer()
799
+ X = self.onnx_data_preprocessor.fit_transform(
800
+ X=X, impute_values=impute_values
801
+ )
802
+ if (
803
+ os.path.exists(os.path.join(self.artifact_dir, ONNX_DATA_TRANSFORMER))
804
+ and not force_overwrite
805
+ ):
806
+ raise ValueError(
807
+ f"{ONNX_DATA_TRANSFORMER} already exists. "
808
+ "Set `force_overwrite` to True if you wish to overwrite."
809
+ )
810
+ else:
811
+ try:
812
+ self.onnx_data_preprocessor.save(
813
+ os.path.join(self.artifact_dir, ONNX_DATA_TRANSFORMER)
814
+ )
815
+ except Exception as e:
816
+ logger.error(
817
+ f"Unable to serialize the data transformer due to: {e}."
818
+ )
819
+ raise e
820
+ except Exception as e:
821
+ logger.warn(f"Onnx Data Transformation was unsuccessful with error: {e}")
822
+ raise e
823
+ return X
824
+
825
+ def prepare(
826
+ self,
827
+ inference_conda_env: str = None,
828
+ inference_python_version: str = None,
829
+ training_conda_env: str = None,
830
+ training_python_version: str = None,
831
+ model_file_name: str = None,
832
+ as_onnx: bool = False,
833
+ initial_types: List[Tuple] = None,
834
+ force_overwrite: bool = False,
835
+ namespace: str = CONDA_BUCKET_NS,
836
+ use_case_type: str = None,
837
+ X_sample: Union[list, tuple, pd.DataFrame, pd.Series, np.ndarray] = None,
838
+ y_sample: Union[list, tuple, pd.DataFrame, pd.Series, np.ndarray] = None,
839
+ training_script_path: str = None,
840
+ training_id: str = _TRAINING_RESOURCE_ID,
841
+ ignore_pending_changes: bool = True,
842
+ max_col_num: int = DATA_SCHEMA_MAX_COL_NUM,
843
+ ignore_conda_error: bool = False,
844
+ score_py_uri: str = None,
845
+ **kwargs: Dict,
846
+ ) -> "GenericModel":
847
+ """Prepare and save the score.py, serialized model and runtime.yaml file.
848
+
849
+ Parameters
850
+ ----------
851
+ inference_conda_env: (str, optional). Defaults to None.
852
+ Can be either slug or object storage path of the conda pack.
853
+ You can only pass in slugs if the conda pack is a service pack.
854
+ inference_python_version: (str, optional). Defaults to None.
855
+ Python version which will be used in deployment.
856
+ training_conda_env: (str, optional). Defaults to None.
857
+ Can be either slug or object storage path of the conda pack.
858
+ You can only pass in slugs if the conda pack is a service pack.
859
+ If `training_conda_env` is not provided, `training_conda_env` will
860
+ use the same value of `training_conda_env`.
861
+ training_python_version: (str, optional). Defaults to None.
862
+ Python version used during training.
863
+ model_file_name: (str, optional). Defaults to `None`.
864
+ Name of the serialized model.
865
+ Will be auto generated if not provided.
866
+ as_onnx: (bool, optional). Defaults to False.
867
+ Whether to serialize as onnx model.
868
+ initial_types: (list[Tuple], optional).
869
+ Defaults to None. Only used for SklearnModel, LightGBMModel and XGBoostModel.
870
+ Each element is a tuple of a variable name and a type.
871
+ Check this link http://onnx.ai/sklearn-onnx/api_summary.html#id2 for
872
+ more explanation and examples for `initial_types`.
873
+ force_overwrite: (bool, optional). Defaults to False.
874
+ Whether to overwrite existing files.
875
+ namespace: (str, optional).
876
+ Namespace of region. This is used for identifying which region the service pack
877
+ is from when you pass a slug to inference_conda_env and training_conda_env.
878
+ use_case_type: str
879
+ The use case type of the model. Use it through UserCaseType class or string provided in `UseCaseType`. For
880
+ example, use_case_type=UseCaseType.BINARY_CLASSIFICATION or use_case_type="binary_classification". Check
881
+ with UseCaseType class to see all supported types.
882
+ X_sample: Union[list, tuple, pd.Series, np.ndarray, pd.DataFrame]. Defaults to None.
883
+ A sample of input data that will be used to generate input schema.
884
+ y_sample: Union[list, tuple, pd.Series, np.ndarray, pd.DataFrame]. Defaults to None.
885
+ A sample of output data that will be used to generate output schema.
886
+ training_script_path: str. Defaults to None.
887
+ Training script path.
888
+ training_id: (str, optional). Defaults to value from environment variables.
889
+ The training OCID for model. Can be notebook session or job OCID.
890
+ ignore_pending_changes: bool. Defaults to False.
891
+ whether to ignore the pending changes in the git.
892
+ max_col_num: (int, optional). Defaults to utils.DATA_SCHEMA_MAX_COL_NUM.
893
+ Do not generate the input schema if the input has more than this
894
+ number of features(columns).
895
+ ignore_conda_error: (bool, optional). Defaults to False.
896
+ Parameter to ignore error when collecting conda information.
897
+ score_py_uri: (str, optional). Defaults to None.
898
+ The uri of the customized score.py, which can be local path or OCI object storage URI.
899
+ When provide with this attibute, the `score.py` will not be auto generated, and the
900
+ provided `score.py` will be added into artifact_dir.
901
+ kwargs:
902
+ impute_values: (dict, optional).
903
+ The dictionary where the key is the column index(or names is accepted
904
+ for pandas dataframe) and the value is the impute value for the corresponding column.
905
+
906
+ Raises
907
+ ------
908
+ FileExistsError
909
+ If files already exist but `force_overwrite` is False.
910
+ ValueError
911
+ If `inference_python_version` is not provided, but also cannot be found
912
+ through manifest file.
913
+
914
+ Returns
915
+ -------
916
+ GenericModel
917
+ An instance of `GenericModel` class.
918
+ """
919
+ # Populate properties from args and kwargs.
920
+ # empty values will be ignored.
921
+
922
+ locals_dict = _extract_locals(locals())
923
+ locals_dict.pop("training_id", None)
924
+ self.properties.with_dict(locals_dict)
925
+
926
+ if training_id != _TRAINING_RESOURCE_ID:
927
+ self.properties.training_id = training_id
928
+ elif not self.properties.training_id:
929
+ self.properties.training_id = _TRAINING_RESOURCE_ID
930
+
931
+ self.ignore_conda_error = ignore_conda_error
932
+ if self.ignore_conda_error:
933
+ logger.info(
934
+ "`ignore_conda_error` is set to True and `.verify()` is targeted to test the generated score.py on the local conda environment, not the container."
935
+ )
936
+ if not self.properties.inference_conda_env:
937
+ try:
938
+ conda_prefix = os.environ.get("CONDA_PREFIX", None)
939
+ manifest = fetch_manifest_from_conda_location(conda_prefix)
940
+ if "pack_path" in manifest:
941
+ self.properties.inference_conda_env = manifest["pack_path"]
942
+ elif not self.ignore_conda_error:
943
+ raise ValueError(
944
+ "`inference_conda_env` must be specified for conda runtime. If you are using container runtime, set `ignore_conda_error=True`."
945
+ )
946
+ self.properties.inference_python_version = (
947
+ manifest["python"]
948
+ if "python" in manifest
949
+ and not self.properties.inference_python_version
950
+ else self.properties.inference_python_version
951
+ )
952
+ except:
953
+ if not self.ignore_conda_error:
954
+ raise ValueError(
955
+ "`inference_conda_env` must be specified for conda runtime. If you are using container runtime, set `ignore_conda_error=True`."
956
+ )
957
+
958
+ self._as_onnx = as_onnx
959
+ if as_onnx:
960
+ self._set_model_save_serializer_to_onnx()
961
+
962
+ self.model_file_name = self._handle_model_file_name(
963
+ as_onnx=as_onnx, model_file_name=model_file_name
964
+ )
965
+ if (
966
+ not isinstance(self.model_file_name, str)
967
+ or self.model_file_name.strip() == ""
968
+ ):
969
+ raise ValueError("The `model_file_name` needs to be provided.")
970
+
971
+ if not ObjectStorageDetails.is_oci_path(self.artifact_dir):
972
+ os.makedirs(self.artifact_dir, exist_ok=True)
973
+
974
+ # Bring in .model-ignore file
975
+ uri_src = os.path.join(
976
+ os.path.dirname(os.path.realpath(__file__)),
977
+ "common/.model-ignore",
978
+ )
979
+ uri_dst = os.path.join(self.artifact_dir, ".model-ignore")
980
+ utils.copy_file(uri_src=uri_src, uri_dst=uri_dst, force_overwrite=True)
981
+
982
+ self.model_artifact = ModelArtifact(
983
+ artifact_dir=self.artifact_dir,
984
+ model_file_name=self.model_file_name,
985
+ auth=self.auth,
986
+ local_copy_dir=self.local_copy_dir,
987
+ )
988
+ try:
989
+ self.runtime_info = self.model_artifact.prepare_runtime_yaml(
990
+ inference_conda_env=self.properties.inference_conda_env,
991
+ inference_python_version=self.properties.inference_python_version,
992
+ training_conda_env=self.properties.training_conda_env,
993
+ training_python_version=self.properties.training_python_version,
994
+ force_overwrite=force_overwrite,
995
+ namespace=namespace,
996
+ bucketname=DEFAULT_CONDA_BUCKET_NAME,
997
+ auth=self.auth,
998
+ ignore_conda_error=self.ignore_conda_error,
999
+ )
1000
+ except ValueError as e:
1001
+ raise e
1002
+
1003
+ self.update_summary_status(
1004
+ detail=PREPARE_STATUS_GEN_RUNTIME_DETAIL, status=ModelState.DONE.value
1005
+ )
1006
+
1007
+ if self.estimator:
1008
+ if as_onnx:
1009
+ X_sample = self._onnx_data_transformer(
1010
+ X_sample,
1011
+ impute_values=kwargs.pop("impute_values", {}),
1012
+ force_overwrite=force_overwrite,
1013
+ )
1014
+ try:
1015
+ self.serialize_model(
1016
+ as_onnx=as_onnx,
1017
+ force_overwrite=force_overwrite,
1018
+ initial_types=initial_types,
1019
+ X_sample=X_sample,
1020
+ **kwargs,
1021
+ )
1022
+ self.update_summary_status(
1023
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
1024
+ status=ModelState.DONE.value,
1025
+ )
1026
+ except SerializeModelNotImplementedError:
1027
+ if not utils.is_path_exists(
1028
+ uri=os.path.join(self.artifact_dir, self.model_file_name),
1029
+ auth=self.auth,
1030
+ ):
1031
+ self.update_summary_action(
1032
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
1033
+ action=(
1034
+ "Model is not automatically serialized. "
1035
+ f"Serialize the model as `{self.model_file_name}` and "
1036
+ f"save to the {self.artifact_dir}."
1037
+ ),
1038
+ )
1039
+ self.update_summary_status(
1040
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
1041
+ status=ModelState.NEEDSACTION.value,
1042
+ )
1043
+ logger.warning(
1044
+ f"{self.model_file_name} not found in {self.artifact_dir}. "
1045
+ f"Save the serialized model under {self.artifact_dir}."
1046
+ )
1047
+ self.update_summary_action(
1048
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL,
1049
+ action=(
1050
+ "`load_model` is not automatically generated. "
1051
+ "Finish implementing it and call .verify to check if it works."
1052
+ ),
1053
+ )
1054
+ except Exception as e:
1055
+ raise e
1056
+
1057
+ if self.framework == Framework.EMBEDDING_ONNX:
1058
+ self.model_artifact.prepare_schema(schema_name="openapi.json")
1059
+
1060
+ if as_onnx:
1061
+ jinja_template_filename = "score_onnx_new"
1062
+ elif self.framework and self.framework != "other":
1063
+ jinja_template_filename = "score_" + self.framework
1064
+ if self.framework == "transformers":
1065
+ jinja_template_filename = "score_" + "huggingface_pipeline"
1066
+ else:
1067
+ jinja_template_filename = (
1068
+ "score-pkl" if self._serialize else "score_generic"
1069
+ )
1070
+
1071
+ if score_py_uri:
1072
+ utils.copy_file(
1073
+ uri_src=score_py_uri,
1074
+ uri_dst=os.path.join(self.artifact_dir, "score.py"),
1075
+ force_overwrite=force_overwrite,
1076
+ auth=self.auth,
1077
+ )
1078
+ else:
1079
+ self.model_artifact.prepare_score_py(
1080
+ jinja_template_filename=jinja_template_filename,
1081
+ model_file_name=self.model_file_name,
1082
+ data_deserializer=self.model_input_serializer.name,
1083
+ model_serializer=self.model_save_serializer.name,
1084
+ auth=self.auth,
1085
+ **{**kwargs, **self._score_args},
1086
+ )
1087
+
1088
+ self.update_summary_status(
1089
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL, status=ModelState.DONE.value
1090
+ )
1091
+
1092
+ self.populate_metadata(
1093
+ use_case_type=use_case_type,
1094
+ X_sample=X_sample,
1095
+ y_sample=y_sample,
1096
+ training_script_path=self.properties.training_script_path,
1097
+ training_id=self.properties.training_id,
1098
+ ignore_pending_changes=ignore_pending_changes,
1099
+ max_col_num=max_col_num,
1100
+ ignore_conda_error=self.ignore_conda_error,
1101
+ auth=self.auth,
1102
+ )
1103
+
1104
+ self.update_summary_status(
1105
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1106
+ status=ModelState.DONE.value,
1107
+ )
1108
+
1109
+ self.update_summary_status(
1110
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1111
+ status=ModelState.AVAILABLE.value,
1112
+ )
1113
+
1114
+ if not self.ignore_conda_error:
1115
+ self.update_summary_status(
1116
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
1117
+ status=ModelState.AVAILABLE.value,
1118
+ )
1119
+
1120
+ self.update_summary_status(
1121
+ detail=SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL,
1122
+ status=ModelState.AVAILABLE.value,
1123
+ )
1124
+ return self
1125
+
1126
+ def _handle_input_data(
1127
+ self, data: Any = None, auto_serialize_data: bool = True, **kwargs
1128
+ ):
1129
+ """Handle input data and serialize it as required.
1130
+
1131
+ Parameters
1132
+ ----------
1133
+ data: Any
1134
+ Data for the prediction.
1135
+ auto_serialize_data: bool
1136
+ Defaults to True. Indicate whether to serialize the input data.
1137
+
1138
+ kwargs:
1139
+ storage_options: dict
1140
+ Passed to ADSImage.open.
1141
+
1142
+ Raises
1143
+ ------
1144
+ TypeError:
1145
+ `data` is not json serializable or bytes. Set `auto_serialize_data` to `True` to serialize the input data.
1146
+ ValueError:
1147
+ Either use `image` argument through kwargs to pass in image file or use `data` argument to pass the data.
1148
+
1149
+ Returns
1150
+ -------
1151
+ object: Data used for a request.
1152
+ """
1153
+ if isinstance(data, bytes):
1154
+ return data
1155
+ if not auto_serialize_data:
1156
+ if not _is_json_serializable(data) and not isinstance(data, bytes):
1157
+ raise TypeError(
1158
+ "`data` is not json serializable or bytes. Set `auto_serialize_data` to `True` to serialize the input data."
1159
+ )
1160
+ return data
1161
+
1162
+ if data is None and "image" not in kwargs.keys():
1163
+ raise ValueError(
1164
+ "Either use `image` argument through kwargs to pass in image file or use `data` argument to pass the data."
1165
+ )
1166
+
1167
+ if "image" in kwargs.keys():
1168
+ data = self._handle_image_input(image=kwargs.pop("image"), **kwargs)
1169
+
1170
+ serialized_data = self.model_input_serializer.serialize(data=data, **kwargs)
1171
+ return serialized_data
1172
+
1173
+ def _handle_image_input(self, image, **kwargs):
1174
+ """Validates the image input and converts it to tensor.
1175
+
1176
+ Parameters
1177
+ ----------
1178
+ image: PIL.Image Object or uri.
1179
+ image file path or opened image file.
1180
+
1181
+ kwargs:
1182
+ storage_options: dict
1183
+ Passed to ADSImage.open.
1184
+
1185
+ Raises
1186
+ ------
1187
+ ValueError: Cannot open or identify the given image file.
1188
+
1189
+ Returns
1190
+ -------
1191
+ tensor: tf.tensor or torch.tensor.
1192
+ """
1193
+ if not isinstance(image, Image.Image):
1194
+ try:
1195
+ image = ADSImage.open(
1196
+ path=image, storage_options=kwargs.pop("storage_options", {})
1197
+ ).img
1198
+ except Exception as e:
1199
+ raise ValueError(
1200
+ f"Cannot open or identify the given image file. See details: {e}"
1201
+ )
1202
+ tensor = self._to_tensor(image)
1203
+ return tensor
1204
+
1205
+ def _to_tensor(self, data):
1206
+ """Only PyTorchModel and TensorflowModel will implement this method.
1207
+
1208
+ Args:
1209
+ data (Any): Data needs to be converted to tensor.
1210
+
1211
+ Raises:
1212
+ NotImplementedError: Only PyTorchModel and TensorflowModel will implement this method.
1213
+ """
1214
+ raise NotImplementedError(
1215
+ "Only PyTorchModel and TensorflowModel will implement this method."
1216
+ )
1217
+
1218
+ def get_data_serializer(self):
1219
+ """Gets data serializer.
1220
+
1221
+ Returns
1222
+ -------
1223
+ object: ads.model.Serializer object.
1224
+ """
1225
+ return self.model_input_serializer
1226
+
1227
+ def get_model_serializer(self):
1228
+ """Gets model serializer."""
1229
+ return self.model_save_serializer
1230
+
1231
+ def verify(
1232
+ self,
1233
+ data: Any = None,
1234
+ reload_artifacts: bool = True,
1235
+ auto_serialize_data: bool = False,
1236
+ **kwargs,
1237
+ ) -> Dict[str, Any]:
1238
+ """Test if deployment works in local environment.
1239
+
1240
+ Examples
1241
+ --------
1242
+ >>> uri = "https://github.com/pytorch/hub/raw/master/images/dog.jpg"
1243
+ >>> prediction = model.verify(image=uri)['prediction']
1244
+
1245
+ >>> # examples on storage options
1246
+ >>> prediction = model.verify(
1247
+ ... image="oci://<bucket>@<tenancy>/myimage.png",
1248
+ ... storage_options=ads.auth.default_signer()
1249
+ ... )['prediction']
1250
+
1251
+ Parameters
1252
+ ----------
1253
+ data: Any
1254
+ Data used to test if deployment works in local environment.
1255
+ reload_artifacts: bool. Defaults to True.
1256
+ Whether to reload artifacts or not.
1257
+ is_json_payload: bool
1258
+ Defaults to False. Indicate whether to send data with a `application/json` MIME TYPE.
1259
+ auto_serialize_data: bool.
1260
+ Whether to auto serialize input data. Defauls to `False` for GenericModel, and `True` for other frameworks.
1261
+ `data` required to be json serializable if `auto_serialize_data=False`.
1262
+ if `auto_serialize_data` set to True, data will be serialized before sending to model deployment endpoint.
1263
+ kwargs:
1264
+ content_type: str, used to indicate the media type of the resource.
1265
+ image: PIL.Image Object or uri for the image.
1266
+ A valid string path for image file can be local path, http(s), oci, s3, gs.
1267
+ storage_options: dict
1268
+ Passed to `fsspec.open` for a particular storage connection.
1269
+ Please see `fsspec` (https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.open) for more details.
1270
+
1271
+ Returns
1272
+ -------
1273
+ Dict
1274
+ A dictionary which contains prediction results.
1275
+ """
1276
+ if self.model_artifact is None:
1277
+ raise ArtifactsNotAvailableError
1278
+
1279
+ endpoint = "http://127.0.0.1:8000/predict"
1280
+ data = self._handle_input_data(data, auto_serialize_data, **kwargs)
1281
+
1282
+ request_body = send_request(
1283
+ data,
1284
+ endpoint,
1285
+ dry_run=True,
1286
+ is_json_payload=_is_json_serializable(data),
1287
+ **kwargs,
1288
+ )
1289
+
1290
+ if reload_artifacts:
1291
+ self.model_artifact.reload()
1292
+
1293
+ prediction = self.model_artifact.predict(request_body)
1294
+
1295
+ try:
1296
+ requests.Request("POST", endpoint, json=prediction)
1297
+ except:
1298
+ raise TypeError(
1299
+ "The prediction result is not json serializable. "
1300
+ "Please modify the score.py."
1301
+ )
1302
+
1303
+ self.update_summary_status(
1304
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL, status=ModelState.DONE.value
1305
+ )
1306
+ return prediction
1307
+
1308
+ def introspect(self) -> pd.DataFrame:
1309
+ """Conducts instrospection.
1310
+
1311
+ Returns
1312
+ -------
1313
+ pandas.DataFrame
1314
+ A pandas DataFrame which contains the instrospection results.
1315
+ """
1316
+ df = self._introspect()
1317
+ return df
1318
+
1319
+ @classmethod
1320
+ def from_model_artifact(
1321
+ cls: Type[Self],
1322
+ uri: str,
1323
+ model_file_name: str = None,
1324
+ artifact_dir: Optional[str] = None,
1325
+ auth: Optional[Dict] = None,
1326
+ force_overwrite: Optional[bool] = False,
1327
+ properties: Optional[ModelProperties] = None,
1328
+ ignore_conda_error: Optional[bool] = False,
1329
+ **kwargs: dict,
1330
+ ) -> Self:
1331
+ """Loads model from a folder, or zip/tar archive.
1332
+
1333
+ Parameters
1334
+ ----------
1335
+ uri: str
1336
+ The folder path, ZIP file path, or TAR file path. It could contain a
1337
+ seriliazed model(required) as well as any files needed for deployment including:
1338
+ serialized model, runtime.yaml, score.py and etc. The content of the folder will be
1339
+ copied to the `artifact_dir` folder.
1340
+ model_file_name: (str, optional). Defaults to `None`.
1341
+ The serialized model file name.
1342
+ Will be extracted from artifacts if not provided.
1343
+ artifact_dir: (str, optional). Defaults to `None`.
1344
+ The artifact directory to store the files needed for deployment.
1345
+ Will be created if not exists.
1346
+ auth: (Dict, optional). Defaults to None.
1347
+ The default authetication is set using `ads.set_auth` API. If you need to override the
1348
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
1349
+ authentication signer and kwargs required to instantiate IdentityClient object.
1350
+ force_overwrite: (bool, optional). Defaults to False.
1351
+ Whether to overwrite existing files or not.
1352
+ properties: (ModelProperties, optional). Defaults to None.
1353
+ ModelProperties object required to save and deploy model.
1354
+ ignore_conda_error: (bool, optional). Defaults to False.
1355
+ Parameter to ignore error when collecting conda information.
1356
+
1357
+ Returns
1358
+ -------
1359
+ Self
1360
+ An instance of `GenericModel` class.
1361
+
1362
+ Raises
1363
+ ------
1364
+ ValueError
1365
+ If `model_file_name` not provided.
1366
+ """
1367
+ if (
1368
+ cls._PREFIX != "spark"
1369
+ and artifact_dir
1370
+ and ObjectStorageDetails.is_oci_path(artifact_dir)
1371
+ ):
1372
+ raise ValueError(
1373
+ f"Unsupported value of `artifact_dir`: {artifact_dir}. "
1374
+ "Only SparkPipelineModel framework supports object storage path as artifact_dir."
1375
+ )
1376
+
1377
+ local_vars = _extract_locals(locals())
1378
+ properties = properties or ModelProperties()
1379
+ properties.with_dict(local_vars)
1380
+ auth = auth or authutil.default_signer()
1381
+ artifact_dir = _prepare_artifact_dir(artifact_dir)
1382
+ reload = kwargs.pop("reload", False)
1383
+ model_artifact = ModelArtifact.from_uri(
1384
+ uri=uri,
1385
+ artifact_dir=artifact_dir,
1386
+ auth=auth,
1387
+ force_overwrite=force_overwrite,
1388
+ ignore_conda_error=ignore_conda_error,
1389
+ model_file_name=model_file_name,
1390
+ reload=reload,
1391
+ )
1392
+ model = cls(
1393
+ estimator=model_artifact.model,
1394
+ artifact_dir=artifact_dir,
1395
+ auth=auth,
1396
+ properties=properties,
1397
+ **kwargs,
1398
+ )
1399
+ model.model_file_name = model_file_name or model_artifact.model_file_name
1400
+ model.local_copy_dir = model_artifact.local_copy_dir
1401
+ model.model_artifact = model_artifact
1402
+ model.ignore_conda_error = ignore_conda_error
1403
+
1404
+ if reload:
1405
+ model.reload_runtime_info()
1406
+ model.update_summary_action(
1407
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1408
+ action="Call .populate_metadata() to populate metadata.",
1409
+ )
1410
+
1411
+ model.update_summary_status(
1412
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL,
1413
+ status=ModelState.NOTAPPLICABLE.value,
1414
+ )
1415
+ model.update_summary_status(
1416
+ detail=PREPARE_STATUS_GEN_RUNTIME_DETAIL,
1417
+ status=ModelState.NOTAPPLICABLE.value,
1418
+ )
1419
+ model.update_summary_status(
1420
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
1421
+ status=ModelState.NOTAPPLICABLE.value,
1422
+ )
1423
+ model.update_summary_status(
1424
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1425
+ status=ModelState.AVAILABLE.value
1426
+ if reload
1427
+ else ModelState.NOTAPPLICABLE.value,
1428
+ )
1429
+
1430
+ return model
1431
+
1432
+ def download_artifact(
1433
+ self,
1434
+ artifact_dir: Optional[str] = None,
1435
+ auth: Optional[Dict] = None,
1436
+ force_overwrite: Optional[bool] = False,
1437
+ bucket_uri: Optional[str] = None,
1438
+ remove_existing_artifact: Optional[bool] = True,
1439
+ **kwargs,
1440
+ ) -> "GenericModel":
1441
+ """Downloads model artifacts from the model catalog.
1442
+
1443
+ Parameters
1444
+ ----------
1445
+ artifact_dir: (str, optional). Defaults to `None`.
1446
+ The artifact directory to store the files needed for deployment.
1447
+ Will be created if not exists.
1448
+ auth: (Dict, optional). Defaults to None.
1449
+ The default authentication is set using `ads.set_auth` API. If you need to override the
1450
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
1451
+ authentication signer and kwargs required to instantiate IdentityClient object.
1452
+ force_overwrite: (bool, optional). Defaults to False.
1453
+ Whether to overwrite existing files or not.
1454
+ bucket_uri: (str, optional). Defaults to None.
1455
+ The OCI Object Storage URI where model artifacts will be copied to.
1456
+ The `bucket_uri` is only necessary for downloading large artifacts with
1457
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
1458
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
1459
+ Whether artifacts uploaded to object storage bucket need to be removed or not.
1460
+
1461
+ Returns
1462
+ -------
1463
+ Self
1464
+ An instance of `GenericModel` class.
1465
+
1466
+ Raises
1467
+ ------
1468
+ ValueError
1469
+ If `model_id` is not available in the GenericModel object.
1470
+ """
1471
+ model_id = self.model_id
1472
+ if not model_id:
1473
+ raise ValueError(
1474
+ "`model_id` is not available, load the GenericModel object first."
1475
+ )
1476
+
1477
+ if not artifact_dir:
1478
+ artifact_dir = self.artifact_dir
1479
+ artifact_dir = _prepare_artifact_dir(artifact_dir)
1480
+
1481
+ target_dir = (
1482
+ _prepare_artifact_dir()
1483
+ if ObjectStorageDetails.is_oci_path(artifact_dir)
1484
+ else artifact_dir
1485
+ )
1486
+
1487
+ dsc_model = DataScienceModel.from_id(model_id)
1488
+ dsc_model.download_artifact(
1489
+ target_dir=target_dir,
1490
+ force_overwrite=force_overwrite,
1491
+ bucket_uri=bucket_uri,
1492
+ remove_existing_artifact=remove_existing_artifact,
1493
+ auth=auth,
1494
+ region=kwargs.pop("region", None),
1495
+ timeout=kwargs.pop("timeout", None),
1496
+ )
1497
+ model_artifact = ModelArtifact.from_uri(
1498
+ uri=target_dir,
1499
+ artifact_dir=artifact_dir,
1500
+ model_file_name=self.model_file_name,
1501
+ force_overwrite=force_overwrite,
1502
+ auth=auth,
1503
+ ignore_conda_error=self.ignore_conda_error,
1504
+ )
1505
+ self.dsc_model = dsc_model
1506
+ self.local_copy_dir = model_artifact.local_copy_dir
1507
+ self.model_artifact = model_artifact
1508
+ self.reload_runtime_info()
1509
+
1510
+ self.update_summary_status(
1511
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL,
1512
+ status=ModelState.DONE.value,
1513
+ )
1514
+ self.update_summary_status(
1515
+ detail=PREPARE_STATUS_GEN_RUNTIME_DETAIL,
1516
+ status=ModelState.DONE.value,
1517
+ )
1518
+ self.update_summary_status(
1519
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL, status=ModelState.DONE.value
1520
+ )
1521
+ self.update_summary_status(
1522
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1523
+ status=ModelState.DONE.value,
1524
+ )
1525
+ self.update_summary_status(
1526
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1527
+ status=ModelState.AVAILABLE.value,
1528
+ )
1529
+ self.update_summary_action(
1530
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1531
+ action="",
1532
+ )
1533
+ self.update_summary_status(
1534
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
1535
+ status=ModelState.AVAILABLE.value,
1536
+ )
1537
+ self.update_summary_status(
1538
+ detail=SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL,
1539
+ status=ModelState.AVAILABLE.value,
1540
+ )
1541
+ return self
1542
+
1543
+ @classmethod
1544
+ def from_model_catalog(
1545
+ cls: Type[Self],
1546
+ model_id: str,
1547
+ model_file_name: str = None,
1548
+ artifact_dir: Optional[str] = None,
1549
+ auth: Optional[Dict] = None,
1550
+ force_overwrite: Optional[bool] = False,
1551
+ properties: Optional[Union[ModelProperties, Dict]] = None,
1552
+ bucket_uri: Optional[str] = None,
1553
+ remove_existing_artifact: Optional[bool] = True,
1554
+ ignore_conda_error: Optional[bool] = False,
1555
+ download_artifact: Optional[bool] = True,
1556
+ **kwargs,
1557
+ ) -> Self:
1558
+ """Loads model from model catalog.
1559
+
1560
+ Parameters
1561
+ ----------
1562
+ model_id: str
1563
+ The model OCID.
1564
+ model_file_name: (str, optional). Defaults to `None`.
1565
+ The name of the serialized model.
1566
+ artifact_dir: (str, optional). Defaults to `None`.
1567
+ The artifact directory to store the files needed for deployment.
1568
+ Will be created if not exists.
1569
+ auth: (Dict, optional). Defaults to None.
1570
+ The default authetication is set using `ads.set_auth` API. If you need to override the
1571
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
1572
+ authentication signer and kwargs required to instantiate IdentityClient object.
1573
+ force_overwrite: (bool, optional). Defaults to False.
1574
+ Whether to overwrite existing files or not.
1575
+ properties: (ModelProperties, optional). Defaults to None.
1576
+ ModelProperties object required to save and deploy model.
1577
+ bucket_uri: (str, optional). Defaults to None.
1578
+ The OCI Object Storage URI where model artifacts will be copied to.
1579
+ The `bucket_uri` is only necessary for downloading large artifacts with
1580
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
1581
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
1582
+ Wether artifacts uploaded to object storage bucket need to be removed or not.
1583
+ ignore_conda_error: (bool, optional). Defaults to False.
1584
+ Parameter to ignore error when collecting conda information.
1585
+ download_artifact: (bool, optional). Defaults to True.
1586
+ Whether to download the model pickle or checkpoints
1587
+ kwargs:
1588
+ compartment_id : (str, optional)
1589
+ Compartment OCID. If not specified, the value will be taken from the environment variables.
1590
+ timeout : (int, optional). Defaults to 10 seconds.
1591
+ The connection timeout in seconds for the client.
1592
+ region: (str, optional). Defaults to `None`.
1593
+ The destination Object Storage bucket region.
1594
+ By default the value will be extracted from the `OCI_REGION_METADATA` environment variables.
1595
+
1596
+ Returns
1597
+ -------
1598
+ Self
1599
+ An instance of GenericModel class.
1600
+ """
1601
+ if (
1602
+ cls._PREFIX != "spark"
1603
+ and artifact_dir
1604
+ and ObjectStorageDetails.is_oci_path(artifact_dir)
1605
+ ):
1606
+ raise ValueError(
1607
+ f"Unsupported value of `artifact_dir`: {artifact_dir}. "
1608
+ "Only SparkPipelineModel framework supports object storage path as artifact_dir."
1609
+ )
1610
+
1611
+ local_vars = _extract_locals(locals())
1612
+ properties = properties or ModelProperties()
1613
+ properties.with_dict(local_vars)
1614
+ properties.compartment_id = properties.compartment_id or _COMPARTMENT_OCID
1615
+ auth = auth or authutil.default_signer()
1616
+ artifact_dir = _prepare_artifact_dir(artifact_dir)
1617
+
1618
+ target_dir = (
1619
+ _prepare_artifact_dir()
1620
+ if ObjectStorageDetails.is_oci_path(artifact_dir)
1621
+ else artifact_dir
1622
+ )
1623
+ bucket_uri = bucket_uri or (
1624
+ artifact_dir if ObjectStorageDetails.is_oci_path(artifact_dir) else None
1625
+ )
1626
+ dsc_model = DataScienceModel.from_id(model_id)
1627
+
1628
+ if not download_artifact:
1629
+ result_model = cls(
1630
+ artifact_dir=artifact_dir,
1631
+ bucket_uri=bucket_uri,
1632
+ auth=auth,
1633
+ properties=properties,
1634
+ ignore_conda_error=ignore_conda_error,
1635
+ **kwargs,
1636
+ )
1637
+ result_model.update_summary_status(
1638
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL,
1639
+ status=ModelState.NOTAPPLICABLE.value,
1640
+ )
1641
+ result_model.update_summary_status(
1642
+ detail=PREPARE_STATUS_GEN_RUNTIME_DETAIL,
1643
+ status=ModelState.NOTAPPLICABLE.value,
1644
+ )
1645
+ result_model.update_summary_status(
1646
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
1647
+ status=ModelState.NOTAPPLICABLE.value,
1648
+ )
1649
+ result_model.update_summary_status(
1650
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1651
+ status=ModelState.NOTAPPLICABLE.value,
1652
+ )
1653
+ result_model.update_summary_status(
1654
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1655
+ status=ModelState.NOTAPPLICABLE.value,
1656
+ )
1657
+ result_model.update_summary_action(
1658
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1659
+ action="Local artifact is not available. "
1660
+ "Set load_artifact flag to True while loading the model or "
1661
+ "call .download_artifact().",
1662
+ )
1663
+ result_model.update_summary_status(
1664
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
1665
+ status=ModelState.NOTAPPLICABLE.value,
1666
+ )
1667
+ result_model.update_summary_status(
1668
+ detail=SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL,
1669
+ status=ModelState.NOTAPPLICABLE.value,
1670
+ )
1671
+ result_model.dsc_model = dsc_model
1672
+ return result_model
1673
+
1674
+ dsc_model.download_artifact(
1675
+ target_dir=target_dir,
1676
+ force_overwrite=force_overwrite,
1677
+ bucket_uri=bucket_uri,
1678
+ remove_existing_artifact=remove_existing_artifact,
1679
+ auth=auth,
1680
+ region=kwargs.pop("region", None),
1681
+ timeout=kwargs.pop("timeout", None),
1682
+ )
1683
+ result_model = cls.from_model_artifact(
1684
+ uri=target_dir,
1685
+ model_file_name=model_file_name,
1686
+ artifact_dir=artifact_dir,
1687
+ auth=auth,
1688
+ force_overwrite=force_overwrite,
1689
+ properties=properties,
1690
+ ignore_conda_error=ignore_conda_error,
1691
+ **kwargs,
1692
+ )
1693
+ result_model.dsc_model = dsc_model
1694
+
1695
+ result_model.update_summary_status(
1696
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1697
+ status=ModelState.DONE.value,
1698
+ )
1699
+ result_model.update_summary_action(
1700
+ detail=PREPARE_STATUS_POPULATE_METADATA_DETAIL,
1701
+ action="",
1702
+ )
1703
+ result_model.update_summary_status(
1704
+ detail=VERIFY_STATUS_LOCAL_TEST_DETAIL,
1705
+ status=ModelState.AVAILABLE.value,
1706
+ )
1707
+ result_model.update_summary_status(
1708
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
1709
+ status=ModelState.AVAILABLE.value
1710
+ if not result_model.ignore_conda_error
1711
+ else ModelState.NOTAVAILABLE.value,
1712
+ )
1713
+ return result_model
1714
+
1715
+ @classmethod
1716
+ def from_model_deployment(
1717
+ cls: Type[Self],
1718
+ model_deployment_id: str,
1719
+ model_file_name: str = None,
1720
+ artifact_dir: Optional[str] = None,
1721
+ auth: Optional[Dict] = None,
1722
+ force_overwrite: Optional[bool] = False,
1723
+ properties: Optional[Union[ModelProperties, Dict]] = None,
1724
+ bucket_uri: Optional[str] = None,
1725
+ remove_existing_artifact: Optional[bool] = True,
1726
+ ignore_conda_error: Optional[bool] = False,
1727
+ download_artifact: Optional[bool] = True,
1728
+ **kwargs,
1729
+ ) -> Self:
1730
+ """Loads model from model deployment.
1731
+
1732
+ Parameters
1733
+ ----------
1734
+ model_deployment_id: str
1735
+ The model deployment OCID.
1736
+ model_file_name: (str, optional). Defaults to `None`.
1737
+ The name of the serialized model.
1738
+ artifact_dir: (str, optional). Defaults to `None`.
1739
+ The artifact directory to store the files needed for deployment.
1740
+ Will be created if not exists.
1741
+ auth: (Dict, optional). Defaults to None.
1742
+ The default authetication is set using `ads.set_auth` API. If you need to override the
1743
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
1744
+ authentication signer and kwargs required to instantiate IdentityClient object.
1745
+ force_overwrite: (bool, optional). Defaults to False.
1746
+ Whether to overwrite existing files or not.
1747
+ properties: (ModelProperties, optional). Defaults to None.
1748
+ ModelProperties object required to save and deploy model.
1749
+ bucket_uri: (str, optional). Defaults to None.
1750
+ The OCI Object Storage URI where model artifacts will be copied to.
1751
+ The `bucket_uri` is only necessary for downloading large artifacts with
1752
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
1753
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
1754
+ Wether artifacts uploaded to object storage bucket need to be removed or not.
1755
+ ignore_conda_error: (bool, optional). Defaults to False.
1756
+ Parameter to ignore error when collecting conda information.
1757
+ download_artifact: (bool, optional). Defaults to True.
1758
+ Whether to download the model pickle or checkpoints
1759
+ kwargs:
1760
+ compartment_id : (str, optional)
1761
+ Compartment OCID. If not specified, the value will be taken from the environment variables.
1762
+ timeout : (int, optional). Defaults to 10 seconds.
1763
+ The connection timeout in seconds for the client.
1764
+ region: (str, optional). Defaults to `None`.
1765
+ The destination Object Storage bucket region.
1766
+ By default the value will be extracted from the `OCI_REGION_METADATA` environment variables.
1767
+
1768
+ Returns
1769
+ -------
1770
+ Self
1771
+ An instance of GenericModel class.
1772
+ """
1773
+ if (
1774
+ cls._PREFIX != "spark"
1775
+ and artifact_dir
1776
+ and ObjectStorageDetails.is_oci_path(artifact_dir)
1777
+ ):
1778
+ raise ValueError(
1779
+ f"Unsupported value of `artifact_dir`: {artifact_dir}. "
1780
+ "Only SparkPipelineModel framework supports object storage path as `artifact_dir`."
1781
+ )
1782
+
1783
+ model_deployment = ModelDeployment.from_id(model_deployment_id)
1784
+
1785
+ current_state = model_deployment.state.name.upper()
1786
+ if current_state != ModelDeploymentState.ACTIVE.name:
1787
+ logger.warning(
1788
+ "This model deployment is not in active state, you will not be able to use predict end point. "
1789
+ f"Current model deployment state: `{current_state}`"
1790
+ )
1791
+
1792
+ model = cls.from_model_catalog(
1793
+ model_id=model_deployment.properties.model_id,
1794
+ model_file_name=model_file_name,
1795
+ artifact_dir=artifact_dir,
1796
+ auth=auth,
1797
+ force_overwrite=force_overwrite,
1798
+ properties=properties,
1799
+ bucket_uri=bucket_uri,
1800
+ remove_existing_artifact=remove_existing_artifact,
1801
+ ignore_conda_error=ignore_conda_error,
1802
+ download_artifact=download_artifact,
1803
+ **kwargs,
1804
+ )
1805
+ model.update_summary_status(
1806
+ detail=SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL,
1807
+ status=ModelState.AVAILABLE.value,
1808
+ )
1809
+
1810
+ model.model_deployment = model_deployment
1811
+ model.update_summary_status(
1812
+ detail=DEPLOY_STATUS_DETAIL,
1813
+ status=model.model_deployment.state.name.upper(),
1814
+ )
1815
+ return model
1816
+
1817
+ @class_or_instance_method
1818
+ def update_deployment(
1819
+ cls,
1820
+ model_deployment_id: str = None,
1821
+ properties: Union[ModelDeploymentProperties, dict, None] = None,
1822
+ wait_for_completion: bool = True,
1823
+ max_wait_time: int = DEFAULT_WAIT_TIME,
1824
+ poll_interval: int = DEFAULT_POLL_INTERVAL,
1825
+ **kwargs,
1826
+ ) -> "ModelDeployment":
1827
+ """Updates a model deployment.
1828
+
1829
+ You can update `model_deployment_configuration_details` and change `instance_shape` and `model_id`
1830
+ when the model deployment is in the ACTIVE lifecycle state.
1831
+ The `bandwidth_mbps` or `instance_count` can only be updated while the model deployment is in the `INACTIVE` state.
1832
+ Changes to the `bandwidth_mbps` or `instance_count` will take effect the next time
1833
+ the `ActivateModelDeployment` action is invoked on the model deployment resource.
1834
+
1835
+ Examples
1836
+ --------
1837
+ >>> # Update access log id, freeform tags and description for the model deployment
1838
+ >>> model.update_deployment(
1839
+ ... access_log={
1840
+ ... log_id=<log_ocid>
1841
+ ... },
1842
+ ... description="Description for Custom Model",
1843
+ ... freeform_tags={"key": "value"},
1844
+ ... )
1845
+
1846
+ Parameters
1847
+ ----------
1848
+ model_deployment_id: str.
1849
+ The model deployment OCID. Defaults to None.
1850
+ If the method called on instance level, then `self.model_deployment.model_deployment_id` will be used.
1851
+ properties: ModelDeploymentProperties or dict
1852
+ The properties for updating the deployment.
1853
+ wait_for_completion: bool
1854
+ Flag set for whether to wait for deployment to complete before proceeding.
1855
+ Defaults to True.
1856
+ max_wait_time: int
1857
+ Maximum amount of time to wait in seconds (Defaults to 1200).
1858
+ Negative implies infinite wait time.
1859
+ poll_interval: int
1860
+ Poll interval in seconds (Defaults to 10).
1861
+ kwargs:
1862
+ auth: (Dict, optional). Defaults to `None`.
1863
+ The default authetication is set using `ads.set_auth` API.
1864
+ If you need to override the default, use the `ads.common.auth.api_keys` or
1865
+ `ads.common.auth.resource_principal` to create appropriate authentication signer
1866
+ and kwargs required to instantiate IdentityClient object.
1867
+ display_name: (str)
1868
+ Model deployment display name
1869
+ description: (str)
1870
+ Model deployment description
1871
+ freeform_tags: (dict)
1872
+ Model deployment freeform tags
1873
+ defined_tags: (dict)
1874
+ Model deployment defined tags
1875
+
1876
+ Additional kwargs arguments.
1877
+ Can be any attribute that `ads.model.deployment.ModelDeploymentCondaRuntime`, `ads.model.deployment.ModelDeploymentContainerRuntime`
1878
+ and `ads.model.deployment.ModelDeploymentInfrastructure` accepts.
1879
+
1880
+ Returns
1881
+ -------
1882
+ ModelDeployment
1883
+ An instance of ModelDeployment class.
1884
+ """
1885
+ if properties:
1886
+ warnings.warn(
1887
+ "Parameter `properties` is deprecated from GenericModel `update_deployment()` in 2.8.6 and will be removed in 3.0.0. Please use kwargs to update model deployment. "
1888
+ "Check: https://accelerated-data-science.readthedocs.io/en/latest/user_guide/model_registration/introduction.html"
1889
+ )
1890
+
1891
+ if not inspect.isclass(cls):
1892
+ if cls.model_deployment:
1893
+ return cls.model_deployment.update(
1894
+ properties=properties,
1895
+ wait_for_completion=wait_for_completion,
1896
+ max_wait_time=max_wait_time,
1897
+ poll_interval=poll_interval,
1898
+ **kwargs,
1899
+ )
1900
+
1901
+ if not model_deployment_id:
1902
+ raise ValueError("Parameter `model_deployment_id` must be provided.")
1903
+
1904
+ model_deployment = ModelDeployment.from_id(model_deployment_id)
1905
+ return model_deployment.update(
1906
+ properties=properties,
1907
+ wait_for_completion=wait_for_completion,
1908
+ max_wait_time=max_wait_time,
1909
+ poll_interval=poll_interval,
1910
+ **kwargs,
1911
+ )
1912
+
1913
+ @classmethod
1914
+ def from_id(
1915
+ cls: Type[Self],
1916
+ ocid: str,
1917
+ model_file_name: str = None,
1918
+ artifact_dir: Optional[str] = None,
1919
+ auth: Optional[Dict] = None,
1920
+ force_overwrite: Optional[bool] = False,
1921
+ properties: Optional[Union[ModelProperties, Dict]] = None,
1922
+ bucket_uri: Optional[str] = None,
1923
+ remove_existing_artifact: Optional[bool] = True,
1924
+ ignore_conda_error: Optional[bool] = False,
1925
+ download_artifact: Optional[bool] = True,
1926
+ **kwargs,
1927
+ ) -> Self:
1928
+ """Loads model from model OCID or model deployment OCID.
1929
+
1930
+ Parameters
1931
+ ----------
1932
+ ocid: str
1933
+ The model OCID or model deployment OCID.
1934
+ model_file_name: (str, optional). Defaults to `None`.
1935
+ The name of the serialized model.
1936
+ artifact_dir: (str, optional). Defaults to `None`.
1937
+ The artifact directory to store the files needed for deployment.
1938
+ Will be created if not exists.
1939
+ auth: (Dict, optional). Defaults to None.
1940
+ The default authetication is set using `ads.set_auth` API. If you need to override the
1941
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
1942
+ authentication signer and kwargs required to instantiate IdentityClient object.
1943
+ force_overwrite: (bool, optional). Defaults to False.
1944
+ Whether to overwrite existing files or not.
1945
+ properties: (ModelProperties, optional). Defaults to None.
1946
+ ModelProperties object required to save and deploy model.
1947
+ bucket_uri: (str, optional). Defaults to None.
1948
+ The OCI Object Storage URI where model artifacts will be copied to.
1949
+ The `bucket_uri` is only necessary for downloading large artifacts with
1950
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
1951
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
1952
+ Wether artifacts uploaded to object storage bucket need to be removed or not.
1953
+ ignore_conda_error: (bool, optional). Defaults to False.
1954
+ Parameter to ignore error when collecting conda information.
1955
+ download_artifact: (bool, optional). Defaults to True.
1956
+ Whether to download the model pickle or checkpoints
1957
+ kwargs:
1958
+ compartment_id : (str, optional)
1959
+ Compartment OCID. If not specified, the value will be taken from the environment variables.
1960
+ timeout : (int, optional). Defaults to 10 seconds.
1961
+ The connection timeout in seconds for the client.
1962
+
1963
+ Returns
1964
+ -------
1965
+ Self
1966
+ An instance of GenericModel class.
1967
+ """
1968
+ ocid = ocid.lower()
1969
+ if DataScienceModelType.MODEL_DEPLOYMENT in ocid:
1970
+ return cls.from_model_deployment(
1971
+ ocid,
1972
+ model_file_name=model_file_name,
1973
+ artifact_dir=artifact_dir,
1974
+ auth=auth,
1975
+ force_overwrite=force_overwrite,
1976
+ properties=properties,
1977
+ bucket_uri=bucket_uri,
1978
+ remove_existing_artifact=remove_existing_artifact,
1979
+ ignore_conda_error=ignore_conda_error,
1980
+ download_artifact=download_artifact,
1981
+ **kwargs,
1982
+ )
1983
+ elif DataScienceModelType.MODEL in ocid:
1984
+ return cls.from_model_catalog(
1985
+ ocid,
1986
+ model_file_name=model_file_name,
1987
+ artifact_dir=artifact_dir,
1988
+ auth=auth,
1989
+ force_overwrite=force_overwrite,
1990
+ properties=properties,
1991
+ bucket_uri=bucket_uri,
1992
+ remove_existing_artifact=remove_existing_artifact,
1993
+ ignore_conda_error=ignore_conda_error,
1994
+ download_artifact=download_artifact,
1995
+ **kwargs,
1996
+ )
1997
+ else:
1998
+ raise ValueError(
1999
+ f"Invalid OCID: {ocid}. Please provide valid model OCID or model deployment OCID."
2000
+ )
2001
+
2002
+ def reload_runtime_info(self) -> None:
2003
+ """Reloads the model artifact file: `runtime.yaml`.
2004
+
2005
+ Returns
2006
+ -------
2007
+ None
2008
+ Nothing.
2009
+ """
2010
+ # reload runtime.yaml
2011
+ runtime_yaml_file = os.path.join(self.artifact_dir, "runtime.yaml")
2012
+ if not utils.is_path_exists(runtime_yaml_file, auth=self.auth):
2013
+ if self.ignore_conda_error:
2014
+ return self.runtime_info
2015
+ else:
2016
+ raise FileNotFoundError(
2017
+ f"`runtime.yaml` does not exist in {self.artifact_dir}. "
2018
+ "Use `RuntimeInfo` class to populate it."
2019
+ )
2020
+ self.runtime_info = RuntimeInfo.from_yaml(
2021
+ uri=runtime_yaml_file, storage_options=self.auth or {}
2022
+ )
2023
+
2024
+ def reload(self) -> "GenericModel":
2025
+ """Reloads the model artifact files: `score.py` and the `runtime.yaml`.
2026
+
2027
+ Returns
2028
+ -------
2029
+ GenericModel
2030
+ An instance of GenericModel class.
2031
+ """
2032
+ # reload the score.py
2033
+ self.model_artifact.reload()
2034
+ # reload runtime.yaml
2035
+ self.reload_runtime_info()
2036
+ return self
2037
+
2038
+ def _random_display_name(self):
2039
+ """Generates a random display name."""
2040
+ return f"{self._PREFIX}-{utils.get_random_name_for_resource()}"
2041
+
2042
+ def save(
2043
+ self,
2044
+ bucket_uri: Optional[str] = None,
2045
+ defined_tags: Optional[dict] = None,
2046
+ description: Optional[str] = None,
2047
+ display_name: Optional[str] = None,
2048
+ featurestore_dataset=None,
2049
+ freeform_tags: Optional[dict] = None,
2050
+ ignore_introspection: Optional[bool] = False,
2051
+ model_version_set: Optional[Union[str, ModelVersionSet]] = None,
2052
+ overwrite_existing_artifact: Optional[bool] = True,
2053
+ parallel_process_count: int = utils.DEFAULT_PARALLEL_PROCESS_COUNT,
2054
+ remove_existing_artifact: Optional[bool] = True,
2055
+ reload: Optional[bool] = True,
2056
+ version_label: Optional[str] = None,
2057
+ model_by_reference: Optional[bool] = False,
2058
+ **kwargs,
2059
+ ) -> str:
2060
+ """Saves model artifacts to the model catalog.
2061
+
2062
+ Parameters
2063
+ ----------
2064
+ display_name: (str, optional). Defaults to None.
2065
+ The name of the model. If a display_name is not provided in kwargs,
2066
+ randomly generated easy to remember name with timestamp will be generated,
2067
+ like 'strange-spider-2022-08-17-23:55.02'.
2068
+ description: (str, optional). Defaults to None.
2069
+ The description of the model.
2070
+ freeform_tags : Dict(str, str), Defaults to None.
2071
+ Freeform tags for the model.
2072
+ defined_tags : (Dict(str, dict(str, object)), optional). Defaults to None.
2073
+ Defined tags for the model.
2074
+ ignore_introspection: (bool, optional). Defaults to None.
2075
+ Determine whether to ignore the result of model introspection or not.
2076
+ If set to True, the save will ignore all model introspection errors.
2077
+ bucket_uri: (str, optional). Defaults to None.
2078
+ The OCI Object Storage URI where model artifacts will be copied to.
2079
+ The `bucket_uri` is only necessary for uploading large artifacts which
2080
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
2081
+ overwrite_existing_artifact: (bool, optional). Defaults to `True`.
2082
+ Overwrite target bucket artifact if exists.
2083
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
2084
+ Whether artifacts uploaded to object storage bucket need to be removed or not.
2085
+ model_version_set: (Union[str, ModelVersionSet], optional). Defaults to None.
2086
+ The model version set OCID, or model version set name, or `ModelVersionSet` instance.
2087
+ version_label: (str, optional). Defaults to None.
2088
+ The model version lebel.
2089
+ featurestore_dataset: (Dataset, optional).
2090
+ The feature store dataset
2091
+ parallel_process_count: (int, optional)
2092
+ The number of worker processes to use in parallel for uploading individual parts of a multipart upload.
2093
+ reload: (bool, optional)
2094
+ Whether to reload to check if `load_model()` works in `score.py`. Default to `True`.
2095
+ model_by_reference: (bool, optional)
2096
+ Whether model artifact is made available to Model Store by reference.
2097
+ kwargs:
2098
+ project_id: (str, optional).
2099
+ Project OCID. If not specified, the value will be taken either
2100
+ from the environment variables or model properties.
2101
+ compartment_id : (str, optional).
2102
+ Compartment OCID. If not specified, the value will be taken either
2103
+ from the environment variables or model properties.
2104
+ region: (str, optional). Defaults to `None`.
2105
+ The destination Object Storage bucket region.
2106
+ By default the value will be extracted from the `OCI_REGION_METADATA` environment variables.
2107
+ timeout: (int, optional). Defaults to 10 seconds.
2108
+ The connection timeout in seconds for the client.
2109
+
2110
+ Also can be any attribute that `oci.data_science.models.Model` accepts.
2111
+
2112
+ Raises
2113
+ ------
2114
+ RuntimeInfoInconsistencyError
2115
+ When `.runtime_info` is not synched with runtime.yaml file.
2116
+
2117
+ Returns
2118
+ -------
2119
+ str
2120
+ The model id.
2121
+
2122
+ Examples
2123
+ --------
2124
+ Example for saving large model artifacts (>2GB):
2125
+ >>> model.save(
2126
+ ... bucket_uri="oci://my-bucket@my-tenancy/",
2127
+ ... overwrite_existing_artifact=True,
2128
+ ... remove_existing_artifact=True,
2129
+ ... parallel_process_count=9,
2130
+ ... )
2131
+
2132
+ """
2133
+ if self.model_artifact is None:
2134
+ raise ArtifactsNotAvailableError
2135
+
2136
+ # Set default display_name if not specified - randomly generated easy to remember name generated
2137
+ if not display_name:
2138
+ display_name = self._random_display_name()
2139
+ # populates properties from args and kwargs. Empty values will be ignored.
2140
+ self.properties.with_dict(_extract_locals(locals()))
2141
+ self.properties.compartment_id = (
2142
+ self.properties.compartment_id or _COMPARTMENT_OCID
2143
+ )
2144
+ self.properties.project_id = self.properties.project_id or PROJECT_OCID
2145
+
2146
+ # check if the runtime_info sync with the runtime.yaml.
2147
+ try:
2148
+ runtime_file_path = os.path.join(self.local_copy_dir, "runtime.yaml")
2149
+ runtime_info_from_yaml = RuntimeInfo.from_yaml(uri=runtime_file_path)
2150
+ if self.runtime_info != runtime_info_from_yaml:
2151
+ raise RuntimeInfoInconsistencyError(
2152
+ "`.runtime_info` does not sync with runtime.yaml file. Call "
2153
+ "`.runtime_info.save()` if you updated `runtime_info`. "
2154
+ "Call `.reload_runtime_info()` if you updated runtime.yaml file."
2155
+ )
2156
+ # reload to check if load_model works in score.py, i.e.
2157
+ # whether the model file has been serialized, and whether it can be loaded
2158
+ # successfully.
2159
+ if reload:
2160
+ self.reload()
2161
+ else:
2162
+ logger.warning(
2163
+ "The score.py file has not undergone testing, and this could result in deployment errors. To verify its functionality, please set `reload=True`."
2164
+ )
2165
+ except:
2166
+ if not self.ignore_conda_error:
2167
+ raise
2168
+ if not self.ignore_conda_error and not ignore_introspection:
2169
+ self._introspect()
2170
+ if self._introspect.status == TEST_STATUS.NOT_PASSED:
2171
+ msg = (
2172
+ "Model introspection not passed. "
2173
+ "Use `.introspect()` method to get detailed information and follow the "
2174
+ "messages to fix it. To save model artifacts ignoring introspection "
2175
+ "use `.save(ignore_introspection=True...)`."
2176
+ )
2177
+ self.update_summary_status(
2178
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL, status="Failed"
2179
+ )
2180
+ self.update_summary_action(
2181
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
2182
+ action="Use `.introspect()` method to get detailed information.",
2183
+ )
2184
+ raise IntrospectionNotPassed(msg)
2185
+ else:
2186
+ self.update_summary_status(
2187
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL,
2188
+ status=ModelState.DONE.value,
2189
+ )
2190
+ self.update_summary_action(
2191
+ detail=SAVE_STATUS_INTROSPECT_TEST_DETAIL, action=""
2192
+ )
2193
+
2194
+ # extract model_version_set_id from model_version_set attribute or environment
2195
+ # variables in case of saving model in context of model version set.
2196
+ model_version_set_id = _extract_model_version_set_id(model_version_set)
2197
+
2198
+ if featurestore_dataset:
2199
+ dataset_details = {
2200
+ "dataset-id": featurestore_dataset.id,
2201
+ "dataset-name": featurestore_dataset.name,
2202
+ }
2203
+ self.metadata_custom.add(
2204
+ "featurestore.dataset",
2205
+ value=str(dataset_details),
2206
+ category=MetadataCustomCategory.TRAINING_AND_VALIDATION_DATASETS,
2207
+ description="feature store dataset",
2208
+ replace=True,
2209
+ )
2210
+
2211
+ self.dsc_model = (
2212
+ self.dsc_model.with_compartment_id(self.properties.compartment_id)
2213
+ .with_project_id(self.properties.project_id)
2214
+ .with_display_name(display_name)
2215
+ .with_description(description)
2216
+ .with_freeform_tags(**(freeform_tags or {}))
2217
+ .with_defined_tags(**(defined_tags or {}))
2218
+ .with_artifact(self.local_copy_dir)
2219
+ .with_model_version_set_id(model_version_set_id)
2220
+ .with_version_label(version_label)
2221
+ ).create(
2222
+ bucket_uri=bucket_uri,
2223
+ overwrite_existing_artifact=overwrite_existing_artifact,
2224
+ remove_existing_artifact=remove_existing_artifact,
2225
+ parallel_process_count=parallel_process_count,
2226
+ model_by_reference=model_by_reference,
2227
+ **kwargs,
2228
+ )
2229
+
2230
+ self.update_summary_status(
2231
+ detail=SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL, status=ModelState.DONE.value
2232
+ )
2233
+ self.update_summary_status(
2234
+ detail=DEPLOY_STATUS_DETAIL, status=ModelState.AVAILABLE.value
2235
+ )
2236
+ self.model_deployment = (
2237
+ ModelDeployment()
2238
+ .with_infrastructure(ModelDeploymentInfrastructure())
2239
+ .with_runtime(ModelDeploymentContainerRuntime())
2240
+ )
2241
+ # Add the model id to the feature store dataset
2242
+ if featurestore_dataset:
2243
+ model_details = ModelDetails().with_items([self.model_id])
2244
+ featurestore_dataset.add_models(model_details)
2245
+
2246
+ return self.model_id
2247
+
2248
+ def _get_files(self):
2249
+ """List out all the file names under the artifact_dir.
2250
+
2251
+ Returns
2252
+ -------
2253
+ List
2254
+ List of the files in the artifact_dir.
2255
+ """
2256
+ return get_files(self.artifact_dir, auth=self.auth)
2257
+
2258
+ def deploy(
2259
+ self,
2260
+ wait_for_completion: Optional[bool] = True,
2261
+ display_name: Optional[str] = None,
2262
+ description: Optional[str] = None,
2263
+ deployment_instance_shape: Optional[str] = None,
2264
+ deployment_instance_subnet_id: Optional[str] = None,
2265
+ deployment_instance_private_endpoint_id: Optional[str] = None,
2266
+ deployment_instance_count: Optional[int] = None,
2267
+ deployment_bandwidth_mbps: Optional[int] = None,
2268
+ deployment_log_group_id: Optional[str] = None,
2269
+ deployment_access_log_id: Optional[str] = None,
2270
+ deployment_predict_log_id: Optional[str] = None,
2271
+ deployment_memory_in_gbs: Optional[float] = None,
2272
+ deployment_ocpus: Optional[float] = None,
2273
+ deployment_image: Optional[str] = None,
2274
+ **kwargs: Dict,
2275
+ ) -> "ModelDeployment":
2276
+ """
2277
+ Deploys a model. The model needs to be saved to the model catalog at first. You can deploy the model
2278
+ on either conda or container runtime. The customized runtime allows you to bring your own service container.
2279
+ To deploy model on container runtime, make sure to build the container and push it to OCIR.
2280
+ For more information, see https://docs.oracle.com/en-us/iaas/data-science/using/mod-dep-byoc.htm.
2281
+
2282
+ Example
2283
+ -------
2284
+ >>> # This is an example to deploy model on container runtime
2285
+ >>> model = GenericModel(estimator=estimator, artifact_dir=tempfile.mkdtemp())
2286
+ >>> model.summary_status()
2287
+ >>> model.prepare(
2288
+ ... model_file_name="toy_model.pkl",
2289
+ ... ignore_conda_error=True, # set ignore_conda_error=True for container runtime
2290
+ ... force_overwrite=True
2291
+ ... )
2292
+ >>> model.verify()
2293
+ >>> model.save()
2294
+ >>> model.deploy(
2295
+ ... deployment_image="iad.ocir.io/<namespace>/<image>:<tag>",
2296
+ ... entrypoint=["python", "/opt/ds/model/deployed_model/api.py"],
2297
+ ... server_port=5000,
2298
+ ... health_check_port=5000,
2299
+ ... environment_variables={"key":"value"}
2300
+ ... )
2301
+
2302
+ Parameters
2303
+ ----------
2304
+ wait_for_completion : (bool, optional). Defaults to True.
2305
+ Flag set for whether to wait for deployment to complete before proceeding.
2306
+ display_name: (str, optional). Defaults to None.
2307
+ The name of the model. If a display_name is not provided in kwargs,
2308
+ a randomly generated easy to remember name with timestamp will be generated,
2309
+ like 'strange-spider-2022-08-17-23:55.02'.
2310
+ description: (str, optional). Defaults to None.
2311
+ The description of the model.
2312
+ deployment_instance_shape: (str, optional). Default to `VM.Standard2.1`.
2313
+ The shape of the instance used for deployment.
2314
+ deployment_instance_subnet_id: (str, optional). Default to None.
2315
+ The subnet id of the instance used for deployment.
2316
+ deployment_instance_private_endpoint_id: (str, optional). Default to None.
2317
+ The private endpoint id of instance used for deployment.
2318
+ deployment_instance_count: (int, optional). Defaults to 1.
2319
+ The number of instance used for deployment.
2320
+ deployment_bandwidth_mbps: (int, optional). Defaults to 10.
2321
+ The bandwidth limit on the load balancer in Mbps.
2322
+ deployment_memory_in_gbs: (float, optional). Defaults to None.
2323
+ Specifies the size of the memory of the model deployment instance in GBs.
2324
+ deployment_ocpus: (float, optional). Defaults to None.
2325
+ Specifies the ocpus count of the model deployment instance.
2326
+ deployment_log_group_id: (str, optional). Defaults to None.
2327
+ The oci logging group id. The access log and predict log share the same log group.
2328
+ deployment_access_log_id: (str, optional). Defaults to None.
2329
+ The access log OCID for the access logs. https://docs.oracle.com/en-us/iaas/data-science/using/model_dep_using_logging.htm
2330
+ deployment_predict_log_id: (str, optional). Defaults to None.
2331
+ The predict log OCID for the predict logs. https://docs.oracle.com/en-us/iaas/data-science/using/model_dep_using_logging.htm
2332
+ deployment_image: (str, optional). Defaults to None.
2333
+ The OCIR path of docker container image. Required for deploying model on container runtime.
2334
+ kwargs:
2335
+ project_id: (str, optional).
2336
+ Project OCID. If not specified, the value will be taken from the environment variables.
2337
+ compartment_id : (str, optional).
2338
+ Compartment OCID. If not specified, the value will be taken from the environment variables.
2339
+ max_wait_time : (int, optional). Defaults to 1200 seconds.
2340
+ Maximum amount of time to wait in seconds.
2341
+ Negative implies infinite wait time.
2342
+ poll_interval : (int, optional). Defaults to 10 seconds.
2343
+ Poll interval in seconds.
2344
+ freeform_tags: (Dict[str, str], optional). Defaults to None.
2345
+ Freeform tags of the model deployment.
2346
+ defined_tags: (Dict[str, dict[str, object]], optional). Defaults to None.
2347
+ Defined tags of the model deployment.
2348
+ image_digest: (str, optional). Defaults to None.
2349
+ The digest of docker container image.
2350
+ cmd: (List, optional). Defaults to empty.
2351
+ The command line arguments for running docker container image.
2352
+ entrypoint: (List, optional). Defaults to empty.
2353
+ The entrypoint for running docker container image.
2354
+ server_port: (int, optional). Defaults to 8080.
2355
+ The server port for docker container image.
2356
+ health_check_port: (int, optional). Defaults to 8080.
2357
+ The health check port for docker container image.
2358
+ deployment_mode: (str, optional). Defaults to HTTPS_ONLY.
2359
+ The deployment mode. Allowed values are: HTTPS_ONLY and STREAM_ONLY.
2360
+ input_stream_ids: (List, optional). Defaults to empty.
2361
+ The input stream ids. Required for STREAM_ONLY mode.
2362
+ output_stream_ids: (List, optional). Defaults to empty.
2363
+ The output stream ids. Required for STREAM_ONLY mode.
2364
+ environment_variables: (Dict, optional). Defaults to empty.
2365
+ The environment variables for model deployment.
2366
+
2367
+ Also can be any keyword argument for initializing the `ads.model.deployment.ModelDeploymentProperties`.
2368
+ See `ads.model.deployment.ModelDeploymentProperties()` for details.
2369
+
2370
+ Returns
2371
+ -------
2372
+ ModelDeployment
2373
+ The ModelDeployment instance.
2374
+
2375
+ Raises
2376
+ ------
2377
+ ValueError
2378
+ If `model_id` is not specified.
2379
+ """
2380
+ # Set default display_name if not specified - randomly generated easy to remember name generated
2381
+ if not display_name:
2382
+ display_name = utils.get_random_name_for_resource()
2383
+ # populates properties from args and kwargs. Empty values will be ignored.
2384
+ override_properties = _extract_locals(locals())
2385
+ # clears out project_id and compartment_id from kwargs, to prevent passing
2386
+ # these params to the deployment via kwargs.
2387
+ kwargs.pop("project_id", None)
2388
+ kwargs.pop("compartment_id", None)
2389
+
2390
+ max_wait_time = kwargs.pop("max_wait_time", DEFAULT_WAIT_TIME)
2391
+ poll_interval = kwargs.pop("poll_interval", DEFAULT_POLL_INTERVAL)
2392
+
2393
+ # GenericModel itself has a ModelDeployment instance. When calling deploy(),
2394
+ # if there are parameters passed in they will override this ModelDeployment instance,
2395
+ # otherwise the properties of the ModelDeployment instance will be applied for deployment.
2396
+ existing_infrastructure = self.model_deployment.infrastructure
2397
+ existing_runtime = self.model_deployment.runtime
2398
+ property_dict = ModelProperties(
2399
+ compartment_id=existing_infrastructure.compartment_id
2400
+ or self.properties.compartment_id
2401
+ or _COMPARTMENT_OCID,
2402
+ project_id=existing_infrastructure.project_id
2403
+ or self.properties.project_id
2404
+ or PROJECT_OCID,
2405
+ deployment_instance_shape=existing_infrastructure.shape_name
2406
+ or self.properties.deployment_instance_shape
2407
+ or MODEL_DEPLOYMENT_INSTANCE_SHAPE,
2408
+ deployment_instance_count=existing_infrastructure.replica
2409
+ or self.properties.deployment_instance_count
2410
+ or MODEL_DEPLOYMENT_INSTANCE_COUNT,
2411
+ deployment_bandwidth_mbps=existing_infrastructure.bandwidth_mbps
2412
+ or self.properties.deployment_bandwidth_mbps
2413
+ or MODEL_DEPLOYMENT_BANDWIDTH_MBPS,
2414
+ deployment_ocpus=existing_infrastructure.shape_config_details.get(
2415
+ "ocpus", None
2416
+ )
2417
+ or self.properties.deployment_ocpus
2418
+ or MODEL_DEPLOYMENT_INSTANCE_OCPUS,
2419
+ deployment_memory_in_gbs=existing_infrastructure.shape_config_details.get(
2420
+ "memoryInGBs", None
2421
+ )
2422
+ or self.properties.deployment_memory_in_gbs
2423
+ or MODEL_DEPLOYMENT_INSTANCE_MEMORY_IN_GBS,
2424
+ deployment_log_group_id=existing_infrastructure.log_group_id
2425
+ or self.properties.deployment_log_group_id,
2426
+ deployment_access_log_id=existing_infrastructure.access_log.get(
2427
+ "log_id", None
2428
+ )
2429
+ or self.properties.deployment_access_log_id,
2430
+ deployment_predict_log_id=existing_infrastructure.predict_log.get(
2431
+ "log_id", None
2432
+ )
2433
+ or self.properties.deployment_predict_log_id,
2434
+ deployment_image=getattr(existing_runtime, "image", None)
2435
+ or self.properties.deployment_image,
2436
+ deployment_instance_subnet_id=existing_infrastructure.subnet_id
2437
+ or self.properties.deployment_instance_subnet_id,
2438
+ deployment_instance_private_endpoint_id=existing_infrastructure.private_endpoint_id
2439
+ or self.properties.deployment_instance_private_endpoint_id,
2440
+ ).to_dict()
2441
+
2442
+ property_dict.update(override_properties)
2443
+ self.properties.with_dict(property_dict)
2444
+
2445
+ if not self.model_id:
2446
+ raise ValueError(
2447
+ "The model needs to be saved to the Model Catalog "
2448
+ "before it can be deployed."
2449
+ )
2450
+
2451
+ if (
2452
+ self.properties.deployment_access_log_id
2453
+ or self.properties.deployment_predict_log_id
2454
+ ) and not self.properties.deployment_log_group_id:
2455
+ raise ValueError(
2456
+ "`deployment_log_group_id` needs to be specified. "
2457
+ "`deployment_access_log_id` and `deployment_predict_log_id` "
2458
+ "cannot be used without `deployment_log_group_id`."
2459
+ )
2460
+
2461
+ if not self.properties.compartment_id:
2462
+ raise ValueError("`compartment_id` has to be provided.")
2463
+ if not self.properties.project_id:
2464
+ raise ValueError("`project_id` has to be provided.")
2465
+ infrastructure = (
2466
+ ModelDeploymentInfrastructure()
2467
+ .with_compartment_id(self.properties.compartment_id)
2468
+ .with_project_id(self.properties.project_id)
2469
+ .with_bandwidth_mbps(self.properties.deployment_bandwidth_mbps)
2470
+ .with_shape_name(self.properties.deployment_instance_shape)
2471
+ .with_replica(self.properties.deployment_instance_count)
2472
+ .with_subnet_id(self.properties.deployment_instance_subnet_id)
2473
+ .with_private_endpoint_id(
2474
+ self.properties.deployment_instance_private_endpoint_id
2475
+ )
2476
+ )
2477
+
2478
+ web_concurrency = (
2479
+ kwargs.pop("web_concurrency", None)
2480
+ or existing_infrastructure.web_concurrency
2481
+ )
2482
+ if web_concurrency:
2483
+ infrastructure.with_web_concurrency(web_concurrency)
2484
+
2485
+ if infrastructure.shape_name.endswith("Flex"):
2486
+ infrastructure.with_shape_config_details(
2487
+ ocpus=self.properties.deployment_ocpus,
2488
+ memory_in_gbs=self.properties.deployment_memory_in_gbs,
2489
+ )
2490
+
2491
+ # specifies the access log id
2492
+ if self.properties.deployment_access_log_id:
2493
+ infrastructure.with_access_log(
2494
+ log_group_id=self.properties.deployment_log_group_id,
2495
+ log_id=self.properties.deployment_access_log_id,
2496
+ )
2497
+
2498
+ # specifies the predict log id
2499
+ if self.properties.deployment_predict_log_id:
2500
+ infrastructure.with_predict_log(
2501
+ log_group_id=self.properties.deployment_log_group_id,
2502
+ log_id=self.properties.deployment_predict_log_id,
2503
+ )
2504
+
2505
+ environment_variables = (
2506
+ kwargs.pop("environment_variables", {}) or existing_runtime.env
2507
+ )
2508
+ deployment_mode = (
2509
+ kwargs.pop("deployment_mode", None)
2510
+ or existing_runtime.deployment_mode
2511
+ or ModelDeploymentMode.HTTPS
2512
+ )
2513
+
2514
+ runtime = None
2515
+ if self.properties.deployment_image:
2516
+ image_digest = kwargs.pop("image_digest", None) or getattr(
2517
+ existing_runtime, "image_digest", None
2518
+ )
2519
+ cmd = kwargs.pop("cmd", []) or getattr(existing_runtime, "cmd", [])
2520
+ entrypoint = kwargs.pop("entrypoint", []) or getattr(
2521
+ existing_runtime, "entrypoint", []
2522
+ )
2523
+ server_port = kwargs.pop("server_port", None) or getattr(
2524
+ existing_runtime, "server_port", None
2525
+ )
2526
+ health_check_port = kwargs.pop("health_check_port", None) or getattr(
2527
+ existing_runtime, "health_check_port", None
2528
+ )
2529
+ runtime = (
2530
+ ModelDeploymentContainerRuntime()
2531
+ .with_image(self.properties.deployment_image)
2532
+ .with_image_digest(image_digest)
2533
+ .with_cmd(cmd)
2534
+ .with_entrypoint(entrypoint)
2535
+ .with_server_port(server_port)
2536
+ .with_health_check_port(health_check_port)
2537
+ .with_deployment_mode(deployment_mode)
2538
+ .with_model_uri(self.model_id)
2539
+ .with_env(environment_variables)
2540
+ )
2541
+ else:
2542
+ runtime = (
2543
+ ModelDeploymentCondaRuntime()
2544
+ .with_env(environment_variables)
2545
+ .with_deployment_mode(deployment_mode)
2546
+ .with_model_uri(self.model_id)
2547
+ )
2548
+
2549
+ if deployment_mode == ModelDeploymentMode.STREAM:
2550
+ input_stream_ids = (
2551
+ kwargs.pop("input_stream_ids", []) or existing_runtime.input_stream_ids
2552
+ )
2553
+ output_stream_ids = (
2554
+ kwargs.pop("output_stream_ids", [])
2555
+ or existing_runtime.output_stream_ids
2556
+ )
2557
+ if not (input_stream_ids and output_stream_ids):
2558
+ raise ValueError(
2559
+ "Parameter `input_stream_ids` and `output_stream_ids` need to be provided for `STREAM_ONLY` mode."
2560
+ )
2561
+
2562
+ runtime.with_input_stream_ids(input_stream_ids)
2563
+ runtime.with_output_stream_ids(output_stream_ids)
2564
+
2565
+ freeform_tags = (
2566
+ kwargs.pop("freeform_tags", {}) or self.model_deployment.freeform_tags
2567
+ )
2568
+ defined_tags = (
2569
+ kwargs.pop("defined_tags", {}) or self.model_deployment.defined_tags
2570
+ )
2571
+
2572
+ model_deployment = (
2573
+ ModelDeployment()
2574
+ .with_display_name(display_name or self.model_deployment.display_name)
2575
+ .with_description(description or self.model_deployment.description)
2576
+ .with_defined_tags(**defined_tags)
2577
+ .with_freeform_tags(**freeform_tags)
2578
+ .with_infrastructure(infrastructure)
2579
+ .with_runtime(runtime)
2580
+ )
2581
+
2582
+ self.model_deployment = model_deployment.deploy(
2583
+ wait_for_completion=wait_for_completion,
2584
+ max_wait_time=max_wait_time,
2585
+ poll_interval=poll_interval,
2586
+ )
2587
+ self.update_summary_status(
2588
+ detail=DEPLOY_STATUS_DETAIL,
2589
+ status=self.model_deployment.state.name.upper(),
2590
+ )
2591
+ return self.model_deployment
2592
+
2593
+ def prepare_save_deploy(
2594
+ self,
2595
+ inference_conda_env: str = None,
2596
+ inference_python_version: str = None,
2597
+ training_conda_env: str = None,
2598
+ training_python_version: str = None,
2599
+ model_file_name: str = None,
2600
+ as_onnx: bool = False,
2601
+ initial_types: List[Tuple] = None,
2602
+ force_overwrite: bool = False,
2603
+ namespace: str = CONDA_BUCKET_NS,
2604
+ use_case_type: str = None,
2605
+ X_sample: Union[list, tuple, pd.DataFrame, pd.Series, np.ndarray] = None,
2606
+ y_sample: Union[list, tuple, pd.DataFrame, pd.Series, np.ndarray] = None,
2607
+ training_script_path: str = None,
2608
+ training_id: str = _TRAINING_RESOURCE_ID,
2609
+ ignore_pending_changes: bool = True,
2610
+ max_col_num: int = DATA_SCHEMA_MAX_COL_NUM,
2611
+ ignore_conda_error: bool = False,
2612
+ model_display_name: Optional[str] = None,
2613
+ model_description: Optional[str] = None,
2614
+ model_freeform_tags: Optional[dict] = None,
2615
+ model_defined_tags: Optional[dict] = None,
2616
+ ignore_introspection: Optional[bool] = False,
2617
+ wait_for_completion: Optional[bool] = True,
2618
+ deployment_display_name: Optional[str] = None,
2619
+ deployment_description: Optional[str] = None,
2620
+ deployment_instance_shape: Optional[str] = None,
2621
+ deployment_instance_subnet_id: Optional[str] = None,
2622
+ deployment_instance_private_endpoint_id: Optional[str] = None,
2623
+ deployment_instance_count: Optional[int] = None,
2624
+ deployment_bandwidth_mbps: Optional[int] = None,
2625
+ deployment_log_group_id: Optional[str] = None,
2626
+ deployment_access_log_id: Optional[str] = None,
2627
+ deployment_predict_log_id: Optional[str] = None,
2628
+ deployment_memory_in_gbs: Optional[float] = None,
2629
+ deployment_ocpus: Optional[float] = None,
2630
+ deployment_image: Optional[str] = None,
2631
+ bucket_uri: Optional[str] = None,
2632
+ overwrite_existing_artifact: Optional[bool] = True,
2633
+ remove_existing_artifact: Optional[bool] = True,
2634
+ model_version_set: Optional[Union[str, ModelVersionSet]] = None,
2635
+ version_label: Optional[str] = None,
2636
+ model_by_reference: Optional[bool] = False,
2637
+ **kwargs: Dict,
2638
+ ) -> "ModelDeployment":
2639
+ """Shortcut for prepare, save and deploy steps.
2640
+
2641
+ Parameters
2642
+ ----------
2643
+ inference_conda_env: (str, optional). Defaults to None.
2644
+ Can be either slug or object storage path of the conda pack.
2645
+ You can only pass in slugs if the conda pack is a service pack.
2646
+ inference_python_version: (str, optional). Defaults to None.
2647
+ Python version which will be used in deployment.
2648
+ training_conda_env: (str, optional). Defaults to None.
2649
+ Can be either slug or object storage path of the conda pack.
2650
+ You can only pass in slugs if the conda pack is a service pack.
2651
+ If `training_conda_env` is not provided, `training_conda_env` will
2652
+ use the same value of `training_conda_env`.
2653
+ training_python_version: (str, optional). Defaults to None.
2654
+ Python version used during training.
2655
+ model_file_name: (str, optional). Defaults to `None`.
2656
+ Name of the serialized model.
2657
+ as_onnx: (bool, optional). Defaults to False.
2658
+ Whether to serialize as onnx model.
2659
+ initial_types: (list[Tuple], optional).
2660
+ Defaults to None. Only used for SklearnModel, LightGBMModel and XGBoostModel.
2661
+ Each element is a tuple of a variable name and a type.
2662
+ Check this link http://onnx.ai/sklearn-onnx/api_summary.html#id2 for
2663
+ more explanation and examples for `initial_types`.
2664
+ force_overwrite: (bool, optional). Defaults to False.
2665
+ Whether to overwrite existing files.
2666
+ namespace: (str, optional).
2667
+ Namespace of region. This is used for identifying which region the service pack
2668
+ is from when you pass a slug to inference_conda_env and training_conda_env.
2669
+ use_case_type: str
2670
+ The use case type of the model. Use it through UserCaseType class or string provided in `UseCaseType`. For
2671
+ example, use_case_type=UseCaseType.BINARY_CLASSIFICATION or use_case_type="binary_classification". Check
2672
+ with UseCaseType class to see all supported types.
2673
+ X_sample: Union[list, tuple, pd.Series, np.ndarray, pd.DataFrame]. Defaults to None.
2674
+ A sample of input data that will be used to generate input schema.
2675
+ y_sample: Union[list, tuple, pd.Series, np.ndarray, pd.DataFrame]. Defaults to None.
2676
+ A sample of output data that will be used to generate output schema.
2677
+ training_script_path: str. Defaults to None.
2678
+ Training script path.
2679
+ training_id: (str, optional). Defaults to value from environment variables.
2680
+ The training OCID for model. Can be notebook session or job OCID.
2681
+ ignore_pending_changes: bool. Defaults to False.
2682
+ whether to ignore the pending changes in the git.
2683
+ max_col_num: (int, optional). Defaults to utils.DATA_SCHEMA_MAX_COL_NUM.
2684
+ Do not generate the input schema if the input has more than this
2685
+ number of features(columns).
2686
+ ignore_conda_error: (bool, optional). Defaults to False.
2687
+ Parameter to ignore error when collecting conda information.
2688
+ model_display_name: (str, optional). Defaults to None.
2689
+ The name of the model. If a model_display_name is not provided in kwargs,
2690
+ a randomly generated easy to remember name with timestamp will be generated,
2691
+ like 'strange-spider-2022-08-17-23:55.02'.
2692
+ model_description: (str, optional). Defaults to None.
2693
+ The description of the model.
2694
+ model_freeform_tags : Dict(str, str), Defaults to None.
2695
+ Freeform tags for the model.
2696
+ model_defined_tags : (Dict(str, dict(str, object)), optional). Defaults to None.
2697
+ Defined tags for the model.
2698
+ ignore_introspection: (bool, optional). Defaults to None.
2699
+ Determine whether to ignore the result of model introspection or not.
2700
+ If set to True, the save will ignore all model introspection errors.
2701
+ wait_for_completion : (bool, optional). Defaults to True.
2702
+ Flag set for whether to wait for deployment to complete before proceeding.
2703
+ deployment_display_name: (str, optional). Defaults to None.
2704
+ The name of the model deployment. If a deployment_display_name is not provided in kwargs,
2705
+ a randomly generated easy to remember name with timestamp will be generated,
2706
+ like 'strange-spider-2022-08-17-23:55.02'.
2707
+ description: (str, optional). Defaults to None.
2708
+ The description of the model.
2709
+ deployment_instance_shape: (str, optional). Default to `VM.Standard2.1`.
2710
+ The shape of the instance used for deployment.
2711
+ deployment_instance_subnet_id: (str, optional). Default to None.
2712
+ The subnet id of the instance used for deployment.
2713
+ deployment_instance_private_endpoint_id: (str, optional). Default to None.
2714
+ The private endpoint id of instance used for deployment.
2715
+ deployment_instance_count: (int, optional). Defaults to 1.
2716
+ The number of instance used for deployment.
2717
+ deployment_bandwidth_mbps: (int, optional). Defaults to 10.
2718
+ The bandwidth limit on the load balancer in Mbps.
2719
+ deployment_log_group_id: (str, optional). Defaults to None.
2720
+ The oci logging group id. The access log and predict log share the same log group.
2721
+ deployment_access_log_id: (str, optional). Defaults to None.
2722
+ The access log OCID for the access logs. https://docs.oracle.com/en-us/iaas/data-science/using/model_dep_using_logging.htm
2723
+ deployment_predict_log_id: (str, optional). Defaults to None.
2724
+ The predict log OCID for the predict logs. https://docs.oracle.com/en-us/iaas/data-science/using/model_dep_using_logging.htm
2725
+ deployment_memory_in_gbs: (float, optional). Defaults to None.
2726
+ Specifies the size of the memory of the model deployment instance in GBs.
2727
+ deployment_ocpus: (float, optional). Defaults to None.
2728
+ Specifies the ocpus count of the model deployment instance.
2729
+ deployment_image: (str, optional). Defaults to None.
2730
+ The OCIR path of docker container image. Required for deploying model on container runtime.
2731
+ bucket_uri: (str, optional). Defaults to None.
2732
+ The OCI Object Storage URI where model artifacts will be copied to.
2733
+ The `bucket_uri` is only necessary for downloading large artifacts with
2734
+ size is greater than 2GB. Example: `oci://<bucket_name>@<namespace>/prefix/`.
2735
+ overwrite_existing_artifact: (bool, optional). Defaults to `True`.
2736
+ Overwrite target bucket artifact if exists.
2737
+ remove_existing_artifact: (bool, optional). Defaults to `True`.
2738
+ Wether artifacts uploaded to object storage bucket need to be removed or not.
2739
+ model_version_set: (Union[str, ModelVersionSet], optional). Defaults to None.
2740
+ The Model version set OCID, or name, or `ModelVersionSet` instance.
2741
+ version_label: (str, optional). Defaults to None.
2742
+ The model version lebel.
2743
+ model_by_reference: (bool, optional)
2744
+ Whether model artifact is made available to Model Store by reference.
2745
+ kwargs:
2746
+ impute_values: (dict, optional).
2747
+ The dictionary where the key is the column index(or names is accepted
2748
+ for pandas dataframe) and the value is the impute value for the corresponding column.
2749
+ project_id: (str, optional).
2750
+ Project OCID. If not specified, the value will be taken either
2751
+ from the environment variables or model properties.
2752
+ compartment_id : (str, optional).
2753
+ Compartment OCID. If not specified, the value will be taken either
2754
+ from the environment variables or model properties.
2755
+ image_digest: (str, optional). Defaults to None.
2756
+ The digest of docker container image.
2757
+ cmd: (List, optional). Defaults to empty.
2758
+ The command line arguments for running docker container image.
2759
+ entrypoint: (List, optional). Defaults to empty.
2760
+ The entrypoint for running docker container image.
2761
+ server_port: (int, optional). Defaults to 8080.
2762
+ The server port for docker container image.
2763
+ health_check_port: (int, optional). Defaults to 8080.
2764
+ The health check port for docker container image.
2765
+ deployment_mode: (str, optional). Defaults to HTTPS_ONLY.
2766
+ The deployment mode. Allowed values are: HTTPS_ONLY and STREAM_ONLY.
2767
+ input_stream_ids: (List, optional). Defaults to empty.
2768
+ The input stream ids. Required for STREAM_ONLY mode.
2769
+ output_stream_ids: (List, optional). Defaults to empty.
2770
+ The output stream ids. Required for STREAM_ONLY mode.
2771
+ environment_variables: (Dict, optional). Defaults to empty.
2772
+ The environment variables for model deployment.
2773
+ timeout: (int, optional). Defaults to 10 seconds.
2774
+ The connection timeout in seconds for the client.
2775
+ max_wait_time : (int, optional). Defaults to 1200 seconds.
2776
+ Maximum amount of time to wait in seconds.
2777
+ Negative implies infinite wait time.
2778
+ poll_interval : (int, optional). Defaults to 10 seconds.
2779
+ Poll interval in seconds.
2780
+ freeform_tags: (Dict[str, str], optional). Defaults to None.
2781
+ Freeform tags of the model deployment.
2782
+ defined_tags: (Dict[str, dict[str, object]], optional). Defaults to None.
2783
+ Defined tags of the model deployment.
2784
+ region: (str, optional). Defaults to `None`.
2785
+ The destination Object Storage bucket region.
2786
+ By default the value will be extracted from the `OCI_REGION_METADATA` environment variables.
2787
+
2788
+ Also can be any keyword argument for initializing the
2789
+ `ads.model.deployment.ModelDeploymentProperties`.
2790
+ See `ads.model.deployment.ModelDeploymentProperties()` for details.
2791
+
2792
+ Returns
2793
+ -------
2794
+ ModelDeployment
2795
+ The ModelDeployment instance.
2796
+
2797
+ Raises
2798
+ ------
2799
+ FileExistsError
2800
+ If files already exist but `force_overwrite` is False.
2801
+ ValueError
2802
+ If `inference_python_version` is not provided,
2803
+ but also cannot be found through manifest file.
2804
+ """
2805
+ locals_dict = _extract_locals(locals())
2806
+ locals_dict.pop("training_id", None)
2807
+ self.properties.with_dict(locals_dict)
2808
+
2809
+ self.prepare(
2810
+ inference_conda_env=self.properties.inference_conda_env,
2811
+ inference_python_version=self.properties.inference_python_version,
2812
+ training_conda_env=self.properties.training_conda_env,
2813
+ training_python_version=self.properties.training_python_version,
2814
+ model_file_name=model_file_name,
2815
+ as_onnx=as_onnx,
2816
+ initial_types=initial_types,
2817
+ force_overwrite=force_overwrite,
2818
+ namespace=namespace,
2819
+ use_case_type=use_case_type,
2820
+ X_sample=X_sample,
2821
+ y_sample=y_sample,
2822
+ training_script_path=self.properties.training_script_path,
2823
+ training_id=self.properties.training_id,
2824
+ ignore_pending_changes=ignore_pending_changes,
2825
+ max_col_num=max_col_num,
2826
+ ignore_conda_error=ignore_conda_error,
2827
+ impute_values=kwargs.pop("impute_values", None),
2828
+ )
2829
+ # Set default model_display_name if not specified - randomly generated easy to remember name generated
2830
+ if not model_display_name:
2831
+ model_display_name = utils.get_random_name_for_resource()
2832
+
2833
+ self.save(
2834
+ display_name=model_display_name,
2835
+ description=model_description,
2836
+ freeform_tags=model_freeform_tags,
2837
+ defined_tags=model_defined_tags,
2838
+ ignore_introspection=ignore_introspection,
2839
+ compartment_id=self.properties.compartment_id,
2840
+ project_id=self.properties.project_id,
2841
+ timeout=kwargs.pop("timeout", None),
2842
+ bucket_uri=bucket_uri,
2843
+ overwrite_existing_artifact=overwrite_existing_artifact,
2844
+ remove_existing_artifact=remove_existing_artifact,
2845
+ model_version_set=model_version_set,
2846
+ version_label=version_label,
2847
+ region=kwargs.pop("region", None),
2848
+ model_by_reference=model_by_reference,
2849
+ )
2850
+ # Set default deployment_display_name if not specified - randomly generated easy to remember name generated
2851
+ if not deployment_display_name:
2852
+ deployment_display_name = utils.get_random_name_for_resource()
2853
+
2854
+ self.deploy(
2855
+ wait_for_completion=wait_for_completion,
2856
+ display_name=deployment_display_name,
2857
+ description=deployment_description,
2858
+ deployment_instance_shape=self.properties.deployment_instance_shape,
2859
+ deployment_instance_subnet_id=self.properties.deployment_instance_subnet_id,
2860
+ deployment_instance_private_endpoint_id=self.properties.deployment_instance_private_endpoint_id,
2861
+ deployment_instance_count=self.properties.deployment_instance_count,
2862
+ deployment_bandwidth_mbps=self.properties.deployment_bandwidth_mbps,
2863
+ deployment_log_group_id=self.properties.deployment_log_group_id,
2864
+ deployment_access_log_id=self.properties.deployment_access_log_id,
2865
+ deployment_predict_log_id=self.properties.deployment_predict_log_id,
2866
+ deployment_memory_in_gbs=self.properties.deployment_memory_in_gbs,
2867
+ deployment_ocpus=self.properties.deployment_ocpus,
2868
+ deployment_image=deployment_image,
2869
+ kwargs=kwargs,
2870
+ )
2871
+ return self.model_deployment
2872
+
2873
+ def predict(
2874
+ self,
2875
+ data: Any = None,
2876
+ auto_serialize_data: bool = False,
2877
+ local: bool = False,
2878
+ **kwargs,
2879
+ ) -> Dict[str, Any]:
2880
+ """Returns prediction of input data run against the model deployment endpoint.
2881
+
2882
+ Examples
2883
+ --------
2884
+ >>> uri = "https://github.com/pytorch/hub/raw/master/images/dog.jpg"
2885
+ >>> prediction = model.predict(image=uri)['prediction']
2886
+
2887
+ >>> # examples on storage options
2888
+ >>> prediction = model.predict(
2889
+ ... image="oci://<bucket>@<tenancy>/myimage.png",
2890
+ ... storage_options=ads.auth.default_signer()
2891
+ ... )['prediction']
2892
+
2893
+ Parameters
2894
+ ----------
2895
+ data: Any
2896
+ Data for the prediction for onnx models, for local serialization
2897
+ method, data can be the data types that each framework support.
2898
+ auto_serialize_data: bool.
2899
+ Whether to auto serialize input data. Defauls to `False` for GenericModel, and `True` for other frameworks.
2900
+ `data` required to be json serializable if `auto_serialize_data=False`.
2901
+ If `auto_serialize_data` set to True, data will be serialized before sending to model deployment endpoint.
2902
+ local: bool.
2903
+ Whether to invoke the prediction locally. Default to False.
2904
+ kwargs:
2905
+ content_type: str, used to indicate the media type of the resource.
2906
+ image: PIL.Image Object or uri for the image.
2907
+ A valid string path for image file can be local path, http(s), oci, s3, gs.
2908
+ storage_options: dict
2909
+ Passed to `fsspec.open` for a particular storage connection.
2910
+ Please see `fsspec` (https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.open) for more details.
2911
+
2912
+ Returns
2913
+ -------
2914
+ Dict[str, Any]
2915
+ Dictionary with the predicted values.
2916
+
2917
+ Raises
2918
+ ------
2919
+ NotActiveDeploymentError
2920
+ If model deployment process was not started or not finished yet.
2921
+ ValueError
2922
+ If model is not deployed yet or the endpoint information is not available.
2923
+ """
2924
+ if local:
2925
+ return self.verify(
2926
+ data=data, auto_serialize_data=auto_serialize_data, **kwargs
2927
+ )
2928
+
2929
+ if not (self.model_deployment and self.model_deployment.url):
2930
+ raise ValueError(
2931
+ "Error invoking the remote endpoint as the model is not "
2932
+ "deployed yet or the endpoint information is not available. "
2933
+ "Use `deploy()` method to start model deployment. "
2934
+ "If you intend to invoke inference using locally available "
2935
+ "model artifact, set parameter `local=True`"
2936
+ )
2937
+
2938
+ current_state = self.model_deployment.state.name.upper()
2939
+ if current_state != ModelDeploymentState.ACTIVE.name:
2940
+ raise NotActiveDeploymentError(current_state)
2941
+
2942
+ data = self._handle_input_data(data, auto_serialize_data, **kwargs)
2943
+ prediction = self.model_deployment.predict(
2944
+ data=data,
2945
+ serializer=self.get_data_serializer(),
2946
+ **kwargs,
2947
+ )
2948
+
2949
+ self.update_summary_status(
2950
+ detail=PREDICT_STATUS_CALL_ENDPOINT_DETAIL, status=ModelState.DONE.value
2951
+ )
2952
+ return prediction
2953
+
2954
+ def summary_status(self) -> pd.DataFrame:
2955
+ """A summary table of the current status.
2956
+
2957
+ Returns
2958
+ -------
2959
+ pd.DataFrame
2960
+ The summary stable of the current status.
2961
+ """
2962
+ if (
2963
+ not self.ignore_conda_error
2964
+ and self.model_file_name
2965
+ and not os.path.exists(
2966
+ os.path.join(self.artifact_dir, self.model_file_name)
2967
+ )
2968
+ ):
2969
+ self.update_summary_action(
2970
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
2971
+ action=f"Model is not automatically serialized. Serialize the model as `{self.model_file_name}` and save to the {self.artifact_dir}.",
2972
+ )
2973
+ self.update_summary_status(
2974
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
2975
+ status=ModelState.NEEDSACTION.value,
2976
+ )
2977
+ else:
2978
+ self.update_summary_action(
2979
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL, action=""
2980
+ )
2981
+ if (
2982
+ ModelState.NEEDSACTION.value
2983
+ in self._summary_status.df.loc[
2984
+ self._summary_status.df["Details"]
2985
+ == PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
2986
+ "Status",
2987
+ ].values
2988
+ ):
2989
+ self.update_summary_status(
2990
+ detail=PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
2991
+ status=ModelState.DONE.value,
2992
+ )
2993
+ if (
2994
+ self._summary_status.df.loc[
2995
+ self._summary_status.df["Details"] == PREPARE_STATUS_GEN_SCORE_DETAIL,
2996
+ "Actions Needed",
2997
+ ].values
2998
+ != ""
2999
+ ):
3000
+ try:
3001
+ self.model_artifact.reload()
3002
+ self.update_summary_action(
3003
+ detail=PREPARE_STATUS_GEN_SCORE_DETAIL, action=""
3004
+ )
3005
+ except:
3006
+ pass
3007
+
3008
+ if self.model_deployment:
3009
+ self.update_summary_status(
3010
+ detail=DEPLOY_STATUS_DETAIL,
3011
+ status=self.model_deployment.state.name.upper(),
3012
+ )
3013
+
3014
+ if self.model_deployment.state == ModelDeploymentState.ACTIVE:
3015
+ self.update_summary_status(
3016
+ detail=PREDICT_STATUS_CALL_ENDPOINT_DETAIL,
3017
+ status=ModelState.AVAILABLE.value,
3018
+ )
3019
+ elif (
3020
+ self.model_deployment.state
3021
+ and self.model_deployment.state != ModelDeploymentState.ACTIVE
3022
+ ):
3023
+ self.update_summary_status(
3024
+ detail=PREDICT_STATUS_CALL_ENDPOINT_DETAIL,
3025
+ status=ModelState.NOTAVAILABLE.value,
3026
+ )
3027
+
3028
+ return self._summary_status.df.set_index(["Step", "Status", "Details"])
3029
+
3030
+ def update_summary_status(self, detail: str, status: str):
3031
+ """Update the status in the summary table.
3032
+
3033
+ Parameters
3034
+ ----------
3035
+ detail: (str)
3036
+ value of the detail in the details column of the summary status table. Used to locate which row to update.
3037
+ status: (str)
3038
+ new status to be updated for the row specified by detail.
3039
+
3040
+
3041
+ Returns
3042
+ -------
3043
+ None
3044
+ """
3045
+ self._summary_status.update_status(detail=detail, status=status)
3046
+
3047
+ def update_summary_action(self, detail: str, action: str):
3048
+ """Update the actions needed from the user in the summary table.
3049
+
3050
+ Parameters
3051
+ ----------
3052
+ detail: (str)
3053
+ value of the detail in the details column of the summary status table. Used to locate which row to update.
3054
+ action: (str)
3055
+ new action to be updated for the row specified by detail.
3056
+
3057
+ Returns
3058
+ -------
3059
+ None
3060
+ """
3061
+ self._summary_status.update_action(detail=detail, action=action)
3062
+
3063
+ def delete_deployment(self, wait_for_completion: bool = True) -> None:
3064
+ """Deletes the current deployment.
3065
+
3066
+ Parameters
3067
+ ----------
3068
+ wait_for_completion: (bool, optional). Defaults to `True`.
3069
+ Whether to wait till completion.
3070
+
3071
+ Returns
3072
+ -------
3073
+ None
3074
+
3075
+ Raises
3076
+ ------
3077
+ ValueError: if there is not deployment attached yet.
3078
+ """
3079
+ if not self.model_deployment:
3080
+ raise ValueError("Use `deploy()` method to start model deployment.")
3081
+ self.model_deployment.delete(wait_for_completion=wait_for_completion)
3082
+
3083
+ def restart_deployment(
3084
+ self,
3085
+ max_wait_time: int = DEFAULT_WAIT_TIME,
3086
+ poll_interval: int = DEFAULT_POLL_INTERVAL,
3087
+ ) -> "ModelDeployment":
3088
+ """Restarts the current deployment.
3089
+
3090
+ Parameters
3091
+ ----------
3092
+ max_wait_time : (int, optional). Defaults to 1200 seconds.
3093
+ Maximum amount of time to wait for activate or deactivate in seconds.
3094
+ Total amount of time to wait for restart deployment is twice as the value.
3095
+ Negative implies infinite wait time.
3096
+ poll_interval : (int, optional). Defaults to 10 seconds.
3097
+ Poll interval in seconds.
3098
+
3099
+ Returns
3100
+ -------
3101
+ ModelDeployment
3102
+ The ModelDeployment instance.
3103
+ """
3104
+ if not self.model_deployment:
3105
+ raise ValueError("Use `deploy()` method to start model deployment.")
3106
+ logger.info(
3107
+ f"Deactivating model deployment {self.model_deployment.model_deployment_id}."
3108
+ )
3109
+ self.model_deployment.deactivate(
3110
+ max_wait_time=max_wait_time, poll_interval=poll_interval
3111
+ )
3112
+ logger.info(
3113
+ f"Model deployment {self.model_deployment.model_deployment_id} has successfully been deactivated."
3114
+ )
3115
+ logger.info(
3116
+ f"Activating model deployment {self.model_deployment.model_deployment_id}."
3117
+ )
3118
+ self.model_deployment.activate(
3119
+ max_wait_time=max_wait_time, poll_interval=poll_interval
3120
+ )
3121
+ logger.info(
3122
+ f"Model deployment {self.model_deployment.model_deployment_id} has successfully been activated."
3123
+ )
3124
+ return self.model_deployment
3125
+
3126
+ @class_or_instance_method
3127
+ def delete(
3128
+ cls,
3129
+ model_id: Optional[str] = None,
3130
+ delete_associated_model_deployment: Optional[bool] = False,
3131
+ delete_model_artifact: Optional[bool] = False,
3132
+ artifact_dir: Optional[str] = None,
3133
+ **kwargs: Dict,
3134
+ ) -> None:
3135
+ """
3136
+ Deletes a model from Model Catalog.
3137
+
3138
+ Parameters
3139
+ ----------
3140
+ model_id: (str, optional). Defaults to None.
3141
+ The model OCID to be deleted.
3142
+ If the method called on instance level, then `self.model_id` will be used.
3143
+ delete_associated_model_deployment: (bool, optional). Defaults to `False`.
3144
+ Whether associated model deployments need to be deleted or not.
3145
+ delete_model_artifact: (bool, optional). Defaults to `False`.
3146
+ Whether associated model artifacts need to be deleted or not.
3147
+ artifact_dir: (str, optional). Defaults to `None`
3148
+ The local path to the model artifacts folder.
3149
+ If the method called on instance level,
3150
+ the `self.artifact_dir` will be used by default.
3151
+
3152
+ Returns
3153
+ -------
3154
+ None
3155
+
3156
+ Raises
3157
+ ------
3158
+ ValueError
3159
+ If `model_id` not provided.
3160
+ """
3161
+ if not inspect.isclass(cls):
3162
+ model_id = model_id or cls.model_id
3163
+ artifact_dir = artifact_dir or cls.artifact_dir
3164
+
3165
+ if not model_id:
3166
+ raise ValueError("The `model_id` must be provided.")
3167
+ if delete_model_artifact and not artifact_dir:
3168
+ raise ValueError("The `artifact_dir` must be provided.")
3169
+
3170
+ DataScienceModel.from_id(model_id).delete(
3171
+ delete_associated_model_deployment=delete_associated_model_deployment
3172
+ )
3173
+
3174
+ if delete_model_artifact:
3175
+ shutil.rmtree(artifact_dir, ignore_errors=True)
3176
+
3177
+ def upload_artifact(
3178
+ self,
3179
+ uri: str,
3180
+ auth: Optional[Dict] = None,
3181
+ force_overwrite: Optional[bool] = False,
3182
+ parallel_process_count: int = utils.DEFAULT_PARALLEL_PROCESS_COUNT,
3183
+ ) -> None:
3184
+ """Uploads model artifacts to the provided `uri`.
3185
+ The artifacts will be zipped before uploading.
3186
+
3187
+ Parameters
3188
+ ----------
3189
+ uri: str
3190
+ The destination location for the model artifacts, which can be a local path or
3191
+ OCI object storage URI. Examples:
3192
+
3193
+ >>> upload_artifact(uri="/some/local/folder/")
3194
+ >>> upload_artifact(uri="oci://bucket@namespace/prefix/")
3195
+
3196
+ auth: (Dict, optional). Defaults to `None`.
3197
+ The default authetication is set using `ads.set_auth` API. If you need to override the
3198
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
3199
+ authentication signer and kwargs required to instantiate IdentityClient object.
3200
+ force_overwrite: bool
3201
+ Overwrite target_dir if exists.
3202
+ parallel_process_count: (int, optional)
3203
+ The number of worker processes to use in parallel for uploading individual parts of a multipart upload.
3204
+ """
3205
+ if not uri:
3206
+ raise ValueError("The `uri` must be provided.")
3207
+
3208
+ if not self.artifact_dir:
3209
+ raise ValueError(
3210
+ "The model artifacts not found. "
3211
+ "Use `prepare()` method to prepare model artifacts."
3212
+ )
3213
+
3214
+ if not os.path.basename(uri) and self.model_id:
3215
+ uri = os.path.join(uri, f"{self.model_id}.zip")
3216
+
3217
+ tmp_artifact_zip_path = None
3218
+ progressbar_description = f"Uploading an artifact ZIP archive to {uri}."
3219
+ try:
3220
+ # Zip artifacts
3221
+ tmp_artifact_zip_path = zip_artifact(self.artifact_dir)
3222
+ # Upload artifacts to the provided destination
3223
+ if ObjectStorageDetails.is_oci_path(
3224
+ uri
3225
+ ) and ObjectStorageDetails.is_valid_uri(uri):
3226
+ utils.upload_to_os(
3227
+ src_uri=tmp_artifact_zip_path,
3228
+ dst_uri=uri,
3229
+ auth=auth,
3230
+ parallel_process_count=parallel_process_count,
3231
+ progressbar_description=progressbar_description,
3232
+ )
3233
+ else:
3234
+ utils.copy_file(
3235
+ uri_src=tmp_artifact_zip_path,
3236
+ uri_dst=uri,
3237
+ auth=auth,
3238
+ force_overwrite=force_overwrite,
3239
+ progressbar_description=progressbar_description,
3240
+ )
3241
+ except Exception as ex:
3242
+ raise RuntimeError(
3243
+ f"Failed to upload model artifact to the given Object Storage path `{uri}`."
3244
+ f"See Exception: {ex}"
3245
+ )
3246
+ finally:
3247
+ if tmp_artifact_zip_path:
3248
+ os.remove(tmp_artifact_zip_path)
3249
+
3250
+ def update(self, **kwargs) -> "GenericModel":
3251
+ """Updates model metadata in the Model Catalog.
3252
+ Updates only metadata information. The model artifacts are immutable and cannot be updated.
3253
+
3254
+ Parameters
3255
+ ----------
3256
+ kwargs
3257
+ display_name: (str, optional). Defaults to None.
3258
+ The name of the model.
3259
+ description: (str, optional). Defaults to None.
3260
+ The description of the model.
3261
+ freeform_tags : Dict(str, str), Defaults to None.
3262
+ Freeform tags for the model.
3263
+ defined_tags : (Dict(str, dict(str, object)), optional). Defaults to None.
3264
+ Defined tags for the model.
3265
+ version_label: (str, optional). Defaults to None.
3266
+ The model version lebel.
3267
+
3268
+ Additional kwargs arguments.
3269
+ Can be any attribute that `oci.data_science.models.Model` accepts.
3270
+
3271
+ Returns
3272
+ -------
3273
+ GenericModel
3274
+ An instance of `GenericModel` (self).
3275
+
3276
+ Raises
3277
+ ------
3278
+ ValueError
3279
+ if model not saved to the Model Catalog.
3280
+ """
3281
+ if not self.model_id:
3282
+ raise ValueError(
3283
+ "Use `save()` method to save a model to the Model Catalog."
3284
+ )
3285
+
3286
+ self.dsc_model = (
3287
+ self.dsc_model.with_display_name(
3288
+ kwargs.pop("display_name", self.dsc_model.display_name)
3289
+ )
3290
+ .with_description(kwargs.pop("description", self.dsc_model.description))
3291
+ .with_freeform_tags(
3292
+ **(
3293
+ kwargs.pop("freeform_tags", self.dsc_model.freeform_tags or {})
3294
+ or {}
3295
+ )
3296
+ )
3297
+ .with_defined_tags(
3298
+ **(kwargs.pop("defined_tags", self.dsc_model.defined_tags or {}) or {})
3299
+ )
3300
+ .with_version_label(
3301
+ kwargs.pop("version_label", self.dsc_model.version_label)
3302
+ )
3303
+ .update(**kwargs)
3304
+ )
3305
+
3306
+ return self
3307
+
3308
+
3309
+ class ModelState(Enum):
3310
+ DONE = "Done"
3311
+ AVAILABLE = "Available"
3312
+ NOTAVAILABLE = "Not Available"
3313
+ NEEDSACTION = "Needs Action"
3314
+ NOTAPPLICABLE = "Not Applicable"
3315
+
3316
+
3317
+ class SummaryStatus:
3318
+ """SummaryStatus class which track the status of the Model frameworks."""
3319
+
3320
+ def __init__(self):
3321
+ summary_data = [
3322
+ [INITIATE_STATUS_NAME, INITIATE_STATUS_DETAIL, ModelState.DONE.value, ""],
3323
+ [
3324
+ PREPARE_STATUS_NAME,
3325
+ PREPARE_STATUS_GEN_RUNTIME_DETAIL,
3326
+ ModelState.AVAILABLE.value,
3327
+ "",
3328
+ ],
3329
+ [
3330
+ PREPARE_STATUS_NAME,
3331
+ PREPARE_STATUS_GEN_SCORE_DETAIL,
3332
+ ModelState.AVAILABLE.value,
3333
+ "",
3334
+ ],
3335
+ [
3336
+ PREPARE_STATUS_NAME,
3337
+ PREPARE_STATUS_SERIALIZE_MODEL_DETAIL,
3338
+ ModelState.AVAILABLE.value,
3339
+ "",
3340
+ ],
3341
+ [
3342
+ PREPARE_STATUS_NAME,
3343
+ PREPARE_STATUS_POPULATE_METADATA_DETAIL,
3344
+ ModelState.AVAILABLE.value,
3345
+ "",
3346
+ ],
3347
+ [
3348
+ VERIFY_STATUS_NAME,
3349
+ VERIFY_STATUS_LOCAL_TEST_DETAIL,
3350
+ ModelState.NOTAVAILABLE.value,
3351
+ "",
3352
+ ],
3353
+ [
3354
+ SAVE_STATUS_NAME,
3355
+ SAVE_STATUS_INTROSPECT_TEST_DETAIL,
3356
+ ModelState.NOTAVAILABLE.value,
3357
+ "",
3358
+ ],
3359
+ [
3360
+ SAVE_STATUS_NAME,
3361
+ SAVE_STATUS_UPLOAD_ARTIFACT_DETAIL,
3362
+ ModelState.NOTAVAILABLE.value,
3363
+ "",
3364
+ ],
3365
+ [
3366
+ DEPLOY_STATUS_NAME,
3367
+ DEPLOY_STATUS_DETAIL,
3368
+ ModelState.NOTAVAILABLE.value,
3369
+ "",
3370
+ ],
3371
+ [
3372
+ PREDICT_STATUS_NAME,
3373
+ PREDICT_STATUS_CALL_ENDPOINT_DETAIL,
3374
+ ModelState.NOTAVAILABLE.value,
3375
+ "",
3376
+ ],
3377
+ ]
3378
+ self.df = pd.DataFrame(
3379
+ summary_data, columns=["Step", "Details", "Status", "Actions Needed"]
3380
+ )
3381
+
3382
+ def update_status(self, detail: str, status: str) -> None:
3383
+ """Updates the status of the summary status table of the corresponding detail.
3384
+
3385
+ Parameters
3386
+ ----------
3387
+ detail: (str)
3388
+ value of the detail in the Details column. Used to locate which row to update.
3389
+ status: (str)
3390
+ new status to be updated for the row specified by detail.
3391
+
3392
+ Returns
3393
+ -------
3394
+ None
3395
+ Nothing.
3396
+ """
3397
+ self.df.loc[self.df["Details"] == detail, "Status"] = status
3398
+
3399
+ def update_action(self, detail: str, action: str) -> None:
3400
+ """Updates the action of the summary status table of the corresponding detail.
3401
+
3402
+ Parameters
3403
+ ----------
3404
+ detail: (str)
3405
+ Value of the detail in the Details column. Used to locate which row to update.
3406
+ action: (str)
3407
+ new action to be updated for the row specified by detail.
3408
+
3409
+ Returns
3410
+ -------
3411
+ None
3412
+ Nothing.
3413
+ """
3414
+ self.df.loc[
3415
+ self.df["Details"] == detail,
3416
+ "Actions Needed",
3417
+ ] = action
3418
+
3419
+
3420
+ class FrameworkSpecificModel(GenericModel):
3421
+ def verify(
3422
+ self,
3423
+ data: Any = None,
3424
+ reload_artifacts: bool = True,
3425
+ auto_serialize_data: bool = True,
3426
+ **kwargs,
3427
+ ) -> Dict[str, Any]:
3428
+ """Test if deployment works in local environment.
3429
+
3430
+ Examples
3431
+ --------
3432
+ >>> uri = "https://github.com/pytorch/hub/raw/master/images/dog.jpg"
3433
+ >>> prediction = model.verify(image=uri)['prediction']
3434
+
3435
+ >>> # examples on storage options
3436
+ >>> prediction = model.verify(
3437
+ ... image="oci://<bucket>@<tenancy>/myimage.png",
3438
+ ... storage_options=ads.auth.default_signer()
3439
+ ... )['prediction']
3440
+
3441
+ Parameters
3442
+ ----------
3443
+ data: Any
3444
+ Data used to test if deployment works in local environment.
3445
+ reload_artifacts: bool. Defaults to True.
3446
+ Whether to reload artifacts or not.
3447
+ auto_serialize_data: bool.
3448
+ Whether to auto serialize input data. Defauls to `False` for GenericModel, and `True` for other frameworks.
3449
+ `data` required to be json serializable if `auto_serialize_data=False`.
3450
+ if `auto_serialize_data` set to True, data will be serialized before sending to model deployment endpoint.
3451
+ kwargs:
3452
+ content_type: str, used to indicate the media type of the resource.
3453
+ image: PIL.Image Object or uri for the image.
3454
+ A valid string path for image file can be local path, http(s), oci, s3, gs.
3455
+ storage_options: dict
3456
+ Passed to `fsspec.open` for a particular storage connection.
3457
+ Please see `fsspec` (https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.open) for more details.
3458
+
3459
+ Returns
3460
+ -------
3461
+ Dict
3462
+ A dictionary which contains prediction results.
3463
+ """
3464
+ return super().verify(
3465
+ data=data,
3466
+ reload_artifacts=reload_artifacts,
3467
+ auto_serialize_data=auto_serialize_data,
3468
+ **kwargs,
3469
+ )
3470
+
3471
+ def predict(
3472
+ self, data: Any = None, auto_serialize_data: bool = True, **kwargs
3473
+ ) -> Dict[str, Any]:
3474
+ """Returns prediction of input data run against the model deployment endpoint.
3475
+
3476
+ Examples
3477
+ --------
3478
+ >>> uri = "https://github.com/pytorch/hub/raw/master/images/dog.jpg"
3479
+ >>> prediction = model.predict(image=uri)['prediction']
3480
+
3481
+ >>> # examples on storage options
3482
+ >>> prediction = model.predict(
3483
+ ... image="oci://<bucket>@<tenancy>/myimage.png",
3484
+ ... storage_options=ads.auth.default_signer()
3485
+ ... )['prediction']
3486
+
3487
+ Parameters
3488
+ ----------
3489
+ data: Any
3490
+ Data for the prediction for onnx models, for local serialization
3491
+ method, data can be the data types that each framework support.
3492
+ auto_serialize_data: bool.
3493
+ Whether to auto serialize input data. Defauls to `False` for GenericModel, and `True` for other frameworks.
3494
+ `data` required to be json serializable if `auto_serialize_data=False`.
3495
+ If `auto_serialize_data` set to True, data will be serialized before sending to model deployment endpoint.
3496
+ kwargs:
3497
+ content_type: str, used to indicate the media type of the resource.
3498
+ image: PIL.Image Object or uri for the image.
3499
+ A valid string path for image file can be local path, http(s), oci, s3, gs.
3500
+ storage_options: dict
3501
+ Passed to `fsspec.open` for a particular storage connection.
3502
+ Please see `fsspec` (https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.open) for more details.
3503
+
3504
+ Returns
3505
+ -------
3506
+ Dict[str, Any]
3507
+ Dictionary with the predicted values.
3508
+
3509
+ Raises
3510
+ ------
3511
+ NotActiveDeploymentError
3512
+ If model deployment process was not started or not finished yet.
3513
+ ValueError
3514
+ If `data` is empty or not JSON serializable.
3515
+ """
3516
+ return super().predict(
3517
+ data=data, auto_serialize_data=auto_serialize_data, **kwargs
3518
+ )