oracle-ads 2.12.10rc0__py3-none-any.whl → 2.13.0__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.
- ads/aqua/__init__.py +2 -1
- ads/aqua/app.py +46 -19
- ads/aqua/client/__init__.py +3 -0
- ads/aqua/client/client.py +799 -0
- ads/aqua/common/enums.py +19 -14
- ads/aqua/common/errors.py +3 -4
- ads/aqua/common/utils.py +2 -2
- ads/aqua/constants.py +1 -0
- ads/aqua/evaluation/constants.py +7 -7
- ads/aqua/evaluation/errors.py +3 -4
- ads/aqua/evaluation/evaluation.py +20 -12
- ads/aqua/extension/aqua_ws_msg_handler.py +14 -7
- ads/aqua/extension/base_handler.py +12 -9
- ads/aqua/extension/model_handler.py +29 -1
- ads/aqua/extension/models/ws_models.py +5 -6
- ads/aqua/finetuning/constants.py +3 -3
- ads/aqua/finetuning/entities.py +3 -0
- ads/aqua/finetuning/finetuning.py +32 -1
- ads/aqua/model/constants.py +7 -7
- ads/aqua/model/entities.py +2 -1
- ads/aqua/model/enums.py +4 -5
- ads/aqua/model/model.py +158 -76
- ads/aqua/modeldeployment/deployment.py +22 -10
- ads/aqua/modeldeployment/entities.py +3 -1
- ads/cli.py +16 -8
- ads/common/auth.py +33 -20
- ads/common/extended_enum.py +52 -44
- ads/llm/__init__.py +11 -8
- ads/llm/langchain/plugins/embeddings/__init__.py +4 -0
- ads/llm/langchain/plugins/embeddings/oci_data_science_model_deployment_endpoint.py +184 -0
- ads/model/artifact_downloader.py +3 -4
- ads/model/datascience_model.py +84 -64
- ads/model/generic_model.py +3 -3
- ads/model/model_metadata.py +17 -11
- ads/model/service/oci_datascience_model.py +12 -14
- ads/opctl/backend/marketplace/helm_helper.py +13 -14
- ads/opctl/cli.py +4 -5
- ads/opctl/cmds.py +28 -32
- ads/opctl/config/merger.py +8 -11
- ads/opctl/config/resolver.py +25 -30
- ads/opctl/operator/cli.py +9 -9
- ads/opctl/operator/common/backend_factory.py +56 -60
- ads/opctl/operator/common/const.py +5 -5
- ads/opctl/operator/lowcode/anomaly/const.py +8 -9
- ads/opctl/operator/lowcode/common/transformations.py +38 -3
- ads/opctl/operator/lowcode/common/utils.py +11 -1
- ads/opctl/operator/lowcode/feature_store_marketplace/operator_utils.py +43 -48
- ads/opctl/operator/lowcode/forecast/__main__.py +10 -0
- ads/opctl/operator/lowcode/forecast/const.py +6 -6
- ads/opctl/operator/lowcode/forecast/model/forecast_datasets.py +1 -1
- ads/opctl/operator/lowcode/forecast/operator_config.py +31 -0
- ads/opctl/operator/lowcode/forecast/schema.yaml +63 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/__init__.py +7 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/deployment_manager.py +233 -0
- ads/opctl/operator/lowcode/forecast/whatifserve/score.py +238 -0
- ads/opctl/operator/lowcode/pii/constant.py +6 -7
- ads/opctl/operator/lowcode/recommender/constant.py +12 -7
- ads/opctl/operator/runtime/marketplace_runtime.py +4 -10
- ads/opctl/operator/runtime/runtime.py +4 -6
- ads/pipeline/ads_pipeline_run.py +13 -25
- ads/pipeline/visualizer/graph_renderer.py +3 -4
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/METADATA +4 -2
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/RECORD +66 -59
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/WHEEL +0 -0
- {oracle_ads-2.12.10rc0.dist-info → oracle_ads-2.13.0.dist-info}/entry_points.txt +0 -0
ads/aqua/model/constants.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
3
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
4
4
|
|
5
5
|
"""
|
@@ -9,10 +9,10 @@ aqua.model.constants
|
|
9
9
|
This module contains constants/enums used in Aqua Model.
|
10
10
|
"""
|
11
11
|
|
12
|
-
from ads.common.extended_enum import
|
12
|
+
from ads.common.extended_enum import ExtendedEnum
|
13
13
|
|
14
14
|
|
15
|
-
class ModelCustomMetadataFields(
|
15
|
+
class ModelCustomMetadataFields(ExtendedEnum):
|
16
16
|
ARTIFACT_LOCATION = "artifact_location"
|
17
17
|
DEPLOYMENT_CONTAINER = "deployment-container"
|
18
18
|
EVALUATION_CONTAINER = "evaluation-container"
|
@@ -20,24 +20,24 @@ class ModelCustomMetadataFields(str, metaclass=ExtendedEnumMeta):
|
|
20
20
|
DEPLOYMENT_CONTAINER_URI = "deployment-container-uri"
|
21
21
|
|
22
22
|
|
23
|
-
class ModelTask(
|
23
|
+
class ModelTask(ExtendedEnum):
|
24
24
|
TEXT_GENERATION = "text-generation"
|
25
25
|
IMAGE_TEXT_TO_TEXT = "image-text-to-text"
|
26
26
|
IMAGE_TO_TEXT = "image-to-text"
|
27
27
|
|
28
28
|
|
29
|
-
class FineTuningMetricCategories(
|
29
|
+
class FineTuningMetricCategories(ExtendedEnum):
|
30
30
|
VALIDATION = "validation"
|
31
31
|
TRAINING = "training"
|
32
32
|
|
33
33
|
|
34
|
-
class ModelType(
|
34
|
+
class ModelType(ExtendedEnum):
|
35
35
|
FT = "FT" # Fine Tuned Model
|
36
36
|
BASE = "BASE" # Base model
|
37
37
|
|
38
38
|
|
39
39
|
# TODO: merge metadata key used in create FT
|
40
|
-
class FineTuningCustomMetadata(
|
40
|
+
class FineTuningCustomMetadata(ExtendedEnum):
|
41
41
|
FT_SOURCE = "fine_tune_source"
|
42
42
|
FT_SOURCE_NAME = "fine_tune_source_name"
|
43
43
|
FT_OUTPUT_PATH = "fine_tune_output_path"
|
ads/aqua/model/entities.py
CHANGED
@@ -283,7 +283,7 @@ class ImportModelDetails(CLIBuilderMixin):
|
|
283
283
|
os_path: str
|
284
284
|
download_from_hf: Optional[bool] = True
|
285
285
|
local_dir: Optional[str] = None
|
286
|
-
cleanup_model_cache: Optional[bool] =
|
286
|
+
cleanup_model_cache: Optional[bool] = False
|
287
287
|
inference_container: Optional[str] = None
|
288
288
|
finetuning_container: Optional[str] = None
|
289
289
|
compartment_id: Optional[str] = None
|
@@ -294,6 +294,7 @@ class ImportModelDetails(CLIBuilderMixin):
|
|
294
294
|
ignore_patterns: Optional[List[str]] = None
|
295
295
|
freeform_tags: Optional[dict] = None
|
296
296
|
defined_tags: Optional[dict] = None
|
297
|
+
ignore_model_artifact_check: Optional[bool] = None
|
297
298
|
|
298
299
|
def __post_init__(self):
|
299
300
|
self._command = "model register"
|
ads/aqua/model/enums.py
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
|
-
#
|
3
|
-
# Copyright (c) 2024 Oracle and/or its affiliates.
|
2
|
+
# Copyright (c) 2024, 2025 Oracle and/or its affiliates.
|
4
3
|
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
5
|
-
from ads.common.extended_enum import
|
4
|
+
from ads.common.extended_enum import ExtendedEnum
|
6
5
|
|
7
6
|
|
8
|
-
class FineTuningDefinedMetadata(
|
7
|
+
class FineTuningDefinedMetadata(ExtendedEnum):
|
9
8
|
"""Represents the defined metadata keys used in Fine Tuning."""
|
10
9
|
|
11
10
|
VAL_SET_SIZE = "val_set_size"
|
12
11
|
TRAINING_DATA = "training_data"
|
13
12
|
|
14
13
|
|
15
|
-
class FineTuningCustomMetadata(
|
14
|
+
class FineTuningCustomMetadata(ExtendedEnum):
|
16
15
|
"""Represents the custom metadata keys used in Fine Tuning."""
|
17
16
|
|
18
17
|
FT_SOURCE = "fine_tune_source"
|
ads/aqua/model/model.py
CHANGED
@@ -15,17 +15,21 @@ from oci.data_science.models import JobRun, Metadata, Model, UpdateModelDetails
|
|
15
15
|
from ads.aqua import ODSC_MODEL_COMPARTMENT_OCID, logger
|
16
16
|
from ads.aqua.app import AquaApp
|
17
17
|
from ads.aqua.common.enums import (
|
18
|
+
ConfigFolder,
|
18
19
|
CustomInferenceContainerTypeFamily,
|
19
20
|
FineTuningContainerTypeFamily,
|
20
21
|
InferenceContainerTypeFamily,
|
21
22
|
Tags,
|
22
23
|
)
|
23
|
-
from ads.aqua.common.errors import
|
24
|
+
from ads.aqua.common.errors import (
|
25
|
+
AquaFileNotFoundError,
|
26
|
+
AquaRuntimeError,
|
27
|
+
AquaValueError,
|
28
|
+
)
|
24
29
|
from ads.aqua.common.utils import (
|
25
30
|
LifecycleStatus,
|
26
31
|
_build_resource_identifier,
|
27
32
|
cleanup_local_hf_model_artifact,
|
28
|
-
copy_model_config,
|
29
33
|
create_word_icon,
|
30
34
|
generate_tei_cmd_var,
|
31
35
|
get_artifact_path,
|
@@ -41,6 +45,7 @@ from ads.aqua.constants import (
|
|
41
45
|
AQUA_MODEL_ARTIFACT_CONFIG_MODEL_NAME,
|
42
46
|
AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE,
|
43
47
|
AQUA_MODEL_ARTIFACT_FILE,
|
48
|
+
AQUA_MODEL_TOKENIZER_CONFIG,
|
44
49
|
AQUA_MODEL_TYPE_CUSTOM,
|
45
50
|
HF_METADATA_FOLDER,
|
46
51
|
LICENSE_TXT,
|
@@ -162,7 +167,7 @@ class AquaModelApp(AquaApp):
|
|
162
167
|
target_compartment = compartment_id or COMPARTMENT_OCID
|
163
168
|
|
164
169
|
if service_model.compartment_id != ODSC_MODEL_COMPARTMENT_OCID:
|
165
|
-
logger.
|
170
|
+
logger.info(
|
166
171
|
f"Aqua Model {model_id} already exists in user's compartment."
|
167
172
|
"Skipped copying."
|
168
173
|
)
|
@@ -193,8 +198,8 @@ class AquaModelApp(AquaApp):
|
|
193
198
|
# TODO: decide what kwargs will be needed.
|
194
199
|
.create(model_by_reference=True, **kwargs)
|
195
200
|
)
|
196
|
-
logger.
|
197
|
-
f"Aqua Model {custom_model.id} created with the service model {model_id}"
|
201
|
+
logger.info(
|
202
|
+
f"Aqua Model {custom_model.id} created with the service model {model_id}."
|
198
203
|
)
|
199
204
|
|
200
205
|
# tracks unique models that were created in the user compartment
|
@@ -225,11 +230,16 @@ class AquaModelApp(AquaApp):
|
|
225
230
|
|
226
231
|
cached_item = self._service_model_details_cache.get(model_id)
|
227
232
|
if cached_item:
|
233
|
+
logger.info(f"Fetching model details for model {model_id} from cache.")
|
228
234
|
return cached_item
|
229
235
|
|
236
|
+
logger.info(f"Fetching model details for model {model_id}.")
|
230
237
|
ds_model = DataScienceModel.from_id(model_id)
|
231
238
|
if not self._if_show(ds_model):
|
232
|
-
raise AquaRuntimeError(
|
239
|
+
raise AquaRuntimeError(
|
240
|
+
f"Target model `{ds_model.id} `is not an Aqua model as it does not contain "
|
241
|
+
f"{Tags.AQUA_TAG} tag."
|
242
|
+
)
|
233
243
|
|
234
244
|
is_fine_tuned_model = bool(
|
235
245
|
ds_model.freeform_tags
|
@@ -248,16 +258,21 @@ class AquaModelApp(AquaApp):
|
|
248
258
|
ds_model.custom_metadata_list._to_oci_metadata()
|
249
259
|
)
|
250
260
|
if artifact_path != UNKNOWN:
|
261
|
+
model_card_path = (
|
262
|
+
f"{artifact_path.rstrip('/')}/config/{README}"
|
263
|
+
if is_verified_type
|
264
|
+
else f"{artifact_path.rstrip('/')}/{README}"
|
265
|
+
)
|
251
266
|
model_card = str(
|
252
267
|
read_file(
|
253
|
-
file_path=
|
254
|
-
f"{artifact_path.rstrip('/')}/config/{README}"
|
255
|
-
if is_verified_type
|
256
|
-
else f"{artifact_path.rstrip('/')}/{README}"
|
257
|
-
),
|
268
|
+
file_path=model_card_path,
|
258
269
|
auth=default_signer(),
|
259
270
|
)
|
260
271
|
)
|
272
|
+
if not model_card:
|
273
|
+
logger.warn(
|
274
|
+
f"Model card for {model_id} is empty or could not be loaded from {model_card_path}."
|
275
|
+
)
|
261
276
|
|
262
277
|
inference_container = ds_model.custom_metadata_list.get(
|
263
278
|
ModelCustomMetadataFields.DEPLOYMENT_CONTAINER,
|
@@ -303,9 +318,10 @@ class AquaModelApp(AquaApp):
|
|
303
318
|
try:
|
304
319
|
jobrun_ocid = ds_model.provenance_metadata.training_id
|
305
320
|
jobrun = self.ds_client.get_job_run(jobrun_ocid).data
|
306
|
-
except Exception:
|
321
|
+
except Exception as e:
|
307
322
|
logger.debug(
|
308
323
|
f"Missing jobrun information in the provenance metadata of the given model {model_id}."
|
324
|
+
f"\nError: {str(e)}"
|
309
325
|
)
|
310
326
|
jobrun = None
|
311
327
|
|
@@ -314,7 +330,10 @@ class AquaModelApp(AquaApp):
|
|
314
330
|
FineTuningCustomMetadata.FT_SOURCE
|
315
331
|
).value
|
316
332
|
except ValueError as e:
|
317
|
-
logger.debug(
|
333
|
+
logger.debug(
|
334
|
+
f"Custom metadata is missing {FineTuningCustomMetadata.FT_SOURCE} key for "
|
335
|
+
f"model {model_id}.\nError: {str(e)}"
|
336
|
+
)
|
318
337
|
source_id = UNKNOWN
|
319
338
|
|
320
339
|
try:
|
@@ -322,7 +341,10 @@ class AquaModelApp(AquaApp):
|
|
322
341
|
FineTuningCustomMetadata.FT_SOURCE_NAME
|
323
342
|
).value
|
324
343
|
except ValueError as e:
|
325
|
-
logger.debug(
|
344
|
+
logger.debug(
|
345
|
+
f"Custom metadata is missing {FineTuningCustomMetadata.FT_SOURCE_NAME} key for "
|
346
|
+
f"model {model_id}.\nError: {str(e)}"
|
347
|
+
)
|
326
348
|
source_name = UNKNOWN
|
327
349
|
|
328
350
|
source_identifier = _build_resource_identifier(
|
@@ -372,6 +394,7 @@ class AquaModelApp(AquaApp):
|
|
372
394
|
Tags.AQUA_FINE_TUNED_MODEL_TAG, None
|
373
395
|
)
|
374
396
|
if is_registered_model or is_fine_tuned_model:
|
397
|
+
logger.info(f"Deleting model {model_id}.")
|
375
398
|
return ds_model.delete()
|
376
399
|
else:
|
377
400
|
raise AquaRuntimeError(
|
@@ -478,6 +501,7 @@ class AquaModelApp(AquaApp):
|
|
478
501
|
freeform_tags=freeform_tags,
|
479
502
|
)
|
480
503
|
AquaApp().update_model(id, update_model_details)
|
504
|
+
logger.info(f"Updated model details for the model {id}.")
|
481
505
|
else:
|
482
506
|
raise AquaRuntimeError("Only registered unverified models can be edited.")
|
483
507
|
|
@@ -546,6 +570,26 @@ class AquaModelApp(AquaApp):
|
|
546
570
|
training_final,
|
547
571
|
]
|
548
572
|
|
573
|
+
def get_hf_tokenizer_config(self, model_id):
|
574
|
+
"""Gets the default chat template for the given Aqua model.
|
575
|
+
|
576
|
+
Parameters
|
577
|
+
----------
|
578
|
+
model_id: str
|
579
|
+
The OCID of the Aqua model.
|
580
|
+
|
581
|
+
Returns
|
582
|
+
-------
|
583
|
+
str:
|
584
|
+
Chat template string.
|
585
|
+
"""
|
586
|
+
config = self.get_config(
|
587
|
+
model_id, AQUA_MODEL_TOKENIZER_CONFIG, ConfigFolder.ARTIFACT
|
588
|
+
)
|
589
|
+
if not config:
|
590
|
+
logger.debug(f"Tokenizer config for model: {model_id} is not available.")
|
591
|
+
return config
|
592
|
+
|
549
593
|
@staticmethod
|
550
594
|
def to_aqua_model(
|
551
595
|
model: Union[
|
@@ -735,7 +779,7 @@ class AquaModelApp(AquaApp):
|
|
735
779
|
)
|
736
780
|
|
737
781
|
logger.info(
|
738
|
-
f"
|
782
|
+
f"Fetched {len(models)} model in compartment_id={compartment_id or ODSC_MODEL_COMPARTMENT_OCID}."
|
739
783
|
)
|
740
784
|
|
741
785
|
aqua_models = []
|
@@ -765,10 +809,12 @@ class AquaModelApp(AquaApp):
|
|
765
809
|
dict with the key used, and True if cache has the key that needs to be deleted.
|
766
810
|
"""
|
767
811
|
res = {}
|
768
|
-
logger.info("Clearing _service_models_cache")
|
769
812
|
with self._cache_lock:
|
770
813
|
if ODSC_MODEL_COMPARTMENT_OCID in self._service_models_cache:
|
771
814
|
self._service_models_cache.pop(key=ODSC_MODEL_COMPARTMENT_OCID)
|
815
|
+
logger.info(
|
816
|
+
f"Cleared models cache for service compartment {ODSC_MODEL_COMPARTMENT_OCID}."
|
817
|
+
)
|
772
818
|
res = {
|
773
819
|
"key": {
|
774
820
|
"compartment_id": ODSC_MODEL_COMPARTMENT_OCID,
|
@@ -785,10 +831,10 @@ class AquaModelApp(AquaApp):
|
|
785
831
|
dict with the key used, and True if cache has the key that needs to be deleted.
|
786
832
|
"""
|
787
833
|
res = {}
|
788
|
-
logger.info(f"Clearing _service_model_details_cache for {model_id}")
|
789
834
|
with self._cache_lock:
|
790
835
|
if model_id in self._service_model_details_cache:
|
791
836
|
self._service_model_details_cache.pop(key=model_id)
|
837
|
+
logger.info(f"Clearing model details cache for model {model_id}.")
|
792
838
|
res = {"key": {"model_id": model_id}, "cache_deleted": True}
|
793
839
|
|
794
840
|
return res
|
@@ -873,7 +919,8 @@ class AquaModelApp(AquaApp):
|
|
873
919
|
metadata = ModelCustomMetadata()
|
874
920
|
if not inference_container:
|
875
921
|
raise AquaRuntimeError(
|
876
|
-
f"Require Inference container information. Model: {model_name} does not have associated inference
|
922
|
+
f"Require Inference container information. Model: {model_name} does not have associated inference "
|
923
|
+
f"container defaults. Check docs for more information on how to pass inference container."
|
877
924
|
)
|
878
925
|
metadata.add(
|
879
926
|
key=AQUA_DEPLOYMENT_CONTAINER_METADATA_NAME,
|
@@ -943,24 +990,6 @@ class AquaModelApp(AquaApp):
|
|
943
990
|
)
|
944
991
|
tags[Tags.LICENSE] = validation_result.tags.get(Tags.LICENSE, UNKNOWN)
|
945
992
|
|
946
|
-
try:
|
947
|
-
# If verified model already has a artifact json, use that.
|
948
|
-
artifact_path = metadata.get(MODEL_BY_REFERENCE_OSS_PATH_KEY).value
|
949
|
-
logger.info(
|
950
|
-
f"Found model artifact in the service bucket. "
|
951
|
-
f"Using artifact from service bucket instead of {os_path}"
|
952
|
-
)
|
953
|
-
|
954
|
-
# todo: implement generic copy_folder method
|
955
|
-
# copy model config from artifact path to user bucket
|
956
|
-
copy_model_config(
|
957
|
-
artifact_path=artifact_path, os_path=os_path, auth=default_signer()
|
958
|
-
)
|
959
|
-
except Exception:
|
960
|
-
logger.debug(
|
961
|
-
f"Proceeding with model registration without copying model config files at {os_path}. "
|
962
|
-
f"Default configuration will be used for deployment and fine-tuning."
|
963
|
-
)
|
964
993
|
# Set artifact location to user bucket, and replace existing key if present.
|
965
994
|
metadata.add(
|
966
995
|
key=MODEL_BY_REFERENCE_OSS_PATH_KEY,
|
@@ -980,7 +1009,7 @@ class AquaModelApp(AquaApp):
|
|
980
1009
|
.with_freeform_tags(**tags)
|
981
1010
|
.with_defined_tags(**(defined_tags or {}))
|
982
1011
|
).create(model_by_reference=True)
|
983
|
-
logger.debug(model)
|
1012
|
+
logger.debug(f"Created model catalog entry for the model:\n{model}")
|
984
1013
|
return model
|
985
1014
|
|
986
1015
|
@staticmethod
|
@@ -1000,13 +1029,23 @@ class AquaModelApp(AquaApp):
|
|
1000
1029
|
# todo: revisit this logic to account for .bin files. In the current state, .bin and .safetensor models
|
1001
1030
|
# are grouped in one category and validation checks for config.json files only.
|
1002
1031
|
if model_format == ModelFormat.SAFETENSORS:
|
1032
|
+
model_files.extend(
|
1033
|
+
list_os_files_with_extension(oss_path=os_path, extension=".safetensors")
|
1034
|
+
)
|
1003
1035
|
try:
|
1004
1036
|
load_config(
|
1005
1037
|
file_path=os_path,
|
1006
1038
|
config_file_name=AQUA_MODEL_ARTIFACT_CONFIG,
|
1007
1039
|
)
|
1008
|
-
except Exception:
|
1009
|
-
|
1040
|
+
except Exception as ex:
|
1041
|
+
message = (
|
1042
|
+
f"The model path {os_path} does not contain the file config.json. "
|
1043
|
+
f"Please check if the path is correct or the model artifacts are available at this location."
|
1044
|
+
)
|
1045
|
+
logger.warning(
|
1046
|
+
f"{message}\n"
|
1047
|
+
f"Details: {ex.reason if isinstance(ex, AquaFileNotFoundError) else str(ex)}\n"
|
1048
|
+
)
|
1010
1049
|
else:
|
1011
1050
|
model_files.append(AQUA_MODEL_ARTIFACT_CONFIG)
|
1012
1051
|
|
@@ -1014,6 +1053,9 @@ class AquaModelApp(AquaApp):
|
|
1014
1053
|
model_files.extend(
|
1015
1054
|
list_os_files_with_extension(oss_path=os_path, extension=".gguf")
|
1016
1055
|
)
|
1056
|
+
logger.debug(
|
1057
|
+
f"Fetched {len(model_files)} model files from {os_path} for model format {model_format}."
|
1058
|
+
)
|
1017
1059
|
return model_files
|
1018
1060
|
|
1019
1061
|
@staticmethod
|
@@ -1050,12 +1092,17 @@ class AquaModelApp(AquaApp):
|
|
1050
1092
|
|
1051
1093
|
for model_sibling in model_siblings:
|
1052
1094
|
extension = pathlib.Path(model_sibling.rfilename).suffix[1:].upper()
|
1053
|
-
if
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1095
|
+
if (
|
1096
|
+
model_format == ModelFormat.SAFETENSORS
|
1097
|
+
and model_sibling.rfilename == AQUA_MODEL_ARTIFACT_CONFIG
|
1098
|
+
):
|
1099
|
+
model_files.append(model_sibling.rfilename)
|
1100
|
+
if extension == model_format.value:
|
1057
1101
|
model_files.append(model_sibling.rfilename)
|
1058
1102
|
|
1103
|
+
logger.debug(
|
1104
|
+
f"Fetched {len(model_files)} model files for the model {model_name} for model format {model_format}."
|
1105
|
+
)
|
1059
1106
|
return model_files
|
1060
1107
|
|
1061
1108
|
def _validate_model(
|
@@ -1089,7 +1136,10 @@ class AquaModelApp(AquaApp):
|
|
1089
1136
|
safetensors_model_files = self.get_hf_model_files(
|
1090
1137
|
model_name, ModelFormat.SAFETENSORS
|
1091
1138
|
)
|
1092
|
-
if
|
1139
|
+
if (
|
1140
|
+
safetensors_model_files
|
1141
|
+
and AQUA_MODEL_ARTIFACT_CONFIG in safetensors_model_files
|
1142
|
+
):
|
1093
1143
|
hf_download_config_present = True
|
1094
1144
|
gguf_model_files = self.get_hf_model_files(model_name, ModelFormat.GGUF)
|
1095
1145
|
else:
|
@@ -1145,8 +1195,11 @@ class AquaModelApp(AquaApp):
|
|
1145
1195
|
Tags.LICENSE: license_value,
|
1146
1196
|
}
|
1147
1197
|
validation_result.tags = hf_tags
|
1148
|
-
except Exception:
|
1149
|
-
|
1198
|
+
except Exception as ex:
|
1199
|
+
logger.debug(
|
1200
|
+
f"An error occurred while getting tag information for model {model_name}. "
|
1201
|
+
f"Error: {str(ex)}"
|
1202
|
+
)
|
1150
1203
|
|
1151
1204
|
validation_result.model_formats = model_formats
|
1152
1205
|
|
@@ -1201,40 +1254,55 @@ class AquaModelApp(AquaApp):
|
|
1201
1254
|
model_name: str = None,
|
1202
1255
|
):
|
1203
1256
|
if import_model_details.download_from_hf:
|
1204
|
-
# validates config.json exists for safetensors model from
|
1205
|
-
if not
|
1257
|
+
# validates config.json exists for safetensors model from huggingface
|
1258
|
+
if not (
|
1259
|
+
hf_download_config_present
|
1260
|
+
or import_model_details.ignore_model_artifact_check
|
1261
|
+
):
|
1206
1262
|
raise AquaRuntimeError(
|
1207
1263
|
f"The model {model_name} does not contain {AQUA_MODEL_ARTIFACT_CONFIG} file as required "
|
1208
1264
|
f"by {ModelFormat.SAFETENSORS.value} format model."
|
1209
1265
|
f" Please check if the model name is correct in Hugging Face repository."
|
1210
1266
|
)
|
1267
|
+
validation_result.telemetry_model_name = model_name
|
1211
1268
|
else:
|
1269
|
+
# validate if config.json is available from object storage, and get model name for telemetry
|
1270
|
+
model_config = None
|
1212
1271
|
try:
|
1213
1272
|
model_config = load_config(
|
1214
1273
|
file_path=import_model_details.os_path,
|
1215
1274
|
config_file_name=AQUA_MODEL_ARTIFACT_CONFIG,
|
1216
1275
|
)
|
1217
1276
|
except Exception as ex:
|
1218
|
-
|
1219
|
-
f"Exception occurred while loading config file from {import_model_details.os_path}"
|
1220
|
-
f"Exception message: {ex}"
|
1221
|
-
)
|
1222
|
-
raise AquaRuntimeError(
|
1277
|
+
message = (
|
1223
1278
|
f"The model path {import_model_details.os_path} does not contain the file config.json. "
|
1224
1279
|
f"Please check if the path is correct or the model artifacts are available at this location."
|
1225
|
-
)
|
1226
|
-
|
1280
|
+
)
|
1281
|
+
if not import_model_details.ignore_model_artifact_check:
|
1282
|
+
logger.error(
|
1283
|
+
f"{message}\n"
|
1284
|
+
f"Details: {ex.reason if isinstance(ex, AquaFileNotFoundError) else str(ex)}"
|
1285
|
+
)
|
1286
|
+
raise AquaRuntimeError(message) from ex
|
1287
|
+
else:
|
1288
|
+
logger.warning(
|
1289
|
+
f"{message}\n"
|
1290
|
+
f"Proceeding with model registration as ignore_model_artifact_check field is set."
|
1291
|
+
)
|
1292
|
+
|
1293
|
+
if verified_model:
|
1294
|
+
# model_type validation, log message if metadata field doesn't match.
|
1227
1295
|
try:
|
1228
1296
|
metadata_model_type = verified_model.custom_metadata_list.get(
|
1229
1297
|
AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE
|
1230
1298
|
).value
|
1231
|
-
if metadata_model_type:
|
1299
|
+
if metadata_model_type and model_config is not None:
|
1232
1300
|
if AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE in model_config:
|
1233
1301
|
if (
|
1234
1302
|
model_config[AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE]
|
1235
1303
|
!= metadata_model_type
|
1236
1304
|
):
|
1237
|
-
|
1305
|
+
logger.debug(
|
1238
1306
|
f"The {AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE} attribute in {AQUA_MODEL_ARTIFACT_CONFIG}"
|
1239
1307
|
f" at {import_model_details.os_path} is invalid, expected {metadata_model_type} for "
|
1240
1308
|
f"the model {model_name}. Please check if the path is correct or "
|
@@ -1246,22 +1314,26 @@ class AquaModelApp(AquaApp):
|
|
1246
1314
|
f"Could not find {AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE} attribute in "
|
1247
1315
|
f"{AQUA_MODEL_ARTIFACT_CONFIG}. Proceeding with model registration."
|
1248
1316
|
)
|
1249
|
-
except Exception:
|
1250
|
-
pass
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1317
|
+
except Exception as ex:
|
1318
|
+
# todo: raise exception if model_type doesn't match. Currently log message and pass since service
|
1319
|
+
# models do not have this metadata.
|
1320
|
+
logger.debug(
|
1321
|
+
f"Error occurred while processing metadata for model {model_name}. "
|
1322
|
+
f"Exception: {str(ex)}"
|
1323
|
+
)
|
1324
|
+
validation_result.telemetry_model_name = verified_model.display_name
|
1325
|
+
elif (
|
1326
|
+
model_config is not None
|
1327
|
+
and AQUA_MODEL_ARTIFACT_CONFIG_MODEL_NAME in model_config
|
1328
|
+
):
|
1329
|
+
validation_result.telemetry_model_name = f"{AQUA_MODEL_TYPE_CUSTOM}_{model_config[AQUA_MODEL_ARTIFACT_CONFIG_MODEL_NAME]}"
|
1330
|
+
elif (
|
1331
|
+
model_config is not None
|
1332
|
+
and AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE in model_config
|
1333
|
+
):
|
1334
|
+
validation_result.telemetry_model_name = f"{AQUA_MODEL_TYPE_CUSTOM}_{model_config[AQUA_MODEL_ARTIFACT_CONFIG_MODEL_TYPE]}"
|
1335
|
+
else:
|
1336
|
+
validation_result.telemetry_model_name = AQUA_MODEL_TYPE_CUSTOM
|
1265
1337
|
|
1266
1338
|
@staticmethod
|
1267
1339
|
def _validate_gguf_format(
|
@@ -1363,6 +1435,10 @@ class AquaModelApp(AquaApp):
|
|
1363
1435
|
allow_patterns=allow_patterns,
|
1364
1436
|
ignore_patterns=ignore_patterns,
|
1365
1437
|
)
|
1438
|
+
# Upload to object storage and skip .cache/huggingface/ folder
|
1439
|
+
logger.debug(
|
1440
|
+
f"Uploading local artifacts from local directory {local_dir} to {os_path}."
|
1441
|
+
)
|
1366
1442
|
# Upload to object storage
|
1367
1443
|
model_artifact_path = upload_folder(
|
1368
1444
|
os_path=os_path,
|
@@ -1409,6 +1485,7 @@ class AquaModelApp(AquaApp):
|
|
1409
1485
|
import_model_details.model.startswith("ocid")
|
1410
1486
|
and "datasciencemodel" in import_model_details.model
|
1411
1487
|
):
|
1488
|
+
logger.info(f"Fetching details for model {import_model_details.model}.")
|
1412
1489
|
verified_model = DataScienceModel.from_id(import_model_details.model)
|
1413
1490
|
else:
|
1414
1491
|
# If users passes model name, check if there is model with the same name in the service model catalog. If it is there, then use that model
|
@@ -1446,7 +1523,6 @@ class AquaModelApp(AquaApp):
|
|
1446
1523
|
).rstrip("/")
|
1447
1524
|
else:
|
1448
1525
|
artifact_path = import_model_details.os_path.rstrip("/")
|
1449
|
-
|
1450
1526
|
# Create Model catalog entry with pass by reference
|
1451
1527
|
ds_model = self._create_model_catalog_entry(
|
1452
1528
|
os_path=artifact_path,
|
@@ -1539,7 +1615,7 @@ class AquaModelApp(AquaApp):
|
|
1539
1615
|
elif model_type == ModelType.BASE:
|
1540
1616
|
filter_tag = Tags.BASE_MODEL_CUSTOM
|
1541
1617
|
else:
|
1542
|
-
raise
|
1618
|
+
raise AquaValueError(
|
1543
1619
|
f"Model of type {model_type} is unknown. The values should be in {ModelType.values()}"
|
1544
1620
|
)
|
1545
1621
|
|
@@ -1579,7 +1655,10 @@ class AquaModelApp(AquaApp):
|
|
1579
1655
|
oci_model = self.ds_client.get_model(model_id).data
|
1580
1656
|
artifact_path = get_artifact_path(oci_model.custom_metadata_list)
|
1581
1657
|
if not artifact_path:
|
1582
|
-
raise AquaRuntimeError(
|
1658
|
+
raise AquaRuntimeError(
|
1659
|
+
f"License could not be loaded. Failed to get artifact path from custom metadata for"
|
1660
|
+
f"the model {model_id}."
|
1661
|
+
)
|
1583
1662
|
|
1584
1663
|
content = str(
|
1585
1664
|
read_file(
|
@@ -1610,6 +1689,9 @@ class AquaModelApp(AquaApp):
|
|
1610
1689
|
|
1611
1690
|
for aqua_model_summary in aqua_model_list:
|
1612
1691
|
if aqua_model_summary.name.lower() == model_id_lower:
|
1692
|
+
logger.info(
|
1693
|
+
f"Found matching verified model id {aqua_model_summary.id} for the model {model_id}"
|
1694
|
+
)
|
1613
1695
|
return aqua_model_summary.id
|
1614
1696
|
|
1615
1697
|
return None
|