beekeeper-monitors-watsonx 1.1.1__py3-none-any.whl → 1.1.3__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.
@@ -202,6 +202,40 @@ class WatsonxExternalPromptMonitor(PromptMonitor):
202
202
 
203
203
  return created_detached_pta.to_dict()["asset_id"]
204
204
 
205
+ def _delete_detached_prompt(self, detached_pta_id: str) -> None:
206
+ from ibm_aigov_facts_client import ( # type: ignore
207
+ AIGovFactsClient,
208
+ CloudPakforDataConfig,
209
+ )
210
+
211
+ try:
212
+ if hasattr(self, "_fact_cpd_creds") and self._fact_cpd_creds:
213
+ cpd_creds = CloudPakforDataConfig(**self._fact_cpd_creds)
214
+
215
+ aigov_client = AIGovFactsClient(
216
+ container_id=self._container_id,
217
+ container_type=self._container_type,
218
+ cloud_pak_for_data_configs=cpd_creds,
219
+ disable_tracing=True,
220
+ )
221
+
222
+ else:
223
+ aigov_client = AIGovFactsClient(
224
+ api_key=self._api_key,
225
+ container_id=self._container_id,
226
+ container_type=self._container_type,
227
+ disable_tracing=True,
228
+ region=self.region.factsheet,
229
+ )
230
+
231
+ except Exception as e:
232
+ logging.error(
233
+ f"Error connecting to IBM watsonx.governance (factsheets): {e}",
234
+ )
235
+ raise
236
+
237
+ suppress_output(aigov_client.assets.delete_prompt_asset, detached_pta_id)
238
+
205
239
  def _create_deployment_pta(self, asset_id: str, name: str, model_id: str) -> str:
206
240
  from ibm_watsonx_ai import APIClient, Credentials # type: ignore
207
241
 
@@ -239,6 +273,30 @@ class WatsonxExternalPromptMonitor(PromptMonitor):
239
273
 
240
274
  return wml_client.deployments.get_uid(created_deployment)
241
275
 
276
+ def _delete_deployment_pta(self, deployment_id: str):
277
+ from ibm_watsonx_ai import APIClient, Credentials # type: ignore
278
+
279
+ try:
280
+ if hasattr(self, "_wml_cpd_creds") and self._wml_cpd_creds:
281
+ creds = Credentials(**self._wml_cpd_creds)
282
+
283
+ wml_client = APIClient(creds)
284
+ wml_client.set.default_space(self.space_id)
285
+
286
+ else:
287
+ creds = Credentials(
288
+ url=self.region.watsonxai,
289
+ api_key=self._api_key,
290
+ )
291
+ wml_client = APIClient(creds)
292
+ wml_client.set.default_space(self.space_id)
293
+
294
+ except Exception as e:
295
+ logging.error(f"Error connecting to IBM watsonx.ai Runtime: {e}")
296
+ raise
297
+
298
+ suppress_output(wml_client.deployments.delete, deployment_id)
299
+
242
300
  @deprecated(
243
301
  reason="'add_prompt_observer()' is deprecated and will be removed in a future version. Use 'create_prompt_monitor()' instead.",
244
302
  version="1.0.5",
@@ -381,6 +439,8 @@ class WatsonxExternalPromptMonitor(PromptMonitor):
381
439
  ```
382
440
  """
383
441
  task_id = TaskType.from_value(task_id).value
442
+ rollback_stack = []
443
+
384
444
  # DEPRECATION NOTICE
385
445
  if input_text is not None:
386
446
  warnings.warn(
@@ -493,11 +553,14 @@ class WatsonxExternalPromptMonitor(PromptMonitor):
493
553
  prompt_details,
494
554
  detached_asset_details,
495
555
  )
556
+ rollback_stack.append(lambda: self._delete_detached_prompt(detached_pta_id))
557
+
496
558
  deployment_id = None
497
559
  if self._container_type == "space":
498
560
  deployment_id = suppress_output(
499
561
  self._create_deployment_pta, detached_pta_id, name, model_id
500
562
  )
563
+ rollback_stack.append(lambda: self._delete_deployment_pta(deployment_id))
501
564
 
502
565
  monitors = {
503
566
  "generative_ai_quality": {
@@ -558,10 +621,18 @@ class WatsonxExternalPromptMonitor(PromptMonitor):
558
621
 
559
622
  generative_ai_monitor_details = generative_ai_monitor_details.result._to_dict()
560
623
 
624
+ wos_status = generative_ai_monitor_details.get("status", {})
625
+ if wos_status.get("state") == "ERROR":
626
+ for rollback_step in reversed(rollback_stack):
627
+ rollback_step()
628
+ raise Exception(wos_status.get("failure"))
629
+
561
630
  return {
562
631
  "detached_prompt_template_asset_id": detached_pta_id,
563
632
  "deployment_id": deployment_id,
564
- "subscription_id": generative_ai_monitor_details["subscription_id"],
633
+ "subscription_id": generative_ai_monitor_details.get(
634
+ "subscription_id", None
635
+ ),
565
636
  }
566
637
 
567
638
  def store_payload_records(
@@ -938,6 +1009,40 @@ class WatsonxPromptMonitor(PromptMonitor):
938
1009
 
939
1010
  return created_pta.to_dict()["asset_id"]
940
1011
 
1012
+ def _delete_prompt(self, pta_id: str) -> None:
1013
+ from ibm_aigov_facts_client import ( # type: ignore
1014
+ AIGovFactsClient,
1015
+ CloudPakforDataConfig,
1016
+ )
1017
+
1018
+ try:
1019
+ if hasattr(self, "_fact_cpd_creds") and self._fact_cpd_creds:
1020
+ cpd_creds = CloudPakforDataConfig(**self._fact_cpd_creds)
1021
+
1022
+ aigov_client = AIGovFactsClient(
1023
+ container_id=self._container_id,
1024
+ container_type=self._container_type,
1025
+ cloud_pak_for_data_configs=cpd_creds,
1026
+ disable_tracing=True,
1027
+ )
1028
+
1029
+ else:
1030
+ aigov_client = AIGovFactsClient(
1031
+ api_key=self._api_key,
1032
+ container_id=self._container_id,
1033
+ container_type=self._container_type,
1034
+ disable_tracing=True,
1035
+ region=self.region.factsheet,
1036
+ )
1037
+
1038
+ except Exception as e:
1039
+ logging.error(
1040
+ f"Error connecting to IBM watsonx.governance (factsheets): {e}",
1041
+ )
1042
+ raise
1043
+
1044
+ suppress_output(aigov_client.assets.delete_prompt_asset, pta_id)
1045
+
941
1046
  def _create_deployment_pta(self, asset_id: str, name: str, model_id: str) -> str:
942
1047
  from ibm_watsonx_ai import APIClient, Credentials # type: ignore
943
1048
 
@@ -976,6 +1081,30 @@ class WatsonxPromptMonitor(PromptMonitor):
976
1081
 
977
1082
  return wml_client.deployments.get_uid(created_deployment)
978
1083
 
1084
+ def _delete_deployment_pta(self, deployment_id: str):
1085
+ from ibm_watsonx_ai import APIClient, Credentials # type: ignore
1086
+
1087
+ try:
1088
+ if hasattr(self, "_wml_cpd_creds") and self._wml_cpd_creds:
1089
+ creds = Credentials(**self._wml_cpd_creds)
1090
+
1091
+ wml_client = APIClient(creds)
1092
+ wml_client.set.default_space(self.space_id)
1093
+
1094
+ else:
1095
+ creds = Credentials(
1096
+ url=self.region.watsonxai,
1097
+ api_key=self._api_key,
1098
+ )
1099
+ wml_client = APIClient(creds)
1100
+ wml_client.set.default_space(self.space_id)
1101
+
1102
+ except Exception as e:
1103
+ logging.error(f"Error connecting to IBM watsonx.ai Runtime: {e}")
1104
+ raise
1105
+
1106
+ suppress_output(wml_client.deployments.delete, deployment_id)
1107
+
979
1108
  @deprecated(
980
1109
  reason="'add_prompt_observer()' is deprecated and will be removed in a future version. Use 'create_prompt_monitor()' instead.",
981
1110
  version="1.0.5",
@@ -1085,6 +1214,8 @@ class WatsonxPromptMonitor(PromptMonitor):
1085
1214
  ```
1086
1215
  """
1087
1216
  task_id = TaskType.from_value(task_id).value
1217
+ rollback_stack = []
1218
+
1088
1219
  # DEPRECATION NOTICE
1089
1220
  if input_text is not None:
1090
1221
  warnings.warn(
@@ -1178,11 +1309,14 @@ class WatsonxPromptMonitor(PromptMonitor):
1178
1309
  pta_id = suppress_output(
1179
1310
  self._create_prompt_template, prompt_details, asset_details
1180
1311
  )
1312
+ rollback_stack.append(lambda: self._delete_detached_prompt(pta_id))
1313
+
1181
1314
  deployment_id = None
1182
1315
  if self._container_type == "space":
1183
1316
  deployment_id = suppress_output(
1184
1317
  self._create_deployment_pta, pta_id, name, model_id
1185
1318
  )
1319
+ rollback_stack.append(lambda: self._delete_deployment_pta(deployment_id))
1186
1320
 
1187
1321
  monitors = {
1188
1322
  "generative_ai_quality": {
@@ -1243,10 +1377,18 @@ class WatsonxPromptMonitor(PromptMonitor):
1243
1377
 
1244
1378
  generative_ai_monitor_details = generative_ai_monitor_details._to_dict()
1245
1379
 
1380
+ wos_status = generative_ai_monitor_details.get("status", {})
1381
+ if wos_status.get("state") == "ERROR":
1382
+ for rollback_step in reversed(rollback_stack):
1383
+ rollback_step()
1384
+ raise Exception(wos_status.get("failure"))
1385
+
1246
1386
  return {
1247
1387
  "prompt_template_asset_id": pta_id,
1248
1388
  "deployment_id": deployment_id,
1249
- "subscription_id": generative_ai_monitor_details["subscription_id"],
1389
+ "subscription_id": generative_ai_monitor_details.get(
1390
+ "subscription_id", None
1391
+ ),
1250
1392
  }
1251
1393
 
1252
1394
  def store_payload_records(
@@ -7,7 +7,7 @@ from beekeeper.monitors.watsonx.supporting_classes.credentials import (
7
7
  CloudPakforDataCredentials,
8
8
  IntegratedSystemCredentials,
9
9
  )
10
- from beekeeper.monitors.watsonx.supporting_classes.enums import Region
10
+ from beekeeper.monitors.watsonx.supporting_classes.enums import DataSetType, Region
11
11
  from beekeeper.monitors.watsonx.supporting_classes.metric import (
12
12
  WatsonxLocalMetric,
13
13
  WatsonxMetric,
@@ -531,6 +531,49 @@ class WatsonxCustomMetricsManager:
531
531
  json_patch_operation=patch_payload,
532
532
  ).result
533
533
 
534
+ def store_record_metric_data(
535
+ self,
536
+ custom_data_set_id: str,
537
+ computed_on: Union[DataSetType, str],
538
+ run_id: str,
539
+ request_records: List[Dict],
540
+ ):
541
+ """
542
+ Stores computed metrics data to the specified transaction record.
543
+
544
+ Args:
545
+ custom_data_set_id (str): The ID of the custom metric data set.
546
+ computed_on (DataSetType): The dataset on which the metric was calculated (e.g., payload or feedback).
547
+ run_id (str): The ID of the monitor run that generated the metrics.
548
+ request_records (List[Dict]): A list of dictionaries containing the records to be stored.
549
+
550
+ Example:
551
+ ```python
552
+ wxgov_client.store_record_metric_data(
553
+ reference_record_id="0196ad39-1b75-7e77-bddb-cc5393d575c2",
554
+ run_id="RUN_ID",
555
+ request_records=[
556
+ {
557
+ "reference_record_id": "304a9270-44a1-4c4d-bfd4-f756541011f8",
558
+ "record_timestamp": "2025-12-09T00:00:00Z",
559
+ "context_quality": 0.786,
560
+ "pii": 0.05,
561
+ }
562
+ ],
563
+ )
564
+ ```
565
+ """
566
+ computed_on = DataSetType.from_value(computed_on).value
567
+
568
+ for record in request_records:
569
+ record["run_id"] = run_id
570
+ record["computed_on"] = computed_on
571
+
572
+ return self._wos_client.data_sets.store_records(
573
+ data_set_id=custom_data_set_id,
574
+ request_body=request_records,
575
+ ).result
576
+
534
577
  # ===== Local Custom Metrics =====
535
578
  @deprecated(
536
579
  reason="'add_local_metric_definition()' is deprecated and will be removed in a future version. Use 'create_local_metric_definition()' from 'beekeeper-monitors-watsonx' instead.",
@@ -549,33 +592,17 @@ class WatsonxCustomMetricsManager:
549
592
  subscription_id=subscription_id,
550
593
  )
551
594
 
595
+ @deprecated(
596
+ reason="'create_local_metric_definition()' is deprecated and will be removed in a future version. Use OOB record level metrics instead.",
597
+ version="1.1.3",
598
+ action="always",
599
+ )
552
600
  def create_local_metric_definition(
553
601
  self,
554
602
  name: str,
555
603
  metrics: List[WatsonxLocalMetric],
556
604
  subscription_id: str,
557
605
  ) -> str:
558
- """
559
- Creates a custom metric definition to compute metrics at the local (transaction) level for IBM watsonx.governance.
560
-
561
- Args:
562
- name (str): The name of the custom transaction metric group.
563
- metrics (List[WatsonxLocalMetric]): A list of metrics to be monitored at the local (transaction) level.
564
- subscription_id (str): The IBM watsonx.governance subscription ID associated with the metric definition.
565
-
566
- Example:
567
- ```python
568
- from beekeeper.monitors.watsonx import WatsonxLocalMetric
569
-
570
- wxgov_client.create_local_metric_definition(
571
- name="Custom LLM Local Metric",
572
- subscription_id="019674ca-0c38-745f-8e9b-58546e95174e",
573
- metrics=[
574
- WatsonxLocalMetric(name="context_quality", data_type="double")
575
- ],
576
- )
577
- ```
578
- """
579
606
  from ibm_watson_openscale.base_classes.watson_open_scale_v2 import (
580
607
  LocationTableName,
581
608
  SparkStruct,
@@ -636,55 +663,30 @@ class WatsonxCustomMetricsManager:
636
663
  request_records=request_records,
637
664
  )
638
665
 
666
+ @deprecated(
667
+ reason="'store_local_metric_data()' is deprecated and will be removed in a future version. Use OOB record level metrics instead.",
668
+ version="1.1.3",
669
+ action="always",
670
+ )
639
671
  def store_local_metric_data(
640
672
  self,
641
673
  metric_instance_id: str,
642
674
  request_records: List[Dict],
643
675
  ):
644
- """
645
- Stores computed metrics data to the specified transaction record.
646
-
647
- Args:
648
- metric_instance_id (str): The unique ID of the custom transaction metric.
649
- request_records (List[Dict]): A list of dictionaries containing the records to be stored.
650
-
651
- Example:
652
- ```python
653
- wxgov_client.store_local_metric_data(
654
- metric_instance_id="0196ad39-1b75-7e77-bddb-cc5393d575c2",
655
- request_records=[
656
- {
657
- "scoring_id": "304a9270-44a1-4c4d-bfd4-f756541011f8",
658
- "run_id": "RUN_ID",
659
- "computed_on": "payload",
660
- "context_quality": 0.786,
661
- }
662
- ],
663
- )
664
- ```
665
- """
666
676
  return self._wos_client.data_sets.store_records(
667
677
  data_set_id=metric_instance_id,
668
678
  request_body=request_records,
669
679
  ).result
670
680
 
681
+ @deprecated(
682
+ reason="'list_local_metrics()' is deprecated and will be removed in a future version. Use OOB record level metrics instead.",
683
+ version="1.1.3",
684
+ action="always",
685
+ )
671
686
  def list_local_metrics(
672
687
  self,
673
688
  metric_instance_id: str,
674
689
  ):
675
- """
676
- Lists records from a custom local metric definition.
677
-
678
- Args:
679
- metric_instance_id (str): The unique ID of the custom transaction metric.
680
-
681
- Example:
682
- ```python
683
- wxgov_client.list_local_metrics(
684
- metric_instance_id="0196ad47-c505-73c0-9d7b-91c082b697e3"
685
- )
686
- ```
687
- """
688
690
  return self._get_dataset_data(metric_instance_id)
689
691
 
690
692
 
@@ -72,6 +72,19 @@ class Region(str, Enum):
72
72
 
73
73
 
74
74
  class TaskType(Enum):
75
+ """
76
+ Supported IBM watsonx.governance tasks.
77
+
78
+ Attributes:
79
+ QUESTION_ANSWERING (str): "question_answering"
80
+ SUMMARIZATION (str): "summarization"
81
+ RETRIEVAL_AUGMENTED_GENERATION (str): "retrieval_augmented_generation"
82
+ CLASSIFICATION (str): "classification"
83
+ GENERATION (str): "generation"
84
+ CODE (str): "code"
85
+ EXTRACTION (str): "extraction"
86
+ """
87
+
75
88
  QUESTION_ANSWERING = "question_answering"
76
89
  SUMMARIZATION = "summarization"
77
90
  RETRIEVAL_AUGMENTED_GENERATION = "retrieval_augmented_generation"
@@ -98,3 +111,35 @@ class TaskType(Enum):
98
111
  raise TypeError(
99
112
  f"Invalid type for parameter 'task_id'. Expected str or TaskType, but received {type(value).__name__}."
100
113
  )
114
+
115
+
116
+ class DataSetType(Enum):
117
+ """
118
+ Supported IBM watsonx.governance tasks.
119
+
120
+ Attributes:
121
+ PAYLOAD (str): "payload"
122
+ FEEDBACK (str): "feedback"
123
+ """
124
+
125
+ PAYLOAD = "payload"
126
+ FEEDBACK = "feedback"
127
+
128
+ @classmethod
129
+ def from_value(cls, value: str) -> "DataSetType":
130
+ if isinstance(value, cls):
131
+ return value
132
+
133
+ if isinstance(value, str):
134
+ try:
135
+ return cls(value.lower())
136
+ except ValueError:
137
+ raise ValueError(
138
+ "Invalid value. Received: '{}'. Valid values are: {}.".format(
139
+ value, [item.value for item in DataSetType]
140
+ )
141
+ )
142
+
143
+ raise TypeError(
144
+ f"Invalid type. Expected str or DataSetType, but received {type(value).__name__}."
145
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beekeeper-monitors-watsonx
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: beekeeper monitors watsonx extension
5
5
  Author-email: Leonardo Furnielis <leonardofurnielis@outlook.com>
6
6
  License: Apache-2.0
@@ -1,12 +1,12 @@
1
1
  beekeeper/monitors/watsonx/__init__.py,sha256=iJv6D68IT00ZC40TNSVYtqyFTen9sWoDqUtxvVVJjOE,789
2
- beekeeper/monitors/watsonx/base.py,sha256=AVgYwk-LgjjZ1RTAkk-8f5_T9pJ-jQoeDm_NX1uaX5I,57089
3
- beekeeper/monitors/watsonx/custom_metric.py,sha256=XdJ26lb0y_P1nirJE_krpKONuqJjP3sWFApoG-DR6hk,23959
2
+ beekeeper/monitors/watsonx/base.py,sha256=HbMPlPDHr6Z4gaolExleDHSR8YqisNzIC3aR2vC2aH8,62233
3
+ beekeeper/monitors/watsonx/custom_metric.py,sha256=7HSn_jMLRK0y4qFx84sra38cdJk9ps-LEGN7QJceG5k,24105
4
4
  beekeeper/monitors/watsonx/supporting_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  beekeeper/monitors/watsonx/supporting_classes/credentials.py,sha256=x4rYoOFvx0pWDhFZfuy6fM0rj7JCivaSYn_jYFXlV8U,5190
6
- beekeeper/monitors/watsonx/supporting_classes/enums.py,sha256=R86yqE_KNHjrrFwqy1tCA2a6UAXwmIzCNxw1vnsH32w,2865
6
+ beekeeper/monitors/watsonx/supporting_classes/enums.py,sha256=KrVgBjhnUIUglWmx0OgY3sWoeKMHE-4pZ_ozxzB8IQE,4111
7
7
  beekeeper/monitors/watsonx/supporting_classes/metric.py,sha256=iERXRi0iBFHITFaLtonoV97nNUCPXbieD7Z1wX6bvX8,3370
8
8
  beekeeper/monitors/watsonx/utils/data_utils.py,sha256=qBLYtHGY0MJ0JJ8BpFDT2YIjA3QOYJQNemLvpA3DMz0,1252
9
9
  beekeeper/monitors/watsonx/utils/instrumentation.py,sha256=ztgR1kZ9h-JvASzRA47AYHdc-Isv33EQum9XBLg-dQk,525
10
- beekeeper_monitors_watsonx-1.1.1.dist-info/METADATA,sha256=5F1R9-ocW3kbbJQfjzFNEuVMiUYiH2B47EeMCEW7yes,716
11
- beekeeper_monitors_watsonx-1.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- beekeeper_monitors_watsonx-1.1.1.dist-info/RECORD,,
10
+ beekeeper_monitors_watsonx-1.1.3.dist-info/METADATA,sha256=xo8UL2_D8Ecft2N0nC7uZwVs67shn6cC1JHpkHO2HVo,716
11
+ beekeeper_monitors_watsonx-1.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ beekeeper_monitors_watsonx-1.1.3.dist-info/RECORD,,