oracle-ads 2.13.6__py3-none-any.whl → 2.13.7__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 (37) hide show
  1. ads/aqua/__init__.py +0 -5
  2. ads/aqua/app.py +133 -20
  3. ads/aqua/cli.py +2 -15
  4. ads/aqua/common/utils.py +12 -83
  5. ads/aqua/config/container_config.py +105 -69
  6. ads/aqua/config/evaluation/evaluation_service_config.py +40 -0
  7. ads/aqua/constants.py +22 -20
  8. ads/aqua/evaluation/evaluation.py +98 -32
  9. ads/aqua/extension/common_handler.py +3 -12
  10. ads/aqua/extension/common_ws_msg_handler.py +3 -24
  11. ads/aqua/extension/model_handler.py +59 -6
  12. ads/aqua/extension/models/ws_models.py +2 -0
  13. ads/aqua/extension/models_ws_msg_handler.py +1 -0
  14. ads/aqua/extension/utils.py +11 -24
  15. ads/aqua/finetuning/entities.py +23 -1
  16. ads/aqua/finetuning/finetuning.py +26 -10
  17. ads/aqua/model/constants.py +8 -0
  18. ads/aqua/model/entities.py +8 -1
  19. ads/aqua/model/model.py +269 -105
  20. ads/aqua/modeldeployment/deployment.py +51 -47
  21. ads/aqua/modeldeployment/utils.py +23 -5
  22. ads/aqua/ui.py +3 -4
  23. ads/config.py +2 -2
  24. ads/model/datascience_model.py +29 -0
  25. ads/model/service/oci_datascience_model.py +1 -1
  26. ads/opctl/operator/lowcode/anomaly/model/anomaly_dataset.py +8 -6
  27. ads/opctl/operator/lowcode/anomaly/model/base_model.py +1 -1
  28. ads/opctl/operator/lowcode/anomaly/operator_config.py +5 -3
  29. ads/opctl/operator/lowcode/common/transformations.py +2 -0
  30. ads/opctl/operator/lowcode/forecast/model/automlx.py +29 -0
  31. ads/type_discovery/typed_feature.py +32 -34
  32. {oracle_ads-2.13.6.dist-info → oracle_ads-2.13.7.dist-info}/METADATA +1 -1
  33. {oracle_ads-2.13.6.dist-info → oracle_ads-2.13.7.dist-info}/RECORD +36 -37
  34. ads/aqua/config/config.py +0 -31
  35. {oracle_ads-2.13.6.dist-info → oracle_ads-2.13.7.dist-info}/WHEEL +0 -0
  36. {oracle_ads-2.13.6.dist-info → oracle_ads-2.13.7.dist-info}/entry_points.txt +0 -0
  37. {oracle_ads-2.13.6.dist-info → oracle_ads-2.13.7.dist-info}/licenses/LICENSE.txt +0 -0
ads/aqua/model/model.py CHANGED
@@ -6,14 +6,14 @@ import os
6
6
  import pathlib
7
7
  from datetime import datetime, timedelta
8
8
  from threading import Lock
9
- from typing import Dict, List, Optional, Set, Union
9
+ from typing import Any, Dict, List, Optional, Set, Union
10
10
 
11
11
  import oci
12
12
  from cachetools import TTLCache
13
13
  from huggingface_hub import snapshot_download
14
14
  from oci.data_science.models import JobRun, Metadata, Model, UpdateModelDetails
15
15
 
16
- from ads.aqua import ODSC_MODEL_COMPARTMENT_OCID, logger
16
+ from ads.aqua import logger
17
17
  from ads.aqua.app import AquaApp
18
18
  from ads.aqua.common.entities import AquaMultiModelRef
19
19
  from ads.aqua.common.enums import (
@@ -37,12 +37,10 @@ from ads.aqua.common.utils import (
37
37
  create_word_icon,
38
38
  generate_tei_cmd_var,
39
39
  get_artifact_path,
40
- get_container_config,
41
40
  get_hf_model_info,
42
41
  get_preferred_compatible_family,
43
42
  list_os_files_with_extension,
44
43
  load_config,
45
- read_file,
46
44
  upload_folder,
47
45
  )
48
46
  from ads.aqua.config.container_config import AquaContainerConfig, Usage
@@ -54,7 +52,7 @@ from ads.aqua.constants import (
54
52
  AQUA_MODEL_TOKENIZER_CONFIG,
55
53
  AQUA_MODEL_TYPE_CUSTOM,
56
54
  HF_METADATA_FOLDER,
57
- LICENSE_TXT,
55
+ LICENSE,
58
56
  MODEL_BY_REFERENCE_OSS_PATH_KEY,
59
57
  README,
60
58
  READY_TO_DEPLOY_STATUS,
@@ -66,6 +64,7 @@ from ads.aqua.constants import (
66
64
  VALIDATION_METRICS_FINAL,
67
65
  )
68
66
  from ads.aqua.model.constants import (
67
+ AquaModelMetadataKeys,
69
68
  FineTuningCustomMetadata,
70
69
  FineTuningMetricCategories,
71
70
  ModelCustomMetadataFields,
@@ -76,6 +75,7 @@ from ads.aqua.model.entities import (
76
75
  AquaFineTuningMetric,
77
76
  AquaModel,
78
77
  AquaModelLicense,
78
+ AquaModelReadme,
79
79
  AquaModelSummary,
80
80
  ImportModelDetails,
81
81
  ModelValidationResult,
@@ -83,16 +83,24 @@ from ads.aqua.model.entities import (
83
83
  from ads.aqua.model.enums import MultiModelSupportedTaskType
84
84
  from ads.common.auth import default_signer
85
85
  from ads.common.oci_resource import SEARCH_TYPE, OCIResource
86
- from ads.common.utils import UNKNOWN, get_console_link
86
+ from ads.common.utils import (
87
+ UNKNOWN,
88
+ get_console_link,
89
+ is_path_exists,
90
+ read_file,
91
+ )
87
92
  from ads.config import (
88
93
  AQUA_DEPLOYMENT_CONTAINER_CMD_VAR_METADATA_NAME,
89
94
  AQUA_DEPLOYMENT_CONTAINER_METADATA_NAME,
90
95
  AQUA_DEPLOYMENT_CONTAINER_URI_METADATA_NAME,
91
96
  AQUA_EVALUATION_CONTAINER_METADATA_NAME,
92
97
  AQUA_FINETUNING_CONTAINER_METADATA_NAME,
98
+ AQUA_SERVICE_MODELS,
93
99
  COMPARTMENT_OCID,
94
100
  PROJECT_OCID,
101
+ SERVICE,
95
102
  TENANCY_OCID,
103
+ USER,
96
104
  )
97
105
  from ads.model import DataScienceModel
98
106
  from ads.model.common.utils import MetadataArtifactPathType
@@ -176,7 +184,8 @@ class AquaModelApp(AquaApp):
176
184
  target_project = project_id or PROJECT_OCID
177
185
  target_compartment = compartment_id or COMPARTMENT_OCID
178
186
 
179
- if service_model.compartment_id != ODSC_MODEL_COMPARTMENT_OCID:
187
+ # Skip model copying if it is registered model
188
+ if service_model.freeform_tags.get(Tags.BASE_MODEL_CUSTOM, None) is not None:
180
189
  logger.info(
181
190
  f"Aqua Model {model_id} already exists in the user's compartment."
182
191
  "Skipped copying."
@@ -261,18 +270,15 @@ class AquaModelApp(AquaApp):
261
270
  display_name_list = []
262
271
  model_custom_metadata = ModelCustomMetadata()
263
272
 
264
- # Get container config
265
- container_config = get_container_config()
266
-
267
- service_inference_containers = AquaContainerConfig.from_container_index_json(
268
- config=container_config
269
- ).inference.values()
273
+ service_inference_containers = (
274
+ self.get_container_config().to_dict().get("inference")
275
+ )
270
276
 
271
277
  supported_container_families = [
272
278
  container_config_item.family
273
279
  for container_config_item in service_inference_containers
274
280
  if any(
275
- usage in container_config_item.usages
281
+ usage.upper() in container_config_item.usages
276
282
  for usage in [Usage.MULTI_MODEL, Usage.OTHER]
277
283
  )
278
284
  ]
@@ -432,7 +438,7 @@ class AquaModelApp(AquaApp):
432
438
  return custom_model
433
439
 
434
440
  @telemetry(entry_point="plugin=model&action=get", name="aqua")
435
- def get(self, model_id: str, load_model_card: Optional[bool] = True) -> "AquaModel":
441
+ def get(self, model_id: str) -> "AquaModel":
436
442
  """Gets the information of an Aqua model.
437
443
 
438
444
  Parameters
@@ -455,6 +461,7 @@ class AquaModelApp(AquaApp):
455
461
 
456
462
  logger.info(f"Fetching model details for model {model_id}.")
457
463
  ds_model = DataScienceModel.from_id(model_id)
464
+
458
465
  if not self._if_show(ds_model):
459
466
  raise AquaRuntimeError(
460
467
  f"Target model `{ds_model.id} `is not an Aqua model as it does not contain "
@@ -466,34 +473,6 @@ class AquaModelApp(AquaApp):
466
473
  and ds_model.freeform_tags.get(Tags.AQUA_FINE_TUNED_MODEL_TAG)
467
474
  )
468
475
 
469
- # todo: consolidate this logic in utils for model and deployment use
470
- is_verified_type = (
471
- ds_model.freeform_tags.get(Tags.READY_TO_IMPORT, "false").upper()
472
- == READY_TO_IMPORT_STATUS
473
- )
474
-
475
- model_card = ""
476
- if load_model_card:
477
- artifact_path = get_artifact_path(
478
- ds_model.custom_metadata_list._to_oci_metadata()
479
- )
480
- if artifact_path != UNKNOWN:
481
- model_card_path = (
482
- f"{artifact_path.rstrip('/')}/config/{README}"
483
- if is_verified_type
484
- else f"{artifact_path.rstrip('/')}/{README}"
485
- )
486
- model_card = str(
487
- read_file(
488
- file_path=model_card_path,
489
- auth=default_signer(),
490
- )
491
- )
492
- if not model_card:
493
- logger.warn(
494
- f"Model card for {model_id} is empty or could not be loaded from {model_card_path}."
495
- )
496
-
497
476
  inference_container = ds_model.custom_metadata_list.get(
498
477
  ModelCustomMetadataFields.DEPLOYMENT_CONTAINER,
499
478
  ModelCustomMetadataItem(key=ModelCustomMetadataFields.DEPLOYMENT_CONTAINER),
@@ -520,7 +499,6 @@ class AquaModelApp(AquaApp):
520
499
  aqua_model_attributes = dict(
521
500
  **self._process_model(ds_model, self.region),
522
501
  project_id=ds_model.project_id,
523
- model_card=model_card,
524
502
  inference_container=inference_container,
525
503
  inference_container_uri=inference_container_uri,
526
504
  finetuning_container=finetuning_container,
@@ -791,7 +769,9 @@ class AquaModelApp(AquaApp):
791
769
  ]
792
770
 
793
771
  def get_hf_tokenizer_config(self, model_id):
794
- """Gets the default chat template for the given Aqua model.
772
+ """
773
+ Gets the default model tokenizer config for the given Aqua model.
774
+ Returns the content of tokenizer_config.json stored in model artifact.
795
775
 
796
776
  Parameters
797
777
  ----------
@@ -800,14 +780,19 @@ class AquaModelApp(AquaApp):
800
780
 
801
781
  Returns
802
782
  -------
803
- str:
804
- Chat template string.
783
+ Dict:
784
+ Model tokenizer config.
805
785
  """
806
786
  config = self.get_config(
807
787
  model_id, AQUA_MODEL_TOKENIZER_CONFIG, ConfigFolder.ARTIFACT
808
788
  ).config
809
789
  if not config:
810
- logger.debug(f"Tokenizer config for model: {model_id} is not available.")
790
+ logger.debug(
791
+ f"{AQUA_MODEL_TOKENIZER_CONFIG} is not available for the model: {model_id}. "
792
+ f"Check if the custom metadata has the artifact path set."
793
+ )
794
+ return config
795
+
811
796
  return config
812
797
 
813
798
  @staticmethod
@@ -832,6 +817,7 @@ class AquaModelApp(AquaApp):
832
817
  oci.resource_search.models.ResourceSummary,
833
818
  ],
834
819
  region: str,
820
+ inference_containers: Optional[List[Any]] = None,
835
821
  ) -> dict:
836
822
  """Constructs required fields for AquaModelSummary."""
837
823
 
@@ -887,9 +873,10 @@ class AquaModelApp(AquaApp):
887
873
  except Exception:
888
874
  model_file = UNKNOWN
889
875
 
890
- inference_containers = AquaContainerConfig.from_container_index_json(
891
- config=get_container_config()
892
- ).inference
876
+ if not inference_containers:
877
+ inference_containers = (
878
+ AquaApp().get_container_config().to_dict().get("inference")
879
+ )
893
880
 
894
881
  model_formats_str = freeform_tags.get(
895
882
  Tags.MODEL_FORMAT, ModelFormat.SAFETENSORS
@@ -898,7 +885,7 @@ class AquaModelApp(AquaApp):
898
885
 
899
886
  supported_platform: Set[str] = set()
900
887
 
901
- for container in inference_containers.values():
888
+ for container in inference_containers:
902
889
  for model_format in model_formats:
903
890
  if model_format in container.model_formats:
904
891
  supported_platform.update(container.platforms)
@@ -932,12 +919,13 @@ class AquaModelApp(AquaApp):
932
919
  def list(
933
920
  self,
934
921
  compartment_id: str = None,
922
+ category: str = None,
935
923
  project_id: str = None,
936
924
  model_type: str = None,
937
925
  **kwargs,
938
926
  ) -> List["AquaModelSummary"]:
939
927
  """Lists all Aqua models within a specified compartment and/or project.
940
- If `compartment_id` is not specified, the method defaults to returning
928
+ If `category` is not specified, the method defaults to returning
941
929
  the service models within the pre-configured default compartment. By default, the list
942
930
  of models in the service compartment are cached. Use clear_model_list_cache() to invalidate
943
931
  the cache.
@@ -946,6 +934,8 @@ class AquaModelApp(AquaApp):
946
934
  ----------
947
935
  compartment_id: (str, optional). Defaults to `None`.
948
936
  The compartment OCID.
937
+ category: (str,optional). Defaults to `SERVICE`
938
+ The category of the models to fetch. Can be either `USER` or `SERVICE`
949
939
  project_id: (str, optional). Defaults to `None`.
950
940
  The project OCID.
951
941
  model_type: (str, optional). Defaults to `None`.
@@ -959,8 +949,9 @@ class AquaModelApp(AquaApp):
959
949
  The list of the `ads.aqua.model.AquaModelSummary`.
960
950
  """
961
951
 
962
- models = []
963
- if compartment_id:
952
+ category = category or kwargs.pop("category", SERVICE)
953
+ compartment_id = compartment_id or COMPARTMENT_OCID
954
+ if category == USER:
964
955
  # tracks number of times custom model listing was called
965
956
  self.telemetry.record_event_async(
966
957
  category="aqua/custom/model", action="list"
@@ -969,48 +960,47 @@ class AquaModelApp(AquaApp):
969
960
  logger.info(f"Fetching custom models from compartment_id={compartment_id}.")
970
961
  model_type = model_type.upper() if model_type else ModelType.FT
971
962
  models = self._rqs(compartment_id, model_type=model_type)
963
+ logger.info(
964
+ f"Fetched {len(models)} models from {compartment_id or COMPARTMENT_OCID}."
965
+ )
972
966
  else:
973
967
  # tracks number of times service model listing was called
974
968
  self.telemetry.record_event_async(
975
969
  category="aqua/service/model", action="list"
976
970
  )
977
971
 
978
- if ODSC_MODEL_COMPARTMENT_OCID in self._service_models_cache:
979
- logger.info(
980
- f"Returning service models list in {ODSC_MODEL_COMPARTMENT_OCID} from cache."
981
- )
982
- return self._service_models_cache.get(ODSC_MODEL_COMPARTMENT_OCID)
983
- logger.info(
984
- f"Fetching service models from compartment_id={ODSC_MODEL_COMPARTMENT_OCID}"
985
- )
972
+ if AQUA_SERVICE_MODELS in self._service_models_cache:
973
+ logger.info("Returning service models list from cache.")
974
+ return self._service_models_cache.get(AQUA_SERVICE_MODELS)
986
975
  lifecycle_state = kwargs.pop(
987
976
  "lifecycle_state", Model.LIFECYCLE_STATE_ACTIVE
988
977
  )
989
978
 
990
979
  models = self.list_resource(
991
980
  self.ds_client.list_models,
992
- compartment_id=ODSC_MODEL_COMPARTMENT_OCID,
981
+ compartment_id=compartment_id,
993
982
  lifecycle_state=lifecycle_state,
983
+ category=category,
994
984
  **kwargs,
995
985
  )
996
-
997
- logger.info(
998
- f"Fetched {len(models)} model in compartment_id={compartment_id or ODSC_MODEL_COMPARTMENT_OCID}."
999
- )
986
+ logger.info(f"Fetched {len(models)} service models.")
1000
987
 
1001
988
  aqua_models = []
1002
-
989
+ inference_containers = self.get_container_config().to_dict().get("inference")
1003
990
  for model in models:
1004
991
  aqua_models.append(
1005
992
  AquaModelSummary(
1006
- **self._process_model(model=model, region=self.region),
993
+ **self._process_model(
994
+ model=model,
995
+ region=self.region,
996
+ inference_containers=inference_containers,
997
+ ),
1007
998
  project_id=project_id or UNKNOWN,
1008
999
  )
1009
1000
  )
1010
-
1011
- if not compartment_id:
1001
+ if category == SERVICE:
1012
1002
  self._service_models_cache.__setitem__(
1013
- key=ODSC_MODEL_COMPARTMENT_OCID, value=aqua_models
1003
+ key=AQUA_SERVICE_MODELS, value=aqua_models
1014
1004
  )
1015
1005
 
1016
1006
  return aqua_models
@@ -1026,15 +1016,10 @@ class AquaModelApp(AquaApp):
1026
1016
  """
1027
1017
  res = {}
1028
1018
  with self._cache_lock:
1029
- if ODSC_MODEL_COMPARTMENT_OCID in self._service_models_cache:
1030
- self._service_models_cache.pop(key=ODSC_MODEL_COMPARTMENT_OCID)
1031
- logger.info(
1032
- f"Cleared models cache for service compartment {ODSC_MODEL_COMPARTMENT_OCID}."
1033
- )
1019
+ if AQUA_SERVICE_MODELS in self._service_models_cache:
1020
+ self._service_models_cache.pop(key=AQUA_SERVICE_MODELS)
1021
+ logger.info("Cleared models cache for service compartment.")
1034
1022
  res = {
1035
- "key": {
1036
- "compartment_id": ODSC_MODEL_COMPARTMENT_OCID,
1037
- },
1038
1023
  "cache_deleted": True,
1039
1024
  }
1040
1025
  return res
@@ -1057,14 +1042,85 @@ class AquaModelApp(AquaApp):
1057
1042
 
1058
1043
  @staticmethod
1059
1044
  def list_valid_inference_containers():
1060
- containers = list(
1061
- AquaContainerConfig.from_container_index_json(
1062
- config=get_container_config(), enable_spec=True
1063
- ).inference.values()
1064
- )
1045
+ containers = AquaApp().get_container_config().to_dict().get("inference")
1065
1046
  family_values = [item.family for item in containers]
1066
1047
  return family_values
1067
1048
 
1049
+ @telemetry(
1050
+ entry_point="plugin=model&action=get_defined_metadata_artifact_content",
1051
+ name="aqua",
1052
+ )
1053
+ def get_defined_metadata_artifact_content(self, model_id: str, metadata_key: str):
1054
+ """
1055
+ Gets the defined metadata artifact content for the given model
1056
+
1057
+ Args:
1058
+ model_id: str
1059
+ model ocid for which defined metadata artifact needs to be created
1060
+ metadata_key: str
1061
+ defined metadata key like Readme , License , DeploymentConfiguration , FinetuningConfiguration
1062
+ Returns:
1063
+ The model defined metadata artifact content. Can be either str or Dict
1064
+
1065
+ """
1066
+
1067
+ content = self.get_config(model_id, metadata_key)
1068
+ if not content:
1069
+ logger.debug(
1070
+ f"Defined metadata artifact {metadata_key} for model: {model_id} is not available."
1071
+ )
1072
+ return content
1073
+
1074
+ @telemetry(
1075
+ entry_point="plugin=model&action=create_defined_metadata_artifact", name="aqua"
1076
+ )
1077
+ def create_defined_metadata_artifact(
1078
+ self,
1079
+ model_id: str,
1080
+ metadata_key: str,
1081
+ path_type: MetadataArtifactPathType,
1082
+ artifact_path_or_content: str,
1083
+ ) -> None:
1084
+ """
1085
+ Creates defined metadata artifact for the registered unverified model
1086
+
1087
+ Args:
1088
+ model_id: str
1089
+ model ocid for which defined metadata artifact needs to be created
1090
+ metadata_key: str
1091
+ defined metadata key like Readme , License , DeploymentConfiguration , FinetuningConfiguration
1092
+ path_type: str
1093
+ path type of the given defined metadata can be local , oss or the content itself
1094
+ artifact_path_or_content: str
1095
+ It can be local path or oss path or the actual content itself
1096
+ Returns:
1097
+ None
1098
+ """
1099
+
1100
+ ds_model = DataScienceModel.from_id(model_id)
1101
+ oci_aqua = ds_model.freeform_tags.get(Tags.AQUA_TAG, None)
1102
+ if not oci_aqua:
1103
+ raise AquaRuntimeError(f"Target model {model_id} is not an Aqua model.")
1104
+ is_registered_model = ds_model.freeform_tags.get(Tags.BASE_MODEL_CUSTOM, None)
1105
+ is_verified_model = ds_model.freeform_tags.get(
1106
+ Tags.AQUA_SERVICE_MODEL_TAG, None
1107
+ )
1108
+ if is_registered_model and not is_verified_model:
1109
+ try:
1110
+ ds_model.create_defined_metadata_artifact(
1111
+ metadata_key_name=metadata_key,
1112
+ artifact_path_or_content=artifact_path_or_content,
1113
+ path_type=path_type,
1114
+ )
1115
+ except Exception as ex:
1116
+ raise AquaRuntimeError(
1117
+ f"Error occurred in creating defined metadata artifact for model {model_id}: {ex}"
1118
+ ) from ex
1119
+ else:
1120
+ raise AquaRuntimeError(
1121
+ f"Cannot create defined metadata artifact for model {model_id}"
1122
+ )
1123
+
1068
1124
  def _create_model_catalog_entry(
1069
1125
  self,
1070
1126
  os_path: str,
@@ -1121,7 +1177,9 @@ class AquaModelApp(AquaApp):
1121
1177
 
1122
1178
  # Remove `ready_to_import` tag that might get copied from service model.
1123
1179
  tags.pop(Tags.READY_TO_IMPORT, None)
1124
-
1180
+ defined_metadata_dict = {}
1181
+ readme_file_path = os_path.rstrip("/") + "/" + README
1182
+ license_file_path = os_path.rstrip("/") + "/" + LICENSE
1125
1183
  if verified_model:
1126
1184
  # Verified model is a model in the service catalog that either has no artifacts but contains all the necessary metadata for deploying and fine tuning.
1127
1185
  # If set, then we copy all the model metadata.
@@ -1130,6 +1188,17 @@ class AquaModelApp(AquaApp):
1130
1188
  model = model.with_model_file_description(
1131
1189
  json_dict=verified_model.model_file_description
1132
1190
  )
1191
+ defined_metadata_list = (
1192
+ verified_model.defined_metadata_list._to_oci_metadata()
1193
+ )
1194
+ for defined_metadata in defined_metadata_list:
1195
+ if defined_metadata.has_artifact:
1196
+ content = (
1197
+ self.ds_client.get_model_defined_metadatum_artifact_content(
1198
+ verified_model.id, defined_metadata.key
1199
+ ).data.content
1200
+ )
1201
+ defined_metadata_dict[defined_metadata.key] = content
1133
1202
  else:
1134
1203
  metadata = ModelCustomMetadata()
1135
1204
  if not inference_container:
@@ -1151,12 +1220,14 @@ class AquaModelApp(AquaApp):
1151
1220
  category="Other",
1152
1221
  )
1153
1222
 
1154
- inference_containers = AquaContainerConfig.from_container_index_json(
1155
- config=get_container_config()
1156
- ).inference
1157
- smc_container_set = {
1158
- container.family for container in inference_containers.values()
1159
- }
1223
+ inference_containers = (
1224
+ AquaContainerConfig.from_service_config(
1225
+ service_containers=self.list_service_containers()
1226
+ )
1227
+ .to_dict()
1228
+ .get("inference")
1229
+ )
1230
+ smc_container_set = {container.family for container in inference_containers}
1160
1231
  # only add cmd vars if inference container is not an SMC
1161
1232
  if (
1162
1233
  inference_container not in smc_container_set
@@ -1225,6 +1296,33 @@ class AquaModelApp(AquaApp):
1225
1296
  .with_defined_tags(**(defined_tags or {}))
1226
1297
  ).create(model_by_reference=True)
1227
1298
  logger.debug(f"Created model catalog entry for the model:\n{model}")
1299
+ for key, value in defined_metadata_dict.items():
1300
+ model.create_defined_metadata_artifact(
1301
+ key, value, MetadataArtifactPathType.CONTENT
1302
+ )
1303
+
1304
+ if is_path_exists(readme_file_path):
1305
+ try:
1306
+ model.create_defined_metadata_artifact(
1307
+ AquaModelMetadataKeys.README,
1308
+ readme_file_path,
1309
+ MetadataArtifactPathType.OSS,
1310
+ )
1311
+ except Exception as ex:
1312
+ logger.error(
1313
+ f"Error Uploading Readme in defined metadata for model: {model.id} : {str(ex)}"
1314
+ )
1315
+ if not verified_model and is_path_exists(license_file_path):
1316
+ try:
1317
+ model.create_defined_metadata_artifact(
1318
+ AquaModelMetadataKeys.LICENSE,
1319
+ license_file_path,
1320
+ MetadataArtifactPathType.OSS,
1321
+ )
1322
+ except Exception as ex:
1323
+ logger.error(
1324
+ f"Error Uploading License in defined metadata for model: {model.id} : {str(ex)}"
1325
+ )
1228
1326
  return model
1229
1327
 
1230
1328
  @staticmethod
@@ -1739,6 +1837,7 @@ class AquaModelApp(AquaApp):
1739
1837
  ).rstrip("/")
1740
1838
  else:
1741
1839
  artifact_path = import_model_details.os_path.rstrip("/")
1840
+
1742
1841
  # Create Model catalog entry with pass by reference
1743
1842
  ds_model = self._create_model_catalog_entry(
1744
1843
  os_path=artifact_path,
@@ -1777,12 +1876,6 @@ class AquaModelApp(AquaApp):
1777
1876
  aqua_model_attributes = dict(
1778
1877
  **self._process_model(ds_model, self.region),
1779
1878
  project_id=ds_model.project_id,
1780
- model_card=str(
1781
- read_file(
1782
- file_path=f"{artifact_path}/{README}",
1783
- auth=default_signer(),
1784
- )
1785
- ),
1786
1879
  inference_container=inference_container,
1787
1880
  inference_container_uri=inference_container_uri,
1788
1881
  finetuning_container=finetuning_container,
@@ -1856,6 +1949,56 @@ class AquaModelApp(AquaApp):
1856
1949
  separator = " " if description else ""
1857
1950
  return f"{description}{separator}{tags_text}"
1858
1951
 
1952
+ @telemetry(entry_point="plugin=model&action=load_readme", name="aqua")
1953
+ def load_readme(self, model_id: str) -> AquaModelReadme:
1954
+ """Loads the readme or the model card for the given model.
1955
+
1956
+ Parameters
1957
+ ----------
1958
+ model_id: str
1959
+ The model id.
1960
+
1961
+ Returns
1962
+ -------
1963
+ AquaModelReadme:
1964
+ The instance of AquaModelReadme.
1965
+ """
1966
+ oci_model = self.ds_client.get_model(model_id).data
1967
+ artifact_path = get_artifact_path(oci_model.custom_metadata_list)
1968
+ if not artifact_path:
1969
+ raise AquaRuntimeError(
1970
+ f"Readme could not be loaded. Failed to get artifact path from custom metadata for"
1971
+ f"the model {model_id}."
1972
+ )
1973
+
1974
+ content = ""
1975
+ try:
1976
+ content = self.ds_client.get_model_defined_metadatum_artifact_content(
1977
+ model_id, AquaModelMetadataKeys.README
1978
+ ).data.content.decode("utf-8", errors="ignore")
1979
+ logger.info(f"Fetched {README} from defined metadata for model: {model_id}")
1980
+ except Exception as ex:
1981
+ logger.error(
1982
+ f"Readme could not be found for model: {model_id} in defined metadata : {str(ex)}"
1983
+ )
1984
+ artifact_path = get_artifact_path(oci_model.custom_metadata_list)
1985
+ readme_path = os.path.join(os.path.dirname(artifact_path), "artifact")
1986
+ if not is_path_exists(readme_path):
1987
+ readme_path = os.path.join(artifact_path.rstrip("/"), "artifact")
1988
+ if not is_path_exists(readme_path):
1989
+ readme_path = f"{artifact_path.rstrip('/')}/"
1990
+
1991
+ readme_file_path = os.path.join(readme_path, README)
1992
+ logger.info(f"Fetching {README} from {readme_file_path}")
1993
+ if is_path_exists(readme_file_path):
1994
+ try:
1995
+ content = str(read_file(readme_file_path, auth=default_signer()))
1996
+ except Exception as e:
1997
+ logger.debug(
1998
+ f"Error occurred while fetching config {README} at path {readme_file_path} : {str(e)}"
1999
+ )
2000
+ return AquaModelReadme(id=model_id, model_card=content)
2001
+
1859
2002
  @telemetry(entry_point="plugin=model&action=load_license", name="aqua")
1860
2003
  def load_license(self, model_id: str) -> AquaModelLicense:
1861
2004
  """Loads the license full text for the given model.
@@ -1878,13 +2021,34 @@ class AquaModelApp(AquaApp):
1878
2021
  f"the model {model_id}."
1879
2022
  )
1880
2023
 
1881
- content = str(
1882
- read_file(
1883
- file_path=f"{os.path.dirname(artifact_path)}/{LICENSE_TXT}",
1884
- auth=default_signer(),
2024
+ content = ""
2025
+ try:
2026
+ content = self.ds_client.get_model_defined_metadatum_artifact_content(
2027
+ model_id, AquaModelMetadataKeys.LICENSE
2028
+ ).data.content.decode("utf-8", errors="ignore")
2029
+ logger.info(
2030
+ f"Fetched {LICENSE} from defined metadata for model: {model_id}"
1885
2031
  )
1886
- )
1887
-
2032
+ except Exception as ex:
2033
+ logger.error(
2034
+ f"License could not be found for model: {model_id} in defined metadata : {str(ex)}"
2035
+ )
2036
+ artifact_path = get_artifact_path(oci_model.custom_metadata_list)
2037
+ license_path = os.path.join(os.path.dirname(artifact_path), "config")
2038
+ if not is_path_exists(license_path):
2039
+ license_path = os.path.join(artifact_path.rstrip("/"), "config")
2040
+ if not is_path_exists(license_path):
2041
+ license_path = f"{artifact_path.rstrip('/')}/"
2042
+
2043
+ license_file_path = os.path.join(license_path, LICENSE)
2044
+ logger.info(f"Fetching {LICENSE} from {license_file_path}")
2045
+ if is_path_exists(license_file_path):
2046
+ try:
2047
+ content = str(read_file(license_file_path, auth=default_signer()))
2048
+ except Exception as e:
2049
+ logger.debug(
2050
+ f"Error occurred while fetching config {LICENSE} at path {license_path} : {str(e)}"
2051
+ )
1888
2052
  return AquaModelLicense(id=model_id, license=content)
1889
2053
 
1890
2054
  def _find_matching_aqua_model(self, model_id: str) -> Optional[str]: