oracle-ads 2.12.8__py3-none-any.whl → 2.12.10rc0__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 +4 -4
- ads/aqua/app.py +12 -2
- ads/aqua/common/enums.py +3 -0
- ads/aqua/common/utils.py +62 -2
- ads/aqua/data.py +2 -19
- ads/aqua/evaluation/entities.py +6 -0
- ads/aqua/evaluation/evaluation.py +25 -3
- ads/aqua/extension/deployment_handler.py +8 -4
- ads/aqua/extension/finetune_handler.py +8 -14
- ads/aqua/extension/model_handler.py +25 -6
- ads/aqua/extension/ui_handler.py +13 -1
- ads/aqua/finetuning/constants.py +5 -2
- ads/aqua/finetuning/entities.py +70 -17
- ads/aqua/finetuning/finetuning.py +79 -82
- ads/aqua/model/entities.py +4 -1
- ads/aqua/model/model.py +95 -29
- ads/aqua/modeldeployment/deployment.py +13 -1
- ads/aqua/modeldeployment/entities.py +7 -4
- ads/aqua/ui.py +24 -2
- ads/common/auth.py +9 -9
- ads/llm/autogen/__init__.py +2 -0
- ads/llm/autogen/constants.py +15 -0
- ads/llm/autogen/reports/__init__.py +2 -0
- ads/llm/autogen/reports/base.py +67 -0
- ads/llm/autogen/reports/data.py +103 -0
- ads/llm/autogen/reports/session.py +526 -0
- ads/llm/autogen/reports/templates/chat_box.html +13 -0
- ads/llm/autogen/reports/templates/chat_box_lt.html +5 -0
- ads/llm/autogen/reports/templates/chat_box_rt.html +6 -0
- ads/llm/autogen/reports/utils.py +56 -0
- ads/llm/autogen/v02/__init__.py +4 -0
- ads/llm/autogen/{client_v02.py → v02/client.py} +23 -10
- ads/llm/autogen/v02/log_handlers/__init__.py +2 -0
- ads/llm/autogen/v02/log_handlers/oci_file_handler.py +83 -0
- ads/llm/autogen/v02/loggers/__init__.py +6 -0
- ads/llm/autogen/v02/loggers/metric_logger.py +320 -0
- ads/llm/autogen/v02/loggers/session_logger.py +580 -0
- ads/llm/autogen/v02/loggers/utils.py +86 -0
- ads/llm/autogen/v02/runtime_logging.py +163 -0
- ads/llm/guardrails/base.py +6 -5
- ads/llm/langchain/plugins/chat_models/oci_data_science.py +46 -20
- ads/llm/langchain/plugins/llms/oci_data_science_model_deployment_endpoint.py +38 -11
- ads/model/__init__.py +11 -13
- ads/model/artifact.py +47 -8
- ads/model/extractor/embedding_onnx_extractor.py +80 -0
- ads/model/framework/embedding_onnx_model.py +438 -0
- ads/model/generic_model.py +26 -24
- ads/model/model_metadata.py +8 -7
- ads/opctl/config/merger.py +13 -14
- ads/opctl/operator/common/operator_config.py +4 -4
- ads/opctl/operator/lowcode/common/transformations.py +12 -5
- ads/opctl/operator/lowcode/common/utils.py +11 -5
- ads/opctl/operator/lowcode/forecast/const.py +3 -0
- ads/opctl/operator/lowcode/forecast/model/arima.py +19 -13
- ads/opctl/operator/lowcode/forecast/model/automlx.py +129 -36
- ads/opctl/operator/lowcode/forecast/model/autots.py +1 -0
- ads/opctl/operator/lowcode/forecast/model/base_model.py +58 -17
- ads/opctl/operator/lowcode/forecast/model/neuralprophet.py +10 -3
- ads/opctl/operator/lowcode/forecast/model/prophet.py +25 -18
- ads/opctl/operator/lowcode/forecast/model_evaluator.py +3 -2
- ads/opctl/operator/lowcode/forecast/schema.yaml +13 -0
- ads/opctl/operator/lowcode/forecast/utils.py +8 -6
- ads/telemetry/base.py +18 -11
- ads/telemetry/client.py +33 -13
- ads/templates/schemas/openapi.json +1740 -0
- ads/templates/score_embedding_onnx.jinja2 +202 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/METADATA +9 -10
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/RECORD +71 -50
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/LICENSE.txt +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/WHEEL +0 -0
- {oracle_ads-2.12.8.dist-info → oracle_ads-2.12.10rc0.dist-info}/entry_points.txt +0 -0
ads/aqua/model/model.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
|
import os
|
5
5
|
import pathlib
|
@@ -15,6 +15,7 @@ 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
|
+
CustomInferenceContainerTypeFamily,
|
18
19
|
FineTuningContainerTypeFamily,
|
19
20
|
InferenceContainerTypeFamily,
|
20
21
|
Tags,
|
@@ -23,6 +24,7 @@ from ads.aqua.common.errors import AquaRuntimeError, AquaValueError
|
|
23
24
|
from ads.aqua.common.utils import (
|
24
25
|
LifecycleStatus,
|
25
26
|
_build_resource_identifier,
|
27
|
+
cleanup_local_hf_model_artifact,
|
26
28
|
copy_model_config,
|
27
29
|
create_word_icon,
|
28
30
|
generate_tei_cmd_var,
|
@@ -127,7 +129,13 @@ class AquaModelApp(AquaApp):
|
|
127
129
|
|
128
130
|
@telemetry(entry_point="plugin=model&action=create", name="aqua")
|
129
131
|
def create(
|
130
|
-
self,
|
132
|
+
self,
|
133
|
+
model_id: str,
|
134
|
+
project_id: str,
|
135
|
+
compartment_id: str = None,
|
136
|
+
freeform_tags: Optional[dict] = None,
|
137
|
+
defined_tags: Optional[dict] = None,
|
138
|
+
**kwargs,
|
131
139
|
) -> DataScienceModel:
|
132
140
|
"""Creates custom aqua model from service model.
|
133
141
|
|
@@ -140,7 +148,10 @@ class AquaModelApp(AquaApp):
|
|
140
148
|
compartment_id: str
|
141
149
|
The compartment id for custom model. Defaults to None.
|
142
150
|
If not provided, compartment id will be fetched from environment variables.
|
143
|
-
|
151
|
+
freeform_tags: dict
|
152
|
+
Freeform tags for the model
|
153
|
+
defined_tags: dict
|
154
|
+
Defined tags for the model
|
144
155
|
Returns
|
145
156
|
-------
|
146
157
|
DataScienceModel:
|
@@ -157,6 +168,16 @@ class AquaModelApp(AquaApp):
|
|
157
168
|
)
|
158
169
|
return service_model
|
159
170
|
|
171
|
+
# combine tags
|
172
|
+
combined_freeform_tags = {
|
173
|
+
**(service_model.freeform_tags or {}),
|
174
|
+
**(freeform_tags or {}),
|
175
|
+
}
|
176
|
+
combined_defined_tags = {
|
177
|
+
**(service_model.defined_tags or {}),
|
178
|
+
**(defined_tags or {}),
|
179
|
+
}
|
180
|
+
|
160
181
|
custom_model = (
|
161
182
|
DataScienceModel()
|
162
183
|
.with_compartment_id(target_compartment)
|
@@ -164,8 +185,8 @@ class AquaModelApp(AquaApp):
|
|
164
185
|
.with_model_file_description(json_dict=service_model.model_file_description)
|
165
186
|
.with_display_name(service_model.display_name)
|
166
187
|
.with_description(service_model.description)
|
167
|
-
.with_freeform_tags(**
|
168
|
-
.with_defined_tags(**
|
188
|
+
.with_freeform_tags(**combined_freeform_tags)
|
189
|
+
.with_defined_tags(**combined_defined_tags)
|
169
190
|
.with_custom_metadata_list(service_model.custom_metadata_list)
|
170
191
|
.with_defined_metadata_list(service_model.defined_metadata_list)
|
171
192
|
.with_provenance_metadata(service_model.provenance_metadata)
|
@@ -357,8 +378,10 @@ class AquaModelApp(AquaApp):
|
|
357
378
|
f"Failed to delete model:{model_id}. Only registered models or finetuned model can be deleted."
|
358
379
|
)
|
359
380
|
|
360
|
-
@telemetry(entry_point="plugin=model&action=
|
361
|
-
def edit_registered_model(
|
381
|
+
@telemetry(entry_point="plugin=model&action=edit", name="aqua")
|
382
|
+
def edit_registered_model(
|
383
|
+
self, id, inference_container, inference_container_uri, enable_finetuning, task
|
384
|
+
):
|
362
385
|
"""Edits the default config of unverified registered model.
|
363
386
|
|
364
387
|
Parameters
|
@@ -367,6 +390,8 @@ class AquaModelApp(AquaApp):
|
|
367
390
|
The model OCID.
|
368
391
|
inference_container: str.
|
369
392
|
The inference container family name
|
393
|
+
inference_container_uri: str
|
394
|
+
The inference container uri for embedding models
|
370
395
|
enable_finetuning: str
|
371
396
|
Flag to enable or disable finetuning over the model. Defaults to None
|
372
397
|
task:
|
@@ -382,19 +407,44 @@ class AquaModelApp(AquaApp):
|
|
382
407
|
if ds_model.freeform_tags.get(Tags.BASE_MODEL_CUSTOM, None):
|
383
408
|
if ds_model.freeform_tags.get(Tags.AQUA_SERVICE_MODEL_TAG, None):
|
384
409
|
raise AquaRuntimeError(
|
385
|
-
|
410
|
+
"Only registered unverified models can be edited."
|
386
411
|
)
|
387
412
|
else:
|
388
413
|
custom_metadata_list = ds_model.custom_metadata_list
|
389
414
|
freeform_tags = ds_model.freeform_tags
|
390
415
|
if inference_container:
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
416
|
+
if (
|
417
|
+
inference_container in CustomInferenceContainerTypeFamily
|
418
|
+
and inference_container_uri is None
|
419
|
+
):
|
420
|
+
raise AquaRuntimeError(
|
421
|
+
"Inference container URI must be provided."
|
422
|
+
)
|
423
|
+
else:
|
424
|
+
custom_metadata_list.add(
|
425
|
+
key=ModelCustomMetadataFields.DEPLOYMENT_CONTAINER,
|
426
|
+
value=inference_container,
|
427
|
+
category=MetadataCustomCategory.OTHER,
|
428
|
+
description="Deployment container mapping for SMC",
|
429
|
+
replace=True,
|
430
|
+
)
|
431
|
+
if inference_container_uri:
|
432
|
+
if (
|
433
|
+
inference_container in CustomInferenceContainerTypeFamily
|
434
|
+
or inference_container is None
|
435
|
+
):
|
436
|
+
custom_metadata_list.add(
|
437
|
+
key=ModelCustomMetadataFields.DEPLOYMENT_CONTAINER_URI,
|
438
|
+
value=inference_container_uri,
|
439
|
+
category=MetadataCustomCategory.OTHER,
|
440
|
+
description=f"Inference container URI for {ds_model.display_name}",
|
441
|
+
replace=True,
|
442
|
+
)
|
443
|
+
else:
|
444
|
+
raise AquaRuntimeError(
|
445
|
+
f"Inference container URI can be edited only with container values: {CustomInferenceContainerTypeFamily.values()}"
|
446
|
+
)
|
447
|
+
|
398
448
|
if enable_finetuning is not None:
|
399
449
|
if enable_finetuning.lower() == "true":
|
400
450
|
custom_metadata_list.add(
|
@@ -414,7 +464,7 @@ class AquaModelApp(AquaApp):
|
|
414
464
|
except Exception as ex:
|
415
465
|
raise AquaRuntimeError(
|
416
466
|
f"The given model already doesn't support finetuning: {ex}"
|
417
|
-
)
|
467
|
+
) from ex
|
418
468
|
|
419
469
|
custom_metadata_list.remove("modelDescription")
|
420
470
|
if task:
|
@@ -429,9 +479,7 @@ class AquaModelApp(AquaApp):
|
|
429
479
|
)
|
430
480
|
AquaApp().update_model(id, update_model_details)
|
431
481
|
else:
|
432
|
-
raise AquaRuntimeError(
|
433
|
-
f"Failed to edit model:{id}. Only registered unverified models can be edited."
|
434
|
-
)
|
482
|
+
raise AquaRuntimeError("Only registered unverified models can be edited.")
|
435
483
|
|
436
484
|
def _fetch_metric_from_metadata(
|
437
485
|
self,
|
@@ -766,6 +814,8 @@ class AquaModelApp(AquaApp):
|
|
766
814
|
compartment_id: Optional[str],
|
767
815
|
project_id: Optional[str],
|
768
816
|
inference_container_uri: Optional[str],
|
817
|
+
freeform_tags: Optional[dict] = None,
|
818
|
+
defined_tags: Optional[dict] = None,
|
769
819
|
) -> DataScienceModel:
|
770
820
|
"""Create model by reference from the object storage path
|
771
821
|
|
@@ -778,6 +828,8 @@ class AquaModelApp(AquaApp):
|
|
778
828
|
compartment_id (Optional[str]): Compartment Id of the compartment where the model has to be created
|
779
829
|
project_id (Optional[str]): Project id of the project where the model has to be created
|
780
830
|
inference_container_uri (Optional[str]): Inference container uri for BYOC
|
831
|
+
freeform_tags (dict): Freeform tags for the model
|
832
|
+
defined_tags (dict): Defined tags for the model
|
781
833
|
|
782
834
|
Returns:
|
783
835
|
DataScienceModel: Returns Datascience model instance.
|
@@ -846,8 +898,7 @@ class AquaModelApp(AquaApp):
|
|
846
898
|
# only add cmd vars if inference container is not an SMC
|
847
899
|
if (
|
848
900
|
inference_container not in smc_container_set
|
849
|
-
and inference_container
|
850
|
-
== InferenceContainerTypeFamily.AQUA_TEI_CONTAINER_FAMILY
|
901
|
+
and inference_container in CustomInferenceContainerTypeFamily.values()
|
851
902
|
):
|
852
903
|
cmd_vars = generate_tei_cmd_var(os_path)
|
853
904
|
metadata.add(
|
@@ -918,6 +969,8 @@ class AquaModelApp(AquaApp):
|
|
918
969
|
category="Other",
|
919
970
|
replace=True,
|
920
971
|
)
|
972
|
+
# override tags with freeform tags if set
|
973
|
+
tags = {**tags, **(freeform_tags or {})}
|
921
974
|
model = (
|
922
975
|
model.with_custom_metadata_list(metadata)
|
923
976
|
.with_compartment_id(compartment_id or COMPARTMENT_OCID)
|
@@ -925,6 +978,7 @@ class AquaModelApp(AquaApp):
|
|
925
978
|
.with_artifact(os_path)
|
926
979
|
.with_display_name(model_name)
|
927
980
|
.with_freeform_tags(**tags)
|
981
|
+
.with_defined_tags(**(defined_tags or {}))
|
928
982
|
).create(model_by_reference=True)
|
929
983
|
logger.debug(model)
|
930
984
|
return model
|
@@ -1296,25 +1350,25 @@ class AquaModelApp(AquaApp):
|
|
1296
1350
|
Returns
|
1297
1351
|
-------
|
1298
1352
|
model_artifact_path (str): Location where the model artifacts are downloaded.
|
1299
|
-
|
1300
1353
|
"""
|
1301
1354
|
# Download the model from hub
|
1302
|
-
if
|
1303
|
-
local_dir = os.path.join(
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1355
|
+
if local_dir:
|
1356
|
+
local_dir = os.path.join(local_dir, model_name)
|
1357
|
+
os.makedirs(local_dir, exist_ok=True)
|
1358
|
+
|
1359
|
+
# if local_dir is not set, the return value points to the cached data folder
|
1360
|
+
local_dir = snapshot_download(
|
1307
1361
|
repo_id=model_name,
|
1308
1362
|
local_dir=local_dir,
|
1309
1363
|
allow_patterns=allow_patterns,
|
1310
1364
|
ignore_patterns=ignore_patterns,
|
1311
1365
|
)
|
1312
|
-
# Upload to object storage
|
1366
|
+
# Upload to object storage
|
1313
1367
|
model_artifact_path = upload_folder(
|
1314
1368
|
os_path=os_path,
|
1315
1369
|
local_dir=local_dir,
|
1316
1370
|
model_name=model_name,
|
1317
|
-
exclude_pattern=f"{HF_METADATA_FOLDER}*"
|
1371
|
+
exclude_pattern=f"{HF_METADATA_FOLDER}*",
|
1318
1372
|
)
|
1319
1373
|
|
1320
1374
|
return model_artifact_path
|
@@ -1339,6 +1393,8 @@ class AquaModelApp(AquaApp):
|
|
1339
1393
|
ignore_patterns (list): Model files matching any of the patterns are not downloaded.
|
1340
1394
|
Example: ["*.json"] will ignore all .json files. ["folder/*"] will ignore all files under `folder`.
|
1341
1395
|
Patterns are Standard Wildcards (globbing patterns) and rules can be found here: https://docs.python.org/3/library/fnmatch.html
|
1396
|
+
cleanup_model_cache (bool): Deletes downloaded files from local machine after model is successfully
|
1397
|
+
registered. Set to True by default.
|
1342
1398
|
|
1343
1399
|
Returns:
|
1344
1400
|
AquaModel:
|
@@ -1402,6 +1458,8 @@ class AquaModelApp(AquaApp):
|
|
1402
1458
|
compartment_id=import_model_details.compartment_id,
|
1403
1459
|
project_id=import_model_details.project_id,
|
1404
1460
|
inference_container_uri=import_model_details.inference_container_uri,
|
1461
|
+
freeform_tags=import_model_details.freeform_tags,
|
1462
|
+
defined_tags=import_model_details.defined_tags,
|
1405
1463
|
)
|
1406
1464
|
# registered model will always have inference and evaluation container, but
|
1407
1465
|
# fine-tuning container may be not set
|
@@ -1446,6 +1504,14 @@ class AquaModelApp(AquaApp):
|
|
1446
1504
|
detail=validation_result.telemetry_model_name,
|
1447
1505
|
)
|
1448
1506
|
|
1507
|
+
if (
|
1508
|
+
import_model_details.download_from_hf
|
1509
|
+
and import_model_details.cleanup_model_cache
|
1510
|
+
):
|
1511
|
+
cleanup_local_hf_model_artifact(
|
1512
|
+
model_name=model_name, local_dir=import_model_details.local_dir
|
1513
|
+
)
|
1514
|
+
|
1449
1515
|
return AquaModel(**aqua_model_attributes)
|
1450
1516
|
|
1451
1517
|
def _if_show(self, model: DataScienceModel) -> bool:
|
@@ -110,6 +110,8 @@ class AquaDeploymentApp(AquaApp):
|
|
110
110
|
private_endpoint_id: Optional[str] = None,
|
111
111
|
container_image_uri: Optional[None] = None,
|
112
112
|
cmd_var: List[str] = None,
|
113
|
+
freeform_tags: Optional[dict] = None,
|
114
|
+
defined_tags: Optional[dict] = None,
|
113
115
|
) -> "AquaDeployment":
|
114
116
|
"""
|
115
117
|
Creates a new Aqua deployment
|
@@ -163,6 +165,10 @@ class AquaDeploymentApp(AquaApp):
|
|
163
165
|
Required parameter for BYOC based deployments if this parameter was not set during model registration.
|
164
166
|
cmd_var: List[str]
|
165
167
|
The cmd of model deployment container runtime.
|
168
|
+
freeform_tags: dict
|
169
|
+
Freeform tags for the model deployment
|
170
|
+
defined_tags: dict
|
171
|
+
Defined tags for the model deployment
|
166
172
|
Returns
|
167
173
|
-------
|
168
174
|
AquaDeployment
|
@@ -172,7 +178,11 @@ class AquaDeploymentApp(AquaApp):
|
|
172
178
|
# TODO validate if the service model has no artifact and if it requires import step before deployment.
|
173
179
|
# Create a model catalog entry in the user compartment
|
174
180
|
aqua_model = AquaModelApp().create(
|
175
|
-
model_id=model_id,
|
181
|
+
model_id=model_id,
|
182
|
+
compartment_id=compartment_id,
|
183
|
+
project_id=project_id,
|
184
|
+
freeform_tags=freeform_tags,
|
185
|
+
defined_tags=defined_tags,
|
176
186
|
)
|
177
187
|
|
178
188
|
tags = {}
|
@@ -418,12 +428,14 @@ class AquaDeploymentApp(AquaApp):
|
|
418
428
|
if cmd_var:
|
419
429
|
container_runtime.with_cmd(cmd_var)
|
420
430
|
|
431
|
+
tags = {**tags, **(freeform_tags or {})}
|
421
432
|
# configure model deployment and deploy model on container runtime
|
422
433
|
deployment = (
|
423
434
|
ModelDeployment()
|
424
435
|
.with_display_name(display_name)
|
425
436
|
.with_description(description)
|
426
437
|
.with_freeform_tags(**tags)
|
438
|
+
.with_defined_tags(**(defined_tags or {}))
|
427
439
|
.with_infrastructure(infrastructure)
|
428
440
|
.with_runtime(container_runtime)
|
429
441
|
).deploy(wait_for_completion=False)
|
@@ -98,9 +98,12 @@ class AquaDeployment(DataClassSerializable):
|
|
98
98
|
),
|
99
99
|
)
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
tags = {}
|
102
|
+
tags.update(oci_model_deployment.freeform_tags or UNKNOWN_DICT)
|
103
|
+
tags.update(oci_model_deployment.defined_tags or UNKNOWN_DICT)
|
104
|
+
|
105
|
+
aqua_service_model_tag = tags.get(Tags.AQUA_SERVICE_MODEL_TAG, None)
|
106
|
+
aqua_model_name = tags.get(Tags.AQUA_MODEL_NAME_TAG, UNKNOWN)
|
104
107
|
private_endpoint_id = getattr(
|
105
108
|
instance_configuration, "private_endpoint_id", UNKNOWN
|
106
109
|
)
|
@@ -125,7 +128,7 @@ class AquaDeployment(DataClassSerializable):
|
|
125
128
|
ocid=oci_model_deployment.id,
|
126
129
|
region=region,
|
127
130
|
),
|
128
|
-
tags=
|
131
|
+
tags=tags,
|
129
132
|
environment_variables=environment_variables,
|
130
133
|
cmd=cmd,
|
131
134
|
)
|
ads/aqua/ui.py
CHANGED
@@ -481,12 +481,12 @@ class AquaUIApp(AquaApp):
|
|
481
481
|
|
482
482
|
@telemetry(entry_point="plugin=ui&action=list_job_shapes", name="aqua")
|
483
483
|
def list_job_shapes(self, **kwargs) -> list:
|
484
|
-
"""Lists all
|
484
|
+
"""Lists all available job shapes for the specified compartment.
|
485
485
|
|
486
486
|
Parameters
|
487
487
|
----------
|
488
488
|
**kwargs
|
489
|
-
|
489
|
+
Additional arguments, such as `compartment_id`,
|
490
490
|
for `list_job_shapes <https://docs.oracle.com/en-us/iaas/tools/python/2.122.0/api/data_science/client/oci.data_science.DataScienceClient.html#oci.data_science.DataScienceClient.list_job_shapes>`_
|
491
491
|
|
492
492
|
Returns
|
@@ -500,6 +500,28 @@ class AquaUIApp(AquaApp):
|
|
500
500
|
).data
|
501
501
|
return sanitize_response(oci_client=self.ds_client, response=res)
|
502
502
|
|
503
|
+
@telemetry(entry_point="plugin=ui&action=list_model_deployment_shapes", name="aqua")
|
504
|
+
def list_model_deployment_shapes(self, **kwargs) -> list:
|
505
|
+
"""Lists all available shapes for model deployment in the specified compartment.
|
506
|
+
|
507
|
+
Parameters
|
508
|
+
----------
|
509
|
+
**kwargs
|
510
|
+
Additional arguments, such as `compartment_id`,
|
511
|
+
for `list_model_deployment_shapes <https://docs.oracle.com/en-us/iaas/api/#/en/data-science/20190101/ModelDeploymentShapeSummary/ListModelDeploymentShapes>`_
|
512
|
+
|
513
|
+
Returns
|
514
|
+
-------
|
515
|
+
str has json representation of `oci.data_science.models.ModelDeploymentShapeSummary`."""
|
516
|
+
compartment_id = kwargs.pop("compartment_id", COMPARTMENT_OCID)
|
517
|
+
logger.info(
|
518
|
+
f"Loading model deployment shape summary from compartment: {compartment_id}"
|
519
|
+
)
|
520
|
+
res = self.ds_client.list_model_deployment_shapes(
|
521
|
+
compartment_id=compartment_id, **kwargs
|
522
|
+
).data
|
523
|
+
return sanitize_response(oci_client=self.ds_client, response=res)
|
524
|
+
|
503
525
|
@telemetry(entry_point="plugin=ui&action=list_vcn", name="aqua")
|
504
526
|
def list_vcn(self, **kwargs) -> list:
|
505
527
|
"""Lists the virtual cloud networks (VCNs) in the specified compartment.
|
ads/common/auth.py
CHANGED
@@ -424,7 +424,7 @@ def create_signer(
|
|
424
424
|
"signer": signer,
|
425
425
|
"client_kwargs": client_kwargs,
|
426
426
|
}
|
427
|
-
logger.
|
427
|
+
logger.debug(f"Using authentication signer type {type(signer)}.")
|
428
428
|
return signer_dict
|
429
429
|
else:
|
430
430
|
signer_args = dict(
|
@@ -492,7 +492,7 @@ def default_signer(client_kwargs: Optional[Dict] = None) -> Dict:
|
|
492
492
|
**(client_kwargs or {}),
|
493
493
|
},
|
494
494
|
}
|
495
|
-
logger.
|
495
|
+
logger.debug(f"Using authentication signer type {type(signer)}.")
|
496
496
|
return signer_dict
|
497
497
|
else:
|
498
498
|
signer_args = dict(
|
@@ -621,7 +621,7 @@ class APIKey(AuthSignerGenerator):
|
|
621
621
|
)
|
622
622
|
|
623
623
|
oci.config.validate_config(configuration)
|
624
|
-
logger.
|
624
|
+
logger.debug(f"Using 'api_key' authentication.")
|
625
625
|
return {
|
626
626
|
"config": configuration,
|
627
627
|
"signer": oci.signer.Signer(
|
@@ -684,7 +684,7 @@ class ResourcePrincipal(AuthSignerGenerator):
|
|
684
684
|
"signer": oci.auth.signers.get_resource_principals_signer(),
|
685
685
|
"client_kwargs": self.client_kwargs,
|
686
686
|
}
|
687
|
-
logger.
|
687
|
+
logger.debug(f"Using 'resource_principal' authentication.")
|
688
688
|
return signer_dict
|
689
689
|
|
690
690
|
@staticmethod
|
@@ -747,7 +747,7 @@ class InstancePrincipal(AuthSignerGenerator):
|
|
747
747
|
),
|
748
748
|
"client_kwargs": self.client_kwargs,
|
749
749
|
}
|
750
|
-
logger.
|
750
|
+
logger.debug(f"Using 'instance_principal' authentication.")
|
751
751
|
return signer_dict
|
752
752
|
|
753
753
|
|
@@ -814,7 +814,7 @@ class SecurityToken(AuthSignerGenerator):
|
|
814
814
|
oci.config.from_file(self.oci_config_location, self.oci_key_profile)
|
815
815
|
)
|
816
816
|
|
817
|
-
logger.
|
817
|
+
logger.debug(f"Using 'security_token' authentication.")
|
818
818
|
|
819
819
|
for parameter in self.SECURITY_TOKEN_REQUIRED:
|
820
820
|
if parameter not in configuration:
|
@@ -883,7 +883,7 @@ class SecurityToken(AuthSignerGenerator):
|
|
883
883
|
)
|
884
884
|
|
885
885
|
date_time = datetime.fromtimestamp(time_expired).strftime("%Y-%m-%d %H:%M:%S")
|
886
|
-
logger.
|
886
|
+
logger.debug(f"Session is valid until {date_time}.")
|
887
887
|
|
888
888
|
def _read_security_token_file(self, security_token_file: str) -> str:
|
889
889
|
"""Reads security token from file.
|
@@ -1020,10 +1020,10 @@ class OCIAuthContext:
|
|
1020
1020
|
"""
|
1021
1021
|
if self.profile:
|
1022
1022
|
ads.set_auth(auth=AuthType.API_KEY, profile=self.profile)
|
1023
|
-
logger.
|
1023
|
+
logger.debug(f"OCI profile set to {self.profile}")
|
1024
1024
|
else:
|
1025
1025
|
ads.set_auth(auth=AuthType.RESOURCE_PRINCIPAL)
|
1026
|
-
logger.
|
1026
|
+
logger.debug(f"OCI auth set to resource principal")
|
1027
1027
|
return self
|
1028
1028
|
|
1029
1029
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
ads/llm/autogen/__init__.py
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
2
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
3
|
+
|
4
|
+
|
5
|
+
class Events:
|
6
|
+
KEY = "event_name"
|
7
|
+
|
8
|
+
EXCEPTION = "exception"
|
9
|
+
LLM_CALL = "llm_call"
|
10
|
+
TOOL_CALL = "tool_call"
|
11
|
+
NEW_AGENT = "new_agent"
|
12
|
+
NEW_CLIENT = "new_client"
|
13
|
+
RECEIVED_MESSAGE = "received_message"
|
14
|
+
SESSION_START = "logging_session_start"
|
15
|
+
SESSION_STOP = "logging_session_stop"
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
2
|
+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
|
3
|
+
import json
|
4
|
+
import logging
|
5
|
+
import os
|
6
|
+
|
7
|
+
from jinja2 import Environment, FileSystemLoader
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class BaseReport:
|
13
|
+
"""Base class containing utilities for generating reports."""
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
def format_json_string(s) -> str:
|
17
|
+
"""Formats the JSON string in markdown."""
|
18
|
+
return f"```json\n{json.dumps(json.loads(s), indent=2)}\n```"
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def _parse_date_time(datetime_string: str):
|
22
|
+
"""Parses a datetime string in the logs into date and time.
|
23
|
+
Keeps only the seconds in the time.
|
24
|
+
"""
|
25
|
+
date_str, time_str = datetime_string.split(" ", 1)
|
26
|
+
time_str = time_str.split(".", 1)[0]
|
27
|
+
return date_str, time_str
|
28
|
+
|
29
|
+
@staticmethod
|
30
|
+
def _preview_message(message: str, max_length=30) -> str:
|
31
|
+
"""Shows the beginning part of a string message."""
|
32
|
+
# Return the entire string if it is less than the max_length
|
33
|
+
if len(message) <= max_length:
|
34
|
+
return message
|
35
|
+
# Go backward until we find the first whitespace
|
36
|
+
idx = 30
|
37
|
+
while not message[idx].isspace() and idx > 0:
|
38
|
+
idx -= 1
|
39
|
+
# If we found a whitespace
|
40
|
+
if idx > 0:
|
41
|
+
return message[:idx] + "..."
|
42
|
+
# If we didn't find a whitespace
|
43
|
+
return message[:30] + "..."
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def _render_template(cls, template_path, **kwargs) -> str:
|
47
|
+
"""Render Jinja template with kwargs."""
|
48
|
+
template_dir = os.path.join(os.path.dirname(__file__), "templates")
|
49
|
+
environment = Environment(
|
50
|
+
loader=FileSystemLoader(template_dir), autoescape=True
|
51
|
+
)
|
52
|
+
template = environment.get_template(template_path)
|
53
|
+
try:
|
54
|
+
html = template.render(**kwargs)
|
55
|
+
except Exception:
|
56
|
+
logger.error(
|
57
|
+
"Unable to render template %s with data:\n%s",
|
58
|
+
template_path,
|
59
|
+
str(kwargs),
|
60
|
+
)
|
61
|
+
return cls._render_template(
|
62
|
+
template_path=template_path,
|
63
|
+
sender=kwargs.get("sender", "N/A"),
|
64
|
+
content="TEMPLATE RENDER ERROR",
|
65
|
+
timestamp=kwargs.get("timestamp", ""),
|
66
|
+
)
|
67
|
+
return html
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# Copyright (c) 2024 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
|
+
"""Contains the data structure for logging and reporting."""
|
5
|
+
import copy
|
6
|
+
import json
|
7
|
+
from dataclasses import asdict, dataclass, field
|
8
|
+
from typing import Optional, Union
|
9
|
+
|
10
|
+
from ads.llm.autogen.constants import Events
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass
|
14
|
+
class LogData:
|
15
|
+
"""Base class for the data field of LogRecord."""
|
16
|
+
|
17
|
+
def to_dict(self):
|
18
|
+
"""Convert the log data to dictionary."""
|
19
|
+
return asdict(self)
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class LogRecord:
|
24
|
+
"""Represents a log record.
|
25
|
+
|
26
|
+
The `data` field is for pre-defined structured data, which should be an instance of LogData.
|
27
|
+
The `kwargs` field is for freeform key value pairs.
|
28
|
+
"""
|
29
|
+
|
30
|
+
session_id: str
|
31
|
+
thread_id: int
|
32
|
+
timestamp: str
|
33
|
+
event_name: str
|
34
|
+
source_id: Optional[int] = None
|
35
|
+
source_name: Optional[str] = None
|
36
|
+
# Structured data for specific type of logs
|
37
|
+
data: Optional[LogData] = None
|
38
|
+
# Freeform data
|
39
|
+
kwargs: dict = field(default_factory=dict)
|
40
|
+
|
41
|
+
def to_dict(self):
|
42
|
+
"""Convert the log record to dictionary."""
|
43
|
+
return asdict(self)
|
44
|
+
|
45
|
+
def to_string(self):
|
46
|
+
"""Serialize the log record to JSON string."""
|
47
|
+
return json.dumps(self.to_dict(), default=str)
|
48
|
+
|
49
|
+
@classmethod
|
50
|
+
def from_dict(cls, data: dict) -> "LogRecord":
|
51
|
+
"""Initializes a LogRecord object from dictionary."""
|
52
|
+
event_mapping = {
|
53
|
+
Events.NEW_AGENT: AgentData,
|
54
|
+
Events.TOOL_CALL: ToolCallData,
|
55
|
+
Events.LLM_CALL: LLMCompletionData,
|
56
|
+
}
|
57
|
+
if Events.KEY not in data:
|
58
|
+
raise KeyError("event_name not found in data.")
|
59
|
+
|
60
|
+
data = copy.deepcopy(data)
|
61
|
+
|
62
|
+
event_name = data["event_name"]
|
63
|
+
if event_name in event_mapping and data.get("data"):
|
64
|
+
data["data"] = event_mapping[event_name](**data.pop("data"))
|
65
|
+
|
66
|
+
return cls(**data)
|
67
|
+
|
68
|
+
|
69
|
+
@dataclass
|
70
|
+
class AgentData(LogData):
|
71
|
+
"""Represents agent log Data."""
|
72
|
+
|
73
|
+
agent_name: str
|
74
|
+
agent_class: str
|
75
|
+
agent_module: Optional[str] = None
|
76
|
+
is_manager: Optional[bool] = None
|
77
|
+
|
78
|
+
|
79
|
+
@dataclass
|
80
|
+
class LLMCompletionData(LogData):
|
81
|
+
"""Represents LLM completion log data."""
|
82
|
+
|
83
|
+
invocation_id: str
|
84
|
+
request: dict
|
85
|
+
response: dict
|
86
|
+
start_time: str
|
87
|
+
end_time: str
|
88
|
+
cost: Optional[float] = None
|
89
|
+
is_cached: Optional[bool] = None
|
90
|
+
|
91
|
+
|
92
|
+
@dataclass
|
93
|
+
class ToolCallData(LogData):
|
94
|
+
"""Represents tool call log data."""
|
95
|
+
|
96
|
+
tool_name: str
|
97
|
+
start_time: str
|
98
|
+
end_time: str
|
99
|
+
agent_name: str
|
100
|
+
agent_class: str
|
101
|
+
agent_module: Optional[str] = None
|
102
|
+
input_args: dict = field(default_factory=dict)
|
103
|
+
returns: Optional[Union[str, list, dict, tuple]] = None
|