fiddler-client 3.1.0.dev2__py3-none-any.whl → 3.1.0.dev4__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.
fiddler/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.0.dev2
1
+ 3.1.0.dev4
fiddler/__init__.py CHANGED
@@ -61,6 +61,7 @@ from fiddler.schemas.xai import ( # noqa
61
61
  SqlSliceQueryDataSource,
62
62
  )
63
63
  from fiddler.schemas.xai_params import XaiParams # noqa
64
+ from fiddler.utils.helpers import group_by # noqa
64
65
  from fiddler.utils.logger import set_logging # noqa
65
66
  from fiddler.version import __version__ # noqa
66
67
 
@@ -141,4 +142,5 @@ __all__ = [
141
142
  'ApiError',
142
143
  # Utilities
143
144
  'set_logging',
145
+ 'group_by',
144
146
  ]
@@ -8,8 +8,8 @@ from uuid import UUID
8
8
  from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
9
9
  from fiddler.decorators import handle_api_error
10
10
  from fiddler.entities.base import BaseEntity
11
- from fiddler.entities.baseline import Baseline, BaselineCompactMixin
12
- from fiddler.entities.model import Model, ModelCompactMixin
11
+ from fiddler.entities.baseline import BaselineCompactMixin
12
+ from fiddler.entities.model import ModelCompactMixin
13
13
  from fiddler.entities.project import ProjectCompactMixin
14
14
  from fiddler.schemas.alert_rule import AlertRuleResp, NotificationConfig
15
15
  from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
@@ -34,6 +34,7 @@ class AlertRule(
34
34
  warning_threshold: float | None = None,
35
35
  columns: list[str] | None = None,
36
36
  baseline_id: UUID | str | None = None,
37
+ segment_id: UUID | str | None = None,
37
38
  compare_bin_delta: int | None = None,
38
39
  ) -> None:
39
40
  """Construct a alert rule instance."""
@@ -49,6 +50,7 @@ class AlertRule(
49
50
  self.critical_threshold = critical_threshold
50
51
  self.condition = condition
51
52
  self.bin_size = bin_size
53
+ self.segment_id = segment_id
52
54
 
53
55
  self.id: UUID | None = None
54
56
  self.project_id: UUID | None = None
@@ -61,6 +63,12 @@ class AlertRule(
61
63
 
62
64
  @staticmethod
63
65
  def _get_url(id_: UUID | str | None = None) -> str:
66
+ """Get model resource/item url."""
67
+ url = '/v3/alert-rules'
68
+ return url if not id_ else f'{url}/{id_}'
69
+
70
+ @staticmethod
71
+ def _get_url_v2(id_: UUID | str | None = None) -> str:
64
72
  """Get model resource/item url."""
65
73
  url = '/v2/alert-configs'
66
74
  return url if not id_ else f'{url}/{id_}'
@@ -76,7 +84,7 @@ class AlertRule(
76
84
  instance = cls(
77
85
  name=resp_obj.name,
78
86
  model_id=resp_obj.model.id,
79
- metric_id=resp_obj.metric_id,
87
+ metric_id=resp_obj.metric.id,
80
88
  priority=resp_obj.priority,
81
89
  compare_to=resp_obj.compare_to,
82
90
  condition=resp_obj.condition,
@@ -84,7 +92,8 @@ class AlertRule(
84
92
  critical_threshold=resp_obj.critical_threshold,
85
93
  warning_threshold=resp_obj.warning_threshold,
86
94
  columns=resp_obj.columns,
87
- baseline_id=resp_obj.baseline_id,
95
+ baseline_id=resp_obj.baseline.id if resp_obj.baseline else None,
96
+ segment_id=resp_obj.segment.id if resp_obj.segment else None,
88
97
  compare_bin_delta=resp_obj.compare_bin_delta,
89
98
  )
90
99
 
@@ -110,11 +119,11 @@ class AlertRule(
110
119
  # Reset properties
111
120
  self.model_id = resp_obj.model.id
112
121
  self.project_id = resp_obj.project.id
122
+ self.metric_id = resp_obj.metric.id
113
123
 
114
124
  # Add remaining fields
115
125
  fields = [
116
126
  'id',
117
- 'metric_id',
118
127
  'created_at',
119
128
  'updated_at',
120
129
  ]
@@ -176,7 +185,9 @@ class AlertRule(
176
185
  if columns:
177
186
  for column in columns:
178
187
  rules.append(
179
- QueryRule(field='columns', operator=OperatorType.ANY, value=column)
188
+ QueryRule(
189
+ field='feature_names', operator=OperatorType.ANY, value=column
190
+ )
180
191
  )
181
192
 
182
193
  _filter = QueryCondition(rules=rules)
@@ -185,7 +196,6 @@ class AlertRule(
185
196
  if ordering:
186
197
  params['ordering'] = ','.join(ordering)
187
198
 
188
- params['organization_name'] = cls.get_organization_name()
189
199
  for rule in cls._paginate(url=cls._get_url(), params=params):
190
200
  yield cls._from_dict(data=rule)
191
201
 
@@ -199,26 +209,22 @@ class AlertRule(
199
209
  @handle_api_error
200
210
  def create(self) -> AlertRule:
201
211
  """Create a new alert rule."""
202
- model = Model.get(self.model_id)
203
212
  payload: dict[str, Any] = {
204
213
  'name': self.name,
205
- 'organization_name': self.organization_name,
206
- 'model_name': model.name,
207
- 'project_name': model.project.name,
214
+ 'model_id': self.model_id,
208
215
  'metric_id': self.metric_id,
209
216
  'priority': self.priority,
210
217
  'compare_to': self.compare_to,
211
218
  'condition': self.condition,
212
219
  'bin_size': self.bin_size,
220
+ 'segment_id': self.segment_id,
213
221
  'critical_threshold': self.critical_threshold,
214
222
  'warning_threshold': self.warning_threshold,
215
223
  'feature_names': self.columns,
216
224
  'compare_bin_delta': self.compare_bin_delta,
217
- 'notifications': self._get_notifications_dict(),
218
225
  }
219
226
  if self.baseline_id:
220
- baseline = Baseline.get(self.baseline_id)
221
- payload['baseline_name'] = baseline.name
227
+ payload['baseline_id'] = self.baseline_id
222
228
 
223
229
  response = self._client().post(
224
230
  url=self._get_url(),
@@ -232,7 +238,7 @@ class AlertRule(
232
238
  def enable_notifications(self) -> None:
233
239
  """Enable notifications for an alert rule"""
234
240
  self._client().patch(
235
- url=self._get_url(id_=self.id), data={'enable_notification': True}
241
+ url=self._get_url_v2(id_=self.id), data={'enable_notification': True}
236
242
  )
237
243
  logger.info(
238
244
  'Notifications have been enabled for alert rule with id: %s', self.id
@@ -242,7 +248,7 @@ class AlertRule(
242
248
  def disable_notifications(self) -> None:
243
249
  """Disable notifications for an alert rule"""
244
250
  self._client().patch(
245
- url=self._get_url(id_=self.id), data={'enable_notification': False}
251
+ url=self._get_url_v2(id_=self.id), data={'enable_notification': False}
246
252
  )
247
253
  logger.info(
248
254
  'Notifications have been disabled for alert rule with id: %s', self.id
@@ -273,7 +279,7 @@ class AlertRule(
273
279
  webhooks=webhooks,
274
280
  )
275
281
  response = self._client().patch(
276
- url=self._get_url(id_=self.id),
282
+ url=self._get_url_v2(id_=self.id),
277
283
  data={'notifications': notifications},
278
284
  )
279
285
 
@@ -289,7 +295,7 @@ class AlertRule(
289
295
  :return: NotificationConfig object
290
296
  """
291
297
 
292
- response = self._client().get(url=self._get_url(id_=self.id))
298
+ response = self._client().get(url=self._get_url_v2(id_=self.id))
293
299
 
294
300
  return self._get_notifications_from_dict(
295
301
  response.json()['data']['notifications']
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import tempfile
4
4
  from pathlib import Path
5
- from typing import Any
5
+ from typing import Any, Callable
6
6
  from uuid import UUID
7
7
 
8
8
  import pandas as pd
@@ -17,6 +17,9 @@ from fiddler.entities.job import Job
17
17
  from fiddler.schemas.dataset import EnvType
18
18
  from fiddler.schemas.events import EventsSource, FileSource
19
19
  from fiddler.schemas.job import JobCompactResp
20
+ from fiddler.utils.logger import get_logger
21
+
22
+ logger = get_logger(__name__)
20
23
 
21
24
 
22
25
  class EventPublisher(ConnectionMixin):
@@ -51,40 +54,72 @@ class EventPublisher(ConnectionMixin):
51
54
 
52
55
  :return: list[UUID] for list of dicts source and Job object for file path or dataframe source.
53
56
  """
57
+
58
+ publish_method = self._get_publish_method(source=source)
59
+
60
+ return publish_method(
61
+ source=source,
62
+ environment=environment,
63
+ dataset_name=dataset_name,
64
+ update=update,
65
+ )
66
+
67
+ def _get_publish_method(
68
+ self, source: list[dict[str, Any]] | str | Path | pd.DataFrame
69
+ ) -> Callable:
54
70
  if isinstance(source, (str, Path)):
55
- return self._publish_file(
56
- source=source,
57
- environment=environment,
58
- dataset_name=dataset_name,
59
- update=update,
60
- )
71
+ return self._publish_file
61
72
 
62
73
  if isinstance(source, pd.DataFrame):
63
- with tempfile.NamedTemporaryFile(suffix='.csv') as temp_file:
64
- source.to_csv(temp_file.name, index=False)
74
+ return self._publish_df
75
+
76
+ if isinstance(source, list):
77
+ return self._publish_stream
78
+
79
+ raise ValueError(f'Unsupported source - {type(source)}')
80
+
81
+ def _publish_df(
82
+ self,
83
+ source: pd.DataFrame,
84
+ environment: EnvType,
85
+ dataset_name: str | None = None,
86
+ update: bool = False,
87
+ ) -> Job:
88
+ with tempfile.NamedTemporaryFile(suffix='.parquet') as temp_file:
89
+ try:
90
+ source.to_parquet(temp_file.name, index=False)
65
91
  return self._publish_file(
66
92
  source=temp_file.name,
67
93
  environment=environment,
68
94
  dataset_name=dataset_name,
69
95
  update=update,
70
96
  )
71
-
72
- elif isinstance(source, list):
73
- return self._publish_stream(source=source, update=update)
74
-
75
- raise ValueError(f'Unsupported source - {type(source)}')
97
+ except Exception:
98
+ logger.warning(
99
+ 'Failed to convert input dataframe to parquet format. Retrying as a CSV file.'
100
+ )
101
+ with tempfile.NamedTemporaryFile(suffix='.csv') as temp_file:
102
+ source.to_csv(temp_file.name, index=False)
103
+ return self._publish_file(
104
+ source=temp_file.name,
105
+ environment=environment,
106
+ dataset_name=dataset_name,
107
+ update=update,
108
+ )
76
109
 
77
110
  def _publish_stream(
78
111
  self,
79
112
  source: list[dict[str, Any]],
113
+ environment: EnvType = EnvType.PRODUCTION,
114
+ dataset_name: str | None = None,
80
115
  update: bool = False,
81
116
  ) -> list[UUID]:
82
117
  event_ids = []
83
118
  for i in tqdm(range(0, len(source), self.STREAM_LIMIT)):
84
119
  response = self._publish_call(
85
120
  source=EventsSource(events=source[i : i + self.STREAM_LIMIT]),
86
- environment=EnvType.PRODUCTION,
87
- dataset_name=None,
121
+ environment=environment,
122
+ dataset_name=dataset_name,
88
123
  update=update,
89
124
  )
90
125
  event_ids.extend(response.json()['data']['event_ids'])
fiddler/entities/model.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import builtins
4
- import copy
5
4
  import typing
5
+ from copy import deepcopy
6
6
  from dataclasses import dataclass
7
7
  from datetime import datetime
8
8
  from functools import cached_property
@@ -33,12 +33,15 @@ from fiddler.schemas.model_spec import ModelSpec
33
33
  from fiddler.schemas.model_task_params import ModelTaskParams
34
34
  from fiddler.schemas.xai_params import XaiParams
35
35
  from fiddler.utils.helpers import raise_not_found
36
+ from fiddler.utils.logger import get_logger
36
37
  from fiddler.utils.model_generator import ModelGenerator
37
38
 
38
39
  if typing.TYPE_CHECKING:
39
40
  from fiddler.entities.baseline import Baseline
40
41
  from fiddler.entities.dataset import Dataset
41
42
 
43
+ logger = get_logger(__name__)
44
+
42
45
 
43
46
  class Model(
44
47
  BaseEntity,
@@ -307,7 +310,9 @@ class Model(
307
310
  params = {'filter': _filter.json()}
308
311
 
309
312
  for model in cls._paginate(url=cls._get_url(), params=params):
310
- yield ModelCompact(id=model['id'], name=model['name'])
313
+ yield ModelCompact(
314
+ id=model['id'], name=model['name'], version=model['version']
315
+ )
311
316
 
312
317
  def duplicate(self, version: str | None = None) -> Model:
313
318
  """
@@ -319,13 +324,21 @@ class Model(
319
324
  :param version: Version name for the new instance
320
325
  :return: Model instance
321
326
  """
322
- self_copy = copy.deepcopy(self)
323
- self_copy.id = None
324
-
325
- if version:
326
- self_copy.version = version
327
-
328
- return self_copy
327
+ return Model(
328
+ name=self.name,
329
+ project_id=self.project_id,
330
+ schema=deepcopy(self.schema),
331
+ spec=deepcopy(self.spec),
332
+ version=version if version else self.version,
333
+ input_type=self.input_type,
334
+ task=self.task,
335
+ task_params=deepcopy(self.task_params),
336
+ description=self.description,
337
+ event_id_col=self.event_id_col,
338
+ event_ts_col=self.event_ts_col,
339
+ event_ts_format=self.event_ts_format,
340
+ xai_params=deepcopy(self.xai_params),
341
+ )
329
342
 
330
343
  @property
331
344
  def datasets(self) -> Iterator[Dataset]:
@@ -456,7 +469,7 @@ class Model(
456
469
  :return: list[UUID] for list of dicts or dataframe source and Job object for
457
470
  file path source.
458
471
  """
459
-
472
+ logger.info('Model[%s/%s] - Publishing events', self.name, self.version)
460
473
  return self._event_publisher.publish(
461
474
  source=source,
462
475
  environment=environment,
@@ -6,7 +6,9 @@ from uuid import UUID
6
6
 
7
7
  from fiddler.decorators import handle_api_error
8
8
  from fiddler.entities.base import BaseEntity
9
+ from fiddler.entities.job import Job
9
10
  from fiddler.entities.project import ProjectCompactMixin
11
+ from fiddler.schemas.job import JobCompactResp
10
12
  from fiddler.schemas.model_deployment import ModelDeploymentResponse
11
13
  from fiddler.utils.logger import get_logger
12
14
 
@@ -94,7 +96,7 @@ class ModelDeployment(
94
96
  self._resp = resp_obj
95
97
 
96
98
  @handle_api_error
97
- def update(self) -> None:
99
+ def update(self) -> Job:
98
100
  """Update an existing model deployment."""
99
101
  payload: dict[str, Any] = {'active': self.active}
100
102
  if self.replicas is not None:
@@ -108,6 +110,8 @@ class ModelDeployment(
108
110
  url=self._get_url(model_id=self.model_id), data=payload
109
111
  )
110
112
  self._refresh_from_response(response=response)
113
+ job_compact = JobCompactResp(**response.json()['data']['job'])
114
+ return Job.get(id_=job_compact.id)
111
115
 
112
116
  @classmethod
113
117
  def of(cls, model_id: UUID | str) -> ModelDeployment:
@@ -6,7 +6,9 @@ from uuid import UUID
6
6
 
7
7
  from fiddler.decorators import handle_api_error
8
8
  from fiddler.entities.base import BaseEntity
9
+ from fiddler.schemas.filter_query import OperatorType, QueryCondition, QueryRule
9
10
  from fiddler.schemas.webhook import WebhookProvider, WebhookResp
11
+ from fiddler.utils.helpers import raise_not_found
10
12
 
11
13
 
12
14
  class Webhook(BaseEntity):
@@ -81,6 +83,22 @@ class Webhook(BaseEntity):
81
83
  response = cls._client().get(url=cls._get_url(id_))
82
84
  return cls._from_response(response=response)
83
85
 
86
+ @classmethod
87
+ @handle_api_error
88
+ def from_name(cls, name: str) -> Webhook:
89
+ """Get the webhook instance using webhook name"""
90
+ _filter = QueryCondition(
91
+ rules=[QueryRule(field='name', operator=OperatorType.EQUAL, value=name)]
92
+ )
93
+
94
+ response = cls._client().get(
95
+ url=cls._get_url(), params={'filter': _filter.json()}
96
+ )
97
+ if response.json()['data']['total'] == 0:
98
+ raise_not_found('Webhook not found for the given identifier')
99
+
100
+ return cls._from_dict(data=response.json()['data']['items'][0])
101
+
84
102
  @classmethod
85
103
  @handle_api_error
86
104
  def list(cls) -> Iterator[Webhook]:
@@ -36,7 +36,8 @@ class TemplateKerasTF2Model:
36
36
  :param hybrid: Boolean value for hybrid data type (for example matrices). Default to False.
37
37
  """
38
38
  import tensorflow as tf
39
- from packtools.keras_ig_helpers import ComputeGradientsKerasTF2
39
+
40
+ from fiddler.packtools.keras_ig_helpers import ComputeGradientsKerasTF2
40
41
 
41
42
  embedding_names = embedding_names or []
42
43
  batch_input_shape_list = batch_input_shape_list or []
@@ -197,7 +198,7 @@ class TemplateTreeShap:
197
198
  :return: explanations_by_output and extras_by_output: two dictionaries with keys the output columns and values
198
199
  the corresponding explanations and extra information necessary
199
200
  """
200
- from packtools.project_attributions_helpers import TreeShapAttributions
201
+ from fiddler.packtools.project_attributions_helpers import TreeShapAttributions
201
202
 
202
203
  if explanation_name != self.tree_shap_explanations:
203
204
  raise NotImplementedError(
@@ -7,29 +7,38 @@ from pydantic import Field
7
7
  from fiddler.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
8
8
  from fiddler.schemas.base import BaseModel
9
9
  from fiddler.schemas.baseline import BaselineCompactResp
10
+ from fiddler.schemas.custom_expression import SegmentCompactResp
10
11
  from fiddler.schemas.model import ModelCompactResp
11
12
  from fiddler.schemas.project import ProjectCompactResp
12
13
 
13
14
 
15
+ class MetricResp(BaseModel):
16
+ id: Union[str, UUID]
17
+ display_name: str
18
+ type: str
19
+ type_display_name: str
20
+
21
+
14
22
  class AlertRuleResp(BaseModel):
15
- id: UUID = Field(alias='uuid')
23
+ id: UUID
16
24
  name: str
17
- model: ModelCompactResp
18
- project: ProjectCompactResp
19
- baseline: Optional[BaselineCompactResp]
20
25
  priority: Union[str, Priority]
21
26
  compare_to: Union[str, CompareTo]
22
- metric_id: Union[str, UUID]
23
- critical_threshold: float
24
27
  condition: Union[str, AlertCondition]
25
- bin_size: Union[str, BinSize]
26
- columns: Optional[List[str]]
27
- baseline_id: Optional[UUID]
28
28
  compare_bin_delta: Optional[int]
29
+ bin_size: Union[str, BinSize]
30
+ columns: Optional[List[str]] = Field(alias='feature_names')
31
+ critical_threshold: float
29
32
  warning_threshold: Optional[float]
30
33
 
31
34
  created_at: datetime
32
- updated_at: datetime = Field(alias='last_updated')
35
+ updated_at: datetime
36
+
37
+ metric: MetricResp
38
+ model: ModelCompactResp
39
+ project: ProjectCompactResp
40
+ baseline: Optional[BaselineCompactResp]
41
+ segment: Optional[SegmentCompactResp]
33
42
 
34
43
 
35
44
  class NotificationConfig(BaseModel):
@@ -29,3 +29,10 @@ class CustomMetricResp(CustomExpressionResp):
29
29
 
30
30
  class SegmentResp(CustomExpressionResp):
31
31
  """Segment response object"""
32
+
33
+
34
+ class SegmentCompactResp(BaseModel):
35
+ """Segment compact response object"""
36
+
37
+ id: UUID
38
+ name: str
@@ -28,60 +28,113 @@ from fiddler.utils.logger import set_logging
28
28
 
29
29
  API_RESPONSE_200 = {
30
30
  'data': {
31
- 'feature_names': ['age'],
32
- 'id': 620,
33
- 'created_at': '2023-11-28T08:04:12.651937+00:00',
34
- 'organization_name': 'mainbuild',
35
- 'compare_period': None,
36
- 'time_bucket': 3600000,
37
- 'alert_type': 'data_integrity',
38
- 'metric_display_name': 'Missing Value Violation',
39
- 'enable_notification': True,
40
- 'last_updated': '2023-11-28T08:04:12.653346+00:00',
41
- 'alert_type_display_name': 'Data Integrity',
42
- 'critical_threshold': 0.0,
43
- 'baseline_name': BASELINE_NAME,
44
- 'baseline': {
45
- 'id': BASELINE_ID,
46
- 'name': BASELINE_NAME,
31
+ 'id': ALERT_RULE_ID,
32
+ 'model': {'id': MODEL_ID, 'name': MODEL_NAME, 'version': 'v1'},
33
+ 'project': {'id': PROJECT_ID, 'name': PROJECT_NAME},
34
+ 'organization': {
35
+ 'id': 'e03d6f02-6efa-4eb1-b828-7ea9d2a083d0',
36
+ 'name': 'scale154',
47
37
  },
48
- 'condition': 'greater',
49
- 'uuid': ALERT_RULE_ID,
38
+ 'baseline': None,
50
39
  'segment': None,
51
- 'warning_threshold': None,
52
- 'name': 'Age Missing 1 Hr',
53
- 'model_name': MODEL_NAME,
54
- 'model': {
55
- 'id': MODEL_ID,
56
- 'name': MODEL_NAME,
40
+ 'version': 'rule_v3',
41
+ 'name': 'skdfvbj',
42
+ 'priority': 'HIGH',
43
+ 'feature_names': ['gender'],
44
+ 'bin_size': 'Hour',
45
+ 'compare_to': 'raw_value',
46
+ 'condition': 'greater',
47
+ 'warning_threshold': 1.0,
48
+ 'critical_threshold': 2.0,
49
+ 'updated_at': '2024-04-17T12:42:15.672909+00:00',
50
+ 'enable_notification': True,
51
+ 'compare_bin_delta': 0,
52
+ 'created_at': '2024-04-17T12:42:15.672909+00:00',
53
+ 'created_by': {
54
+ 'id': '287949c2-13f8-49fc-a559-55b2e6f36e9b',
55
+ 'full_name': 'Fiddler Administrator',
56
+ 'email': 'admin@fiddler.ai',
57
57
  },
58
+ 'updated_by': {
59
+ 'id': '287949c2-13f8-49fc-a559-55b2e6f36e9b',
60
+ 'full_name': 'Fiddler Administrator',
61
+ 'email': 'admin@fiddler.ai',
62
+ },
63
+ 'metric': {
64
+ 'id': 'null_violation_percentage',
65
+ 'display_name': '% Missing Value Violation',
66
+ 'type': 'data_integrity',
67
+ 'type_display_name': 'Data Integrity',
68
+ },
69
+ },
70
+ 'api_version': '3.0',
71
+ 'kind': 'NORMAL',
72
+ }
73
+
74
+ API_RESPONSE_200_V2 = {
75
+ 'data': {
76
+ 'id': 794,
77
+ 'organization_name': 'mainbuild',
78
+ 'project_name': PROJECT_NAME,
79
+ 'model_id': 285,
80
+ 'name': 'test_rule',
81
+ 'metric': 'jsd',
82
+ 'metric_id': 'jsd',
83
+ 'metric_display_name': 'Jensen-Shannon Distance',
84
+ 'alert_type': 'drift',
85
+ 'alert_type_display_name': 'Data Drift',
86
+ 'priority': 'MEDIUM',
87
+ 'baseline_name': BASELINE_NAME,
88
+ 'feature_names': ['creditscore'],
89
+ 'time_bucket': 3600000,
90
+ 'category': None,
91
+ 'bin_size': 'Hour',
92
+ 'compare_to': 'raw_value',
93
+ 'condition': 'greater',
94
+ 'compare_period': None,
95
+ 'warning_threshold': 1.0,
96
+ 'critical_threshold': 2.3,
58
97
  'is_active': True,
59
98
  'created_by': 'admin@fiddler.ai',
60
- 'bin_size': 'Hour',
61
- 'category': None,
62
- 'project_name': PROJECT_NAME,
63
- 'project': {
64
- 'id': PROJECT_ID,
65
- 'name': PROJECT_NAME,
99
+ 'created_at': '2024-04-23T10:34:14.321895+00:00',
100
+ 'last_updated': '2024-04-23T10:34:14.323554+00:00',
101
+ 'model_name': 'bank_churn',
102
+ 'enable_notification': True,
103
+ 'segment': {
104
+ 'id': '1c9b551a-808b-4ef0-b67b-e788eaf1e6de',
105
+ 'organization_name': 'mainbuild',
106
+ 'project_name': 'nick_test_project_11',
107
+ 'model_name': 'bank_churn',
108
+ 'name': 'xyzab',
109
+ 'definition': 'Age > 10',
110
+ 'description': 'meh',
111
+ 'created_at': '2024-04-23T10:31:52.181550+00:00',
112
+ 'created_by': {
113
+ 'id': 1,
114
+ 'full_name': 'Fiddler Administrator',
115
+ 'email': 'admin@fiddler.ai',
116
+ },
66
117
  },
67
- 'metric': 'null_violation_count',
68
- 'metric_id': 'null_violation_count',
69
- 'compare_to': 'raw_value',
70
- 'priority': 'HIGH',
118
+ 'project': {'id': PROJECT_ID, 'name': PROJECT_NAME},
119
+ 'model': {'id': MODEL_ID, 'name': MODEL_NAME, 'version': 'v1'},
120
+ 'baseline': {'id': BASELINE_ID, 'name': BASELINE_NAME},
121
+ 'compare_bin_delta': None,
122
+ 'uuid': ALERT_RULE_ID,
71
123
  'notifications': {
72
- 'emails': {'alert_config_uuid': ALERT_RULE_ID, 'email': 'admin@fiddler.ai'},
73
124
  'pagerduty': {
74
- 'severity': '',
75
125
  'alert_config_uuid': ALERT_RULE_ID,
76
126
  'service': '',
127
+ 'severity': '',
77
128
  },
78
- 'webhooks': [{'uuid': 'e20bf4cc-d2cf-4540-baef-d96913b14f1b'}],
129
+ 'emails': {'email': ''},
130
+ 'webhooks': [],
79
131
  },
80
132
  },
81
133
  'api_version': '2.0',
82
134
  'kind': 'NORMAL',
83
135
  }
84
136
 
137
+
85
138
  API_RESPONSE_404 = {
86
139
  'error': {
87
140
  'code': 404,
@@ -109,46 +162,44 @@ LIST_API_RESPONSE = {
109
162
  'items': [
110
163
  API_RESPONSE_200['data'],
111
164
  {
112
- 'critical_threshold': 100.0,
113
- 'created_by': 'admin@fiddler.ai',
114
- 'metric_display_name': 'Traffic',
115
- 'condition': 'lesser',
116
- 'metric': 'traffic',
117
- 'metric_id': 'traffic',
165
+ 'id': '3431b746-d18f-4aed-99ea-2da8d5b46fb6',
166
+ 'model': {'id': MODEL_ID, 'name': MODEL_NAME, 'version': 'v1'},
167
+ 'project': {'id': PROJECT_ID, 'name': PROJECT_NAME},
168
+ 'organization': {
169
+ 'id': 'e03d6f02-6efa-4eb1-b828-7ea9d2a083d0',
170
+ 'name': 'scale154',
171
+ },
172
+ 'baseline': {'id': BASELINE_ID, 'name': BASELINE_NAME},
173
+ 'segment': None,
174
+ 'version': 'rule_v3',
175
+ 'name': 'sfdvsefv',
176
+ 'priority': 'HIGH',
177
+ 'feature_names': ['numofproducts'],
118
178
  'bin_size': 'Hour',
179
+ 'compare_to': 'raw_value',
180
+ 'condition': 'greater',
181
+ 'warning_threshold': 1e-05,
182
+ 'critical_threshold': 0.001,
183
+ 'updated_at': '2024-04-17T12:43:23.871997+00:00',
119
184
  'enable_notification': True,
120
- 'is_active': True,
121
- 'project_name': PROJECT_NAME,
122
- 'project': {
123
- 'id': PROJECT_ID,
124
- 'name': PROJECT_NAME,
185
+ 'compare_bin_delta': 0,
186
+ 'created_at': '2024-04-17T12:43:23.871997+00:00',
187
+ 'created_by': {
188
+ 'id': '287949c2-13f8-49fc-a559-55b2e6f36e9b',
189
+ 'full_name': 'Fiddler Administrator',
190
+ 'email': 'admin@fiddler.ai',
125
191
  },
126
- 'name': 'traffic-lt-1hr',
127
- 'created_at': '2023-11-28T08:04:10.916498+00:00',
128
- 'baseline_name': 'DEFAULT (bank_churn)',
129
- 'baseline': {
130
- 'id': BASELINE_ID,
131
- 'name': BASELINE_NAME,
192
+ 'updated_by': {
193
+ 'id': '287949c2-13f8-49fc-a559-55b2e6f36e9b',
194
+ 'full_name': 'Fiddler Administrator',
195
+ 'email': 'admin@fiddler.ai',
132
196
  },
133
- 'organization_name': 'mainbuild',
134
- 'priority': 'HIGH',
135
- 'category': None,
136
- 'warning_threshold': 200.0,
137
- 'segment': None,
138
- 'alert_type': 'service_metrics',
139
- 'time_bucket': 3600000,
140
- 'alert_type_display_name': 'Traffic',
141
- 'compare_period': 5,
142
- 'compare_to': 'time_period',
143
- 'uuid': '42eb6d51-dc5c-4e04-82aa-440b2d840704',
144
- 'id': 618,
145
- 'feature_names': None,
146
- 'model_name': MODEL_NAME,
147
- 'model': {
148
- 'id': MODEL_ID,
149
- 'name': MODEL_NAME,
197
+ 'metric': {
198
+ 'id': 'jsd',
199
+ 'display_name': 'Jensen-Shannon Distance',
200
+ 'type': 'drift',
201
+ 'type_display_name': 'Data Drift',
150
202
  },
151
- 'last_updated': '2023-11-28T08:04:10.918587+00:00',
152
203
  },
153
204
  ],
154
205
  }
@@ -170,7 +221,7 @@ LIST_API_RESPONSE_EMPTY = {
170
221
  @responses.activate
171
222
  def test_get_alert_rule_success() -> None:
172
223
  responses.get(
173
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
224
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
174
225
  json=API_RESPONSE_200,
175
226
  )
176
227
 
@@ -182,7 +233,7 @@ def test_get_alert_rule_success() -> None:
182
233
  @responses.activate
183
234
  def test_get_alert_rule_not_found() -> None:
184
235
  responses.get(
185
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
236
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
186
237
  json=API_RESPONSE_404,
187
238
  status=HTTPStatus.NOT_FOUND,
188
239
  )
@@ -194,7 +245,7 @@ def test_get_alert_rule_not_found() -> None:
194
245
  @responses.activate
195
246
  def test_alert_rule_list_success() -> None:
196
247
  responses.get(
197
- url=f'{URL}/v2/alert-configs',
248
+ url=f'{URL}/v3/alert-rules',
198
249
  json=LIST_API_RESPONSE,
199
250
  )
200
251
  for rule in AlertRule.list(model_id=MODEL_ID):
@@ -205,7 +256,7 @@ def test_alert_rule_list_success() -> None:
205
256
  def test_alert_rule_list_empty() -> None:
206
257
 
207
258
  responses.get(
208
- url=f'{URL}/v2/alert-configs',
259
+ url=f'{URL}/v3/alert-rules',
209
260
  json=LIST_API_RESPONSE_EMPTY,
210
261
  )
211
262
 
@@ -215,13 +266,13 @@ def test_alert_rule_list_empty() -> None:
215
266
  @responses.activate
216
267
  def test_delete_alert_rule() -> None:
217
268
  responses.get(
218
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
269
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
219
270
  json=API_RESPONSE_200,
220
271
  )
221
272
  rule = AlertRule.get(id_=ALERT_RULE_ID)
222
273
 
223
274
  responses.delete(
224
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
275
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
225
276
  )
226
277
 
227
278
  rule.delete()
@@ -230,13 +281,13 @@ def test_delete_alert_rule() -> None:
230
281
  @responses.activate
231
282
  def test_delete_alert_rule_not_found() -> None:
232
283
  responses.get(
233
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
284
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
234
285
  json=API_RESPONSE_200,
235
286
  )
236
287
  rule = AlertRule.get(id_=ALERT_RULE_ID)
237
288
 
238
289
  responses.delete(
239
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
290
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
240
291
  json=API_RESPONSE_404,
241
292
  status=HTTPStatus.NOT_FOUND,
242
293
  )
@@ -256,7 +307,7 @@ def test_add_alert_rule_success() -> None:
256
307
  json=BASELINE_API_RESPONSE_200,
257
308
  )
258
309
  responses.post(
259
- url=f'{URL}/v2/alert-configs',
310
+ url=f'{URL}/v3/alert-rules',
260
311
  json=API_RESPONSE_200,
261
312
  )
262
313
  alert_rule = AlertRule(
@@ -281,7 +332,7 @@ def test_add_alert_rule_success() -> None:
281
332
  @responses.activate
282
333
  def test_enable_notifications(caplog) -> None:
283
334
  responses.get(
284
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
335
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
285
336
  json=API_RESPONSE_200,
286
337
  )
287
338
 
@@ -289,7 +340,7 @@ def test_enable_notifications(caplog) -> None:
289
340
 
290
341
  resp = responses.patch(
291
342
  url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
292
- json=API_RESPONSE_200,
343
+ json=API_RESPONSE_200_V2,
293
344
  )
294
345
  set_logging(logging.INFO)
295
346
 
@@ -304,7 +355,7 @@ def test_enable_notifications(caplog) -> None:
304
355
  @responses.activate
305
356
  def test_disable_notifications(caplog) -> None:
306
357
  responses.get(
307
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
358
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
308
359
  json=API_RESPONSE_200,
309
360
  )
310
361
 
@@ -314,7 +365,7 @@ def test_disable_notifications(caplog) -> None:
314
365
 
315
366
  resp = responses.patch(
316
367
  url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
317
- json=API_RESPONSE_200,
368
+ json=API_RESPONSE_200_V2,
318
369
  )
319
370
 
320
371
  set_logging(logging.INFO)
@@ -329,12 +380,12 @@ def test_disable_notifications(caplog) -> None:
329
380
  @responses.activate
330
381
  def test_set_notifications() -> None:
331
382
  responses.get(
332
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
383
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
333
384
  json=API_RESPONSE_200,
334
385
  )
335
386
 
336
387
  alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
337
- API_RESPONSE_200['data']['notifications'] = {
388
+ API_RESPONSE_200_V2['data']['notifications'] = {
338
389
  'webhooks': [
339
390
  {'uuid': 'e20bf4cc-d2cf-4540-baef-d96913b14f1b'},
340
391
  {'uuid': '6e796fda-0111-4a72-82cd-f0f219e903e1'},
@@ -351,7 +402,7 @@ def test_set_notifications() -> None:
351
402
  }
352
403
  responses.patch(
353
404
  url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
354
- json=API_RESPONSE_200,
405
+ json=API_RESPONSE_200_V2,
355
406
  )
356
407
  notifications = alert_rule.set_notification_config(
357
408
  emails=['nikhil@fiddler.ai', 'admin@fiddler.ai'],
@@ -374,14 +425,14 @@ def test_set_notifications() -> None:
374
425
  @responses.activate
375
426
  def test_get_notifications() -> None:
376
427
  responses.get(
377
- url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
428
+ url=f'{URL}/v3/alert-rules/{ALERT_RULE_ID}',
378
429
  json=API_RESPONSE_200,
379
430
  )
380
431
 
381
432
  alert_rule = AlertRule.get(id_=ALERT_RULE_ID)
382
433
  responses.get(
383
434
  url=f'{URL}/v2/alert-configs/{ALERT_RULE_ID}',
384
- json=API_RESPONSE_200,
435
+ json=API_RESPONSE_200_V2,
385
436
  )
386
437
  notifications = alert_rule.get_notification_config()
387
438
  assert notifications == NotificationConfig(
@@ -471,6 +471,7 @@ def test_model_list_success() -> None:
471
471
  models = Model.list(project_id=PROJECT_ID)
472
472
  for model in models:
473
473
  assert isinstance(model, ModelCompact)
474
+ assert model.version is not None
474
475
 
475
476
 
476
477
  @responses.activate
@@ -654,14 +655,26 @@ def test_model_duplicate() -> None:
654
655
  model = Model.get(id_=MODEL_ID)
655
656
 
656
657
  assert model.id == UUID(MODEL_ID)
658
+ assert model._event_publisher.model_id == model.id
657
659
 
658
660
  # Without version parameter
659
661
  model_copy = model.duplicate()
662
+
660
663
  assert model_copy.id is None
661
664
  assert model_copy.version == model.version
662
665
 
666
+ with pytest.raises(AssertionError):
667
+ # since id is None
668
+ _ = model_copy._event_publisher
669
+
663
670
  # With version parameter
664
671
  new_version = 'v2'
665
672
  model_copy = model.duplicate(version=new_version)
666
673
  assert model_copy.id is None
667
674
  assert model_copy.version == new_version
675
+
676
+ # Update new version
677
+ assert model.schema['CreditScore'].max == 850
678
+ model_copy.schema['CreditScore'].max = 900
679
+ assert model.schema['CreditScore'].max == 850
680
+ assert model_copy.schema['CreditScore'].max == 900
@@ -3,9 +3,12 @@ from http import HTTPStatus
3
3
  import pytest
4
4
  import responses
5
5
 
6
+ from fiddler.entities.job import Job
6
7
  from fiddler.entities.model_deployment import ModelDeployment
7
8
  from fiddler.exceptions import NotFound
8
9
  from fiddler.tests.constants import (
10
+ JOB_ID,
11
+ JOB_NAME,
9
12
  MODEL_DEPLOYMENT_ID,
10
13
  MODEL_ID,
11
14
  MODEL_NAME,
@@ -50,6 +53,7 @@ API_RESPONSE_200 = {
50
53
  'full_name': USER_NAME,
51
54
  'email': USER_EMAIL,
52
55
  },
56
+ 'job': {'id': JOB_ID, 'name': 'Deploy artifact model - manual'},
53
57
  },
54
58
  }
55
59
 
@@ -67,6 +71,31 @@ API_RESPONSE_404 = {
67
71
  }
68
72
  }
69
73
 
74
+ JOB_API_RESPONSE_200 = {
75
+ 'api_version': '3.0',
76
+ 'kind': 'NORMAL',
77
+ 'data': {
78
+ 'name': JOB_NAME,
79
+ 'info': {
80
+ 'resource_type': 'MODEL',
81
+ 'resource_name': 'bank_churn',
82
+ 'project_name': 'bank_churn',
83
+ },
84
+ 'id': JOB_ID,
85
+ 'status': 'SUCCESS',
86
+ 'progress': 100,
87
+ 'error_message': None,
88
+ 'error_reason': None,
89
+ 'extras': {
90
+ 'e36d1cf2-766f-4705-8269-b6f93bf1ca14': {
91
+ 'status': 'SUCCESS',
92
+ 'result': {'result': 'Success'},
93
+ 'error_message': None,
94
+ }
95
+ },
96
+ },
97
+ }
98
+
70
99
 
71
100
  @responses.activate
72
101
  def test_update_model_deployment_success() -> None:
@@ -79,8 +108,13 @@ def test_update_model_deployment_success() -> None:
79
108
  model_deployment.cpu = 300
80
109
  model_deployment.active = True
81
110
 
82
- model_deployment.update()
111
+ responses.get(
112
+ url=f'{URL}/v3/jobs/{JOB_ID}',
113
+ json=JOB_API_RESPONSE_200,
114
+ )
115
+ job = model_deployment.update()
83
116
  assert isinstance(model_deployment, ModelDeployment)
117
+ assert isinstance(job, Job)
84
118
  assert model_deployment.cpu == 300
85
119
  assert model_deployment.active
86
120
 
@@ -48,6 +48,29 @@ API_RESPONSE_404 = {
48
48
  'kind': 'ERROR',
49
49
  }
50
50
 
51
+ API_RESPONSE_FROM_NAME = {
52
+ 'data': {
53
+ 'page_size': 100,
54
+ 'total': 1,
55
+ 'item_count': 1,
56
+ 'page_count': 1,
57
+ 'page_index': 1,
58
+ 'offset': 0,
59
+ 'items': [
60
+ {
61
+ 'id': 1,
62
+ 'uuid': WEBHOOK_ID,
63
+ 'name': WEBHOOK_NAME,
64
+ 'url': WEBHOOK_URL,
65
+ 'provider': WEBHOOK_PROVIDER,
66
+ 'created_at': '2024-04-30T13:38:08.408013+00:00',
67
+ 'updated_at': '2024-04-30T13:38:08.408013+00:00',
68
+ 'organization_name': ORG_NAME,
69
+ }
70
+ ],
71
+ }
72
+ }
73
+
51
74
  LIST_API_RESPONSE = {
52
75
  'data': {
53
76
  'page_size': 100,
@@ -124,6 +147,40 @@ def test_get_webhook_not_found() -> None:
124
147
  Webhook.get(id_=webhook_id)
125
148
 
126
149
 
150
+ @responses.activate
151
+ def test_webhook_from_name_success() -> None:
152
+ params = {
153
+ 'filter': '{"condition": "AND", "rules": [{"field": "name", "operator": "equal", "value": "test_webhook_config_name"}]}'
154
+ }
155
+ responses.get(
156
+ url=f'{URL}/v2/webhooks',
157
+ json=API_RESPONSE_FROM_NAME,
158
+ match=[responses.matchers.query_param_matcher(params)],
159
+ )
160
+ webhook = Webhook.from_name(name=WEBHOOK_NAME)
161
+ assert isinstance(webhook, Webhook)
162
+
163
+
164
+ @responses.activate
165
+ def test_webhook_from_name_not_found() -> None:
166
+ resp = API_RESPONSE_FROM_NAME.copy()
167
+ resp['data']['total'] = 0
168
+ resp['data']['item_count'] = 0
169
+ resp['data']['items'] = []
170
+
171
+ params = {
172
+ 'filter': '{"condition": "AND", "rules": [{"field": "name", "operator": "equal", "value": "test_webhook_config_name"}]}'
173
+ }
174
+ responses.get(
175
+ url=f'{URL}/v2/webhooks',
176
+ json=resp,
177
+ match=[responses.matchers.query_param_matcher(params)],
178
+ )
179
+
180
+ with pytest.raises(NotFound):
181
+ Webhook.from_name(name=WEBHOOK_NAME)
182
+
183
+
127
184
  @responses.activate
128
185
  def test_webhook_list_success() -> None:
129
186
  responses.get(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 3.1.0.dev2
3
+ Version: 3.1.0.dev4
4
4
  Summary: Python client for Fiddler Platform
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -20,6 +20,7 @@ Requires-Dist: tqdm
20
20
  Requires-Dist: simplejson >=3.17.0
21
21
  Requires-Dist: pyarrow >=7.0.0
22
22
  Requires-Dist: pyyaml
23
+ Requires-Dist: typing-extensions <=4.5.0
23
24
 
24
25
  Fiddler Client
25
26
  =============
@@ -1,5 +1,5 @@
1
- fiddler/VERSION,sha256=WD4o9JNY0sUSbj2lyaWkw1u_ZLCHeKFmWEpL-GcrgSI,11
2
- fiddler/__init__.py,sha256=U9g19CmjOoli4bMAcD_LD-qTmFFBG3uCCIFm34vcTac,3757
1
+ fiddler/VERSION,sha256=H4NIgZvgBtvg0Z66xzllqEkQ_AMRCrUw2l3eCzDowk0,11
2
+ fiddler/__init__.py,sha256=BfKccyHmcEVThtxSPYLBqn5pOtE0EJ9f_y1_bf3suHg,3824
3
3
  fiddler/configs.py,sha256=ZimSo0Gk7j1BFkjDHdRdycrGZ8oh-7G5TBXYiOh1HvU,217
4
4
  fiddler/connection.py,sha256=fLdSXpu5dwoK-h4Vtc9nbdKENOJ7jfEmrnDhVAtChck,5677
5
5
  fiddler/decorators.py,sha256=tWZliQQeUGwY0rU52FO9JXuOBueQXVEJywEbrgUEw1U,1820
@@ -17,22 +17,22 @@ fiddler/constants/model_deployment.py,sha256=SfagLKVD7tK1QmYQFJLDrA4-6FaSeNF6tik
17
17
  fiddler/constants/xai.py,sha256=GR8VguB6FTfMJZ291FIbfDsY4S9BGOft3VxNW5jMf90,214
18
18
  fiddler/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  fiddler/entities/alert_record.py,sha256=RcDACWDNpntkiId-JpkLQvVeIbuaZAzn6AWl2zYIh9A,3564
20
- fiddler/entities/alert_rule.py,sha256=kLrK1U96gzN8I5G-hTTMmrIA0TywHVt-kb7CipgqjqE,11569
20
+ fiddler/entities/alert_rule.py,sha256=JQknBnSNnjIL4CeYvCBy5TVNN7LVE4-7BtBFpaQ9tJ0,11744
21
21
  fiddler/entities/base.py,sha256=YCTLt1ta8UbD7u-5BW7v_ocA4S7LevEncI5XPS_SB60,2106
22
22
  fiddler/entities/baseline.py,sha256=k3D-K8WC5MkHDILyejRaH1v9jdCIymT96McDBOVQ9A0,7907
23
23
  fiddler/entities/custom_expression.py,sha256=SdS61JiI0gOxWwHAGxkHh1vqS5XsRtyeNSDs5E-Sg2U,6568
24
24
  fiddler/entities/dataset.py,sha256=kwD1pZMG6DQGIjejU7A2KUUBRgOi0o1qbbUX-PSlnGg,4399
25
- fiddler/entities/events.py,sha256=SGA4GFmEzS9U7osodTNslfyoXhJe0j_GgyGmgkCXluk,4291
25
+ fiddler/entities/events.py,sha256=_orqFyg0m5tBREa21f36ZaX_4kKEtpA2Hsff0d__Uw0,5383
26
26
  fiddler/entities/file.py,sha256=dk8ISfjy0--F2eF23Ae8vGiEZmJW6e9LMqNmKfrY2mE,4710
27
27
  fiddler/entities/job.py,sha256=Feiqo6ns4bRcp2uaV-kuGYAKs90-aYXvzqqi1yLivYE,5220
28
- fiddler/entities/model.py,sha256=NS_pTF2XyfsSVPbcttf3E1b1-BCwbGlvm5GOJNu_Oxw,18613
28
+ fiddler/entities/model.py,sha256=giqLWvnqXsqrekJ3sIeHf3vUUYO43PxrGh6I_KsGfH4,19271
29
29
  fiddler/entities/model_artifact.py,sha256=Y7o1mFs-nVDz7HI9mVBu9ICwkqGD_QbT3q6vf8KKesk,5520
30
- fiddler/entities/model_deployment.py,sha256=mxEsMYiUO-m9X1ND7UuJ1b3LgEcyvOM5PMEmRvOuftk,3769
30
+ fiddler/entities/model_deployment.py,sha256=pzS6xPg4zuhrIzMbF44ptK_ZwV8yN6URF0hDwyVhnwY,3966
31
31
  fiddler/entities/organization.py,sha256=XvUAdBUOYXzdmblxIs4hi0mAg45NtAwy5DBaMiqi47o,1074
32
32
  fiddler/entities/project.py,sha256=G5omjjKHEjvhenMvW-R0bYwrkRVHixIOhTPZb1pS7FI,4631
33
33
  fiddler/entities/surrogate.py,sha256=94RkJmv8uwNhRL8PaliuiRv-R0EXDMKJTimE9boXKwQ,3077
34
34
  fiddler/entities/user.py,sha256=ev_Xx9QHAdEHYzNDafzQihXOcD8ME5XkpKgc8MiqCnw,1243
35
- fiddler/entities/webhook.py,sha256=I-mcl92Tg2-oUUqNMOeDPBe0XawVYhNcTGXHBway7_A,3798
35
+ fiddler/entities/webhook.py,sha256=BhwV-05EaFtOATbnlPWUaGeziRSewBPSNSGsYFbIRfc,4514
36
36
  fiddler/entities/xai.py,sha256=tJ5HQnaV_svR7do1secIIIvQ0ckJMnW0xjoThn8Cz6s,20250
37
37
  fiddler/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  fiddler/libs/http_client.py,sha256=bl2V-q66NoPHm950CiDqOoF-kCPztYWUYNy9hVUsbqg,6027
@@ -42,13 +42,13 @@ fiddler/packtools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
42
42
  fiddler/packtools/gem.py,sha256=jzODf1sbAbAXMU74nrU9x7T5eqU4kiExzrT2Hd__olo,4637
43
43
  fiddler/packtools/keras_ig_helpers.py,sha256=ht_ILtpkOxCl2B5Q-KFnKV0k_oB-HkMbRJm3h3pjb5Y,7941
44
44
  fiddler/packtools/project_attributions_helpers.py,sha256=K-xpsKfwRS5GOMYwTmXY-J3t7gtGbdVSpKB38cpe-fY,15799
45
- fiddler/packtools/template_model.py,sha256=x_ECfGak3uGrxHIf-FvsXqDkYFjrpa6T28qe2pwppdk,10467
45
+ fiddler/packtools/template_model.py,sha256=slQjl5eEjhDUtvWeIF_WvSUerX7VjW0822uo4Qkx-gg,10484
46
46
  fiddler/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  fiddler/schemas/alert_record.py,sha256=Edfe264zUwqF856tMblN85CsEa_wn9oZCoLruvsNAbo,668
48
- fiddler/schemas/alert_rule.py,sha256=-V0AibEImrfcEZfJ4J_Ed5SuZISOGsk-nIoVlX5mOOg,1222
48
+ fiddler/schemas/alert_rule.py,sha256=XbNZDBd5adLVvmyTydnG7lkdZ-ieI8maWACwBX-FQD0,1387
49
49
  fiddler/schemas/base.py,sha256=upzAmneEz169h_w-UDH_tY0Abo7DeK68YOZ5qVwIMa8,189
50
50
  fiddler/schemas/baseline.py,sha256=tBQji1GLYt0ZYgEK6ZTmXxk5nUYTI6oxMmSjNXnRfWw,933
51
- fiddler/schemas/custom_expression.py,sha256=6Y4Q89HIOjUwVS9u9-wMAXvcPMmtQ7puLEkx27Gr-wY,844
51
+ fiddler/schemas/custom_expression.py,sha256=LGHht3LB0HGghEfy808VnaF3nIQVGZjhf__f1CcLRoU,953
52
52
  fiddler/schemas/custom_features.py,sha256=U33Rlyt9TxNqEQ2_3aQTgvlIuI2_QPg-6YnQBzJuyoE,5531
53
53
  fiddler/schemas/dataset.py,sha256=rGmpMrMfPLSs9d3_sxDTjrKqWp-o-bCe9pf_nlYyHfw,657
54
54
  fiddler/schemas/events.py,sha256=dH6SGPBO_rgGZetIhSo4Fq0L1pTU7TEKR7zW7gg3fnI,409
@@ -78,7 +78,7 @@ fiddler/tests/test_utils.py,sha256=AF6y7UfboEkCa-nNw0aF30SdHC7yW2Hh78J4H_4s78k,3
78
78
  fiddler/tests/utils.py,sha256=FEDbASW4pYZktdEK2FLnIDyZCwBzpb60m6EzkvOkwSc,335
79
79
  fiddler/tests/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  fiddler/tests/apis/test_alert_record.py,sha256=_0EBRDn87TqTiO1KYEHKQQVtVZjj4lYjbt8Ix-RRTSg,3118
81
- fiddler/tests/apis/test_alert_rule.py,sha256=3fmcxiGXOokMqFRWo5w4CL4m0k6rCnG17ZRfj1wlZ04,11231
81
+ fiddler/tests/apis/test_alert_rule.py,sha256=ax4-ravAzwbYbKay_Z8mksamTBaxlwZydFCD3EhLmfc,13196
82
82
  fiddler/tests/apis/test_baseline.py,sha256=R_vvbZdSenpYMSydurENJrE_uNWE3sJR9sHJksfU_Jk,7494
83
83
  fiddler/tests/apis/test_custom_metric.py,sha256=QlNa80M9PxqaqzW-3nCtH5kKLRHYu2iqFDautBusbos,8208
84
84
  fiddler/tests/apis/test_dataset.py,sha256=1Xc9Ng91fLMc2C6dpKfse42fQ0anza3ZOKOD1TqCvTQ,4636
@@ -87,13 +87,13 @@ fiddler/tests/apis/test_files.py,sha256=-BisPck7bHMSW3N40ffdQJe027Qe3079tjTlU2OI
87
87
  fiddler/tests/apis/test_generate_model.py,sha256=J8foDsZIUoHJyzLODQM57jw8OFVD81jc67RIubq-CVs,5089
88
88
  fiddler/tests/apis/test_job.py,sha256=GlJXhxK60q9u5QJ6ToLrw4y1G3M0DzAAR2u-JDbk3D0,1891
89
89
  fiddler/tests/apis/test_mixin.py,sha256=RhA2pY1MXrqxNQG8ujVLvTMBT4iZBwa6Y3Nk0TRfI1o,2517
90
- fiddler/tests/apis/test_model.py,sha256=AL4BdP8vZjRLkh0XESFKjLzg5gVG-vxhnyE6adku6tA,18346
90
+ fiddler/tests/apis/test_model.py,sha256=fpE8bytrlZPUjlwXDSl2NBU9NN_bl9dkmImHXSv0pmc,18779
91
91
  fiddler/tests/apis/test_model_artifact.py,sha256=oQVasstDc41EesAzN39wCTZi7KtpeQdVcGcLxERjmw0,5635
92
- fiddler/tests/apis/test_model_deployment.py,sha256=AWGdbepFrU3qT17XAZC68n8LlXh7OKNqSwg3_ug9G5I,2441
92
+ fiddler/tests/apis/test_model_deployment.py,sha256=GBHJ3-aMFn5JBZq6COZHhCYmqdkrrRlBESP4TJWyJng,3350
93
93
  fiddler/tests/apis/test_model_surrogate.py,sha256=h3OPgD1-_n6gTd0YH_hDcBBRjBfXv1xUsZxNWUU69KQ,4443
94
94
  fiddler/tests/apis/test_project.py,sha256=IEYT3imD4dZJg-OT888G4jQJ_AxxHN5_VkCHcmwUnGA,6015
95
95
  fiddler/tests/apis/test_segment.py,sha256=hQiXpZEKLJrnlRBLLMsP3jph8H8K7AEUw17sMK6BuF8,7804
96
- fiddler/tests/apis/test_webhook.py,sha256=DTaEI9r2lossAaXb3b1CX4C8L3bYAzZmLIWH8VeauUs,6440
96
+ fiddler/tests/apis/test_webhook.py,sha256=Tf6bggAFeUA0a9TKTjJ34dM_UM_l6_Q-5N9utyuieeE,8099
97
97
  fiddler/tests/apis/test_xai.py,sha256=mV-bcu6Tkw_wM4nCc9Uf6OXU38Hz0gX3eiVMCLGAsbQ,28590
98
98
  fiddler/utils/__init__.py,sha256=ooAJR6_tVaF6UKZriz5ynZPj8IeCzaDIPKV23F-e4Fk,53
99
99
  fiddler/utils/helpers.py,sha256=Xl_T_se9SOeMTmVJAOVzzmkekUsmpFMlAb2KvPCWfTw,2908
@@ -101,8 +101,8 @@ fiddler/utils/logger.py,sha256=FdJ3LkS9dbRjWsw5oJmNNsd7q0XRVEIvx5-TWys7L0k,669
101
101
  fiddler/utils/model_generator.py,sha256=TwQMQDpy-0gcq6HyL68s37N-sk_nGPq33mmppK6i7hI,2203
102
102
  fiddler/utils/validations.py,sha256=i8NtgrpCsitq6BPa5lygpKDh07oaOXu7PAlCIcMvqzY,408
103
103
  fiddler/utils/version.py,sha256=iC8Ry7UFl9EJW_xU1WbzO_l4yK6V7eQ6U5exB3xT864,531
104
- fiddler_client-3.1.0.dev2.dist-info/LICENSE.txt,sha256=w8-LUAb_VLBWSsCNmih0pAqLIicJfGu8OJXpDjkIg_o,559
105
- fiddler_client-3.1.0.dev2.dist-info/METADATA,sha256=5DHmXRtXAVN1tadTh3bHPQf0s4l00jTzcJjaEHZlBDA,1556
106
- fiddler_client-3.1.0.dev2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
107
- fiddler_client-3.1.0.dev2.dist-info/top_level.txt,sha256=ndC6LqvKmrTTs8czRlBOYdYgSqZbHuMf0zHt_HWpzzk,8
108
- fiddler_client-3.1.0.dev2.dist-info/RECORD,,
104
+ fiddler_client-3.1.0.dev4.dist-info/LICENSE.txt,sha256=w8-LUAb_VLBWSsCNmih0pAqLIicJfGu8OJXpDjkIg_o,559
105
+ fiddler_client-3.1.0.dev4.dist-info/METADATA,sha256=QHGMbBeeNbvV5D8mnAz0pedtQn2LgfNUY9ZaHER-spQ,1597
106
+ fiddler_client-3.1.0.dev4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
107
+ fiddler_client-3.1.0.dev4.dist-info/top_level.txt,sha256=ndC6LqvKmrTTs8czRlBOYdYgSqZbHuMf0zHt_HWpzzk,8
108
+ fiddler_client-3.1.0.dev4.dist-info/RECORD,,