fiddler-client 2.4.0.dev2__py3-none-any.whl → 2.5.0.dev2__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.
Files changed (61) hide show
  1. fiddler/__init__.py +2 -0
  2. fiddler/_version.py +1 -1
  3. fiddler/api/alert_mixin.py +51 -1
  4. fiddler/api/webhooks_mixin.py +6 -8
  5. fiddler/core_objects.py +76 -26
  6. fiddler/schema/alert.py +9 -2
  7. fiddler/schemas/custom_features.py +44 -1
  8. fiddler3/__init__.py +121 -38
  9. fiddler3/configs.py +3 -0
  10. fiddler3/connection.py +68 -1
  11. fiddler3/constants/alert_rule.py +30 -0
  12. fiddler3/constants/events.py +7 -0
  13. fiddler3/constants/model.py +9 -0
  14. fiddler3/entities/__init__.py +0 -7
  15. fiddler3/entities/alert_record.py +106 -0
  16. fiddler3/entities/alert_rule.py +323 -0
  17. fiddler3/entities/base.py +2 -16
  18. fiddler3/entities/baseline.py +21 -15
  19. fiddler3/entities/dataset.py +1 -1
  20. fiddler3/entities/events.py +136 -0
  21. fiddler3/entities/file.py +162 -0
  22. fiddler3/entities/model.py +141 -24
  23. fiddler3/entities/model_artifact.py +52 -224
  24. fiddler3/entities/model_deployment.py +12 -1
  25. fiddler3/entities/project.py +2 -2
  26. fiddler3/entities/{model_surrogate.py → surrogate.py} +27 -29
  27. fiddler3/entities/webhook.py +128 -0
  28. fiddler3/entities/xai.py +271 -5
  29. fiddler3/libs/http_client.py +1 -1
  30. fiddler3/libs/json_encoder.py +1 -1
  31. fiddler3/schemas/__init__.py +0 -9
  32. fiddler3/schemas/alert_record.py +27 -0
  33. fiddler3/schemas/alert_rule.py +39 -0
  34. fiddler3/schemas/custom_features.py +68 -12
  35. fiddler3/schemas/events.py +15 -0
  36. fiddler3/schemas/file.py +23 -0
  37. fiddler3/schemas/model.py +1 -6
  38. fiddler3/schemas/model_deployment.py +5 -4
  39. fiddler3/schemas/webhook.py +23 -0
  40. fiddler3/tests/apis/test_alert_record.py +99 -0
  41. fiddler3/tests/apis/test_alert_rule.py +393 -0
  42. fiddler3/tests/apis/test_events.py +169 -0
  43. fiddler3/tests/apis/test_files.py +164 -0
  44. fiddler3/tests/apis/test_model.py +60 -9
  45. fiddler3/tests/apis/test_model_artifact.py +21 -0
  46. fiddler3/tests/apis/test_project.py +3 -3
  47. fiddler3/tests/apis/test_webhook.py +257 -0
  48. fiddler3/tests/apis/test_xai.py +233 -1
  49. fiddler3/tests/conftest.py +2 -2
  50. fiddler3/tests/constants.py +5 -0
  51. fiddler3/tests/test_connection.py +24 -1
  52. fiddler3/tests/test_json_encoder.py +2 -2
  53. fiddler3/utils/helpers.py +20 -0
  54. {fiddler_client-2.4.0.dev2.dist-info → fiddler_client-2.5.0.dev2.dist-info}/METADATA +15 -5
  55. {fiddler_client-2.4.0.dev2.dist-info → fiddler_client-2.5.0.dev2.dist-info}/RECORD +59 -44
  56. tests/fiddler/test_alert.py +95 -5
  57. fiddler3/entities/helpers.py +0 -21
  58. fiddler3/schemas/model_artifact.py +0 -6
  59. {fiddler_client-2.4.0.dev2.dist-info → fiddler_client-2.5.0.dev2.dist-info}/LICENSE.txt +0 -0
  60. {fiddler_client-2.4.0.dev2.dist-info → fiddler_client-2.5.0.dev2.dist-info}/WHEEL +0 -0
  61. {fiddler_client-2.4.0.dev2.dist-info → fiddler_client-2.5.0.dev2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,30 @@
1
+ import enum
2
+
3
+
4
+ @enum.unique
5
+ class BinSize(str, enum.Enum):
6
+ HOUR = 'Hour'
7
+ DAY = 'Day'
8
+ WEEK = 'Week'
9
+ MONTH = 'Month'
10
+
11
+
12
+ @enum.unique
13
+ class CompareTo(str, enum.Enum):
14
+ """Comparison with Absolute(raw_value) or Relative(time_period)"""
15
+
16
+ TIME_PERIOD = 'time_period'
17
+ RAW_VALUE = 'raw_value'
18
+
19
+
20
+ @enum.unique
21
+ class AlertCondition(str, enum.Enum):
22
+ GREATER = 'greater'
23
+ LESSER = 'lesser'
24
+
25
+
26
+ @enum.unique
27
+ class Priority(str, enum.Enum):
28
+ HIGH = 'HIGH'
29
+ MEDIUM = 'MEDIUM'
30
+ LOW = 'LOW'
@@ -0,0 +1,7 @@
1
+ import enum
2
+
3
+
4
+ @enum.unique
5
+ class PublishEventsSourceType(str, enum.Enum):
6
+ EVENTS = 'EVENTS'
7
+ FILE = 'FILE'
@@ -62,3 +62,12 @@ class ArtifactStatus(str, enum.Enum):
62
62
  NO_MODEL = 'no_model'
63
63
  SURROGATE = 'surrogate'
64
64
  USER_UPLOADED = 'user_uploaded'
65
+
66
+
67
+ @enum.unique
68
+ class CustomFeatureType(str, enum.Enum):
69
+ FROM_COLUMNS = 'FROM_COLUMNS'
70
+ FROM_VECTOR = 'FROM_VECTOR'
71
+ FROM_TEXT_EMBEDDING = 'FROM_TEXT_EMBEDDING'
72
+ FROM_IMAGE_EMBEDDING = 'FROM_IMAGE_EMBEDDING'
73
+ ENRICHMENT = 'ENRICHMENT'
@@ -1,7 +0,0 @@
1
- """Initialize all new entities."""
2
- from fiddler3.entities.baseline import Baseline # noqa
3
- from fiddler3.entities.dataset import Dataset # noqa
4
- from fiddler3.entities.job import Job # noqa
5
- from fiddler3.entities.model import Model # noqa
6
- from fiddler3.entities.model_deployment import ModelDeployment # noqa
7
- from fiddler3.entities.project import Project # noqa
@@ -0,0 +1,106 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime, timedelta
4
+ from typing import Any, Iterator
5
+ from uuid import UUID
6
+
7
+ from fiddler3.decorators import handle_api_error
8
+ from fiddler3.entities.base import BaseEntity
9
+ from fiddler3.schemas.alert_record import AlertRecordResp
10
+
11
+
12
+ class AlertRecord(BaseEntity):
13
+ def __init__(self) -> None:
14
+ """Construct a alert record instance"""
15
+
16
+ self.alert_run_start_time: int | None = None
17
+ self.alert_time_bucket: int | None = None
18
+ self.alert_value: float | None = None
19
+ self.baseline_time_bucket: int | None = None
20
+ self.baseline_value: float | None = None
21
+ self.is_alert: bool | None = None
22
+ self.severity: str | None = None
23
+ self.failure_reason: str | None = None
24
+ self.message: str | None = None
25
+ self.feature_name: str | None = None
26
+ self.alert_record_main_version: int | None = None
27
+ self.alert_record_sub_version: int | None = None
28
+
29
+ self.id: UUID | None = None
30
+ self.alert_rule_id: UUID | None = None
31
+ self.created_at: datetime | None = None
32
+ self.updated_at: datetime | None = None
33
+
34
+ # Deserialized response object
35
+ self._resp: AlertRecordResp | None = None
36
+
37
+ @classmethod
38
+ def _from_dict(cls, data: dict) -> AlertRecord:
39
+ """Build alert record object from the given dictionary"""
40
+
41
+ # Deserialize the response
42
+ resp_obj = AlertRecordResp(**data)
43
+
44
+ # Initialize
45
+ instance = cls()
46
+
47
+ # Add remaining fields
48
+ fields = [
49
+ 'id',
50
+ 'alert_rule_id',
51
+ 'alert_run_start_time',
52
+ 'alert_time_bucket',
53
+ 'alert_value',
54
+ 'baseline_time_bucket',
55
+ 'baseline_value',
56
+ 'is_alert',
57
+ 'severity',
58
+ 'failure_reason',
59
+ 'message',
60
+ 'feature_name',
61
+ 'alert_record_main_version',
62
+ 'alert_record_sub_version',
63
+ 'created_at',
64
+ 'updated_at',
65
+ ]
66
+ for field in fields:
67
+ setattr(instance, field, getattr(resp_obj, field, None))
68
+
69
+ instance._resp = resp_obj
70
+
71
+ return instance
72
+
73
+ @staticmethod
74
+ def _get_url(alert_rule_id: UUID | str, id_: UUID | str | None = None) -> str:
75
+ """Get alert record resource/item url"""
76
+ url = f'/v2/alert-configs/{alert_rule_id}/records'
77
+
78
+ return url if not id_ else f'{url}/{id_}'
79
+
80
+ @classmethod
81
+ @handle_api_error
82
+ def list(
83
+ cls,
84
+ alert_rule_id: UUID | str,
85
+ start_time: datetime | None = None,
86
+ end_time: datetime | None = None,
87
+ ordering: list[str] | None = None,
88
+ ) -> Iterator[AlertRecord]:
89
+ """
90
+ List alert records triggered for an alert rule
91
+
92
+ :param alert_rule_id: unique identifier for alert rule
93
+ :param start_time: Start time to filter trigger alerts :default: 7 days ago
94
+ :param end_time: End time to filter trigger alerts :default: time now
95
+
96
+ :return: paginated list of alert records for the given alert rule
97
+ """
98
+ params: dict[str, Any] = {
99
+ 'start_time': start_time or datetime.now() - timedelta(days=7),
100
+ 'end_time': end_time or datetime.now(),
101
+ }
102
+ if ordering:
103
+ params['ordering'] = ordering
104
+
105
+ for record in cls._paginate(url=cls._get_url(alert_rule_id), params=params):
106
+ yield cls._from_dict(data=record)
@@ -0,0 +1,323 @@
1
+ from __future__ import annotations
2
+
3
+ import builtins
4
+ from datetime import datetime
5
+ from typing import Any, Iterator
6
+ from uuid import UUID
7
+
8
+ from fiddler3.constants.alert_rule import AlertCondition, BinSize, CompareTo, Priority
9
+ from fiddler3.decorators import handle_api_error
10
+ from fiddler3.entities.base import BaseEntity
11
+ from fiddler3.entities.baseline import Baseline, BaselineCompactMixin
12
+ from fiddler3.entities.model import Model, ModelCompactMixin
13
+ from fiddler3.entities.project import ProjectCompactMixin
14
+ from fiddler3.schemas.alert_rule import AlertRuleResp, NotificationConfig
15
+ from fiddler3.schemas.filter_query import OperatorType, QueryCondition, QueryRule
16
+ from fiddler3.utils.logger import get_logger
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ class AlertRule(
22
+ BaseEntity, ModelCompactMixin, ProjectCompactMixin, BaselineCompactMixin
23
+ ):
24
+ def __init__( # pylint: disable=too-many-arguments
25
+ self,
26
+ name: str,
27
+ model_id: UUID,
28
+ metric_id: str | UUID,
29
+ priority: Priority | str,
30
+ compare_to: CompareTo | str,
31
+ condition: AlertCondition | str,
32
+ bin_size: BinSize | str,
33
+ critical_threshold: float,
34
+ warning_threshold: float | None = None,
35
+ columns: list[str] | None = None,
36
+ baseline_id: UUID | None = None,
37
+ compare_bin_delta: int | None = None,
38
+ ) -> None:
39
+ """Construct a alert rule instance."""
40
+ self.name = name
41
+ self.model_id = model_id
42
+ self.metric_id = metric_id
43
+ self.columns = columns
44
+ self.baseline_id = baseline_id
45
+ self.priority = priority
46
+ self.compare_to = compare_to
47
+ self.compare_bin_delta = compare_bin_delta
48
+ self.warning_threshold = warning_threshold
49
+ self.critical_threshold = critical_threshold
50
+ self.condition = condition
51
+ self.bin_size = bin_size
52
+
53
+ self.id: UUID | None = None
54
+ self.project_id: UUID | None = None
55
+
56
+ self.created_at: datetime | None = None
57
+ self.updated_at: datetime | None = None
58
+
59
+ # Deserialized response object
60
+ self._resp: AlertRuleResp | None = None
61
+
62
+ @staticmethod
63
+ def _get_url(id_: UUID | str | None = None) -> str:
64
+ """Get model resource/item url."""
65
+ url = '/v2/alert-configs'
66
+ return url if not id_ else f'{url}/{id_}'
67
+
68
+ @classmethod
69
+ def _from_dict(cls, data: dict) -> AlertRule:
70
+ """Build entity object from the given dictionary."""
71
+
72
+ # Deserialize the response
73
+ resp_obj = AlertRuleResp(**data)
74
+
75
+ # Initialize
76
+ instance = cls(
77
+ name=resp_obj.name,
78
+ model_id=resp_obj.model.id,
79
+ metric_id=resp_obj.metric_id,
80
+ priority=resp_obj.priority,
81
+ compare_to=resp_obj.compare_to,
82
+ condition=resp_obj.condition,
83
+ bin_size=resp_obj.bin_size,
84
+ critical_threshold=resp_obj.critical_threshold,
85
+ warning_threshold=resp_obj.warning_threshold,
86
+ columns=resp_obj.columns,
87
+ baseline_id=resp_obj.baseline_id,
88
+ compare_bin_delta=resp_obj.compare_bin_delta,
89
+ )
90
+
91
+ # Add remaining fields
92
+ fields = [
93
+ 'id',
94
+ # 'notifications_config',
95
+ 'created_at',
96
+ 'updated_at',
97
+ ]
98
+ for field in fields:
99
+ setattr(instance, field, getattr(resp_obj, field, None))
100
+
101
+ instance.project_id = resp_obj.project.id
102
+ instance._resp = resp_obj
103
+
104
+ return instance
105
+
106
+ def _refresh(self, data: dict) -> None:
107
+ """Refresh the fields of this instance from the given response dictionary"""
108
+ # Deserialize the response
109
+ resp_obj = AlertRuleResp(**data)
110
+
111
+ # Reset properties
112
+ self.model_id = resp_obj.model.id
113
+ self.project_id = resp_obj.project.id
114
+
115
+ # Add remaining fields
116
+ fields = [
117
+ 'id',
118
+ 'created_at',
119
+ 'updated_at',
120
+ ]
121
+ for field in fields:
122
+ setattr(self, field, getattr(resp_obj, field, None))
123
+
124
+ self._resp = resp_obj
125
+
126
+ @classmethod
127
+ @handle_api_error
128
+ def get(cls, id_: UUID | str) -> AlertRule:
129
+ """
130
+ Get the alert rule instance using alert rule id.
131
+
132
+ :param id_: unique uuid format identifier for alert rule
133
+ :return: alert rule instance
134
+ """
135
+
136
+ response = cls._client().get(url=cls._get_url(id_=id_))
137
+ return cls._from_response(response=response)
138
+
139
+ @classmethod
140
+ @handle_api_error
141
+ def list( # pylint: disable=too-many-arguments
142
+ cls,
143
+ model_id: UUID | None = None,
144
+ project_id: UUID | None = None,
145
+ metric_id: UUID | str | None = None,
146
+ columns: list[str] | None = None,
147
+ baseline_id: UUID | None = None,
148
+ ordering: list[str] | None = None,
149
+ ) -> Iterator[AlertRule]:
150
+ """Get a list of all alert rules in the organization."""
151
+ rules: list[QueryRule | QueryCondition] = []
152
+
153
+ if model_id:
154
+ rules.append(
155
+ QueryRule(field='model_id', operator=OperatorType.EQUAL, value=model_id)
156
+ )
157
+ if project_id:
158
+ rules.append(
159
+ QueryRule(
160
+ field='project_id', operator=OperatorType.EQUAL, value=project_id
161
+ )
162
+ )
163
+ if baseline_id:
164
+ rules.append(
165
+ QueryRule(
166
+ field='baseline_id', operator=OperatorType.EQUAL, value=baseline_id
167
+ )
168
+ )
169
+ if metric_id:
170
+ rules.append(
171
+ QueryRule(
172
+ field='metric_id', operator=OperatorType.EQUAL, value=metric_id
173
+ )
174
+ )
175
+ if columns:
176
+ for column in columns:
177
+ rules.append(
178
+ QueryRule(field='columns', operator=OperatorType.ANY, value=column)
179
+ )
180
+
181
+ _filter = QueryCondition(rules=rules)
182
+ params: dict[str, Any] = {'filter': _filter.json()}
183
+
184
+ if ordering:
185
+ params['ordering'] = ','.join(ordering)
186
+
187
+ params['organization_name'] = cls.get_organization_name()
188
+ for rule in cls._paginate(url=cls._get_url(), params=params):
189
+ yield cls._from_dict(data=rule)
190
+
191
+ @handle_api_error
192
+ def delete(self) -> None:
193
+ """Delete an alert rule."""
194
+ assert self.id is not None
195
+
196
+ self._client().delete(url=self._get_url(id_=self.id))
197
+
198
+ @handle_api_error
199
+ def create(self) -> AlertRule:
200
+ """Create a new alert rule."""
201
+ model = Model.get(self.model_id)
202
+ payload: dict[str, Any] = {
203
+ 'name': self.name,
204
+ 'organization_name': self.organization_name,
205
+ 'model_name': model.name,
206
+ 'project_name': model.project.name,
207
+ 'metric_id': self.metric_id,
208
+ 'priority': self.priority,
209
+ 'compare_to': self.compare_to,
210
+ 'condition': self.condition,
211
+ 'bin_size': self.bin_size,
212
+ 'critical_threshold': self.critical_threshold,
213
+ 'warning_threshold': self.warning_threshold,
214
+ 'feature_names': self.columns,
215
+ 'compare_bin_delta': self.compare_bin_delta,
216
+ }
217
+ if self.baseline_id:
218
+ baseline = Baseline.get(self.baseline_id)
219
+ payload['baseline_name'] = baseline.name
220
+
221
+ response = self._client().post(
222
+ url=self._get_url(),
223
+ data=payload,
224
+ )
225
+
226
+ self._refresh_from_response(response=response)
227
+ return self
228
+
229
+ @handle_api_error
230
+ def enable_notifications(self) -> None:
231
+ """Enable notifications for an alert rule"""
232
+ self._client().patch(
233
+ url=self._get_url(id_=self.id), data={'enable_notification': True}
234
+ )
235
+ logger.info(
236
+ 'Notifications have been enabled for alert rule with id: %s', self.id
237
+ )
238
+
239
+ @handle_api_error
240
+ def disable_notifications(self) -> None:
241
+ """Disable notifications for an alert rule"""
242
+ self._client().patch(
243
+ url=self._get_url(id_=self.id), data={'enable_notification': False}
244
+ )
245
+ logger.info(
246
+ 'Notifications have been disabled for alert rule with id: %s', self.id
247
+ )
248
+
249
+ @handle_api_error
250
+ def set_notification_config(
251
+ self,
252
+ emails: builtins.list[str] | None = None,
253
+ pagerduty_services: builtins.list[str] | None = None,
254
+ pagerduty_severity: str | None = None,
255
+ webhooks: builtins.list[UUID] | None = None,
256
+ ) -> NotificationConfig:
257
+ """
258
+ Set notifications for an alert rule
259
+
260
+ :param emails: list of emails
261
+ :param pagerduty_services: list of pagerduty services
262
+ :param pagerduty_severity: severity of pagerduty
263
+ :param webhooks: list of webhooks UUIDs
264
+
265
+ :return: AlertNotifications object
266
+ """
267
+ notifications = {
268
+ 'emails': {
269
+ 'email': ','.join(emails) if emails else '',
270
+ },
271
+ 'pagerduty': {
272
+ 'service': ','.join(pagerduty_services) if pagerduty_services else '',
273
+ 'severity': pagerduty_severity,
274
+ },
275
+ 'webhooks': [{'uuid': webhook_uuid} for webhook_uuid in webhooks]
276
+ if webhooks
277
+ else None,
278
+ }
279
+ response = self._client().patch(
280
+ url=self._get_url(id_=self.id),
281
+ data={'notifications': notifications},
282
+ )
283
+
284
+ return self._get_notifications_from_dict(
285
+ response.json()['data']['notifications']
286
+ )
287
+
288
+ @handle_api_error
289
+ def get_notification_config(self) -> NotificationConfig:
290
+ """
291
+ Get notifications setting for an alert rule
292
+
293
+ :return: AlertNotifications object
294
+ """
295
+
296
+ response = self._client().get(url=self._get_url(id_=self.id))
297
+
298
+ return self._get_notifications_from_dict(
299
+ response.json()['data']['notifications']
300
+ )
301
+
302
+ @staticmethod
303
+ def _get_notifications_from_dict(notif_dict: dict) -> NotificationConfig:
304
+ emails = notif_dict.get('emails', {}).get('email')
305
+ notifications: dict = {}
306
+ if emails:
307
+ notifications['emails'] = [email.strip() for email in emails.split(',')]
308
+
309
+ pd_services = notif_dict.get('pagerduty', {}).get('service')
310
+ if pd_services:
311
+ notifications['pagerduty_services'] = [
312
+ pd_service.strip() for pd_service in pd_services.split(',')
313
+ ]
314
+ notifications['pagerduty_severity'] = notif_dict.get('pagerduty', {}).get(
315
+ 'severity'
316
+ )
317
+
318
+ if notif_dict.get('webhooks'):
319
+ notifications['webhooks'] = [
320
+ webhook['uuid'] for webhook in notif_dict.get('webhooks', [])
321
+ ]
322
+
323
+ return NotificationConfig(**notifications)
fiddler3/entities/base.py CHANGED
@@ -6,8 +6,7 @@ from typing import Iterator, TypeVar
6
6
  from requests import Response
7
7
 
8
8
  from fiddler3.configs import DEFAULT_PAGE_SIZE
9
- from fiddler3.connection import Connection
10
- from fiddler3.libs.http_client import RequestClient
9
+ from fiddler3.connection import ConnectionMixin
11
10
  from fiddler3.schemas.response import PaginatedApiResponse
12
11
 
13
12
  BaseEntityType = TypeVar( # pylint: disable=invalid-name
@@ -15,20 +14,7 @@ BaseEntityType = TypeVar( # pylint: disable=invalid-name
15
14
  )
16
15
 
17
16
 
18
- class BaseEntity(ABC):
19
- @classmethod
20
- def _connection(cls) -> Connection:
21
- """Fiddler connection instance"""
22
- from fiddler3 import connection # pylint: disable=import-outside-toplevel
23
-
24
- assert connection is not None
25
- return connection
26
-
27
- @classmethod
28
- def _client(cls) -> RequestClient:
29
- """Request client instance"""
30
- return cls._connection().client
31
-
17
+ class BaseEntity(ABC, ConnectionMixin):
32
18
  @classmethod
33
19
  def _from_response(cls: type[BaseEntityType], response: Response) -> BaseEntityType:
34
20
  """Build entity object from the given response"""
@@ -9,11 +9,11 @@ from fiddler3.constants.dataset import EnvType
9
9
  from fiddler3.decorators import handle_api_error
10
10
  from fiddler3.entities.base import BaseEntity
11
11
  from fiddler3.entities.dataset import DatasetCompactMixin
12
- from fiddler3.entities.helpers import raise_not_found
13
12
  from fiddler3.entities.model import ModelCompactMixin
14
13
  from fiddler3.entities.project import ProjectCompactMixin
15
14
  from fiddler3.schemas.baseline import BaselineResp
16
15
  from fiddler3.schemas.filter_query import OperatorType, QueryCondition, QueryRule
16
+ from fiddler3.utils.helpers import raise_not_found
17
17
 
18
18
 
19
19
  class Baseline(
@@ -138,9 +138,9 @@ class Baseline(
138
138
  """
139
139
  Get the baseline instance using baseline name, model name and project name.
140
140
 
141
- :param name: baseline name
142
- :param model_name: name of the model associated with the baseline
143
- :param project_name: name of the project associated with the baseline
141
+ :param name: Baseline name
142
+ :param model_name: Name of the model associated with the baseline
143
+ :param project_name: Name of the project associated with the baseline
144
144
  :return: Baseline instance for the provided params
145
145
  """
146
146
 
@@ -179,19 +179,25 @@ class Baseline(
179
179
  @handle_api_error
180
180
  def create(self) -> Baseline:
181
181
  """Create a new baseline."""
182
+ payload = {
183
+ 'name': self.name,
184
+ 'model_id': self.model_id,
185
+ 'type': self.type,
186
+ 'env_type': self.environment,
187
+ 'env_id': self.dataset_id,
188
+ }
189
+ if self.start_time:
190
+ payload['start_time'] = self.start_time
191
+ if self.end_time:
192
+ payload['end_time'] = self.end_time
193
+ if self.offset:
194
+ payload['offset'] = self.offset
195
+ if self.window_size:
196
+ payload['window_size'] = self.window_size
197
+
182
198
  response = self._client().post(
183
199
  url=self._get_url(),
184
- data={
185
- 'name': self.name,
186
- 'model_id': self.model_id,
187
- 'type': self.type,
188
- 'env_type': self.environment,
189
- 'start_time': self.start_time,
190
- 'end_time': self.end_time,
191
- 'offset': self.offset,
192
- 'window_size': self.window_size,
193
- 'env_id': self.dataset_id,
194
- },
200
+ data=payload,
195
201
  )
196
202
  self._refresh_from_response(response=response)
197
203
  return self
@@ -7,10 +7,10 @@ from uuid import UUID
7
7
  from fiddler3.constants.dataset import EnvType
8
8
  from fiddler3.decorators import handle_api_error
9
9
  from fiddler3.entities.base import BaseEntity
10
- from fiddler3.entities.helpers import raise_not_found
11
10
  from fiddler3.entities.project import ProjectCompactMixin
12
11
  from fiddler3.schemas.dataset import DatasetResp
13
12
  from fiddler3.schemas.filter_query import OperatorType, QueryCondition, QueryRule
13
+ from fiddler3.utils.helpers import raise_not_found
14
14
 
15
15
 
16
16
  class Dataset(BaseEntity, ProjectCompactMixin):