fiddler-client 3.1.0.dev2__tar.gz → 3.1.0.dev4__tar.gz

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 (116) hide show
  1. {fiddler-client-3.1.0.dev2/fiddler_client.egg-info → fiddler_client-3.1.0.dev4}/PKG-INFO +2 -1
  2. fiddler_client-3.1.0.dev4/fiddler/VERSION +1 -0
  3. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/__init__.py +2 -0
  4. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/alert_rule.py +24 -18
  5. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/events.py +51 -16
  6. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/model.py +23 -10
  7. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/model_deployment.py +5 -1
  8. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/webhook.py +18 -0
  9. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/packtools/template_model.py +3 -2
  10. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/alert_rule.py +19 -10
  11. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/custom_expression.py +7 -0
  12. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_alert_rule.py +141 -90
  13. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_model.py +13 -0
  14. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_model_deployment.py +35 -1
  15. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_webhook.py +57 -0
  16. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4/fiddler_client.egg-info}/PKG-INFO +2 -1
  17. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler_client.egg-info/requires.txt +1 -0
  18. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/setup.py +1 -0
  19. fiddler-client-3.1.0.dev2/fiddler/VERSION +0 -1
  20. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/LICENSE.txt +0 -0
  21. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/MANIFEST.in +0 -0
  22. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/PUBLIC.md +0 -0
  23. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/README.md +0 -0
  24. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/configs.py +0 -0
  25. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/connection.py +0 -0
  26. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/__init__.py +0 -0
  27. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/alert_rule.py +0 -0
  28. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/baseline.py +0 -0
  29. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/common.py +0 -0
  30. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/dataset.py +0 -0
  31. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/events.py +0 -0
  32. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/job.py +0 -0
  33. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/model.py +0 -0
  34. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/model_deployment.py +0 -0
  35. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/constants/xai.py +0 -0
  36. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/decorators.py +0 -0
  37. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/__init__.py +0 -0
  38. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/alert_record.py +0 -0
  39. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/base.py +0 -0
  40. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/baseline.py +0 -0
  41. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/custom_expression.py +0 -0
  42. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/dataset.py +0 -0
  43. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/file.py +0 -0
  44. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/job.py +0 -0
  45. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/model_artifact.py +0 -0
  46. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/organization.py +0 -0
  47. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/project.py +0 -0
  48. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/surrogate.py +0 -0
  49. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/user.py +0 -0
  50. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/entities/xai.py +0 -0
  51. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/exceptions.py +0 -0
  52. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/libs/__init__.py +0 -0
  53. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/libs/http_client.py +0 -0
  54. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/libs/json_encoder.py +0 -0
  55. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/libs/semver.py +0 -0
  56. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/packtools/__init__.py +0 -0
  57. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/packtools/gem.py +0 -0
  58. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/packtools/keras_ig_helpers.py +0 -0
  59. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/packtools/project_attributions_helpers.py +0 -0
  60. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/__init__.py +0 -0
  61. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/alert_record.py +0 -0
  62. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/base.py +0 -0
  63. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/baseline.py +0 -0
  64. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/custom_features.py +0 -0
  65. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/dataset.py +0 -0
  66. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/events.py +0 -0
  67. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/file.py +0 -0
  68. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/filter_query.py +0 -0
  69. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/job.py +0 -0
  70. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/model.py +0 -0
  71. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/model_deployment.py +0 -0
  72. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/model_schema.py +0 -0
  73. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/model_spec.py +0 -0
  74. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/model_task_params.py +0 -0
  75. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/organization.py +0 -0
  76. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/project.py +0 -0
  77. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/response.py +0 -0
  78. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/server_info.py +0 -0
  79. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/user.py +0 -0
  80. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/webhook.py +0 -0
  81. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/xai.py +0 -0
  82. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/schemas/xai_params.py +0 -0
  83. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/__init__.py +0 -0
  84. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/__init__.py +0 -0
  85. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_alert_record.py +0 -0
  86. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_baseline.py +0 -0
  87. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_custom_metric.py +0 -0
  88. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_dataset.py +0 -0
  89. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_events.py +0 -0
  90. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_files.py +0 -0
  91. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_generate_model.py +0 -0
  92. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_job.py +0 -0
  93. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_mixin.py +0 -0
  94. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_model_artifact.py +0 -0
  95. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_model_surrogate.py +0 -0
  96. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_project.py +0 -0
  97. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_segment.py +0 -0
  98. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/apis/test_xai.py +0 -0
  99. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/conftest.py +0 -0
  100. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/constants.py +0 -0
  101. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/test_connection.py +0 -0
  102. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/test_json_encoder.py +0 -0
  103. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/test_logger.py +0 -0
  104. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/test_utils.py +0 -0
  105. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/tests/utils.py +0 -0
  106. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/__init__.py +0 -0
  107. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/helpers.py +0 -0
  108. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/logger.py +0 -0
  109. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/model_generator.py +0 -0
  110. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/validations.py +0 -0
  111. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/utils/version.py +0 -0
  112. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler/version.py +0 -0
  113. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler_client.egg-info/SOURCES.txt +0 -0
  114. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler_client.egg-info/dependency_links.txt +0 -0
  115. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/fiddler_client.egg-info/top_level.txt +0 -0
  116. {fiddler-client-3.1.0.dev2 → fiddler_client-3.1.0.dev4}/setup.cfg +0 -0
@@ -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
  =============
@@ -0,0 +1 @@
1
+ 3.1.0.dev4
@@ -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'])
@@ -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