oracle-ads 2.13.9rc0__py3-none-any.whl → 2.13.10__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 (858) hide show
  1. ads/aqua/__init__.py +40 -0
  2. ads/aqua/app.py +507 -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 +274 -0
  10. ads/aqua/common/enums.py +134 -0
  11. ads/aqua/common/errors.py +109 -0
  12. ads/aqua/common/utils.py +1295 -0
  13. ads/aqua/config/__init__.py +4 -0
  14. ads/aqua/config/container_config.py +246 -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 +381 -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 +300 -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 +2134 -0
  57. ads/aqua/model/utils.py +52 -0
  58. ads/aqua/modeldeployment/__init__.py +6 -0
  59. ads/aqua/modeldeployment/constants.py +10 -0
  60. ads/aqua/modeldeployment/deployment.py +1315 -0
  61. ads/aqua/modeldeployment/entities.py +653 -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 +519 -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 +179 -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/config.py +1 -0
  120. ads/data_labeling/__init__.py +13 -0
  121. ads/data_labeling/boundingbox.py +253 -0
  122. ads/data_labeling/constants.py +47 -0
  123. ads/data_labeling/data_labeling_service.py +244 -0
  124. ads/data_labeling/interface/__init__.py +5 -0
  125. ads/data_labeling/interface/loader.py +16 -0
  126. ads/data_labeling/interface/parser.py +16 -0
  127. ads/data_labeling/interface/reader.py +23 -0
  128. ads/data_labeling/loader/__init__.py +5 -0
  129. ads/data_labeling/loader/file_loader.py +241 -0
  130. ads/data_labeling/metadata.py +110 -0
  131. ads/data_labeling/mixin/__init__.py +5 -0
  132. ads/data_labeling/mixin/data_labeling.py +232 -0
  133. ads/data_labeling/ner.py +129 -0
  134. ads/data_labeling/parser/__init__.py +5 -0
  135. ads/data_labeling/parser/dls_record_parser.py +388 -0
  136. ads/data_labeling/parser/export_metadata_parser.py +94 -0
  137. ads/data_labeling/parser/export_record_parser.py +473 -0
  138. ads/data_labeling/reader/__init__.py +5 -0
  139. ads/data_labeling/reader/dataset_reader.py +574 -0
  140. ads/data_labeling/reader/dls_record_reader.py +121 -0
  141. ads/data_labeling/reader/export_record_reader.py +62 -0
  142. ads/data_labeling/reader/jsonl_reader.py +75 -0
  143. ads/data_labeling/reader/metadata_reader.py +203 -0
  144. ads/data_labeling/reader/record_reader.py +263 -0
  145. ads/data_labeling/record.py +52 -0
  146. ads/data_labeling/visualizer/__init__.py +5 -0
  147. ads/data_labeling/visualizer/image_visualizer.py +525 -0
  148. ads/data_labeling/visualizer/text_visualizer.py +357 -0
  149. ads/database/__init__.py +5 -0
  150. ads/database/connection.py +338 -0
  151. ads/dataset/__init__.py +10 -0
  152. ads/dataset/capabilities.md +51 -0
  153. ads/dataset/classification_dataset.py +339 -0
  154. ads/dataset/correlation.py +226 -0
  155. ads/dataset/correlation_plot.py +563 -0
  156. ads/dataset/dask_series.py +173 -0
  157. ads/dataset/dataframe_transformer.py +110 -0
  158. ads/dataset/dataset.py +1979 -0
  159. ads/dataset/dataset_browser.py +360 -0
  160. ads/dataset/dataset_with_target.py +995 -0
  161. ads/dataset/exception.py +25 -0
  162. ads/dataset/factory.py +987 -0
  163. ads/dataset/feature_engineering_transformer.py +35 -0
  164. ads/dataset/feature_selection.py +107 -0
  165. ads/dataset/forecasting_dataset.py +26 -0
  166. ads/dataset/helper.py +1450 -0
  167. ads/dataset/label_encoder.py +99 -0
  168. ads/dataset/mixin/__init__.py +5 -0
  169. ads/dataset/mixin/dataset_accessor.py +134 -0
  170. ads/dataset/pipeline.py +58 -0
  171. ads/dataset/plot.py +710 -0
  172. ads/dataset/progress.py +86 -0
  173. ads/dataset/recommendation.py +297 -0
  174. ads/dataset/recommendation_transformer.py +502 -0
  175. ads/dataset/regression_dataset.py +14 -0
  176. ads/dataset/sampled_dataset.py +1050 -0
  177. ads/dataset/target.py +98 -0
  178. ads/dataset/timeseries.py +18 -0
  179. ads/dbmixin/__init__.py +5 -0
  180. ads/dbmixin/db_pandas_accessor.py +153 -0
  181. ads/environment/__init__.py +9 -0
  182. ads/environment/ml_runtime.py +66 -0
  183. ads/evaluations/README.md +14 -0
  184. ads/evaluations/__init__.py +109 -0
  185. ads/evaluations/evaluation_plot.py +983 -0
  186. ads/evaluations/evaluator.py +1334 -0
  187. ads/evaluations/statistical_metrics.py +543 -0
  188. ads/experiments/__init__.py +9 -0
  189. ads/experiments/capabilities.md +0 -0
  190. ads/explanations/__init__.py +21 -0
  191. ads/explanations/base_explainer.py +142 -0
  192. ads/explanations/capabilities.md +83 -0
  193. ads/explanations/explainer.py +190 -0
  194. ads/explanations/mlx_global_explainer.py +1050 -0
  195. ads/explanations/mlx_interface.py +386 -0
  196. ads/explanations/mlx_local_explainer.py +287 -0
  197. ads/explanations/mlx_whatif_explainer.py +201 -0
  198. ads/feature_engineering/__init__.py +20 -0
  199. ads/feature_engineering/accessor/__init__.py +5 -0
  200. ads/feature_engineering/accessor/dataframe_accessor.py +535 -0
  201. ads/feature_engineering/accessor/mixin/__init__.py +5 -0
  202. ads/feature_engineering/accessor/mixin/correlation.py +166 -0
  203. ads/feature_engineering/accessor/mixin/eda_mixin.py +266 -0
  204. ads/feature_engineering/accessor/mixin/eda_mixin_series.py +85 -0
  205. ads/feature_engineering/accessor/mixin/feature_types_mixin.py +211 -0
  206. ads/feature_engineering/accessor/mixin/utils.py +65 -0
  207. ads/feature_engineering/accessor/series_accessor.py +431 -0
  208. ads/feature_engineering/adsimage/__init__.py +5 -0
  209. ads/feature_engineering/adsimage/image.py +192 -0
  210. ads/feature_engineering/adsimage/image_reader.py +170 -0
  211. ads/feature_engineering/adsimage/interface/__init__.py +5 -0
  212. ads/feature_engineering/adsimage/interface/reader.py +19 -0
  213. ads/feature_engineering/adsstring/__init__.py +7 -0
  214. ads/feature_engineering/adsstring/oci_language/__init__.py +8 -0
  215. ads/feature_engineering/adsstring/string/__init__.py +8 -0
  216. ads/feature_engineering/data_schema.json +57 -0
  217. ads/feature_engineering/dataset/__init__.py +5 -0
  218. ads/feature_engineering/dataset/zip_code_data.py +42062 -0
  219. ads/feature_engineering/exceptions.py +40 -0
  220. ads/feature_engineering/feature_type/__init__.py +133 -0
  221. ads/feature_engineering/feature_type/address.py +184 -0
  222. ads/feature_engineering/feature_type/adsstring/__init__.py +5 -0
  223. ads/feature_engineering/feature_type/adsstring/common_regex_mixin.py +164 -0
  224. ads/feature_engineering/feature_type/adsstring/oci_language.py +93 -0
  225. ads/feature_engineering/feature_type/adsstring/parsers/__init__.py +5 -0
  226. ads/feature_engineering/feature_type/adsstring/parsers/base.py +47 -0
  227. ads/feature_engineering/feature_type/adsstring/parsers/nltk_parser.py +96 -0
  228. ads/feature_engineering/feature_type/adsstring/parsers/spacy_parser.py +221 -0
  229. ads/feature_engineering/feature_type/adsstring/string.py +258 -0
  230. ads/feature_engineering/feature_type/base.py +58 -0
  231. ads/feature_engineering/feature_type/boolean.py +183 -0
  232. ads/feature_engineering/feature_type/category.py +146 -0
  233. ads/feature_engineering/feature_type/constant.py +137 -0
  234. ads/feature_engineering/feature_type/continuous.py +151 -0
  235. ads/feature_engineering/feature_type/creditcard.py +314 -0
  236. ads/feature_engineering/feature_type/datetime.py +190 -0
  237. ads/feature_engineering/feature_type/discrete.py +134 -0
  238. ads/feature_engineering/feature_type/document.py +43 -0
  239. ads/feature_engineering/feature_type/gis.py +251 -0
  240. ads/feature_engineering/feature_type/handler/__init__.py +5 -0
  241. ads/feature_engineering/feature_type/handler/feature_validator.py +524 -0
  242. ads/feature_engineering/feature_type/handler/feature_warning.py +319 -0
  243. ads/feature_engineering/feature_type/handler/warnings.py +128 -0
  244. ads/feature_engineering/feature_type/integer.py +142 -0
  245. ads/feature_engineering/feature_type/ip_address.py +144 -0
  246. ads/feature_engineering/feature_type/ip_address_v4.py +138 -0
  247. ads/feature_engineering/feature_type/ip_address_v6.py +138 -0
  248. ads/feature_engineering/feature_type/lat_long.py +256 -0
  249. ads/feature_engineering/feature_type/object.py +43 -0
  250. ads/feature_engineering/feature_type/ordinal.py +132 -0
  251. ads/feature_engineering/feature_type/phone_number.py +135 -0
  252. ads/feature_engineering/feature_type/string.py +171 -0
  253. ads/feature_engineering/feature_type/text.py +93 -0
  254. ads/feature_engineering/feature_type/unknown.py +43 -0
  255. ads/feature_engineering/feature_type/zip_code.py +164 -0
  256. ads/feature_engineering/feature_type_manager.py +406 -0
  257. ads/feature_engineering/schema.py +795 -0
  258. ads/feature_engineering/utils.py +245 -0
  259. ads/feature_store/.readthedocs.yaml +19 -0
  260. ads/feature_store/README.md +65 -0
  261. ads/feature_store/__init__.py +9 -0
  262. ads/feature_store/common/__init__.py +0 -0
  263. ads/feature_store/common/enums.py +339 -0
  264. ads/feature_store/common/exceptions.py +18 -0
  265. ads/feature_store/common/spark_session_singleton.py +125 -0
  266. ads/feature_store/common/utils/__init__.py +0 -0
  267. ads/feature_store/common/utils/base64_encoder_decoder.py +72 -0
  268. ads/feature_store/common/utils/feature_schema_mapper.py +283 -0
  269. ads/feature_store/common/utils/transformation_utils.py +82 -0
  270. ads/feature_store/common/utils/utility.py +403 -0
  271. ads/feature_store/data_validation/__init__.py +0 -0
  272. ads/feature_store/data_validation/great_expectation.py +129 -0
  273. ads/feature_store/dataset.py +1230 -0
  274. ads/feature_store/dataset_job.py +530 -0
  275. ads/feature_store/docs/Dockerfile +7 -0
  276. ads/feature_store/docs/Makefile +44 -0
  277. ads/feature_store/docs/conf.py +28 -0
  278. ads/feature_store/docs/requirements.txt +14 -0
  279. ads/feature_store/docs/source/ads.feature_store.query.rst +20 -0
  280. ads/feature_store/docs/source/cicd.rst +137 -0
  281. ads/feature_store/docs/source/conf.py +86 -0
  282. ads/feature_store/docs/source/data_versioning.rst +33 -0
  283. ads/feature_store/docs/source/dataset.rst +388 -0
  284. ads/feature_store/docs/source/dataset_job.rst +27 -0
  285. ads/feature_store/docs/source/demo.rst +70 -0
  286. ads/feature_store/docs/source/entity.rst +78 -0
  287. ads/feature_store/docs/source/feature_group.rst +624 -0
  288. ads/feature_store/docs/source/feature_group_job.rst +29 -0
  289. ads/feature_store/docs/source/feature_store.rst +122 -0
  290. ads/feature_store/docs/source/feature_store_class.rst +123 -0
  291. ads/feature_store/docs/source/feature_validation.rst +66 -0
  292. ads/feature_store/docs/source/figures/cicd.png +0 -0
  293. ads/feature_store/docs/source/figures/data_validation.png +0 -0
  294. ads/feature_store/docs/source/figures/data_versioning.png +0 -0
  295. ads/feature_store/docs/source/figures/dataset.gif +0 -0
  296. ads/feature_store/docs/source/figures/dataset.png +0 -0
  297. ads/feature_store/docs/source/figures/dataset_lineage.png +0 -0
  298. ads/feature_store/docs/source/figures/dataset_statistics.png +0 -0
  299. ads/feature_store/docs/source/figures/dataset_statistics_viz.png +0 -0
  300. ads/feature_store/docs/source/figures/dataset_validation_results.png +0 -0
  301. ads/feature_store/docs/source/figures/dataset_validation_summary.png +0 -0
  302. ads/feature_store/docs/source/figures/drift_monitoring.png +0 -0
  303. ads/feature_store/docs/source/figures/entity.png +0 -0
  304. ads/feature_store/docs/source/figures/feature_group.png +0 -0
  305. ads/feature_store/docs/source/figures/feature_group_lineage.png +0 -0
  306. ads/feature_store/docs/source/figures/feature_group_statistics_viz.png +0 -0
  307. ads/feature_store/docs/source/figures/feature_store_deployment.png +0 -0
  308. ads/feature_store/docs/source/figures/feature_store_overview.png +0 -0
  309. ads/feature_store/docs/source/figures/featuregroup.gif +0 -0
  310. ads/feature_store/docs/source/figures/lineage_d1.png +0 -0
  311. ads/feature_store/docs/source/figures/lineage_d2.png +0 -0
  312. ads/feature_store/docs/source/figures/lineage_fg.png +0 -0
  313. ads/feature_store/docs/source/figures/logo-dark-mode.png +0 -0
  314. ads/feature_store/docs/source/figures/logo-light-mode.png +0 -0
  315. ads/feature_store/docs/source/figures/overview.png +0 -0
  316. ads/feature_store/docs/source/figures/resource_manager.png +0 -0
  317. ads/feature_store/docs/source/figures/resource_manager_feature_store_stack.png +0 -0
  318. ads/feature_store/docs/source/figures/resource_manager_home.png +0 -0
  319. ads/feature_store/docs/source/figures/stats_1.png +0 -0
  320. ads/feature_store/docs/source/figures/stats_2.png +0 -0
  321. ads/feature_store/docs/source/figures/stats_d.png +0 -0
  322. ads/feature_store/docs/source/figures/stats_fg.png +0 -0
  323. ads/feature_store/docs/source/figures/transformation.png +0 -0
  324. ads/feature_store/docs/source/figures/transformations.gif +0 -0
  325. ads/feature_store/docs/source/figures/validation.png +0 -0
  326. ads/feature_store/docs/source/figures/validation_fg.png +0 -0
  327. ads/feature_store/docs/source/figures/validation_results.png +0 -0
  328. ads/feature_store/docs/source/figures/validation_summary.png +0 -0
  329. ads/feature_store/docs/source/index.rst +81 -0
  330. ads/feature_store/docs/source/module.rst +8 -0
  331. ads/feature_store/docs/source/notebook.rst +94 -0
  332. ads/feature_store/docs/source/overview.rst +47 -0
  333. ads/feature_store/docs/source/quickstart.rst +176 -0
  334. ads/feature_store/docs/source/release_notes.rst +194 -0
  335. ads/feature_store/docs/source/setup_feature_store.rst +81 -0
  336. ads/feature_store/docs/source/statistics.rst +58 -0
  337. ads/feature_store/docs/source/transformation.rst +199 -0
  338. ads/feature_store/docs/source/ui.rst +65 -0
  339. ads/feature_store/docs/source/user_guides.setup.feature_store_operator.rst +66 -0
  340. ads/feature_store/docs/source/user_guides.setup.helm_chart.rst +192 -0
  341. ads/feature_store/docs/source/user_guides.setup.terraform.rst +338 -0
  342. ads/feature_store/entity.py +718 -0
  343. ads/feature_store/execution_strategy/__init__.py +0 -0
  344. ads/feature_store/execution_strategy/delta_lake/__init__.py +0 -0
  345. ads/feature_store/execution_strategy/delta_lake/delta_lake_service.py +375 -0
  346. ads/feature_store/execution_strategy/engine/__init__.py +0 -0
  347. ads/feature_store/execution_strategy/engine/spark_engine.py +316 -0
  348. ads/feature_store/execution_strategy/execution_strategy.py +113 -0
  349. ads/feature_store/execution_strategy/execution_strategy_provider.py +47 -0
  350. ads/feature_store/execution_strategy/spark/__init__.py +0 -0
  351. ads/feature_store/execution_strategy/spark/spark_execution.py +618 -0
  352. ads/feature_store/feature.py +192 -0
  353. ads/feature_store/feature_group.py +1494 -0
  354. ads/feature_store/feature_group_expectation.py +346 -0
  355. ads/feature_store/feature_group_job.py +602 -0
  356. ads/feature_store/feature_lineage/__init__.py +0 -0
  357. ads/feature_store/feature_lineage/graphviz_service.py +180 -0
  358. ads/feature_store/feature_option_details.py +50 -0
  359. ads/feature_store/feature_statistics/__init__.py +0 -0
  360. ads/feature_store/feature_statistics/statistics_service.py +99 -0
  361. ads/feature_store/feature_store.py +699 -0
  362. ads/feature_store/feature_store_registrar.py +518 -0
  363. ads/feature_store/input_feature_detail.py +149 -0
  364. ads/feature_store/mixin/__init__.py +4 -0
  365. ads/feature_store/mixin/oci_feature_store.py +145 -0
  366. ads/feature_store/model_details.py +73 -0
  367. ads/feature_store/query/__init__.py +0 -0
  368. ads/feature_store/query/filter.py +266 -0
  369. ads/feature_store/query/generator/__init__.py +0 -0
  370. ads/feature_store/query/generator/query_generator.py +298 -0
  371. ads/feature_store/query/join.py +161 -0
  372. ads/feature_store/query/query.py +403 -0
  373. ads/feature_store/query/validator/__init__.py +0 -0
  374. ads/feature_store/query/validator/query_validator.py +57 -0
  375. ads/feature_store/response/__init__.py +0 -0
  376. ads/feature_store/response/response_builder.py +68 -0
  377. ads/feature_store/service/__init__.py +0 -0
  378. ads/feature_store/service/oci_dataset.py +139 -0
  379. ads/feature_store/service/oci_dataset_job.py +199 -0
  380. ads/feature_store/service/oci_entity.py +125 -0
  381. ads/feature_store/service/oci_feature_group.py +164 -0
  382. ads/feature_store/service/oci_feature_group_job.py +214 -0
  383. ads/feature_store/service/oci_feature_store.py +182 -0
  384. ads/feature_store/service/oci_lineage.py +87 -0
  385. ads/feature_store/service/oci_transformation.py +104 -0
  386. ads/feature_store/statistics/__init__.py +0 -0
  387. ads/feature_store/statistics/abs_feature_value.py +49 -0
  388. ads/feature_store/statistics/charts/__init__.py +0 -0
  389. ads/feature_store/statistics/charts/abstract_feature_plot.py +37 -0
  390. ads/feature_store/statistics/charts/box_plot.py +148 -0
  391. ads/feature_store/statistics/charts/frequency_distribution.py +65 -0
  392. ads/feature_store/statistics/charts/probability_distribution.py +68 -0
  393. ads/feature_store/statistics/charts/top_k_frequent_elements.py +98 -0
  394. ads/feature_store/statistics/feature_stat.py +126 -0
  395. ads/feature_store/statistics/generic_feature_value.py +33 -0
  396. ads/feature_store/statistics/statistics.py +41 -0
  397. ads/feature_store/statistics_config.py +101 -0
  398. ads/feature_store/templates/feature_store_template.yaml +45 -0
  399. ads/feature_store/transformation.py +499 -0
  400. ads/feature_store/validation_output.py +57 -0
  401. ads/hpo/__init__.py +9 -0
  402. ads/hpo/_imports.py +91 -0
  403. ads/hpo/ads_search_space.py +439 -0
  404. ads/hpo/distributions.py +325 -0
  405. ads/hpo/objective.py +280 -0
  406. ads/hpo/search_cv.py +1657 -0
  407. ads/hpo/stopping_criterion.py +75 -0
  408. ads/hpo/tuner_artifact.py +413 -0
  409. ads/hpo/utils.py +91 -0
  410. ads/hpo/validation.py +140 -0
  411. ads/hpo/visualization/__init__.py +5 -0
  412. ads/hpo/visualization/_contour.py +23 -0
  413. ads/hpo/visualization/_edf.py +20 -0
  414. ads/hpo/visualization/_intermediate_values.py +21 -0
  415. ads/hpo/visualization/_optimization_history.py +25 -0
  416. ads/hpo/visualization/_parallel_coordinate.py +169 -0
  417. ads/hpo/visualization/_param_importances.py +26 -0
  418. ads/jobs/__init__.py +53 -0
  419. ads/jobs/ads_job.py +663 -0
  420. ads/jobs/builders/__init__.py +5 -0
  421. ads/jobs/builders/base.py +156 -0
  422. ads/jobs/builders/infrastructure/__init__.py +6 -0
  423. ads/jobs/builders/infrastructure/base.py +165 -0
  424. ads/jobs/builders/infrastructure/dataflow.py +1252 -0
  425. ads/jobs/builders/infrastructure/dsc_job.py +1894 -0
  426. ads/jobs/builders/infrastructure/dsc_job_runtime.py +1233 -0
  427. ads/jobs/builders/infrastructure/utils.py +65 -0
  428. ads/jobs/builders/runtimes/__init__.py +5 -0
  429. ads/jobs/builders/runtimes/artifact.py +338 -0
  430. ads/jobs/builders/runtimes/base.py +325 -0
  431. ads/jobs/builders/runtimes/container_runtime.py +242 -0
  432. ads/jobs/builders/runtimes/python_runtime.py +1016 -0
  433. ads/jobs/builders/runtimes/pytorch_runtime.py +204 -0
  434. ads/jobs/cli.py +104 -0
  435. ads/jobs/env_var_parser.py +131 -0
  436. ads/jobs/extension.py +160 -0
  437. ads/jobs/schema/__init__.py +5 -0
  438. ads/jobs/schema/infrastructure_schema.json +116 -0
  439. ads/jobs/schema/job_schema.json +42 -0
  440. ads/jobs/schema/runtime_schema.json +183 -0
  441. ads/jobs/schema/validator.py +141 -0
  442. ads/jobs/serializer.py +296 -0
  443. ads/jobs/templates/__init__.py +5 -0
  444. ads/jobs/templates/container.py +6 -0
  445. ads/jobs/templates/driver_notebook.py +177 -0
  446. ads/jobs/templates/driver_oci.py +500 -0
  447. ads/jobs/templates/driver_python.py +48 -0
  448. ads/jobs/templates/driver_pytorch.py +852 -0
  449. ads/jobs/templates/driver_utils.py +615 -0
  450. ads/jobs/templates/hostname_from_env.c +55 -0
  451. ads/jobs/templates/oci_metrics.py +181 -0
  452. ads/jobs/utils.py +104 -0
  453. ads/llm/__init__.py +28 -0
  454. ads/llm/autogen/__init__.py +2 -0
  455. ads/llm/autogen/constants.py +15 -0
  456. ads/llm/autogen/reports/__init__.py +2 -0
  457. ads/llm/autogen/reports/base.py +67 -0
  458. ads/llm/autogen/reports/data.py +103 -0
  459. ads/llm/autogen/reports/session.py +526 -0
  460. ads/llm/autogen/reports/templates/chat_box.html +13 -0
  461. ads/llm/autogen/reports/templates/chat_box_lt.html +5 -0
  462. ads/llm/autogen/reports/templates/chat_box_rt.html +6 -0
  463. ads/llm/autogen/reports/utils.py +56 -0
  464. ads/llm/autogen/v02/__init__.py +4 -0
  465. ads/llm/autogen/v02/client.py +295 -0
  466. ads/llm/autogen/v02/log_handlers/__init__.py +2 -0
  467. ads/llm/autogen/v02/log_handlers/oci_file_handler.py +83 -0
  468. ads/llm/autogen/v02/loggers/__init__.py +6 -0
  469. ads/llm/autogen/v02/loggers/metric_logger.py +320 -0
  470. ads/llm/autogen/v02/loggers/session_logger.py +580 -0
  471. ads/llm/autogen/v02/loggers/utils.py +86 -0
  472. ads/llm/autogen/v02/runtime_logging.py +163 -0
  473. ads/llm/chain.py +268 -0
  474. ads/llm/chat_template.py +31 -0
  475. ads/llm/deploy.py +63 -0
  476. ads/llm/guardrails/__init__.py +5 -0
  477. ads/llm/guardrails/base.py +442 -0
  478. ads/llm/guardrails/huggingface.py +44 -0
  479. ads/llm/langchain/__init__.py +5 -0
  480. ads/llm/langchain/plugins/__init__.py +5 -0
  481. ads/llm/langchain/plugins/chat_models/__init__.py +5 -0
  482. ads/llm/langchain/plugins/chat_models/oci_data_science.py +1027 -0
  483. ads/llm/langchain/plugins/embeddings/__init__.py +4 -0
  484. ads/llm/langchain/plugins/embeddings/oci_data_science_model_deployment_endpoint.py +184 -0
  485. ads/llm/langchain/plugins/llms/__init__.py +5 -0
  486. ads/llm/langchain/plugins/llms/oci_data_science_model_deployment_endpoint.py +979 -0
  487. ads/llm/requirements.txt +3 -0
  488. ads/llm/serialize.py +219 -0
  489. ads/llm/serializers/__init__.py +0 -0
  490. ads/llm/serializers/retrieval_qa.py +153 -0
  491. ads/llm/serializers/runnable_parallel.py +27 -0
  492. ads/llm/templates/score_chain.jinja2 +155 -0
  493. ads/llm/templates/tool_chat_template_hermes.jinja +130 -0
  494. ads/llm/templates/tool_chat_template_mistral_parallel.jinja +94 -0
  495. ads/model/__init__.py +52 -0
  496. ads/model/artifact.py +573 -0
  497. ads/model/artifact_downloader.py +254 -0
  498. ads/model/artifact_uploader.py +267 -0
  499. ads/model/base_properties.py +238 -0
  500. ads/model/common/.model-ignore +66 -0
  501. ads/model/common/__init__.py +5 -0
  502. ads/model/common/utils.py +142 -0
  503. ads/model/datascience_model.py +2635 -0
  504. ads/model/deployment/__init__.py +20 -0
  505. ads/model/deployment/common/__init__.py +5 -0
  506. ads/model/deployment/common/utils.py +308 -0
  507. ads/model/deployment/model_deployer.py +466 -0
  508. ads/model/deployment/model_deployment.py +1846 -0
  509. ads/model/deployment/model_deployment_infrastructure.py +671 -0
  510. ads/model/deployment/model_deployment_properties.py +493 -0
  511. ads/model/deployment/model_deployment_runtime.py +838 -0
  512. ads/model/extractor/__init__.py +5 -0
  513. ads/model/extractor/automl_extractor.py +74 -0
  514. ads/model/extractor/embedding_onnx_extractor.py +80 -0
  515. ads/model/extractor/huggingface_extractor.py +88 -0
  516. ads/model/extractor/keras_extractor.py +84 -0
  517. ads/model/extractor/lightgbm_extractor.py +93 -0
  518. ads/model/extractor/model_info_extractor.py +114 -0
  519. ads/model/extractor/model_info_extractor_factory.py +105 -0
  520. ads/model/extractor/pytorch_extractor.py +87 -0
  521. ads/model/extractor/sklearn_extractor.py +112 -0
  522. ads/model/extractor/spark_extractor.py +89 -0
  523. ads/model/extractor/tensorflow_extractor.py +85 -0
  524. ads/model/extractor/xgboost_extractor.py +94 -0
  525. ads/model/framework/__init__.py +5 -0
  526. ads/model/framework/automl_model.py +178 -0
  527. ads/model/framework/embedding_onnx_model.py +438 -0
  528. ads/model/framework/huggingface_model.py +399 -0
  529. ads/model/framework/lightgbm_model.py +266 -0
  530. ads/model/framework/pytorch_model.py +266 -0
  531. ads/model/framework/sklearn_model.py +250 -0
  532. ads/model/framework/spark_model.py +326 -0
  533. ads/model/framework/tensorflow_model.py +254 -0
  534. ads/model/framework/xgboost_model.py +258 -0
  535. ads/model/generic_model.py +3518 -0
  536. ads/model/model_artifact_boilerplate/README.md +381 -0
  537. ads/model/model_artifact_boilerplate/__init__.py +5 -0
  538. ads/model/model_artifact_boilerplate/artifact_introspection_test/__init__.py +5 -0
  539. ads/model/model_artifact_boilerplate/artifact_introspection_test/model_artifact_validate.py +427 -0
  540. ads/model/model_artifact_boilerplate/artifact_introspection_test/requirements.txt +2 -0
  541. ads/model/model_artifact_boilerplate/runtime.yaml +7 -0
  542. ads/model/model_artifact_boilerplate/score.py +61 -0
  543. ads/model/model_file_description_schema.json +68 -0
  544. ads/model/model_introspect.py +331 -0
  545. ads/model/model_metadata.py +1810 -0
  546. ads/model/model_metadata_mixin.py +460 -0
  547. ads/model/model_properties.py +63 -0
  548. ads/model/model_version_set.py +739 -0
  549. ads/model/runtime/__init__.py +5 -0
  550. ads/model/runtime/env_info.py +306 -0
  551. ads/model/runtime/model_deployment_details.py +37 -0
  552. ads/model/runtime/model_provenance_details.py +58 -0
  553. ads/model/runtime/runtime_info.py +81 -0
  554. ads/model/runtime/schemas/inference_env_info_schema.yaml +16 -0
  555. ads/model/runtime/schemas/model_provenance_schema.yaml +36 -0
  556. ads/model/runtime/schemas/training_env_info_schema.yaml +16 -0
  557. ads/model/runtime/utils.py +201 -0
  558. ads/model/serde/__init__.py +5 -0
  559. ads/model/serde/common.py +40 -0
  560. ads/model/serde/model_input.py +547 -0
  561. ads/model/serde/model_serializer.py +1184 -0
  562. ads/model/service/__init__.py +5 -0
  563. ads/model/service/oci_datascience_model.py +1076 -0
  564. ads/model/service/oci_datascience_model_deployment.py +500 -0
  565. ads/model/service/oci_datascience_model_version_set.py +176 -0
  566. ads/model/transformer/__init__.py +5 -0
  567. ads/model/transformer/onnx_transformer.py +324 -0
  568. ads/mysqldb/__init__.py +5 -0
  569. ads/mysqldb/mysql_db.py +227 -0
  570. ads/opctl/__init__.py +18 -0
  571. ads/opctl/anomaly_detection.py +11 -0
  572. ads/opctl/backend/__init__.py +5 -0
  573. ads/opctl/backend/ads_dataflow.py +353 -0
  574. ads/opctl/backend/ads_ml_job.py +710 -0
  575. ads/opctl/backend/ads_ml_pipeline.py +164 -0
  576. ads/opctl/backend/ads_model_deployment.py +209 -0
  577. ads/opctl/backend/base.py +146 -0
  578. ads/opctl/backend/local.py +1053 -0
  579. ads/opctl/backend/marketplace/__init__.py +9 -0
  580. ads/opctl/backend/marketplace/helm_helper.py +173 -0
  581. ads/opctl/backend/marketplace/local_marketplace.py +271 -0
  582. ads/opctl/backend/marketplace/marketplace_backend_runner.py +71 -0
  583. ads/opctl/backend/marketplace/marketplace_operator_interface.py +44 -0
  584. ads/opctl/backend/marketplace/marketplace_operator_runner.py +24 -0
  585. ads/opctl/backend/marketplace/marketplace_utils.py +212 -0
  586. ads/opctl/backend/marketplace/models/__init__.py +5 -0
  587. ads/opctl/backend/marketplace/models/bearer_token.py +94 -0
  588. ads/opctl/backend/marketplace/models/marketplace_type.py +70 -0
  589. ads/opctl/backend/marketplace/models/ocir_details.py +56 -0
  590. ads/opctl/backend/marketplace/prerequisite_checker.py +238 -0
  591. ads/opctl/cli.py +707 -0
  592. ads/opctl/cmds.py +869 -0
  593. ads/opctl/conda/__init__.py +5 -0
  594. ads/opctl/conda/cli.py +193 -0
  595. ads/opctl/conda/cmds.py +749 -0
  596. ads/opctl/conda/config.yaml +34 -0
  597. ads/opctl/conda/manifest_template.yaml +13 -0
  598. ads/opctl/conda/multipart_uploader.py +188 -0
  599. ads/opctl/conda/pack.py +89 -0
  600. ads/opctl/config/__init__.py +5 -0
  601. ads/opctl/config/base.py +57 -0
  602. ads/opctl/config/diagnostics/__init__.py +5 -0
  603. ads/opctl/config/diagnostics/distributed/default_requirements_config.yaml +62 -0
  604. ads/opctl/config/merger.py +255 -0
  605. ads/opctl/config/resolver.py +297 -0
  606. ads/opctl/config/utils.py +79 -0
  607. ads/opctl/config/validator.py +17 -0
  608. ads/opctl/config/versioner.py +68 -0
  609. ads/opctl/config/yaml_parsers/__init__.py +7 -0
  610. ads/opctl/config/yaml_parsers/base.py +58 -0
  611. ads/opctl/config/yaml_parsers/distributed/__init__.py +7 -0
  612. ads/opctl/config/yaml_parsers/distributed/yaml_parser.py +201 -0
  613. ads/opctl/constants.py +66 -0
  614. ads/opctl/decorator/__init__.py +5 -0
  615. ads/opctl/decorator/common.py +129 -0
  616. ads/opctl/diagnostics/__init__.py +5 -0
  617. ads/opctl/diagnostics/__main__.py +25 -0
  618. ads/opctl/diagnostics/check_distributed_job_requirements.py +212 -0
  619. ads/opctl/diagnostics/check_requirements.py +144 -0
  620. ads/opctl/diagnostics/requirement_exception.py +9 -0
  621. ads/opctl/distributed/README.md +109 -0
  622. ads/opctl/distributed/__init__.py +5 -0
  623. ads/opctl/distributed/certificates.py +32 -0
  624. ads/opctl/distributed/cli.py +207 -0
  625. ads/opctl/distributed/cmds.py +731 -0
  626. ads/opctl/distributed/common/__init__.py +5 -0
  627. ads/opctl/distributed/common/abstract_cluster_provider.py +449 -0
  628. ads/opctl/distributed/common/abstract_framework_spec_builder.py +88 -0
  629. ads/opctl/distributed/common/cluster_config_helper.py +103 -0
  630. ads/opctl/distributed/common/cluster_provider_factory.py +21 -0
  631. ads/opctl/distributed/common/cluster_runner.py +54 -0
  632. ads/opctl/distributed/common/framework_factory.py +29 -0
  633. ads/opctl/docker/Dockerfile.job +103 -0
  634. ads/opctl/docker/Dockerfile.job.arm +107 -0
  635. ads/opctl/docker/Dockerfile.job.gpu +175 -0
  636. ads/opctl/docker/base-env.yaml +13 -0
  637. ads/opctl/docker/cuda.repo +6 -0
  638. ads/opctl/docker/operator/.dockerignore +0 -0
  639. ads/opctl/docker/operator/Dockerfile +41 -0
  640. ads/opctl/docker/operator/Dockerfile.gpu +85 -0
  641. ads/opctl/docker/operator/cuda.repo +6 -0
  642. ads/opctl/docker/operator/environment.yaml +8 -0
  643. ads/opctl/forecast.py +11 -0
  644. ads/opctl/index.yaml +3 -0
  645. ads/opctl/model/__init__.py +5 -0
  646. ads/opctl/model/cli.py +65 -0
  647. ads/opctl/model/cmds.py +73 -0
  648. ads/opctl/operator/README.md +4 -0
  649. ads/opctl/operator/__init__.py +31 -0
  650. ads/opctl/operator/cli.py +344 -0
  651. ads/opctl/operator/cmd.py +596 -0
  652. ads/opctl/operator/common/__init__.py +5 -0
  653. ads/opctl/operator/common/backend_factory.py +460 -0
  654. ads/opctl/operator/common/const.py +27 -0
  655. ads/opctl/operator/common/data/synthetic.csv +16001 -0
  656. ads/opctl/operator/common/dictionary_merger.py +148 -0
  657. ads/opctl/operator/common/errors.py +42 -0
  658. ads/opctl/operator/common/operator_config.py +99 -0
  659. ads/opctl/operator/common/operator_loader.py +811 -0
  660. ads/opctl/operator/common/operator_schema.yaml +130 -0
  661. ads/opctl/operator/common/operator_yaml_generator.py +152 -0
  662. ads/opctl/operator/common/utils.py +208 -0
  663. ads/opctl/operator/lowcode/__init__.py +5 -0
  664. ads/opctl/operator/lowcode/anomaly/MLoperator +16 -0
  665. ads/opctl/operator/lowcode/anomaly/README.md +207 -0
  666. ads/opctl/operator/lowcode/anomaly/__init__.py +5 -0
  667. ads/opctl/operator/lowcode/anomaly/__main__.py +103 -0
  668. ads/opctl/operator/lowcode/anomaly/cmd.py +35 -0
  669. ads/opctl/operator/lowcode/anomaly/const.py +167 -0
  670. ads/opctl/operator/lowcode/anomaly/environment.yaml +10 -0
  671. ads/opctl/operator/lowcode/anomaly/model/__init__.py +5 -0
  672. ads/opctl/operator/lowcode/anomaly/model/anomaly_dataset.py +146 -0
  673. ads/opctl/operator/lowcode/anomaly/model/anomaly_merlion.py +162 -0
  674. ads/opctl/operator/lowcode/anomaly/model/automlx.py +99 -0
  675. ads/opctl/operator/lowcode/anomaly/model/autots.py +115 -0
  676. ads/opctl/operator/lowcode/anomaly/model/base_model.py +404 -0
  677. ads/opctl/operator/lowcode/anomaly/model/factory.py +110 -0
  678. ads/opctl/operator/lowcode/anomaly/model/isolationforest.py +78 -0
  679. ads/opctl/operator/lowcode/anomaly/model/oneclasssvm.py +78 -0
  680. ads/opctl/operator/lowcode/anomaly/model/randomcutforest.py +120 -0
  681. ads/opctl/operator/lowcode/anomaly/model/tods.py +119 -0
  682. ads/opctl/operator/lowcode/anomaly/operator_config.py +127 -0
  683. ads/opctl/operator/lowcode/anomaly/schema.yaml +401 -0
  684. ads/opctl/operator/lowcode/anomaly/utils.py +88 -0
  685. ads/opctl/operator/lowcode/common/__init__.py +5 -0
  686. ads/opctl/operator/lowcode/common/const.py +10 -0
  687. ads/opctl/operator/lowcode/common/data.py +116 -0
  688. ads/opctl/operator/lowcode/common/errors.py +47 -0
  689. ads/opctl/operator/lowcode/common/transformations.py +296 -0
  690. ads/opctl/operator/lowcode/common/utils.py +384 -0
  691. ads/opctl/operator/lowcode/feature_store_marketplace/MLoperator +13 -0
  692. ads/opctl/operator/lowcode/feature_store_marketplace/README.md +30 -0
  693. ads/opctl/operator/lowcode/feature_store_marketplace/__init__.py +5 -0
  694. ads/opctl/operator/lowcode/feature_store_marketplace/__main__.py +116 -0
  695. ads/opctl/operator/lowcode/feature_store_marketplace/cmd.py +85 -0
  696. ads/opctl/operator/lowcode/feature_store_marketplace/const.py +15 -0
  697. ads/opctl/operator/lowcode/feature_store_marketplace/environment.yaml +0 -0
  698. ads/opctl/operator/lowcode/feature_store_marketplace/models/__init__.py +4 -0
  699. ads/opctl/operator/lowcode/feature_store_marketplace/models/apigw_config.py +32 -0
  700. ads/opctl/operator/lowcode/feature_store_marketplace/models/db_config.py +43 -0
  701. ads/opctl/operator/lowcode/feature_store_marketplace/models/mysql_config.py +120 -0
  702. ads/opctl/operator/lowcode/feature_store_marketplace/models/serializable_yaml_model.py +34 -0
  703. ads/opctl/operator/lowcode/feature_store_marketplace/operator_utils.py +386 -0
  704. ads/opctl/operator/lowcode/feature_store_marketplace/schema.yaml +160 -0
  705. ads/opctl/operator/lowcode/forecast/MLoperator +25 -0
  706. ads/opctl/operator/lowcode/forecast/README.md +209 -0
  707. ads/opctl/operator/lowcode/forecast/__init__.py +5 -0
  708. ads/opctl/operator/lowcode/forecast/__main__.py +89 -0
  709. ads/opctl/operator/lowcode/forecast/cmd.py +40 -0
  710. ads/opctl/operator/lowcode/forecast/const.py +92 -0
  711. ads/opctl/operator/lowcode/forecast/environment.yaml +20 -0
  712. ads/opctl/operator/lowcode/forecast/errors.py +26 -0
  713. ads/opctl/operator/lowcode/forecast/model/__init__.py +5 -0
  714. ads/opctl/operator/lowcode/forecast/model/arima.py +279 -0
  715. ads/opctl/operator/lowcode/forecast/model/automlx.py +553 -0
  716. ads/opctl/operator/lowcode/forecast/model/autots.py +312 -0
  717. ads/opctl/operator/lowcode/forecast/model/base_model.py +875 -0
  718. ads/opctl/operator/lowcode/forecast/model/factory.py +106 -0
  719. ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +492 -0
  720. ads/opctl/operator/lowcode/forecast/model/ml_forecast.py +243 -0
  721. ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +482 -0
  722. ads/opctl/operator/lowcode/forecast/model/prophet.py +450 -0
  723. ads/opctl/operator/lowcode/forecast/model_evaluator.py +244 -0
  724. ads/opctl/operator/lowcode/forecast/operator_config.py +234 -0
  725. ads/opctl/operator/lowcode/forecast/schema.yaml +506 -0
  726. ads/opctl/operator/lowcode/forecast/utils.py +397 -0
  727. ads/opctl/operator/lowcode/forecast/whatifserve/__init__.py +7 -0
  728. ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +285 -0
  729. ads/opctl/operator/lowcode/forecast/whatifserve/score.py +246 -0
  730. ads/opctl/operator/lowcode/pii/MLoperator +17 -0
  731. ads/opctl/operator/lowcode/pii/README.md +208 -0
  732. ads/opctl/operator/lowcode/pii/__init__.py +5 -0
  733. ads/opctl/operator/lowcode/pii/__main__.py +78 -0
  734. ads/opctl/operator/lowcode/pii/cmd.py +39 -0
  735. ads/opctl/operator/lowcode/pii/constant.py +84 -0
  736. ads/opctl/operator/lowcode/pii/environment.yaml +17 -0
  737. ads/opctl/operator/lowcode/pii/errors.py +27 -0
  738. ads/opctl/operator/lowcode/pii/model/__init__.py +5 -0
  739. ads/opctl/operator/lowcode/pii/model/factory.py +82 -0
  740. ads/opctl/operator/lowcode/pii/model/guardrails.py +167 -0
  741. ads/opctl/operator/lowcode/pii/model/pii.py +145 -0
  742. ads/opctl/operator/lowcode/pii/model/processor/__init__.py +34 -0
  743. ads/opctl/operator/lowcode/pii/model/processor/email_replacer.py +34 -0
  744. ads/opctl/operator/lowcode/pii/model/processor/mbi_replacer.py +35 -0
  745. ads/opctl/operator/lowcode/pii/model/processor/name_replacer.py +225 -0
  746. ads/opctl/operator/lowcode/pii/model/processor/number_replacer.py +73 -0
  747. ads/opctl/operator/lowcode/pii/model/processor/remover.py +26 -0
  748. ads/opctl/operator/lowcode/pii/model/report.py +487 -0
  749. ads/opctl/operator/lowcode/pii/operator_config.py +95 -0
  750. ads/opctl/operator/lowcode/pii/schema.yaml +108 -0
  751. ads/opctl/operator/lowcode/pii/utils.py +43 -0
  752. ads/opctl/operator/lowcode/recommender/MLoperator +16 -0
  753. ads/opctl/operator/lowcode/recommender/README.md +206 -0
  754. ads/opctl/operator/lowcode/recommender/__init__.py +5 -0
  755. ads/opctl/operator/lowcode/recommender/__main__.py +82 -0
  756. ads/opctl/operator/lowcode/recommender/cmd.py +33 -0
  757. ads/opctl/operator/lowcode/recommender/constant.py +30 -0
  758. ads/opctl/operator/lowcode/recommender/environment.yaml +11 -0
  759. ads/opctl/operator/lowcode/recommender/model/base_model.py +212 -0
  760. ads/opctl/operator/lowcode/recommender/model/factory.py +56 -0
  761. ads/opctl/operator/lowcode/recommender/model/recommender_dataset.py +25 -0
  762. ads/opctl/operator/lowcode/recommender/model/svd.py +106 -0
  763. ads/opctl/operator/lowcode/recommender/operator_config.py +81 -0
  764. ads/opctl/operator/lowcode/recommender/schema.yaml +265 -0
  765. ads/opctl/operator/lowcode/recommender/utils.py +13 -0
  766. ads/opctl/operator/runtime/__init__.py +5 -0
  767. ads/opctl/operator/runtime/const.py +17 -0
  768. ads/opctl/operator/runtime/container_runtime_schema.yaml +50 -0
  769. ads/opctl/operator/runtime/marketplace_runtime.py +50 -0
  770. ads/opctl/operator/runtime/python_marketplace_runtime_schema.yaml +21 -0
  771. ads/opctl/operator/runtime/python_runtime_schema.yaml +21 -0
  772. ads/opctl/operator/runtime/runtime.py +115 -0
  773. ads/opctl/schema.yaml.yml +36 -0
  774. ads/opctl/script.py +40 -0
  775. ads/opctl/spark/__init__.py +5 -0
  776. ads/opctl/spark/cli.py +43 -0
  777. ads/opctl/spark/cmds.py +147 -0
  778. ads/opctl/templates/diagnostic_report_template.jinja2 +102 -0
  779. ads/opctl/utils.py +344 -0
  780. ads/oracledb/__init__.py +5 -0
  781. ads/oracledb/oracle_db.py +346 -0
  782. ads/pipeline/__init__.py +39 -0
  783. ads/pipeline/ads_pipeline.py +2279 -0
  784. ads/pipeline/ads_pipeline_run.py +772 -0
  785. ads/pipeline/ads_pipeline_step.py +605 -0
  786. ads/pipeline/builders/__init__.py +5 -0
  787. ads/pipeline/builders/infrastructure/__init__.py +5 -0
  788. ads/pipeline/builders/infrastructure/custom_script.py +32 -0
  789. ads/pipeline/cli.py +119 -0
  790. ads/pipeline/extension.py +291 -0
  791. ads/pipeline/schema/__init__.py +5 -0
  792. ads/pipeline/schema/cs_step_schema.json +35 -0
  793. ads/pipeline/schema/ml_step_schema.json +31 -0
  794. ads/pipeline/schema/pipeline_schema.json +71 -0
  795. ads/pipeline/visualizer/__init__.py +5 -0
  796. ads/pipeline/visualizer/base.py +570 -0
  797. ads/pipeline/visualizer/graph_renderer.py +272 -0
  798. ads/pipeline/visualizer/text_renderer.py +84 -0
  799. ads/secrets/__init__.py +11 -0
  800. ads/secrets/adb.py +386 -0
  801. ads/secrets/auth_token.py +86 -0
  802. ads/secrets/big_data_service.py +365 -0
  803. ads/secrets/mysqldb.py +149 -0
  804. ads/secrets/oracledb.py +160 -0
  805. ads/secrets/secrets.py +407 -0
  806. ads/telemetry/__init__.py +7 -0
  807. ads/telemetry/base.py +69 -0
  808. ads/telemetry/client.py +122 -0
  809. ads/telemetry/telemetry.py +257 -0
  810. ads/templates/dataflow_pyspark.jinja2 +13 -0
  811. ads/templates/dataflow_sparksql.jinja2 +22 -0
  812. ads/templates/func.jinja2 +20 -0
  813. ads/templates/schemas/openapi.json +1740 -0
  814. ads/templates/score-pkl.jinja2 +173 -0
  815. ads/templates/score.jinja2 +322 -0
  816. ads/templates/score_embedding_onnx.jinja2 +202 -0
  817. ads/templates/score_generic.jinja2 +165 -0
  818. ads/templates/score_huggingface_pipeline.jinja2 +217 -0
  819. ads/templates/score_lightgbm.jinja2 +185 -0
  820. ads/templates/score_onnx.jinja2 +407 -0
  821. ads/templates/score_onnx_new.jinja2 +473 -0
  822. ads/templates/score_oracle_automl.jinja2 +185 -0
  823. ads/templates/score_pyspark.jinja2 +154 -0
  824. ads/templates/score_pytorch.jinja2 +219 -0
  825. ads/templates/score_scikit-learn.jinja2 +184 -0
  826. ads/templates/score_tensorflow.jinja2 +184 -0
  827. ads/templates/score_xgboost.jinja2 +178 -0
  828. ads/text_dataset/__init__.py +5 -0
  829. ads/text_dataset/backends.py +211 -0
  830. ads/text_dataset/dataset.py +445 -0
  831. ads/text_dataset/extractor.py +207 -0
  832. ads/text_dataset/options.py +53 -0
  833. ads/text_dataset/udfs.py +22 -0
  834. ads/text_dataset/utils.py +49 -0
  835. ads/type_discovery/__init__.py +9 -0
  836. ads/type_discovery/abstract_detector.py +21 -0
  837. ads/type_discovery/constant_detector.py +41 -0
  838. ads/type_discovery/continuous_detector.py +54 -0
  839. ads/type_discovery/credit_card_detector.py +99 -0
  840. ads/type_discovery/datetime_detector.py +92 -0
  841. ads/type_discovery/discrete_detector.py +118 -0
  842. ads/type_discovery/document_detector.py +146 -0
  843. ads/type_discovery/ip_detector.py +68 -0
  844. ads/type_discovery/latlon_detector.py +90 -0
  845. ads/type_discovery/phone_number_detector.py +63 -0
  846. ads/type_discovery/type_discovery_driver.py +87 -0
  847. ads/type_discovery/typed_feature.py +594 -0
  848. ads/type_discovery/unknown_detector.py +41 -0
  849. ads/type_discovery/zipcode_detector.py +48 -0
  850. ads/vault/__init__.py +7 -0
  851. ads/vault/vault.py +237 -0
  852. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.10.dist-info}/METADATA +150 -149
  853. oracle_ads-2.13.10.dist-info/RECORD +858 -0
  854. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.10.dist-info}/WHEEL +1 -2
  855. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.10.dist-info}/entry_points.txt +2 -1
  856. oracle_ads-2.13.9rc0.dist-info/RECORD +0 -9
  857. oracle_ads-2.13.9rc0.dist-info/top_level.txt +0 -1
  858. {oracle_ads-2.13.9rc0.dist-info → oracle_ads-2.13.10.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,1814 @@
1
+ #!/usr/bin/env python
2
+ # Copyright (c) 2024, 2025 Oracle and/or its affiliates.
3
+ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
4
+ import base64
5
+ import json
6
+ import os
7
+ import re
8
+ import tempfile
9
+ from concurrent.futures import ThreadPoolExecutor, as_completed
10
+ from datetime import datetime, timedelta
11
+ from pathlib import Path
12
+ from threading import Lock
13
+ from typing import Any, Dict, List, Optional, Union
14
+
15
+ import oci
16
+ from cachetools import TTLCache
17
+ from oci.data_science.models import (
18
+ JobRun,
19
+ Metadata,
20
+ UpdateModelDetails,
21
+ UpdateModelProvenanceDetails,
22
+ )
23
+
24
+ from ads.aqua import logger
25
+ from ads.aqua.app import AquaApp
26
+ from ads.aqua.common import utils
27
+ from ads.aqua.common.entities import AquaMultiModelRef
28
+ from ads.aqua.common.enums import (
29
+ DataScienceResource,
30
+ Resource,
31
+ RqsAdditionalDetails,
32
+ Tags,
33
+ )
34
+ from ads.aqua.common.errors import (
35
+ AquaFileExistsError,
36
+ AquaFileNotFoundError,
37
+ AquaMissingKeyError,
38
+ AquaRuntimeError,
39
+ AquaValueError,
40
+ )
41
+ from ads.aqua.common.utils import (
42
+ extract_id_and_name_from_tag,
43
+ fire_and_forget,
44
+ is_valid_ocid,
45
+ upload_local_to_os,
46
+ )
47
+ from ads.aqua.config.evaluation.evaluation_service_config import (
48
+ DEFAULT_EVALUATION_CONTAINER,
49
+ EvaluationServiceConfig,
50
+ MetricConfig,
51
+ )
52
+ from ads.aqua.constants import (
53
+ CONSOLE_LINK_RESOURCE_TYPE_MAPPING,
54
+ EVALUATION_REPORT,
55
+ EVALUATION_REPORT_JSON,
56
+ EVALUATION_REPORT_MD,
57
+ JOB_INFRASTRUCTURE_TYPE_DEFAULT_NETWORKING,
58
+ LIFECYCLE_DETAILS_MISSING_JOBRUN,
59
+ NB_SESSION_IDENTIFIER,
60
+ )
61
+ from ads.aqua.evaluation.constants import (
62
+ EVAL_TERMINATION_STATE,
63
+ EvaluationConfig,
64
+ EvaluationCustomMetadata,
65
+ EvaluationMetricResult,
66
+ EvaluationReportJson,
67
+ )
68
+ from ads.aqua.evaluation.entities import (
69
+ AquaEvalMetric,
70
+ AquaEvalMetrics,
71
+ AquaEvalMetricSummary,
72
+ AquaEvalParams,
73
+ AquaEvalReport,
74
+ AquaEvaluationCommands,
75
+ AquaEvaluationDetail,
76
+ AquaEvaluationSummary,
77
+ AquaResourceIdentifier,
78
+ CreateAquaEvaluationDetails,
79
+ )
80
+ from ads.aqua.evaluation.errors import EVALUATION_JOB_EXIT_CODE_MESSAGE
81
+ from ads.aqua.model.constants import ModelCustomMetadataFields
82
+ from ads.common.auth import default_signer
83
+ from ads.common.object_storage_details import ObjectStorageDetails
84
+ from ads.common.utils import (
85
+ UNKNOWN,
86
+ get_console_link,
87
+ get_files,
88
+ get_log_links,
89
+ read_file,
90
+ )
91
+ from ads.config import (
92
+ AQUA_JOB_SUBNET_ID,
93
+ COMPARTMENT_OCID,
94
+ CONDA_BUCKET_NS,
95
+ PROJECT_OCID,
96
+ )
97
+ from ads.jobs.ads_job import DataScienceJobRun, Job
98
+ from ads.jobs.builders.infrastructure.dsc_job import DataScienceJob
99
+ from ads.jobs.builders.runtimes.base import Runtime
100
+ from ads.jobs.builders.runtimes.container_runtime import ContainerRuntime
101
+ from ads.model.datascience_model import DataScienceModel
102
+ from ads.model.deployment import ModelDeploymentContainerRuntime
103
+ from ads.model.deployment.model_deployment import ModelDeployment
104
+ from ads.model.generic_model import ModelDeploymentRuntimeType
105
+ from ads.model.model_metadata import (
106
+ MetadataTaxonomyKeys,
107
+ ModelCustomMetadata,
108
+ ModelCustomMetadataItem,
109
+ ModelProvenanceMetadata,
110
+ ModelTaxonomyMetadata,
111
+ )
112
+ from ads.model.model_version_set import ModelVersionSet
113
+ from ads.telemetry import telemetry
114
+
115
+
116
+ class AquaEvaluationApp(AquaApp):
117
+ """Provides a suite of APIs to interact with Aqua evaluations within the
118
+ Oracle Cloud Infrastructure Data Science service, serving as an interface
119
+ for managing model evalutions.
120
+
121
+
122
+ Methods
123
+ -------
124
+ create(evaluation_source_id, evaluation_name, ...) -> AquaEvaluationSummary:
125
+ Creates Aqua evaluation for resource.
126
+ get(model_id: str) -> AquaEvaluationSummary:
127
+ Retrieves details of an Aqua evaluation by its unique identifier.
128
+ list(compartment_id: str = None, project_id: str = None, **kwargs) -> List[AquaEvaluationSummary]:
129
+ Lists all Aqua evaluation within a specified compartment and/or project.
130
+
131
+ Note:
132
+ This class is designed to work within the Oracle Cloud Infrastructure
133
+ and requires proper configuration and authentication set up to interact
134
+ with OCI services.
135
+ """
136
+
137
+ _report_cache = TTLCache(maxsize=10, ttl=timedelta(hours=5), timer=datetime.now)
138
+ _metrics_cache = TTLCache(maxsize=10, ttl=timedelta(hours=5), timer=datetime.now)
139
+ _eval_cache = TTLCache(maxsize=200, ttl=timedelta(hours=10), timer=datetime.now)
140
+ _deletion_cache = TTLCache(
141
+ maxsize=10, ttl=timedelta(minutes=10), timer=datetime.now
142
+ )
143
+ _cache_lock = Lock()
144
+
145
+ @telemetry(entry_point="plugin=evaluation&action=create", name="aqua")
146
+ def create(
147
+ self,
148
+ create_aqua_evaluation_details: CreateAquaEvaluationDetails = None,
149
+ **kwargs,
150
+ ) -> "AquaEvaluationSummary":
151
+ """Creates Aqua evaluation for resource.\n
152
+ For detailed information about CLI flags see: https://github.com/oracle-samples/oci-data-science-ai-samples/blob/main/ai-quick-actions/cli-tips.md#model-evaluation
153
+
154
+ Parameters
155
+ ----------
156
+ create_aqua_evaluation_details: CreateAquaEvaluationDetails
157
+ The CreateAquaEvaluationDetails data class which contains all
158
+ required and optional fields to create the aqua evaluation.
159
+ kwargs:
160
+ evaluation_source_id: str
161
+ The evaluation source id. Must be either model or model deployment ocid.
162
+ evaluation_name: str
163
+ The name for evaluation.
164
+ dataset_path: str
165
+ The dataset path for the evaluation. Could be either a local path from notebook session
166
+ or an object storage path.
167
+ report_path: str
168
+ The report path for the evaluation. Must be an object storage path.
169
+ model_parameters: dict
170
+ The parameters for the evaluation.
171
+ shape_name: str
172
+ The shape name for the evaluation job infrastructure.
173
+ memory_in_gbs: float
174
+ The memory in gbs for the shape selected.
175
+ ocpus: float
176
+ The ocpu count for the shape selected.
177
+ block_storage_size: int
178
+ The storage for the evaluation job infrastructure.
179
+ compartment_id: (str, optional). Defaults to `None`.
180
+ The compartment id for the evaluation.
181
+ project_id: (str, optional). Defaults to `None`.
182
+ The project id for the evaluation.
183
+ evaluation_description: (str, optional). Defaults to `None`.
184
+ The description for evaluation
185
+ experiment_id: (str, optional). Defaults to `None`.
186
+ The evaluation model version set id. If provided,
187
+ evaluation model will be associated with it.
188
+ experiment_name: (str, optional). Defaults to `None`.
189
+ The evaluation model version set name. If provided,
190
+ the model version set with the same name will be used if exists,
191
+ otherwise a new model version set will be created with the name.
192
+ experiment_description: (str, optional). Defaults to `None`.
193
+ The description for the evaluation model version set.
194
+ log_group_id: (str, optional). Defaults to `None`.
195
+ The log group id for the evaluation job infrastructure.
196
+ log_id: (str, optional). Defaults to `None`.
197
+ The log id for the evaluation job infrastructure.
198
+ metrics: (list, optional). Defaults to `None`.
199
+ The metrics for the evaluation.
200
+ force_overwrite: (bool, optional). Defaults to `False`.
201
+ Whether to force overwrite the existing file in object storage.
202
+ freeform_tags: (dict, optional)
203
+ Freeform tags for the evaluation model
204
+ defined_tags: (dict, optional)
205
+ Defined tags for the evaluation model
206
+
207
+ kwargs:
208
+ The kwargs for creating CreateAquaEvaluationDetails instance if
209
+ no create_aqua_evaluation_details provided.
210
+
211
+ Returns
212
+ -------
213
+ AquaEvaluationSummary:
214
+ The instance of AquaEvaluationSummary.
215
+ """
216
+ if not create_aqua_evaluation_details:
217
+ try:
218
+ create_aqua_evaluation_details = CreateAquaEvaluationDetails(**kwargs)
219
+ except Exception as ex:
220
+ custom_errors = {
221
+ ".".join(map(str, e["loc"])): e["msg"]
222
+ for e in json.loads(ex.json())
223
+ }
224
+ raise AquaValueError(
225
+ f"Invalid create evaluation parameters. Error details: {custom_errors}."
226
+ ) from ex
227
+
228
+ if not is_valid_ocid(create_aqua_evaluation_details.evaluation_source_id):
229
+ raise AquaValueError(
230
+ f"Invalid evaluation source {create_aqua_evaluation_details.evaluation_source_id}. "
231
+ "Specify either a model or model deployment id."
232
+ )
233
+
234
+ # The model to evaluate
235
+ evaluation_source = None
236
+ eval_inference_configuration: Dict = {}
237
+
238
+ if (
239
+ DataScienceResource.MODEL_DEPLOYMENT
240
+ in create_aqua_evaluation_details.evaluation_source_id
241
+ ):
242
+ evaluation_source = ModelDeployment.from_id(
243
+ create_aqua_evaluation_details.evaluation_source_id
244
+ )
245
+
246
+ if Tags.MULTIMODEL_TYPE_TAG in evaluation_source.freeform_tags:
247
+ multi_model_id = evaluation_source.freeform_tags.get(
248
+ Tags.AQUA_MODEL_ID_TAG, UNKNOWN
249
+ )
250
+
251
+ if not multi_model_id:
252
+ raise AquaRuntimeError(
253
+ f"Invalid multi model deployment {multi_model_id}."
254
+ f"Make sure the {Tags.AQUA_MODEL_ID_TAG} tag is added to the deployment."
255
+ )
256
+
257
+ aqua_model = DataScienceModel.from_id(multi_model_id)
258
+ AquaEvaluationApp.validate_model_name(
259
+ aqua_model, create_aqua_evaluation_details
260
+ )
261
+
262
+ try:
263
+ if (
264
+ evaluation_source.runtime.type
265
+ == ModelDeploymentRuntimeType.CONTAINER
266
+ ):
267
+ runtime = ModelDeploymentContainerRuntime.from_dict(
268
+ evaluation_source.runtime.to_dict()
269
+ )
270
+ inference_config = (
271
+ self.get_container_config().to_dict().get("inference")
272
+ )
273
+ for container in inference_config:
274
+ if container.name == runtime.image[: runtime.image.rfind(":")]:
275
+ eval_inference_configuration = (
276
+ container.spec.evaluation_configuration
277
+ )
278
+ except Exception as ex:
279
+ logger.debug(
280
+ f"Could not load inference config details for the evaluation source id: "
281
+ f"{create_aqua_evaluation_details.evaluation_source_id}. Please check if the container"
282
+ f" runtime has the correct SMC image information.\nError: {str(ex)}"
283
+ )
284
+ elif (
285
+ DataScienceResource.MODEL
286
+ in create_aqua_evaluation_details.evaluation_source_id
287
+ ):
288
+ evaluation_source = DataScienceModel.from_id(
289
+ create_aqua_evaluation_details.evaluation_source_id
290
+ )
291
+ else:
292
+ raise AquaValueError(
293
+ f"Invalid evaluation source {create_aqua_evaluation_details.evaluation_source_id}. "
294
+ "Specify either a model or model deployment id."
295
+ )
296
+
297
+ if not ObjectStorageDetails.is_oci_path(
298
+ create_aqua_evaluation_details.report_path
299
+ ):
300
+ raise AquaValueError(
301
+ "Evaluation report path must be an object storage path."
302
+ )
303
+
304
+ evaluation_dataset_path = create_aqua_evaluation_details.dataset_path
305
+ if not ObjectStorageDetails.is_oci_path(evaluation_dataset_path):
306
+ # format: oci://<bucket>@<namespace>/<prefix>/<dataset_file_name>
307
+ dataset_file = os.path.basename(evaluation_dataset_path)
308
+ dst_uri = f"{create_aqua_evaluation_details.report_path.rstrip('/')}/{dataset_file}"
309
+ try:
310
+ upload_local_to_os(
311
+ src_uri=evaluation_dataset_path,
312
+ dst_uri=dst_uri,
313
+ auth=default_signer(),
314
+ force_overwrite=create_aqua_evaluation_details.force_overwrite,
315
+ )
316
+ except FileExistsError as err:
317
+ raise AquaFileExistsError(
318
+ f"Dataset {dataset_file} already exists in {create_aqua_evaluation_details.report_path}. "
319
+ "Please use a new dataset file name, report path or set `force_overwrite` as True."
320
+ ) from err
321
+ logger.debug(
322
+ f"Uploaded local file {evaluation_dataset_path} to object storage {dst_uri}."
323
+ )
324
+ # tracks the size of dataset uploaded by user to the destination.
325
+ self.telemetry.record_event_async(
326
+ category="aqua/evaluation/upload",
327
+ action="size",
328
+ detail=os.path.getsize(os.path.expanduser(evaluation_dataset_path)),
329
+ )
330
+ evaluation_dataset_path = dst_uri
331
+
332
+ evaluation_model_parameters = AquaEvalParams(
333
+ shape=create_aqua_evaluation_details.shape_name,
334
+ dataset_path=evaluation_dataset_path,
335
+ report_path=create_aqua_evaluation_details.report_path,
336
+ **create_aqua_evaluation_details.model_parameters,
337
+ )
338
+
339
+ evaluation_model_defined_tags = (
340
+ create_aqua_evaluation_details.defined_tags or {}
341
+ )
342
+
343
+ target_compartment = (
344
+ create_aqua_evaluation_details.compartment_id or COMPARTMENT_OCID
345
+ )
346
+ target_project = create_aqua_evaluation_details.project_id or PROJECT_OCID
347
+
348
+ experiment_model_version_set_id = create_aqua_evaluation_details.experiment_id
349
+ experiment_model_version_set_name = (
350
+ create_aqua_evaluation_details.experiment_name
351
+ )
352
+
353
+ if (
354
+ not experiment_model_version_set_id
355
+ and not experiment_model_version_set_name
356
+ ):
357
+ raise AquaValueError(
358
+ "Either experiment id or experiment name must be provided."
359
+ )
360
+
361
+ if not experiment_model_version_set_id:
362
+ try:
363
+ model_version_set = ModelVersionSet.from_name(
364
+ name=experiment_model_version_set_name,
365
+ compartment_id=target_compartment,
366
+ )
367
+ if not utils._is_valid_mvs(model_version_set, Tags.AQUA_EVALUATION):
368
+ raise AquaValueError(
369
+ f"Invalid experiment name. Please provide an experiment with `{Tags.AQUA_EVALUATION}` in tags."
370
+ )
371
+ except Exception:
372
+ logger.info(
373
+ f"Model version set {experiment_model_version_set_name} doesn't exist. "
374
+ "Creating new model version set."
375
+ )
376
+
377
+ evaluation_mvs_freeform_tags = {
378
+ Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
379
+ }
380
+ evaluation_mvs_freeform_tags = {
381
+ **evaluation_mvs_freeform_tags,
382
+ **(create_aqua_evaluation_details.freeform_tags or {}),
383
+ }
384
+
385
+ model_version_set = (
386
+ ModelVersionSet()
387
+ .with_compartment_id(target_compartment)
388
+ .with_project_id(target_project)
389
+ .with_name(experiment_model_version_set_name)
390
+ .with_description(
391
+ create_aqua_evaluation_details.experiment_description
392
+ )
393
+ .with_freeform_tags(**evaluation_mvs_freeform_tags)
394
+ .with_defined_tags(**evaluation_model_defined_tags)
395
+ # TODO: decide what parameters will be needed
396
+ .create(**kwargs)
397
+ )
398
+ logger.debug(
399
+ f"Successfully created model version set {experiment_model_version_set_name} with id {model_version_set.id}."
400
+ )
401
+ experiment_model_version_set_id = model_version_set.id
402
+ else:
403
+ model_version_set = ModelVersionSet.from_id(experiment_model_version_set_id)
404
+ if not utils._is_valid_mvs(model_version_set, Tags.AQUA_EVALUATION):
405
+ raise AquaValueError(
406
+ f"Invalid experiment id. Please provide an experiment with `{Tags.AQUA_EVALUATION}` in tags."
407
+ )
408
+ experiment_model_version_set_name = model_version_set.name
409
+
410
+ evaluation_model_custom_metadata = ModelCustomMetadata()
411
+ evaluation_model_custom_metadata.add(
412
+ key=EvaluationCustomMetadata.EVALUATION_SOURCE,
413
+ value=create_aqua_evaluation_details.evaluation_source_id,
414
+ )
415
+ evaluation_model_custom_metadata.add(
416
+ key=EvaluationCustomMetadata.EVALUATION_OUTPUT_PATH,
417
+ value=create_aqua_evaluation_details.report_path,
418
+ )
419
+ evaluation_model_custom_metadata.add(
420
+ key=EvaluationCustomMetadata.EVALUATION_SOURCE_NAME,
421
+ value=evaluation_source.display_name,
422
+ )
423
+
424
+ evaluation_model_taxonomy_metadata = ModelTaxonomyMetadata()
425
+ evaluation_model_taxonomy_metadata[
426
+ MetadataTaxonomyKeys.HYPERPARAMETERS
427
+ ].value = {"model_params": evaluation_model_parameters.to_dict()}
428
+
429
+ evaluation_model = (
430
+ DataScienceModel()
431
+ .with_compartment_id(target_compartment)
432
+ .with_project_id(target_project)
433
+ .with_display_name(create_aqua_evaluation_details.evaluation_name)
434
+ .with_description(create_aqua_evaluation_details.evaluation_description)
435
+ .with_model_version_set_id(experiment_model_version_set_id)
436
+ .with_custom_metadata_list(evaluation_model_custom_metadata)
437
+ .with_defined_metadata_list(evaluation_model_taxonomy_metadata)
438
+ .with_provenance_metadata(ModelProvenanceMetadata(training_id=UNKNOWN))
439
+ .with_defined_tags(**evaluation_model_defined_tags)
440
+ # TODO uncomment this once the evaluation container will get the updated version of the ADS
441
+ # .with_input_schema(create_aqua_evaluation_details.to_dict())
442
+ # TODO: decide what parameters will be needed
443
+ .create(
444
+ remove_existing_artifact=False, # TODO: added here for the purpose of demo and will revisit later
445
+ **kwargs,
446
+ )
447
+ )
448
+ logger.debug(
449
+ f"Successfully created evaluation model {evaluation_model.id} for {create_aqua_evaluation_details.evaluation_source_id}."
450
+ )
451
+
452
+ # TODO: validate metrics if it's provided
453
+
454
+ evaluation_job_freeform_tags = {
455
+ Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
456
+ Tags.AQUA_EVALUATION_MODEL_ID: evaluation_model.id,
457
+ }
458
+ evaluation_job_freeform_tags = {
459
+ **evaluation_job_freeform_tags,
460
+ **(create_aqua_evaluation_details.freeform_tags or {}),
461
+ }
462
+
463
+ evaluation_job = Job(name=evaluation_model.display_name).with_infrastructure(
464
+ DataScienceJob()
465
+ .with_log_group_id(create_aqua_evaluation_details.log_group_id)
466
+ .with_log_id(create_aqua_evaluation_details.log_id)
467
+ .with_compartment_id(target_compartment)
468
+ .with_project_id(target_project)
469
+ .with_shape_name(create_aqua_evaluation_details.shape_name)
470
+ .with_block_storage_size(create_aqua_evaluation_details.block_storage_size)
471
+ .with_freeform_tag(**evaluation_job_freeform_tags)
472
+ .with_defined_tag(**evaluation_model_defined_tags)
473
+ )
474
+ if (
475
+ create_aqua_evaluation_details.memory_in_gbs
476
+ and create_aqua_evaluation_details.ocpus
477
+ ):
478
+ evaluation_job.infrastructure.with_shape_config_details(
479
+ memory_in_gbs=create_aqua_evaluation_details.memory_in_gbs,
480
+ ocpus=create_aqua_evaluation_details.ocpus,
481
+ )
482
+ if AQUA_JOB_SUBNET_ID:
483
+ evaluation_job.infrastructure.with_subnet_id(AQUA_JOB_SUBNET_ID)
484
+ elif NB_SESSION_IDENTIFIER in os.environ:
485
+ # apply default subnet id for job by setting ME_STANDALONE
486
+ # so as to avoid using the notebook session's networking when running on it
487
+ # https://accelerated-data-science.readthedocs.io/en/latest/user_guide/jobs/infra_and_runtime.html#networking
488
+ evaluation_job.infrastructure.with_job_infrastructure_type(
489
+ JOB_INFRASTRUCTURE_TYPE_DEFAULT_NETWORKING
490
+ )
491
+
492
+ container_image = (
493
+ create_aqua_evaluation_details.container_image_uri
494
+ or self._get_evaluation_container(
495
+ create_aqua_evaluation_details.evaluation_source_id
496
+ )
497
+ )
498
+
499
+ evaluation_job.with_runtime(
500
+ self._build_evaluation_runtime(
501
+ evaluation_id=evaluation_model.id,
502
+ evaluation_source_id=(
503
+ create_aqua_evaluation_details.evaluation_source_id
504
+ ),
505
+ container_image=container_image,
506
+ dataset_path=evaluation_dataset_path,
507
+ report_path=create_aqua_evaluation_details.report_path,
508
+ model_parameters={
509
+ **create_aqua_evaluation_details.model_parameters,
510
+ },
511
+ metrics=create_aqua_evaluation_details.metrics,
512
+ inference_configuration=eval_inference_configuration or {},
513
+ )
514
+ ).create(**kwargs) ## TODO: decide what parameters will be needed
515
+ logger.debug(
516
+ f"Successfully created evaluation job {evaluation_job.id} for {create_aqua_evaluation_details.evaluation_source_id}."
517
+ )
518
+
519
+ evaluation_job_run = evaluation_job.run(
520
+ name=evaluation_model.display_name,
521
+ freeform_tags=evaluation_job_freeform_tags,
522
+ defined_tags=evaluation_model_defined_tags,
523
+ wait=False,
524
+ )
525
+ logger.debug(
526
+ f"Successfully created evaluation job run {evaluation_job_run.id} for {create_aqua_evaluation_details.evaluation_source_id}."
527
+ )
528
+
529
+ evaluation_model_custom_metadata.add(
530
+ key=EvaluationCustomMetadata.EVALUATION_JOB_ID,
531
+ value=evaluation_job.id,
532
+ )
533
+ evaluation_model_custom_metadata.add(
534
+ key=EvaluationCustomMetadata.EVALUATION_JOB_RUN_ID,
535
+ value=evaluation_job_run.id,
536
+ )
537
+ updated_custom_metadata_list = [
538
+ Metadata(**metadata)
539
+ for metadata in evaluation_model_custom_metadata.to_dict()["data"]
540
+ ]
541
+
542
+ evaluation_model_freeform_tags = {
543
+ Tags.AQUA_EVALUATION: Tags.AQUA_EVALUATION,
544
+ **(create_aqua_evaluation_details.freeform_tags or {}),
545
+ }
546
+
547
+ self.ds_client.update_model(
548
+ model_id=evaluation_model.id,
549
+ update_model_details=UpdateModelDetails(
550
+ custom_metadata_list=updated_custom_metadata_list,
551
+ freeform_tags=evaluation_model_freeform_tags,
552
+ ),
553
+ )
554
+
555
+ self.ds_client.update_model_provenance(
556
+ model_id=evaluation_model.id,
557
+ update_model_provenance_details=UpdateModelProvenanceDetails(
558
+ training_id=evaluation_job_run.id
559
+ ),
560
+ )
561
+
562
+ # tracks shapes used in evaluation that were created for the given evaluation source
563
+ self.telemetry.record_event_async(
564
+ category="aqua/evaluation/create",
565
+ action="shape",
566
+ detail=create_aqua_evaluation_details.shape_name,
567
+ value=self._get_service_model_name(evaluation_source),
568
+ )
569
+
570
+ # tracks unique evaluation that were created for the given evaluation source
571
+ self.telemetry.record_event_async(
572
+ category="aqua/evaluation",
573
+ action="create",
574
+ detail=self._get_service_model_name(evaluation_source),
575
+ )
576
+
577
+ return AquaEvaluationSummary(
578
+ id=evaluation_model.id,
579
+ name=evaluation_model.display_name,
580
+ console_url=get_console_link(
581
+ resource=Resource.MODEL,
582
+ ocid=evaluation_model.id,
583
+ region=self.region,
584
+ ),
585
+ time_created=str(evaluation_model.dsc_model.time_created),
586
+ lifecycle_state=evaluation_job_run.lifecycle_state or UNKNOWN,
587
+ lifecycle_details=evaluation_job_run.lifecycle_details or UNKNOWN,
588
+ experiment=AquaResourceIdentifier(
589
+ id=experiment_model_version_set_id,
590
+ name=experiment_model_version_set_name,
591
+ url=get_console_link(
592
+ resource=Resource.MODEL_VERSION_SET,
593
+ ocid=experiment_model_version_set_id,
594
+ region=self.region,
595
+ ),
596
+ ),
597
+ source=AquaResourceIdentifier(
598
+ id=create_aqua_evaluation_details.evaluation_source_id,
599
+ name=evaluation_source.display_name,
600
+ url=get_console_link(
601
+ resource=(
602
+ Resource.MODEL_DEPLOYMENT
603
+ if DataScienceResource.MODEL_DEPLOYMENT
604
+ in create_aqua_evaluation_details.evaluation_source_id
605
+ else Resource.MODEL
606
+ ),
607
+ ocid=create_aqua_evaluation_details.evaluation_source_id,
608
+ region=self.region,
609
+ ),
610
+ ),
611
+ job=AquaResourceIdentifier(
612
+ id=evaluation_job.id,
613
+ name=evaluation_job.name,
614
+ url=get_console_link(
615
+ resource=Resource.JOB,
616
+ ocid=evaluation_job.id,
617
+ region=self.region,
618
+ ),
619
+ ),
620
+ tags={
621
+ "aqua_evaluation": Tags.AQUA_EVALUATION,
622
+ "evaluation_job_id": evaluation_job.id,
623
+ "evaluation_source": create_aqua_evaluation_details.evaluation_source_id,
624
+ "evaluation_experiment_id": experiment_model_version_set_id,
625
+ **evaluation_model_freeform_tags,
626
+ **evaluation_model_defined_tags,
627
+ },
628
+ parameters=AquaEvalParams(),
629
+ )
630
+
631
+ @staticmethod
632
+ def validate_model_name(
633
+ evaluation_source: DataScienceModel,
634
+ create_aqua_evaluation_details: CreateAquaEvaluationDetails,
635
+ ) -> None:
636
+ """
637
+ Validates the user input for the model name when creating an Aqua evaluation.
638
+
639
+ This function verifies that:
640
+ - The model group is not empty.
641
+ - The model multi metadata is present in the DataScienceModel metadata.
642
+ - The user provided a non-empty model name.
643
+ - The provided model name exists in the DataScienceModel metadata.
644
+ - The deployment configuration contains core metadata required for validation.
645
+
646
+ Parameters
647
+ ----------
648
+ evaluation_source : DataScienceModel
649
+ The DataScienceModel object containing metadata about each model in the deployment.
650
+ create_aqua_evaluation_details : CreateAquaEvaluationDetails
651
+ Contains required and optional fields for creating the Aqua evaluation.
652
+
653
+ Raises
654
+ ------
655
+ AquaValueError
656
+ If the user fails to provide a model name or if the provided model name does not match
657
+ any of the valid model names in the deployment metadata.
658
+ AquaRuntimeError
659
+ If the metadata is missing the model group count or if the model group count is invalid.
660
+ """
661
+ user_model_parameters = create_aqua_evaluation_details.model_parameters
662
+ custom_metadata_list = evaluation_source.custom_metadata_list
663
+ user_model_name = user_model_parameters.get("model")
664
+
665
+ # Ensure that a non-empty model name was provided.
666
+ if not user_model_name:
667
+ error_message = (
668
+ "No model name was provided for evaluation. For multi-model deployment, "
669
+ "a model must be specified in the model parameters."
670
+ )
671
+ logger.debug(error_message)
672
+ raise AquaValueError(error_message)
673
+
674
+ # Retrieve and convert the model group count from metadata.
675
+ model_count = custom_metadata_list.get(
676
+ ModelCustomMetadataFields.MULTIMODEL_GROUP_COUNT
677
+ )
678
+ try:
679
+ model_group_count = int(model_count.value)
680
+ except Exception as ex:
681
+ error_message = (
682
+ "Missing or invalid `MULTIMODEL_GROUP_COUNT` "
683
+ f"in custom metadata for evaluation source ID '{create_aqua_evaluation_details.evaluation_source_id}'. "
684
+ f"Details: {ex}"
685
+ )
686
+ logger.error(error_message)
687
+
688
+ if model_group_count < 1:
689
+ logger.error(
690
+ f"Invalid model group count: {model_group_count} for evaluation source ID "
691
+ f"'{create_aqua_evaluation_details.evaluation_source_id}'. A valid multi-model deployment "
692
+ f"requires at least one model."
693
+ )
694
+ raise AquaRuntimeError(
695
+ f"Unable to retrieve details for the multi-model deployment evaluation. A valid multi-model deployment "
696
+ f"must include at least one model. However, the provided evaluation source ID "
697
+ f"'{create_aqua_evaluation_details.evaluation_source_id}' does not contain any information about deployed models."
698
+ )
699
+
700
+ multi_model_metadata_value = custom_metadata_list.get(
701
+ ModelCustomMetadataFields.MULTIMODEL_METADATA,
702
+ ModelCustomMetadataItem(key=ModelCustomMetadataFields.MULTIMODEL_METADATA),
703
+ ).value
704
+
705
+ if not multi_model_metadata_value:
706
+ error_message = (
707
+ f"Required model metadata is missing for evaluation source ID: {evaluation_source.id}. "
708
+ f"A valid multi-model deployment requires {ModelCustomMetadataFields.MULTIMODEL_METADATA}. "
709
+ "Please recreate the model deployment and retry the evaluation, as an issue occurred during the initialization of the model group."
710
+ )
711
+ logger.debug(error_message)
712
+ raise AquaRuntimeError(error_message)
713
+
714
+ try:
715
+ multi_model_metadata = json.loads(
716
+ evaluation_source.dsc_model.get_custom_metadata_artifact(
717
+ metadata_key_name=ModelCustomMetadataFields.MULTIMODEL_METADATA
718
+ ).decode("utf-8")
719
+ )
720
+ except Exception as ex:
721
+ error_message = (
722
+ f"Error fetching {ModelCustomMetadataFields.MULTIMODEL_METADATA} "
723
+ f"from custom metadata for evaluation source ID '{evaluation_source.id}'. "
724
+ f"Details: {ex}"
725
+ )
726
+ logger.error(error_message)
727
+ raise AquaRuntimeError(error_message) from ex
728
+
729
+ # Build the list of valid model names from custom metadata.
730
+ model_names = [
731
+ AquaMultiModelRef(**metadata).model_name
732
+ for metadata in multi_model_metadata
733
+ ]
734
+
735
+ # Check if the provided model name is among the valid names.
736
+ if user_model_name not in model_names:
737
+ error_message = (
738
+ f"Provided model name '{user_model_name}' does not match any valid model names {model_names} "
739
+ f"for evaluation source ID '{create_aqua_evaluation_details.evaluation_source_id}'. "
740
+ "Please provide the correct model name."
741
+ )
742
+ logger.debug(error_message)
743
+ raise AquaValueError(error_message)
744
+
745
+ def _build_evaluation_runtime(
746
+ self,
747
+ evaluation_id: str,
748
+ evaluation_source_id: str,
749
+ container_image: str,
750
+ dataset_path: str,
751
+ report_path: str,
752
+ model_parameters: dict,
753
+ metrics: List = None,
754
+ inference_configuration: dict = None,
755
+ ) -> Runtime:
756
+ """Builds evaluation runtime for Job."""
757
+ # TODO the image name needs to be extracted from the mapping index.json file.
758
+ runtime = (
759
+ ContainerRuntime()
760
+ .with_image(container_image)
761
+ .with_environment_variable(
762
+ **{
763
+ "AIP_SMC_EVALUATION_ARGUMENTS": json.dumps(
764
+ {
765
+ **self._build_launch_cmd(
766
+ evaluation_id=evaluation_id,
767
+ evaluation_source_id=evaluation_source_id,
768
+ dataset_path=dataset_path,
769
+ report_path=report_path,
770
+ model_parameters=model_parameters,
771
+ metrics=metrics,
772
+ ).to_dict(),
773
+ **(inference_configuration or {}),
774
+ },
775
+ ),
776
+ "CONDA_BUCKET_NS": CONDA_BUCKET_NS,
777
+ },
778
+ )
779
+ )
780
+
781
+ return runtime
782
+
783
+ @staticmethod
784
+ def _get_service_model_name(
785
+ source: Union[ModelDeployment, DataScienceModel],
786
+ ) -> str:
787
+ """Gets the service model name from source. If it's ModelDeployment, needs to check
788
+ if its model has been fine tuned or not.
789
+
790
+ Parameters
791
+ ----------
792
+ source: Union[ModelDeployment, DataScienceModel]
793
+ An instance of either ModelDeployment or DataScienceModel
794
+
795
+ Returns
796
+ -------
797
+ str:
798
+ The service model name of source.
799
+ """
800
+ if isinstance(source, ModelDeployment):
801
+ fine_tuned_model_tag = source.freeform_tags.get(
802
+ Tags.AQUA_FINE_TUNED_MODEL_TAG, UNKNOWN
803
+ )
804
+ if not fine_tuned_model_tag:
805
+ return source.freeform_tags.get(Tags.AQUA_MODEL_NAME_TAG)
806
+ else:
807
+ return extract_id_and_name_from_tag(fine_tuned_model_tag)[1]
808
+
809
+ return source.display_name
810
+
811
+ def _get_evaluation_container(self, source_id: str) -> str:
812
+ # todo: use the source, identify if it is a model or a deployment. If latter, then fetch the base model id
813
+ # from the deployment object, and call ds_client.get_model() to get model details. Use custom metadata to
814
+ # get the container_type_key. Pass this key as container_type to get_container_image method.
815
+
816
+ # fetch image name from config
817
+ container_image = self.get_container_image(
818
+ container_type="odsc-llm-evaluate",
819
+ )
820
+ logger.info(f"Aqua Image used for evaluating {source_id} :{container_image}")
821
+ return container_image
822
+
823
+ def _build_launch_cmd(
824
+ self,
825
+ evaluation_id: str,
826
+ evaluation_source_id: str,
827
+ dataset_path: str,
828
+ report_path: str,
829
+ model_parameters: dict,
830
+ metrics: List = None,
831
+ ):
832
+ return AquaEvaluationCommands(
833
+ evaluation_id=evaluation_id,
834
+ evaluation_target_id=evaluation_source_id,
835
+ input_data={
836
+ "format": Path(dataset_path).suffix,
837
+ "url": dataset_path,
838
+ },
839
+ metrics=metrics or [],
840
+ output_dir=report_path,
841
+ params=model_parameters or {},
842
+ )
843
+
844
+ @telemetry(entry_point="plugin=evaluation&action=get", name="aqua")
845
+ def get(self, eval_id) -> AquaEvaluationDetail:
846
+ """Gets the information of an Aqua evalution.
847
+
848
+ Parameters
849
+ ----------
850
+ eval_id: str
851
+ The model OCID.
852
+
853
+ Returns
854
+ -------
855
+ AquaEvaluationDetail:
856
+ The instance of AquaEvaluationDetail.
857
+ """
858
+ logger.info(f"Fetching evaluation: {eval_id} details ...")
859
+
860
+ resource = utils.query_resource(eval_id)
861
+ if not resource:
862
+ raise AquaRuntimeError(
863
+ f"Failed to retrieve evalution {eval_id}."
864
+ "Please check if the OCID is correct."
865
+ )
866
+ model_provenance = self.ds_client.get_model_provenance(eval_id).data
867
+
868
+ jobrun_id = model_provenance.training_id
869
+ job_run_details = self._fetch_jobrun(
870
+ resource, use_rqs=False, jobrun_id=jobrun_id
871
+ )
872
+
873
+ try:
874
+ log_id = job_run_details.log_details.log_id
875
+ except Exception as e:
876
+ logger.debug(f"Failed to get associated log. {str(e)}")
877
+ log_id = ""
878
+
879
+ try:
880
+ loggroup_id = job_run_details.log_details.log_group_id
881
+ except Exception as e:
882
+ logger.debug(f"Failed to get associated loggroup. {str(e)}")
883
+ loggroup_id = ""
884
+
885
+ loggroup_url = get_log_links(region=self.region, log_group_id=loggroup_id)
886
+ log_url = (
887
+ get_log_links(
888
+ region=self.region,
889
+ log_group_id=loggroup_id,
890
+ log_id=log_id,
891
+ compartment_id=job_run_details.compartment_id,
892
+ source_id=jobrun_id,
893
+ )
894
+ if job_run_details
895
+ else ""
896
+ )
897
+
898
+ log_name = None
899
+ loggroup_name = None
900
+
901
+ if log_id:
902
+ try:
903
+ log = utils.query_resource(log_id, return_all=False)
904
+ log_name = log.display_name if log else ""
905
+ except Exception as ex:
906
+ logger.debug(f"Failed to get associated log name. Error: {ex}")
907
+ pass
908
+
909
+ if loggroup_id:
910
+ try:
911
+ loggroup = utils.query_resource(loggroup_id, return_all=False)
912
+ loggroup_name = loggroup.display_name if loggroup else ""
913
+ except Exception as ex:
914
+ logger.debug(f"Failed to get associated loggroup name. Error: {ex}")
915
+ pass
916
+
917
+ try:
918
+ introspection = json.loads(
919
+ self._get_attribute_from_model_metadata(resource, "ArtifactTestResults")
920
+ )
921
+ except Exception as ex:
922
+ logger.debug(
923
+ f"There was an issue loading the model attribute as json object for evaluation {eval_id}. "
924
+ f"Setting introspection to empty.\n Error:{ex}"
925
+ )
926
+ introspection = {}
927
+
928
+ summary = AquaEvaluationDetail(
929
+ **self._process(resource),
930
+ **self._get_status(model=resource, jobrun=job_run_details),
931
+ job=self._build_job_identifier(
932
+ job_run_details=job_run_details,
933
+ ),
934
+ log_group=AquaResourceIdentifier(loggroup_id, loggroup_name, loggroup_url),
935
+ log=AquaResourceIdentifier(log_id, log_name, log_url),
936
+ introspection=introspection,
937
+ )
938
+ summary.parameters.shape = (
939
+ job_run_details.job_infrastructure_configuration_details.shape_name
940
+ )
941
+ return summary
942
+
943
+ @telemetry(entry_point="plugin=evaluation&action=list", name="aqua")
944
+ def list(self, compartment_id: str = None) -> List[AquaEvaluationSummary]:
945
+ """List Aqua evaluations in a given compartment and under certain project.
946
+
947
+ Parameters
948
+ ----------
949
+ compartment_id: (str, optional). Defaults to `None`.
950
+ The compartment OCID.
951
+
952
+ Returns
953
+ -------
954
+ List[AquaEvaluationSummary]:
955
+ The list of the `ads.aqua.evalution.AquaEvaluationSummary`.
956
+ """
957
+ compartment_id = compartment_id or COMPARTMENT_OCID
958
+ logger.info(f"Fetching evaluations from compartment {compartment_id}.")
959
+ models = utils.query_resources(
960
+ compartment_id=compartment_id,
961
+ resource_type="datasciencemodel",
962
+ tag_list=[Tags.AQUA_EVALUATION],
963
+ )
964
+ logger.info(f"Fetched {len(models)} evaluations.")
965
+
966
+ mapping = self._prefetch_resources(compartment_id)
967
+
968
+ evaluations = []
969
+ async_tasks = []
970
+ for model in models:
971
+ if model.identifier in self._eval_cache:
972
+ logger.debug(f"Retrieving evaluation {model.identifier} from cache.")
973
+ evaluations.append(self._eval_cache.get(model.identifier))
974
+
975
+ else:
976
+ jobrun_id = self._get_attribute_from_model_metadata(
977
+ model, EvaluationCustomMetadata.EVALUATION_JOB_RUN_ID
978
+ )
979
+ job_run = mapping.get(jobrun_id)
980
+
981
+ if not job_run:
982
+ async_tasks.append((model, jobrun_id))
983
+ else:
984
+ evaluations.append(self._process_evaluation_summary(model, job_run))
985
+
986
+ with ThreadPoolExecutor(max_workers=10) as executor:
987
+ future_to_model = {
988
+ executor.submit(
989
+ self._fetch_jobrun, model, use_rqs=True, jobrun_id=jobrun_id
990
+ ): model
991
+ for model, jobrun_id in async_tasks
992
+ }
993
+ for future in as_completed(future_to_model):
994
+ model = future_to_model[future]
995
+ try:
996
+ jobrun = future.result()
997
+ evaluations.append(
998
+ self._process_evaluation_summary(model=model, jobrun=jobrun)
999
+ )
1000
+ except Exception as exc:
1001
+ logger.debug(
1002
+ f"Processing evaluation: {model.identifier} generated an exception: {exc}"
1003
+ )
1004
+ evaluations.append(
1005
+ self._process_evaluation_summary(model=model, jobrun=None)
1006
+ )
1007
+
1008
+ # tracks number of times deployment listing was called
1009
+ self.telemetry.record_event_async(category="aqua/evaluation", action="list")
1010
+
1011
+ return evaluations
1012
+
1013
+ def _process_evaluation_summary(
1014
+ self,
1015
+ model: oci.resource_search.models.ResourceSummary,
1016
+ jobrun: oci.resource_search.models.ResourceSummary = None,
1017
+ ) -> AquaEvaluationSummary:
1018
+ """Builds AquaEvaluationSummary from model and jobrun."""
1019
+
1020
+ evaluation_summary = AquaEvaluationSummary(
1021
+ **self._process(model),
1022
+ **self._get_status(
1023
+ model=model,
1024
+ jobrun=jobrun,
1025
+ ),
1026
+ job=self._build_job_identifier(
1027
+ job_run_details=jobrun,
1028
+ ),
1029
+ )
1030
+
1031
+ # Add evaluation in terminal state into cache
1032
+ if evaluation_summary.lifecycle_state in EVAL_TERMINATION_STATE:
1033
+ self._eval_cache.__setitem__(key=model.identifier, value=evaluation_summary)
1034
+
1035
+ return evaluation_summary
1036
+
1037
+ def _if_eval_artifact_exist(
1038
+ self, model: oci.resource_search.models.ResourceSummary
1039
+ ) -> bool:
1040
+ """Checks if the evaluation artifact exists."""
1041
+ try:
1042
+ response = self.ds_client.head_model_artifact(model_id=model.identifier)
1043
+ return response.status == 200
1044
+ except oci.exceptions.ServiceError as ex:
1045
+ if ex.status == 404:
1046
+ logger.debug(f"Evaluation artifact not found for {model.identifier}.")
1047
+ return False
1048
+
1049
+ @telemetry(entry_point="plugin=evaluation&action=get_status", name="aqua")
1050
+ def get_status(self, eval_id: str) -> dict:
1051
+ """Gets evaluation's current status.
1052
+
1053
+ Parameters
1054
+ ----------
1055
+ eval_id: str
1056
+ The evaluation ocid.
1057
+
1058
+ Returns
1059
+ -------
1060
+ dict
1061
+ """
1062
+ eval = utils.query_resource(eval_id)
1063
+
1064
+ if not eval:
1065
+ raise AquaRuntimeError(
1066
+ f"Failed to retrieve evalution {eval_id}."
1067
+ "Please check if the OCID is correct."
1068
+ )
1069
+
1070
+ model_provenance = self.ds_client.get_model_provenance(eval_id).data
1071
+
1072
+ jobrun_id = model_provenance.training_id
1073
+ job_run_details = self._fetch_jobrun(eval, use_rqs=False, jobrun_id=jobrun_id)
1074
+
1075
+ try:
1076
+ log_id = job_run_details.log_details.log_id
1077
+ except Exception as e:
1078
+ logger.debug(f"Failed to get associated log.\nError: {str(e)}")
1079
+ log_id = ""
1080
+
1081
+ try:
1082
+ loggroup_id = job_run_details.log_details.log_group_id
1083
+ except Exception as e:
1084
+ logger.debug(f"Failed to get associated log.\nError: {str(e)}")
1085
+ loggroup_id = ""
1086
+
1087
+ loggroup_url = get_log_links(region=self.region, log_group_id=loggroup_id)
1088
+ log_url = (
1089
+ get_log_links(
1090
+ region=self.region,
1091
+ log_group_id=loggroup_id,
1092
+ log_id=log_id,
1093
+ compartment_id=job_run_details.compartment_id,
1094
+ source_id=jobrun_id,
1095
+ )
1096
+ if job_run_details
1097
+ else ""
1098
+ )
1099
+ return {
1100
+ "id": eval_id,
1101
+ **self._get_status(
1102
+ model=eval,
1103
+ jobrun=job_run_details,
1104
+ ),
1105
+ "log_id": log_id,
1106
+ "log_url": log_url,
1107
+ "loggroup_id": loggroup_id,
1108
+ "loggroup_url": loggroup_url,
1109
+ }
1110
+
1111
+ def get_supported_metrics(self) -> List[MetricConfig]:
1112
+ """Gets a list of supported metrics for evaluation."""
1113
+ containers = self.list_service_containers()
1114
+ container_item = next(
1115
+ c
1116
+ for c in containers
1117
+ if c.is_latest and c.family_name == DEFAULT_EVALUATION_CONTAINER
1118
+ )
1119
+ evaluation_service_config = EvaluationServiceConfig.from_oci_container_config(
1120
+ container_item
1121
+ )
1122
+ return evaluation_service_config.ui_config.metrics
1123
+
1124
+ @telemetry(entry_point="plugin=evaluation&action=load_metrics", name="aqua")
1125
+ def load_metrics(self, eval_id: str) -> AquaEvalMetrics:
1126
+ """Loads evalution metrics markdown from artifacts.
1127
+
1128
+ Parameters
1129
+ ----------
1130
+ eval_id: str
1131
+ The evaluation ocid.
1132
+
1133
+ Returns
1134
+ -------
1135
+ AquaEvalMetrics:
1136
+ An instance of AquaEvalMetrics.
1137
+ """
1138
+ if eval_id in self._metrics_cache:
1139
+ logger.info("Returning metrics from cache.")
1140
+ eval_metrics = self._metrics_cache.get(eval_id)
1141
+ if len(eval_metrics.report) > 0:
1142
+ return eval_metrics
1143
+
1144
+ with tempfile.TemporaryDirectory() as temp_dir:
1145
+ logger.info(f"Downloading evaluation artifact: {eval_id}.")
1146
+
1147
+ dsc_model = DataScienceModel.from_id(eval_id)
1148
+ if dsc_model.if_model_custom_metadata_artifact_exist(
1149
+ EVALUATION_REPORT_MD
1150
+ ) and dsc_model.if_model_custom_metadata_artifact_exist(
1151
+ EVALUATION_REPORT_JSON
1152
+ ):
1153
+ logger.info(
1154
+ f"Fetching {EVALUATION_REPORT_MD} and {EVALUATION_REPORT_JSON} from custom metadata..."
1155
+ )
1156
+ dsc_model.get_custom_metadata_artifact(EVALUATION_REPORT_MD, temp_dir)
1157
+ dsc_model.get_custom_metadata_artifact(EVALUATION_REPORT_JSON, temp_dir)
1158
+ else:
1159
+ logger.info("Fetching Evaluation Reports from OSS bucket...")
1160
+ dsc_model.download_artifact(
1161
+ temp_dir,
1162
+ auth=self._auth,
1163
+ )
1164
+
1165
+ files_in_artifact = get_files(temp_dir)
1166
+ md_report_content = self._read_from_artifact(
1167
+ temp_dir, files_in_artifact, EVALUATION_REPORT_MD
1168
+ )
1169
+
1170
+ # json report not available for failed evaluation
1171
+ try:
1172
+ json_report = json.loads(
1173
+ self._read_from_artifact(
1174
+ temp_dir, files_in_artifact, EVALUATION_REPORT_JSON
1175
+ )
1176
+ )
1177
+ except Exception as e:
1178
+ logger.debug(
1179
+ f"Failed to load `report.json` from evaluation artifact.\nError: {str(e)}"
1180
+ )
1181
+ json_report = {}
1182
+
1183
+ eval_metrics = AquaEvalMetrics(
1184
+ id=eval_id,
1185
+ report=base64.b64encode(md_report_content).decode(),
1186
+ metric_results=[
1187
+ AquaEvalMetric(
1188
+ key=metadata.get(EvaluationMetricResult.SHORT_NAME, utils.UNKNOWN),
1189
+ name=metadata.get(EvaluationMetricResult.NAME, utils.UNKNOWN),
1190
+ description=metadata.get(
1191
+ EvaluationMetricResult.DESCRIPTION, utils.UNKNOWN
1192
+ ),
1193
+ )
1194
+ for _, metadata in json_report.get(
1195
+ EvaluationReportJson.METRIC_RESULT, {}
1196
+ ).items()
1197
+ ],
1198
+ metric_summary_result=[
1199
+ AquaEvalMetricSummary(**m)
1200
+ for m in json_report.get(
1201
+ EvaluationReportJson.METRIC_SUMMARY_RESULT, [{}]
1202
+ )
1203
+ ],
1204
+ )
1205
+
1206
+ if md_report_content:
1207
+ self._metrics_cache.__setitem__(key=eval_id, value=eval_metrics)
1208
+
1209
+ return eval_metrics
1210
+
1211
+ def _read_from_artifact(self, artifact_dir, files, target):
1212
+ """Reads target file from artifacts.
1213
+
1214
+ Parameters
1215
+ ----------
1216
+ artifact_dir: str
1217
+ Path of the artifact.
1218
+ files: list
1219
+ List of files name in artifacts.
1220
+ target: str
1221
+ Target file name.
1222
+
1223
+ Return
1224
+ ------
1225
+ bytes
1226
+ """
1227
+ content = None
1228
+ for f in files:
1229
+ if os.path.basename(f) == target:
1230
+ logger.info(f"Reading {f}...")
1231
+ with open(os.path.join(artifact_dir, f), "rb") as f:
1232
+ content = f.read()
1233
+ break
1234
+
1235
+ if not content:
1236
+ raise AquaFileNotFoundError(
1237
+ "Related Resource Not Authorized Or Not Found:"
1238
+ f"Missing `{target}` in evaluation artifact."
1239
+ )
1240
+ return content
1241
+
1242
+ @telemetry(entry_point="plugin=evaluation&action=download_report", name="aqua")
1243
+ def download_report(self, eval_id) -> AquaEvalReport:
1244
+ """Downloads HTML report from model artifact.
1245
+
1246
+ Parameters
1247
+ ----------
1248
+ eval_id: str
1249
+ The evaluation ocid.
1250
+
1251
+ Returns
1252
+ -------
1253
+ AquaEvalReport:
1254
+ An instance of AquaEvalReport.
1255
+
1256
+ Raises
1257
+ ------
1258
+ AquaFileNotFoundError:
1259
+ When missing `report.html` in evaluation artifact.
1260
+ """
1261
+ if eval_id in self._report_cache:
1262
+ logger.info("Returning report from cache.")
1263
+ report = self._report_cache.get(eval_id)
1264
+ if report.content:
1265
+ return report
1266
+
1267
+ with tempfile.TemporaryDirectory() as temp_dir:
1268
+ logger.info(f"Downloading evaluation artifact for {eval_id}.")
1269
+ dsc_model = DataScienceModel.from_id(eval_id)
1270
+ if_custom_metadata_exists = (
1271
+ dsc_model.if_model_custom_metadata_artifact_exist(EVALUATION_REPORT)
1272
+ )
1273
+ if if_custom_metadata_exists:
1274
+ logger.info(f"Fetching {EVALUATION_REPORT} from custom metadata.")
1275
+ dsc_model.get_custom_metadata_artifact(EVALUATION_REPORT, temp_dir)
1276
+ else:
1277
+ logger.info(f"Fetching {EVALUATION_REPORT} from Model artifact.")
1278
+ dsc_model.download_artifact(
1279
+ temp_dir,
1280
+ auth=self._auth,
1281
+ )
1282
+ files_in_artifact = get_files(temp_dir)
1283
+ if not len(files_in_artifact):
1284
+ try:
1285
+ evaluation_output_path = dsc_model.custom_metadata_list.get(
1286
+ EvaluationCustomMetadata.EVALUATION_OUTPUT_PATH
1287
+ ).value
1288
+ report_path = (
1289
+ evaluation_output_path.rstrip("/")
1290
+ + "/"
1291
+ + eval_id
1292
+ + "/"
1293
+ + EVALUATION_REPORT
1294
+ )
1295
+ logger.info(
1296
+ f"Fetching {EVALUATION_REPORT} from {report_path} for evaluation {eval_id}"
1297
+ )
1298
+ content = read_file(
1299
+ file_path=report_path, auth=default_signer()
1300
+ ).encode()
1301
+ except ValueError as err:
1302
+ raise AquaValueError(
1303
+ f"{EvaluationCustomMetadata.EVALUATION_OUTPUT_PATH} is missing from custom metadata for the model {eval_id}"
1304
+ ) from err
1305
+ else:
1306
+ content = self._read_from_artifact(
1307
+ temp_dir, files_in_artifact, EVALUATION_REPORT
1308
+ )
1309
+ report = AquaEvalReport(
1310
+ evaluation_id=eval_id, content=base64.b64encode(content).decode()
1311
+ )
1312
+
1313
+ self._report_cache.__setitem__(key=eval_id, value=report)
1314
+
1315
+ return report
1316
+
1317
+ @telemetry(entry_point="plugin=evaluation&action=cancel", name="aqua")
1318
+ def cancel(self, eval_id) -> dict:
1319
+ """Cancels the job run for the given evaluation id.
1320
+ Parameters
1321
+ ----------
1322
+ eval_id: str
1323
+ The evaluation ocid.
1324
+
1325
+ Returns
1326
+ -------
1327
+ dict containing id, status and time_accepted
1328
+
1329
+ Raises
1330
+ ------
1331
+ AquaRuntimeError:
1332
+ if a model doesn't exist for the given eval_id
1333
+ AquaMissingKeyError:
1334
+ if training_id is missing the job run id
1335
+ """
1336
+ model = DataScienceModel.from_id(eval_id)
1337
+ if not model:
1338
+ raise AquaRuntimeError(
1339
+ f"Failed to get evaluation details for model {eval_id}"
1340
+ )
1341
+
1342
+ job_run_id = (
1343
+ model.provenance_metadata.training_id if model.provenance_metadata else None
1344
+ )
1345
+ if not job_run_id:
1346
+ raise AquaMissingKeyError(
1347
+ "Model provenance is missing job run training_id key"
1348
+ )
1349
+
1350
+ status = {"id": eval_id, "lifecycle_state": UNKNOWN, "time_accepted": UNKNOWN}
1351
+ run = DataScienceJobRun.from_ocid(job_run_id)
1352
+ if run.lifecycle_state in [
1353
+ DataScienceJobRun.LIFECYCLE_STATE_ACCEPTED,
1354
+ DataScienceJobRun.LIFECYCLE_STATE_IN_PROGRESS,
1355
+ DataScienceJobRun.LIFECYCLE_STATE_NEEDS_ATTENTION,
1356
+ ]:
1357
+ self._cancel_job_run(run, model)
1358
+ status = {
1359
+ "id": eval_id,
1360
+ "lifecycle_state": "CANCELING",
1361
+ "time_accepted": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f%z"),
1362
+ }
1363
+ return status
1364
+
1365
+ @staticmethod
1366
+ @fire_and_forget
1367
+ def _cancel_job_run(run, model):
1368
+ try:
1369
+ run.cancel()
1370
+ logger.info(f"Canceling Job Run: {run.id} for evaluation {model.id}")
1371
+ except oci.exceptions.ServiceError as ex:
1372
+ logger.error(
1373
+ f"Exception occurred while canceling job run: {run.id} for evaluation {model.id}. "
1374
+ f"Exception message: {ex}"
1375
+ )
1376
+
1377
+ @telemetry(entry_point="plugin=evaluation&action=delete", name="aqua")
1378
+ def delete(self, eval_id):
1379
+ """Deletes the job and the associated model for the given evaluation id.
1380
+
1381
+ Parameters
1382
+ ----------
1383
+ eval_id: str
1384
+ The evaluation ocid.
1385
+
1386
+ Returns
1387
+ -------
1388
+ dict containing id, status and time_accepted
1389
+
1390
+ Raises
1391
+ ------
1392
+ AquaRuntimeError:
1393
+ if a model doesn't exist for the given eval_id.
1394
+ AquaMissingKeyError:
1395
+ if job/jobrun id is missing.
1396
+ """
1397
+
1398
+ model = DataScienceModel.from_id(eval_id)
1399
+ if not model:
1400
+ raise AquaRuntimeError(
1401
+ f"Failed to get evaluation details for model {eval_id}"
1402
+ )
1403
+
1404
+ try:
1405
+ job_id = model.custom_metadata_list.get(
1406
+ EvaluationCustomMetadata.EVALUATION_JOB_ID
1407
+ ).value
1408
+ except Exception as ex:
1409
+ raise AquaMissingKeyError(
1410
+ f"Custom metadata is missing {EvaluationCustomMetadata.EVALUATION_JOB_ID} key"
1411
+ ) from ex
1412
+
1413
+ job = DataScienceJob.from_id(job_id)
1414
+
1415
+ self._delete_job_and_model(job, model)
1416
+
1417
+ try:
1418
+ jobrun_id = model.custom_metadata_list.get(
1419
+ EvaluationCustomMetadata.EVALUATION_JOB_RUN_ID
1420
+ ).value
1421
+ jobrun = utils.query_resource(jobrun_id, return_all=False)
1422
+ except Exception:
1423
+ logger.debug("Associated Job Run OCID is missing.")
1424
+ jobrun = None
1425
+
1426
+ self._eval_cache.pop(key=eval_id, default=None)
1427
+ self._deletion_cache.__setitem__(key=eval_id, value="")
1428
+
1429
+ status = {
1430
+ "id": eval_id,
1431
+ "lifecycle_state": jobrun.lifecycle_state if jobrun else "DELETING",
1432
+ "time_accepted": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f%z"),
1433
+ }
1434
+ return status
1435
+
1436
+ @staticmethod
1437
+ @fire_and_forget
1438
+ def _delete_job_and_model(job: DataScienceJob, model: DataScienceModel):
1439
+ try:
1440
+ job.dsc_job.delete(force_delete=True)
1441
+ logger.info(f"Deleting Job: {job.job_id} for evaluation {model.id}")
1442
+ model.delete()
1443
+ logger.info(f"Deleting evaluation: {model.id}")
1444
+ except oci.exceptions.ServiceError as ex:
1445
+ logger.error(
1446
+ f"Exception occurred while deleting job: {job.job_id} for evaluation {model.id}. "
1447
+ f"Exception message: {ex}"
1448
+ )
1449
+
1450
+ def load_evaluation_config(
1451
+ self, container: Optional[str] = DEFAULT_EVALUATION_CONTAINER
1452
+ ) -> Dict:
1453
+ """Loads evaluation config."""
1454
+
1455
+ logger.info("Loading evaluation container config.")
1456
+ # retrieve the evaluation config by container family name
1457
+ containers = self.list_service_containers()
1458
+ container_item = next(
1459
+ c for c in containers if c.is_latest and c.family_name == container
1460
+ )
1461
+ evaluation_config = EvaluationServiceConfig.from_oci_container_config(
1462
+ container_item
1463
+ )
1464
+
1465
+ # convert the new config representation to the old one
1466
+ return {
1467
+ "model_params": evaluation_config.ui_config.model_params.default,
1468
+ "shape": {
1469
+ shape.name: shape.to_dict()
1470
+ for shape in evaluation_config.ui_config.shapes
1471
+ },
1472
+ "default": (
1473
+ evaluation_config.ui_config.shapes[0].to_dict()
1474
+ if len(evaluation_config.ui_config.shapes) > 0
1475
+ else {}
1476
+ ),
1477
+ }
1478
+
1479
+ def _get_attribute_from_model_metadata(
1480
+ self,
1481
+ model: oci.resource_search.models.ResourceSummary,
1482
+ target_attribute: str,
1483
+ ) -> str:
1484
+ try:
1485
+ return self._extract_metadata(
1486
+ model.additional_details.get(RqsAdditionalDetails.METADATA),
1487
+ target_attribute,
1488
+ )
1489
+ except Exception:
1490
+ logger.debug(
1491
+ f"Missing `{target_attribute}` in custom metadata of the evaluation."
1492
+ f"Evaluation id: {model.identifier} "
1493
+ )
1494
+ return ""
1495
+
1496
+ def _extract_metadata(self, metadata_list: List[Dict], key: str) -> Any:
1497
+ for metadata in metadata_list:
1498
+ if metadata.get("key") == key:
1499
+ return metadata.get("value")
1500
+ raise AquaMissingKeyError(
1501
+ f"Missing `{key}` in custom metadata of the evaluation."
1502
+ )
1503
+
1504
+ def _get_source(
1505
+ self,
1506
+ evaluation: oci.resource_search.models.ResourceSummary,
1507
+ resources_mapping: dict = None,
1508
+ ) -> tuple:
1509
+ """Returns ocid and name of the model has been evaluated."""
1510
+ source_id = self._get_attribute_from_model_metadata(
1511
+ evaluation,
1512
+ EvaluationCustomMetadata.EVALUATION_SOURCE,
1513
+ )
1514
+
1515
+ try:
1516
+ source_name = None
1517
+ if resources_mapping:
1518
+ source = resources_mapping.get(source_id)
1519
+ source_name = (
1520
+ source.display_name
1521
+ if source
1522
+ else self._get_attribute_from_model_metadata(
1523
+ evaluation, EvaluationCustomMetadata.EVALUATION_SOURCE_NAME
1524
+ )
1525
+ )
1526
+
1527
+ # try to resolve source_name from source id
1528
+ if source_id and not source_name:
1529
+ resource_type = utils.get_resource_type(source_id)
1530
+
1531
+ if resource_type.startswith("datasciencemodeldeployment"):
1532
+ source_name = self.ds_client.get_model_deployment(
1533
+ source_id
1534
+ ).data.display_name
1535
+ elif resource_type.startswith("datasciencemodel"):
1536
+ source_name = self.ds_client.get_model(source_id).data.display_name
1537
+ else:
1538
+ raise AquaRuntimeError(
1539
+ f"Not supported source type: {resource_type}"
1540
+ )
1541
+ except Exception as ex:
1542
+ logger.debug(
1543
+ f"Failed to retrieve source information for evaluation {evaluation.identifier}.\nError: {str(ex)}"
1544
+ )
1545
+ source_name = ""
1546
+
1547
+ return source_id, source_name
1548
+
1549
+ def _get_experiment_info(
1550
+ self, model: oci.resource_search.models.ResourceSummary
1551
+ ) -> tuple:
1552
+ """Returns ocid and name of the experiment."""
1553
+ return (
1554
+ model.additional_details.get(RqsAdditionalDetails.MODEL_VERSION_SET_ID),
1555
+ model.additional_details.get(RqsAdditionalDetails.MODEL_VERSION_SET_NAME),
1556
+ )
1557
+
1558
+ def _process(
1559
+ self,
1560
+ model: oci.resource_search.models.ResourceSummary,
1561
+ resources_mapping: dict = None,
1562
+ ) -> dict:
1563
+ """Constructs AquaEvaluationSummary from `oci.resource_search.models.ResourceSummary`."""
1564
+
1565
+ tags = {}
1566
+ tags.update(model.defined_tags or {})
1567
+ tags.update(model.freeform_tags or {})
1568
+
1569
+ model_id = model.identifier
1570
+ console_url = get_console_link(
1571
+ resource="models",
1572
+ ocid=model_id,
1573
+ region=self.region,
1574
+ )
1575
+ source_model_id, source_model_name = self._get_source(
1576
+ model, resources_mapping if resources_mapping else {}
1577
+ )
1578
+ experiment_id, experiment_name = self._get_experiment_info(model)
1579
+ parameters = self._fetch_runtime_params(model)
1580
+
1581
+ return {
1582
+ "id": model_id,
1583
+ "name": model.display_name,
1584
+ "console_url": console_url,
1585
+ "time_created": str(model.time_created),
1586
+ "tags": tags,
1587
+ "experiment": self._build_resource_identifier(
1588
+ id=experiment_id,
1589
+ name=experiment_name,
1590
+ ),
1591
+ "source": self._build_resource_identifier(
1592
+ id=source_model_id, name=source_model_name
1593
+ ),
1594
+ "parameters": parameters,
1595
+ }
1596
+
1597
+ def _build_resource_identifier(
1598
+ self, id: str = None, name: str = None
1599
+ ) -> AquaResourceIdentifier:
1600
+ """Constructs AquaResourceIdentifier based on the given ocid and display name."""
1601
+ try:
1602
+ resource_type = CONSOLE_LINK_RESOURCE_TYPE_MAPPING.get(
1603
+ utils.get_resource_type(id)
1604
+ )
1605
+
1606
+ return AquaResourceIdentifier(
1607
+ id=id,
1608
+ name=name,
1609
+ url=get_console_link(
1610
+ resource=resource_type,
1611
+ ocid=id,
1612
+ region=self.region,
1613
+ ),
1614
+ )
1615
+ except Exception as e:
1616
+ logger.debug(
1617
+ f"Failed to construct AquaResourceIdentifier from given id=`{id}`, and name=`{name}`. "
1618
+ f"DEBUG INFO: {str(e)}"
1619
+ )
1620
+ return AquaResourceIdentifier()
1621
+
1622
+ def _fetch_jobrun(
1623
+ self,
1624
+ resource: oci.resource_search.models.ResourceSummary,
1625
+ use_rqs: bool = True,
1626
+ jobrun_id: str = None,
1627
+ ) -> Union[
1628
+ oci.resource_search.models.ResourceSummary, oci.data_science.models.JobRun
1629
+ ]:
1630
+ """Extracts job run id from metadata, and gets related job run information."""
1631
+
1632
+ jobrun_id = jobrun_id or self._get_attribute_from_model_metadata(
1633
+ resource, EvaluationCustomMetadata.EVALUATION_JOB_RUN_ID
1634
+ )
1635
+
1636
+ logger.info(f"Fetching associated job run: {jobrun_id}")
1637
+
1638
+ try:
1639
+ jobrun = (
1640
+ utils.query_resource(jobrun_id, return_all=False)
1641
+ if use_rqs
1642
+ else self.ds_client.get_job_run(jobrun_id).data
1643
+ )
1644
+ except Exception as e:
1645
+ logger.debug(
1646
+ f"Failed to retreive job run: {jobrun_id}. DEBUG INFO: {str(e)}"
1647
+ )
1648
+ jobrun = None
1649
+
1650
+ return jobrun
1651
+
1652
+ def _fetch_runtime_params(
1653
+ self, resource: oci.resource_search.models.ResourceSummary
1654
+ ) -> AquaEvalParams:
1655
+ """Extracts model parameters from metadata. Shape is the shape used in job run."""
1656
+ try:
1657
+ params = json.loads(
1658
+ self._get_attribute_from_model_metadata(
1659
+ resource, MetadataTaxonomyKeys.HYPERPARAMETERS
1660
+ )
1661
+ )
1662
+ if not params.get(EvaluationConfig.PARAMS):
1663
+ raise AquaMissingKeyError(
1664
+ "model parameters have not been saved in correct format in model taxonomy. ",
1665
+ service_payload={"params": params},
1666
+ )
1667
+
1668
+ return AquaEvalParams(**params[EvaluationConfig.PARAMS])
1669
+ except Exception as e:
1670
+ logger.debug(
1671
+ f"Failed to retrieve model parameters for the model: {str(resource)}."
1672
+ f"DEBUG INFO: {str(e)}."
1673
+ )
1674
+ return AquaEvalParams()
1675
+
1676
+ def _build_job_identifier(
1677
+ self,
1678
+ job_run_details: Union[
1679
+ oci.data_science.models.JobRun, oci.resource_search.models.ResourceSummary
1680
+ ] = None,
1681
+ ) -> AquaResourceIdentifier:
1682
+ try:
1683
+ job_id = (
1684
+ job_run_details.id
1685
+ if isinstance(job_run_details, oci.data_science.models.JobRun)
1686
+ else job_run_details.identifier
1687
+ )
1688
+ return self._build_resource_identifier(
1689
+ id=job_id, name=job_run_details.display_name
1690
+ )
1691
+
1692
+ except Exception as e:
1693
+ logger.debug(
1694
+ f"Failed to get job details from job_run_details: {job_run_details} "
1695
+ f"DEBUG INFO:{str(e)}"
1696
+ )
1697
+ return AquaResourceIdentifier()
1698
+
1699
+ def _get_status(
1700
+ self,
1701
+ model: oci.resource_search.models.ResourceSummary,
1702
+ jobrun: Union[
1703
+ oci.resource_search.models.ResourceSummary, oci.data_science.models.JobRun
1704
+ ] = None,
1705
+ ) -> dict:
1706
+ """Builds evaluation status based on the model status and job run status.
1707
+ When missing jobrun information, the status will be decided based on:
1708
+
1709
+ * If the evaluation just has been deleted, the jobrun status should be deleted.
1710
+ * When detect `aqua_evaluation_error` in custom metadata, the jobrun is failed.
1711
+ * If jobrun failed before saving this meta, we need to check the existance
1712
+ of the evaluation artifact.
1713
+
1714
+ """
1715
+ model_status = model.lifecycle_state
1716
+ job_run_status = None
1717
+
1718
+ if jobrun:
1719
+ job_run_status = jobrun.lifecycle_state
1720
+
1721
+ if jobrun is None:
1722
+ if model.identifier in self._deletion_cache:
1723
+ job_run_status = JobRun.LIFECYCLE_STATE_DELETED
1724
+
1725
+ elif self._get_attribute_from_model_metadata(
1726
+ model, EvaluationCustomMetadata.EVALUATION_ERROR
1727
+ ):
1728
+ job_run_status = JobRun.LIFECYCLE_STATE_FAILED
1729
+
1730
+ elif self._if_eval_artifact_exist(model):
1731
+ job_run_status = JobRun.LIFECYCLE_STATE_SUCCEEDED
1732
+ else:
1733
+ job_run_status = JobRun.LIFECYCLE_STATE_FAILED
1734
+
1735
+ lifecycle_state = utils.LifecycleStatus.get_status(
1736
+ evaluation_status=model_status, job_run_status=job_run_status
1737
+ )
1738
+
1739
+ try:
1740
+ lifecycle_details = (
1741
+ LIFECYCLE_DETAILS_MISSING_JOBRUN
1742
+ if not jobrun
1743
+ else self._extract_job_lifecycle_details(jobrun.lifecycle_details)
1744
+ )
1745
+ except Exception:
1746
+ # ResourceSummary does not have lifecycle_details attr
1747
+ lifecycle_details = ""
1748
+
1749
+ return {
1750
+ "lifecycle_state": (
1751
+ lifecycle_state if isinstance(lifecycle_state, str) else lifecycle_state
1752
+ ),
1753
+ "lifecycle_details": lifecycle_details,
1754
+ }
1755
+
1756
+ def _prefetch_resources(self, compartment_id) -> dict:
1757
+ """Fetches all AQUA resources."""
1758
+ resources = utils.query_resources(
1759
+ compartment_id=compartment_id,
1760
+ resource_type="all",
1761
+ tag_list=[Tags.AQUA_EVALUATION, "OCI_AQUA"],
1762
+ connect_by_ampersands=False,
1763
+ return_all=False,
1764
+ )
1765
+ logger.debug(f"Fetched {len(resources)} AQUA resources.")
1766
+ return {item.identifier: item for item in resources}
1767
+
1768
+ def _extract_job_lifecycle_details(self, lifecycle_details: str) -> str:
1769
+ """
1770
+ Extracts the exit code from a job lifecycle detail string and associates it
1771
+ with a corresponding message from the EVALUATION_JOB_EXIT_CODE_MESSAGE dictionary.
1772
+
1773
+ This method searches the provided lifecycle detail string for an exit code pattern.
1774
+ Upon finding an exit code, it retrieves the related human-readable message
1775
+ from a predefined dictionary of exit codes and their meanings. If the exit code
1776
+ is not found within the string, or if it does not exist in the dictionary,
1777
+ the original `lifecycle_details` message will be returned.
1778
+
1779
+ Parameters
1780
+ ----------
1781
+ lifecycle_details : str
1782
+ A string containing the details of the job's lifecycle, typically including an exit code.
1783
+
1784
+ Returns
1785
+ -------
1786
+ str
1787
+ A message that combines the extracted exit code with its corresponding descriptive text.
1788
+ If no exit code is found, or if the exit code is not in the dictionary,
1789
+ the original `lifecycle_details` message will be returned.
1790
+
1791
+ Examples
1792
+ --------
1793
+ >>> _extract_job_lifecycle_details("Job run artifact execution failed with exit code 16")
1794
+ 'Validation errors in the evaluation config. Exit code: 16.'
1795
+
1796
+ >>> _extract_job_lifecycle_details("Job completed successfully.")
1797
+ 'Job completed successfully.'
1798
+ """
1799
+ if not lifecycle_details:
1800
+ return lifecycle_details
1801
+
1802
+ message = lifecycle_details
1803
+ try:
1804
+ # Extract exit code
1805
+ match = re.search(r"exit code (\d+)", lifecycle_details)
1806
+ if match:
1807
+ exit_code = int(match.group(1))
1808
+ exit_code_message = EVALUATION_JOB_EXIT_CODE_MESSAGE.get(exit_code)
1809
+ if exit_code_message:
1810
+ message = f"{exit_code_message} Exit code: {exit_code}."
1811
+ except Exception:
1812
+ pass
1813
+
1814
+ return message