datarobot-moderations 11.2.5__py3-none-any.whl → 11.2.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.
- datarobot_dome/async_http_client.py +2 -1
- datarobot_dome/drum_integration.py +8 -4
- datarobot_dome/pipeline/llm_pipeline.py +9 -16
- datarobot_dome/pipeline/pipeline.py +37 -25
- {datarobot_moderations-11.2.5.dist-info → datarobot_moderations-11.2.7.dist-info}/METADATA +1 -1
- {datarobot_moderations-11.2.5.dist-info → datarobot_moderations-11.2.7.dist-info}/RECORD +7 -7
- {datarobot_moderations-11.2.5.dist-info → datarobot_moderations-11.2.7.dist-info}/WHEEL +0 -0
|
@@ -232,9 +232,10 @@ class AsyncHTTPClient:
|
|
|
232
232
|
try:
|
|
233
233
|
response = await self.session.post(url, json=payload, headers=self.json_headers)
|
|
234
234
|
if response.status != HTTPStatus.ACCEPTED:
|
|
235
|
+
response_text = await response.text()
|
|
235
236
|
raise Exception(
|
|
236
237
|
f"Error uploading custom metrics: Status Code: {response.status}"
|
|
237
|
-
f"Message: {
|
|
238
|
+
f"Message: {response_text}"
|
|
238
239
|
)
|
|
239
240
|
self._logger.info("Successfully uploaded custom metrics")
|
|
240
241
|
except Exception as e:
|
|
@@ -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
|
-
#
|
|
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.
|
|
@@ -801,6 +798,13 @@ def guard_chat_wrapper(
|
|
|
801
798
|
if association_id:
|
|
802
799
|
data[association_id_column_name] = [association_id]
|
|
803
800
|
|
|
801
|
+
# DRUM initializes the pipeline (which reads the deployment's list of custom metrics)
|
|
802
|
+
# at start time.
|
|
803
|
+
# If there are no extra_body fields (meaning no user-defined custom metrics to report),
|
|
804
|
+
# then the list does not need to be reread.
|
|
805
|
+
if chat_extra_body_params:
|
|
806
|
+
pipeline.lookup_custom_metric_ids()
|
|
807
|
+
|
|
804
808
|
# report any metrics from extra_body. They are not tied to a prompt or response phase.
|
|
805
809
|
_logger.debug("Report extra_body params as custom metrics")
|
|
806
810
|
pipeline.report_custom_metrics_from_extra_body(association_id, chat_extra_body_params)
|
|
@@ -380,20 +380,13 @@ 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:
|
|
395
386
|
"""
|
|
396
387
|
Add any key-value pairs extracted from extra_body as custom metrics.
|
|
388
|
+
The custom metrics must be deployment-based, not model-specific.
|
|
389
|
+
(Bulk upload does not support heterogeneous model/non-model metrics.)
|
|
397
390
|
:param association_id: Association ID of the chat request
|
|
398
391
|
:param extra_params: a dict of {"name": value} for all extra_body parameters found
|
|
399
392
|
"""
|
|
@@ -412,19 +405,19 @@ class LLMPipeline(Pipeline):
|
|
|
412
405
|
f"will not be sent: {name}"
|
|
413
406
|
)
|
|
414
407
|
continue
|
|
415
|
-
if name not in self.
|
|
408
|
+
if name not in self.custom_metric_names_to_ids:
|
|
416
409
|
self._logger.warning(f"extra_body custom metric ID not in map: {name}")
|
|
417
410
|
continue
|
|
418
|
-
metric_id = self.
|
|
411
|
+
metric_id = self.custom_metric_names_to_ids.get(name)
|
|
419
412
|
if not metric_id:
|
|
413
|
+
# this should not be possible, as the name/id information
|
|
414
|
+
# is taken directly from DataRobot API
|
|
420
415
|
self._logger.warning(f"extra_body custom metric has missing ID: {name}")
|
|
421
416
|
continue
|
|
422
417
|
payload["buckets"].append(
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
"associationId": association_id,
|
|
427
|
-
}
|
|
418
|
+
self.custom_metric_individual_payload(
|
|
419
|
+
metric_id=metric_id, value=value, association_id=association_id
|
|
420
|
+
)
|
|
428
421
|
)
|
|
429
422
|
self._logger.debug(f"Sending custom metrics payload from extra_body: {payload}")
|
|
430
423
|
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
|
-
|
|
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,38 @@ 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, refresh the list when a chat request arrives.
|
|
207
|
+
Side effect: updates self.custom_metric_names_to_ids
|
|
208
|
+
"""
|
|
209
|
+
# set up DataRobot API client, only if not already set up
|
|
210
|
+
self.create_dr_client()
|
|
211
|
+
|
|
212
|
+
# Manually paginate; the dmm list_custom_metrics does not implement pagination
|
|
213
|
+
custom_metrics_list = []
|
|
214
|
+
offset, limit = 0, 50
|
|
215
|
+
while True:
|
|
216
|
+
response_list = self.dr_client.get(
|
|
217
|
+
f"deployments/{self._deployment_id}/customMetrics/?offset={offset}&limit={limit}"
|
|
218
|
+
).json()
|
|
219
|
+
custom_metrics_list.extend(response_list["data"])
|
|
220
|
+
offset += response_list["count"]
|
|
221
|
+
if response_list["next"] is None:
|
|
222
|
+
break
|
|
223
|
+
|
|
224
|
+
if not custom_metrics_list:
|
|
225
|
+
self._logger.warning(
|
|
226
|
+
"lookup_custom_metric_ids: result list is empty; no custom metrics to process"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
self.custom_metric_names_to_ids = {m["name"]: m["id"] for m in custom_metrics_list}
|
|
230
|
+
self._logger.debug(f"lookup_custom_metric_ids(): found {self.custom_metric_names_to_ids}")
|
|
231
|
+
|
|
201
232
|
def create_custom_metrics(self):
|
|
202
233
|
"""
|
|
203
234
|
Creates all the custom-metrics in the DR app for an active deployment.
|
|
@@ -268,35 +299,16 @@ class Pipeline:
|
|
|
268
299
|
# Now query all the metrics and get their custom metric ids. Specifically,
|
|
269
300
|
# required in case a metric is duplicated, in which case, we don't have its
|
|
270
301
|
# 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
|
|
302
|
+
self.lookup_custom_metric_ids()
|
|
288
303
|
|
|
289
304
|
# assign IDs to the "metric by name" maps so we can upload by ID later
|
|
290
|
-
for
|
|
291
|
-
metric_name = metric["name"]
|
|
305
|
+
for metric_name, metric_id in self.custom_metric_names_to_ids.items():
|
|
292
306
|
if metric_name in self.custom_metric_map:
|
|
293
|
-
self.custom_metric_map[metric_name]["id"] =
|
|
294
|
-
elif metric_name in self.extra_body_custom_metric_map:
|
|
295
|
-
self.extra_body_custom_metric_map[metric_name]["id"] = metric["id"]
|
|
307
|
+
self.custom_metric_map[metric_name]["id"] = metric_id
|
|
296
308
|
else:
|
|
297
309
|
self._logger.warning(
|
|
298
310
|
f"Metric '{metric_name}' exists at DR but not in moderation; "
|
|
299
|
-
"no value will be reported"
|
|
311
|
+
"no moderation value will be reported for it"
|
|
300
312
|
)
|
|
301
313
|
continue
|
|
302
314
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
datarobot_dome/__init__.py,sha256=B5Rx8_CNCNsOpxBbRj27XOXCfRZmvmrAR-NzlzIKnDw,583
|
|
2
|
-
datarobot_dome/async_http_client.py,sha256=
|
|
2
|
+
datarobot_dome/async_http_client.py,sha256=YVkzSSP7ItOEwEskjH0MAs1kJW0jXfbvJWkF_52K7CE,9863
|
|
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=
|
|
5
|
+
datarobot_dome/drum_integration.py,sha256=SLKpK-0pI9Dsi6iMBVhPv_w-SF0rqs2of-OYF3_KSPk,45983
|
|
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=
|
|
18
|
-
datarobot_dome/pipeline/pipeline.py,sha256=
|
|
17
|
+
datarobot_dome/pipeline/llm_pipeline.py,sha256=bindyorJq9VSPZt2X8w0-3REaXui7wIA-8c-zNOIdZU,20961
|
|
18
|
+
datarobot_dome/pipeline/pipeline.py,sha256=vCcP8dgu4TE-af6wUt7RqD4Xg7MzfwfK8njjC4XLnIA,19249
|
|
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.
|
|
23
|
-
datarobot_moderations-11.2.
|
|
24
|
-
datarobot_moderations-11.2.
|
|
22
|
+
datarobot_moderations-11.2.7.dist-info/METADATA,sha256=RqNHfInWAiYqI346wVcJEwZj2sTvJ3qvC9FXZEEKLAE,4741
|
|
23
|
+
datarobot_moderations-11.2.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
24
|
+
datarobot_moderations-11.2.7.dist-info/RECORD,,
|
|
File without changes
|