datarobot-moderations 11.2.5__py3-none-any.whl → 11.2.6__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.
@@ -774,11 +774,8 @@ def guard_chat_wrapper(
774
774
  # extract any fields mentioned in "datarobot_metrics" to send as custom metrics later
775
775
  completion_create_params, chat_extra_body_params = filter_extra_body(completion_create_params)
776
776
 
777
- # register them for ID lookup later
778
- pipeline.add_extra_body_custom_metric_definition(chat_extra_body_params)
779
-
780
777
  # define all pipeline-based and guard-based custom metrics (but not those from extra_body)
781
- # sends single API request to look up IDs for all custom metrics (including extra_body)
778
+ # note: this is usually partially done at pipeline init; see delayed_custom_metric_creation
782
779
  pipeline.get_new_metrics_payload()
783
780
 
784
781
  # the chat request is not a dataframe, but we'll build a DF internally for moderation.
@@ -380,15 +380,6 @@ class LLMPipeline(Pipeline):
380
380
  buckets = self._add_guard_specific_custom_metrics(row, self.get_postscore_guards())
381
381
  payload["buckets"].extend(buckets)
382
382
 
383
- def add_extra_body_custom_metric_definition(self, chat_extra_body_params: dict) -> None:
384
- """
385
- For each name found in extra_body earlier, add to the internal map for reporting later.
386
- Custom metric IDs are looked up in create_custom_metrics().
387
- :param chat_extra_body_params: dict of name=value pairs
388
- """
389
- for name in chat_extra_body_params.keys():
390
- self.extra_body_custom_metric_map[name] = {"id": None}
391
-
392
383
  def report_custom_metrics_from_extra_body(
393
384
  self, association_id: str, extra_params: dict
394
385
  ) -> None:
@@ -412,19 +403,19 @@ class LLMPipeline(Pipeline):
412
403
  f"will not be sent: {name}"
413
404
  )
414
405
  continue
415
- if name not in self.extra_body_custom_metric_map:
406
+ if name not in self.custom_metric_names_to_ids:
416
407
  self._logger.warning(f"extra_body custom metric ID not in map: {name}")
417
408
  continue
418
- metric_id = self.extra_body_custom_metric_map[name].get("id")
409
+ metric_id = self.custom_metric_names_to_ids.get(name)
419
410
  if not metric_id:
411
+ # this should not be possible, as the name/id information
412
+ # is taken directly from DataRobot API
420
413
  self._logger.warning(f"extra_body custom metric has missing ID: {name}")
421
414
  continue
422
415
  payload["buckets"].append(
423
- {
424
- "customMetricId": metric_id,
425
- "value": value,
426
- "associationId": association_id,
427
- }
416
+ self.custom_metric_individual_payload(
417
+ metric_id=metric_id, value=value, association_id=association_id
418
+ )
428
419
  )
429
420
  self._logger.debug(f"Sending custom metrics payload from extra_body: {payload}")
430
421
  self.upload_custom_metrics(payload)
@@ -53,8 +53,7 @@ class Pipeline:
53
53
  self._custom_metrics_bulk_upload_url = None
54
54
  self.aggregate_custom_metric = None
55
55
  self.custom_metric_map = dict()
56
- # even though only LLMPipeline really uses the next map, Pipeline still references it
57
- self.extra_body_custom_metric_map = dict()
56
+ self.custom_metric_names_to_ids = dict()
58
57
  self.delayed_custom_metric_creation = False
59
58
  self.upload_custom_metrics_tasks = set()
60
59
 
@@ -198,6 +197,33 @@ class Pipeline:
198
197
  **kwargs,
199
198
  }
200
199
 
200
+ def lookup_custom_metric_ids(self):
201
+ """
202
+ The deployment's list of custom metrics is known when the pipeline is created.
203
+ The complete set of guard metrics is also known at that time.
204
+ However, the extra_body metrics needed are not known until guard_chat_wrapper
205
+ parses extra_body.
206
+ For that reason, read and cache all the metric name/id pairs at pipeline create time.
207
+ Side effect: updates self.custom_metric_names_to_ids
208
+ """
209
+ if self.custom_metric_names_to_ids:
210
+ self._logger.debug("lookup_custom_metric_ids(): IDs were already read; skipping")
211
+ return
212
+
213
+ # Manually paginate; the dmm list_custom_metrics does not implement pagination
214
+ custom_metrics_list = []
215
+ offset, limit = 0, 50
216
+ while True:
217
+ response_list = self.dr_client.get(
218
+ f"deployments/{self._deployment_id}/customMetrics/?offset={offset}&limit={limit}"
219
+ ).json()
220
+ custom_metrics_list.extend(response_list["data"])
221
+ offset += response_list["count"]
222
+ if response_list["next"] is None:
223
+ break
224
+
225
+ self.custom_metric_names_to_ids = {m["name"]: m["id"] for m in custom_metrics_list}
226
+
201
227
  def create_custom_metrics(self):
202
228
  """
203
229
  Creates all the custom-metrics in the DR app for an active deployment.
@@ -268,35 +294,16 @@ class Pipeline:
268
294
  # Now query all the metrics and get their custom metric ids. Specifically,
269
295
  # required in case a metric is duplicated, in which case, we don't have its
270
296
  # id in the loop above
271
- #
272
- # Note: user-defined custom metrics (such as for extra_body params) will also
273
- # be included in the list. We will warn if an existing metric is not found
274
- # in either list, which means this chat request does not have a value for it.
275
- #
276
- # We have to go through pagination - dmm list_custom_metrics does not implement
277
- # pagination
278
- custom_metrics_list = []
279
- offset, limit = 0, 50
280
- while True:
281
- response_list = self.dr_client.get(
282
- f"deployments/{self._deployment_id}/customMetrics/?offset={offset}&limit={limit}"
283
- ).json()
284
- custom_metrics_list.extend(response_list["data"])
285
- offset += response_list["count"]
286
- if response_list["next"] is None:
287
- break
297
+ self.lookup_custom_metric_ids()
288
298
 
289
299
  # assign IDs to the "metric by name" maps so we can upload by ID later
290
- for metric in custom_metrics_list:
291
- metric_name = metric["name"]
300
+ for metric_name, metric_id in self.custom_metric_names_to_ids.items():
292
301
  if metric_name in self.custom_metric_map:
293
- self.custom_metric_map[metric_name]["id"] = metric["id"]
294
- elif metric_name in self.extra_body_custom_metric_map:
295
- self.extra_body_custom_metric_map[metric_name]["id"] = metric["id"]
302
+ self.custom_metric_map[metric_name]["id"] = metric_id
296
303
  else:
297
304
  self._logger.warning(
298
305
  f"Metric '{metric_name}' exists at DR but not in moderation; "
299
- "no value will be reported"
306
+ "no moderation value will be reported for it"
300
307
  )
301
308
  continue
302
309
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datarobot-moderations
3
- Version: 11.2.5
3
+ Version: 11.2.6
4
4
  Summary: DataRobot Monitoring and Moderation framework
5
5
  License: DataRobot Tool and Utility Agreement
6
6
  Author: DataRobot
@@ -2,7 +2,7 @@ datarobot_dome/__init__.py,sha256=B5Rx8_CNCNsOpxBbRj27XOXCfRZmvmrAR-NzlzIKnDw,58
2
2
  datarobot_dome/async_http_client.py,sha256=cQFoSI2ovt0Kyk4XWQPXod5PAfA-ZPkjLYVWQZhDGDE,9809
3
3
  datarobot_dome/chat_helper.py,sha256=BzvtUyZSZxzOqq-5a2wQKhHhr2kMlcP1MFrHaDAeD_o,9671
4
4
  datarobot_dome/constants.py,sha256=jvgpHa3Wh_nZVZmfU-6ab8FHnKNW3KxOPYIIEb_oS6U,10662
5
- datarobot_dome/drum_integration.py,sha256=DIGeiw6fwKCbgi6mb-mJdjPEB6C1uMc-pZotpTnlGZQ,45770
5
+ datarobot_dome/drum_integration.py,sha256=NWTYJWGPM_z8RQYXteEOWQkCVBXzJ5XRZEWJYeUdHf8,45656
6
6
  datarobot_dome/guard.py,sha256=xJds9hcbUaS-KD5nC1mn0GiPdBrileFUu6BuTAjDNuY,34668
7
7
  datarobot_dome/guard_executor.py,sha256=ox5_jOHcqMaxaaagIYJJHhCwEI7Wg-rUEiu5rutsfVU,35363
8
8
  datarobot_dome/guard_helpers.py,sha256=jfu8JTWCcxu4WD1MKxeP1n53DeebY3SSuP-t5sWyV1U,17187
@@ -14,11 +14,11 @@ datarobot_dome/metrics/citation_metrics.py,sha256=l2mnV1gz7nQeJ_yfaS4dcP3DFWf0p5
14
14
  datarobot_dome/metrics/factory.py,sha256=7caa8paI9LuFXDgguXdC4on28V7IwwIsKJT2Z-Aps8A,2187
15
15
  datarobot_dome/metrics/metric_scorer.py,sha256=uJ_IJRw7ZFHueg8xjsaXbt0ypO7JiydZ0WapCp96yng,2540
16
16
  datarobot_dome/pipeline/__init__.py,sha256=B5Rx8_CNCNsOpxBbRj27XOXCfRZmvmrAR-NzlzIKnDw,583
17
- datarobot_dome/pipeline/llm_pipeline.py,sha256=g8XZQjJPPs43GPqaBG4TtsCbvu1o7TWraOmzhtUGB_o,21172
18
- datarobot_dome/pipeline/pipeline.py,sha256=iDR6h25RDp4bnTW1eGWErG9W_ZXDdJ_sQGVD-tT_Ll0,18805
17
+ datarobot_dome/pipeline/llm_pipeline.py,sha256=PRJ7t5Bc8S2ZbD0yK8ztdTD1hPC7Yo8IvhFlWEkMkmU,20810
18
+ datarobot_dome/pipeline/pipeline.py,sha256=m8m_QtoQNwJ5U-bbJGdtlmAbdI-UpobcMCuRz-U_H_Y,19052
19
19
  datarobot_dome/pipeline/vdb_pipeline.py,sha256=zt5d_41oJjdT8qOtvpgz-l5uvImwKE9f6pQsAU_TdR4,9866
20
20
  datarobot_dome/runtime.py,sha256=FD8wXOweqoQVzbZMh-mucL66xT2kGxPsJUGAcJBgwxw,1468
21
21
  datarobot_dome/streaming.py,sha256=DkvKEH0yN0aPEWMTAjMFJB3Kx4iLGdjUMQU1pAplbeg,17751
22
- datarobot_moderations-11.2.5.dist-info/METADATA,sha256=9Aj3fZnLvcgKpiAQwnvkkAzA3SxaBq2j45ctWEMCEaI,4741
23
- datarobot_moderations-11.2.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
24
- datarobot_moderations-11.2.5.dist-info/RECORD,,
22
+ datarobot_moderations-11.2.6.dist-info/METADATA,sha256=U20ej2pA1_79GwOl4f7qShgB9Q4F_zb-phsOBTITOF0,4741
23
+ datarobot_moderations-11.2.6.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
24
+ datarobot_moderations-11.2.6.dist-info/RECORD,,