fiddler-client 2.0.0.dev9__tar.gz → 2.0.0.dev10__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 (106) hide show
  1. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/PKG-INFO +10 -1
  2. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/PUBLIC.md +9 -0
  3. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/__init__.py +7 -4
  4. fiddler-client-2.0.0.dev10/fiddler/_version.py +1 -0
  5. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/alert_mixin.py +34 -12
  6. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/api.py +2 -0
  7. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/events_mixin.py +18 -7
  8. fiddler-client-2.0.0.dev10/fiddler/api/webhooks_mixin.py +121 -0
  9. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/core_objects.py +20 -52
  10. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/alert.py +16 -3
  11. fiddler-client-2.0.0.dev10/fiddler/schema/webhook.py +10 -0
  12. fiddler-client-2.0.0.dev10/fiddler/schemas/custom_features.py +96 -0
  13. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler_client.egg-info/PKG-INFO +10 -1
  14. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler_client.egg-info/SOURCES.txt +3 -0
  15. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_alert.py +335 -9
  16. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_events_api.py +1 -0
  17. fiddler-client-2.0.0.dev10/tests/fiddler/test_webhook.py +124 -0
  18. fiddler-client-2.0.0.dev9/fiddler/_version.py +0 -1
  19. fiddler-client-2.0.0.dev9/fiddler/schemas/custom_features.py +0 -56
  20. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/MANIFEST.in +0 -0
  21. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/README.md +0 -0
  22. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/__init__.py +0 -0
  23. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/baseline_mixin.py +0 -0
  24. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/compatibility_mixin.py +0 -0
  25. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/dataset_mixin.py +0 -0
  26. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/explainability_mixin.py +0 -0
  27. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/generate_schema_mixin.py +0 -0
  28. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/helpers.py +0 -0
  29. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/job_mixin.py +0 -0
  30. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/model_artifact_deploy.py +0 -0
  31. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/model_deployment_mixin.py +0 -0
  32. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/model_mixin.py +0 -0
  33. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/api/project_mixin.py +0 -0
  34. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/assets/__init__.py +0 -0
  35. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/assets/pg_reserved_words.py +0 -0
  36. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/constants.py +0 -0
  37. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/exceptions.py +0 -0
  38. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/libs/__init__.py +0 -0
  39. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/libs/http_client.py +0 -0
  40. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/packtools/__init__.py +0 -0
  41. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/packtools/gem.py +0 -0
  42. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/packtools/keras_ig_helpers.py +0 -0
  43. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/packtools/project_attributions_helpers.py +0 -0
  44. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/packtools/template_model.py +0 -0
  45. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/__init__.py +0 -0
  46. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/base.py +0 -0
  47. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/baseline.py +0 -0
  48. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/dataset.py +0 -0
  49. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/events.py +0 -0
  50. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/job.py +0 -0
  51. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/model.py +0 -0
  52. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/model_deployment.py +0 -0
  53. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/project.py +0 -0
  54. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/server_info.py +0 -0
  55. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schema/user.py +0 -0
  56. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schemas/__init__.py +0 -0
  57. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schemas/model_schema.py +0 -0
  58. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schemas/model_spec.py +0 -0
  59. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schemas/model_task_params.py +0 -0
  60. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/schemas/xai_params.py +0 -0
  61. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/__init__.py +0 -0
  62. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/compatibility_helpers.py +0 -0
  63. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/decorators.py +0 -0
  64. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/exceptions.py +0 -0
  65. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/formatting.py +0 -0
  66. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/general_checks.py +0 -0
  67. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/helpers.py +0 -0
  68. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/logger.py +0 -0
  69. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/pandas_helper.py +0 -0
  70. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/response_handler.py +0 -0
  71. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/semver_version.py +0 -0
  72. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/validations.py +0 -0
  73. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/utils/validator.py +0 -0
  74. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/validators/__init__.py +0 -0
  75. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler/validators/dataset_validator.py +0 -0
  76. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler_client.egg-info/dependency_links.txt +0 -0
  77. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler_client.egg-info/requires.txt +0 -0
  78. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/fiddler_client.egg-info/top_level.txt +0 -0
  79. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/setup.cfg +0 -0
  80. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/setup.py +0 -0
  81. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/__init__.py +0 -0
  82. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/__init__.py +0 -0
  83. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/base.py +0 -0
  84. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/helper.py +0 -0
  85. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_add_model.py +0 -0
  86. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_baseline.py +0 -0
  87. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_check_version_decorator.py +0 -0
  88. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_custom_features.py +0 -0
  89. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_dataset_api.py +0 -0
  90. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_exceptions.py +0 -0
  91. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_explainability_apis.py +0 -0
  92. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_file_upload.py +0 -0
  93. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_generate_schema.py +0 -0
  94. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_helpers.py +0 -0
  95. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_job.py +0 -0
  96. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_model.py +0 -0
  97. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_project.py +0 -0
  98. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_response_handler.py +0 -0
  99. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_upload_dataset.py +0 -0
  100. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/test_validations.py +0 -0
  101. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/utils/__init__.py +0 -0
  102. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/utils/test_general_checks.py +0 -0
  103. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/utils/test_pandas.py +0 -0
  104. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/fiddler/utils/tests_utils.py +0 -0
  105. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/test_object_inference.py +0 -0
  106. {fiddler-client-2.0.0.dev9 → fiddler-client-2.0.0.dev10}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 2.0.0.dev9
3
+ Version: 2.0.0.dev10
4
4
  Summary: Python client for Fiddler Service
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -47,6 +47,15 @@ Description: Fiddler Client
47
47
  - Add `monitor_components` as an attribute of `CustomFeature`. Default to `False`
48
48
  - Remove `column` as a parameter in `add_alert_rule` and `get_alert_rules` functions
49
49
 
50
+ ### 1.8.4
51
+ - #### **New Features**
52
+ - New DeploymentType enum for MANUAL deployment
53
+
54
+ ### 1.8.3
55
+ - ### **Modifications**
56
+ - New `columns` parameter in add_alert_rule and get_alert_rules to support multiple columns to be used for server version >= 23.3.0
57
+ - get_triggered_alerts supports `alert_value` as a float as well as a dict
58
+
50
59
  ### 1.8.2
51
60
  - #### **Modifications**
52
61
  - Fixed a bug where `min` and `max` for columns of type `float` in `dataset_info` are cast into `int` after uploaded
@@ -40,6 +40,15 @@ Version History
40
40
  - Add `monitor_components` as an attribute of `CustomFeature`. Default to `False`
41
41
  - Remove `column` as a parameter in `add_alert_rule` and `get_alert_rules` functions
42
42
 
43
+ ### 1.8.4
44
+ - #### **New Features**
45
+ - New DeploymentType enum for MANUAL deployment
46
+
47
+ ### 1.8.3
48
+ - ### **Modifications**
49
+ - New `columns` parameter in add_alert_rule and get_alert_rules to support multiple columns to be used for server version >= 23.3.0
50
+ - get_triggered_alerts supports `alert_value` as a float as well as a dict
51
+
43
52
  ### 1.8.2
44
53
  - #### **Modifications**
45
54
  - Fixed a bug where `min` and `max` for columns of type `float` in `dataset_info` are cast into `int` after uploaded
@@ -23,7 +23,6 @@ from fiddler.core_objects import (
23
23
  Column,
24
24
  DatasetInfo,
25
25
  DataType,
26
- DeploymentType,
27
26
  ExplanationMethod,
28
27
  FiddlerPublishSchema,
29
28
  FiddlerTimestamp,
@@ -43,9 +42,9 @@ from fiddler.schema.alert import (
43
42
  Metric,
44
43
  Priority,
45
44
  )
46
- from fiddler.schema.model_deployment import DeploymentParams
47
- from fiddler.schemas.custom_features import Multivariate, TextEmbedding, ImageEmbedding
48
- from fiddler.utils import logger, ColorLogger
45
+ from fiddler.schema.model_deployment import DeploymentParams, DeploymentType
46
+ from fiddler.schemas.custom_features import CustomFeature, ImageEmbedding, Multivariate, TextEmbedding, VectorFeature, CustomFeatureType
47
+ from fiddler.utils import ColorLogger, logger
49
48
  from fiddler.utils.validator import (
50
49
  PackageValidator,
51
50
  ValidationChainSettings,
@@ -61,13 +60,17 @@ __all__ = [
61
60
  '__version__',
62
61
  'BatchPublishType',
63
62
  'Column',
63
+ 'CustomFeature',
64
+ 'CustomFeatureType',
64
65
  'Multivariate',
66
+ 'VectorFeature',
65
67
  'TextEmbedding',
66
68
  'ImageEmbedding',
67
69
  'ColorLogger',
68
70
  'DatasetInfo',
69
71
  'DataType',
70
72
  'DeploymentParams',
73
+ 'DeploymentType',
71
74
  'FiddlerClient',
72
75
  'FiddlerApi',
73
76
  'FiddlerTimestamp',
@@ -0,0 +1 @@
1
+ __version__ = '2.0.0.dev10'
@@ -35,7 +35,7 @@ class AlertMixin:
35
35
  FILTER_ALERT_RULES_API_VERSION = '>=23.1.0'
36
36
  GROUP_OF_COLUMNS_API_VERSION = '>=23.3.0'
37
37
  RULE_V3_API_VERSION = '>=23.4.0'
38
-
38
+
39
39
  client: RequestClient
40
40
  organization_name: str
41
41
 
@@ -54,6 +54,7 @@ class AlertMixin:
54
54
  alert_type: Optional[AlertType] = None,
55
55
  baseline_name: Optional[str] = None,
56
56
  compare_period: Optional[ComparePeriod] = None,
57
+ column: Optional[str] = None,
57
58
  columns: Optional[List[str]] = None,
58
59
  warning_threshold: Optional[float] = None,
59
60
  project_name: str = None,
@@ -120,19 +121,13 @@ class AlertMixin:
120
121
  :param condition: Select from:
121
122
  1) AlertCondition.LESSER
122
123
  2) AlertCondition.GREATER
124
+ :param column: column name on which alert rule is to be created. Supported by server version 23.3.0 or lower.
123
125
  :param columns: List of column names on which alert rule is to be created. It can take ['__ANY__'] to check for all columns
124
126
  :param notifications_config: notifications config object created using helper method build_notifications_config()
125
127
  :param baseline_name: Name of the baselne, whose histogram is compared against the same derived from current data.
126
128
  Used only when alert type is AlertType.DATA_DRIFT.
127
129
  :return: created alert rule object
128
- """
129
- if columns and not match_semver(
130
- self.server_info.server_version, self.GROUP_OF_COLUMNS_API_VERSION
131
- ):
132
- raise ValueError(
133
- f'columns parameter works with server version {self.GROUP_OF_COLUMNS_API_VERSION}'
134
- )
135
-
130
+ """
136
131
  project_name = project_id_compat(
137
132
  project_id=project_id, project_name=project_name
138
133
  )
@@ -154,7 +149,7 @@ class AlertMixin:
154
149
  if compare_period and compare_period not in ComparePeriod.keys():
155
150
  raise ValueError(f'compare_period should be one of{ComparePeriod.keys()}')
156
151
 
157
- request_body = AlertRulePayload(
152
+ alert_rule_payload = AlertRulePayload(
158
153
  organization_name=self.organization_name,
159
154
  project_name=project_name,
160
155
  model_name=model_name,
@@ -166,14 +161,41 @@ class AlertMixin:
166
161
  compare_period=compare_period,
167
162
  priority=priority,
168
163
  baseline_name=baseline_name,
169
- feature_names=columns,
170
164
  warning_threshold=warning_threshold,
171
165
  critical_threshold=critical_threshold,
172
166
  condition=condition,
173
167
  time_bucket=bin_size.value[0],
174
168
  bin_size=bin_size.value[1],
175
169
  notifications=notifications_config,
176
- ).dict()
170
+ )
171
+
172
+ if columns and not match_semver(
173
+ self.server_info.server_version, self.GROUP_OF_COLUMNS_API_VERSION
174
+ ):
175
+ raise ValueError(
176
+ f'columns parameter works with server version {self.GROUP_OF_COLUMNS_API_VERSION}'
177
+ )
178
+
179
+ if match_semver(self.server_info.server_version, self.GROUP_OF_COLUMNS_API_VERSION):
180
+ if columns:
181
+ if match_semver(self.server_info.server_version, self.RULE_V3_API_VERSION):
182
+ alert_rule_payload.feature_names=columns
183
+ else:
184
+ # version 23.3 support columns is comma separated string
185
+ alert_rule_payload.feature_names=",".join(columns)
186
+ elif column:
187
+ if match_semver(self.server_info.server_version, self.RULE_V3_API_VERSION):
188
+ alert_rule_payload.feature_names=[column]
189
+ else:
190
+ alert_rule_payload.feature_names=column
191
+ else:
192
+ # we do not support columns in server version < 23.3
193
+ if columns:
194
+ raise ValueError(f'columns is not supported in the server version {self.server_info.server_version}. Please use column instead.')
195
+ if column:
196
+ alert_rule_payload.feature_name=column
197
+
198
+ request_body = alert_rule_payload.dict()
177
199
  response = self.client.post(
178
200
  url='alert-configs',
179
201
  data=request_body,
@@ -15,6 +15,7 @@ from fiddler.api.job_mixin import JobMixin
15
15
  from fiddler.api.model_deployment_mixin import ModelDeploymentMixin
16
16
  from fiddler.api.model_mixin import ModelMixin
17
17
  from fiddler.api.project_mixin import ProjectMixin
18
+ from fiddler.api.webhooks_mixin import WebhookMixin
18
19
  from fiddler.constants import (
19
20
  CURRENT_API_VERSION,
20
21
  FIDDLER_CLIENT_VERSION_HEADER,
@@ -41,6 +42,7 @@ class FiddlerClient(
41
42
  ExplainabilityMixin,
42
43
  ModelDeploymentMixin,
43
44
  GenerateSchemaMixin,
45
+ WebhookMixin
44
46
  ):
45
47
  def __init__(
46
48
  self,
@@ -14,11 +14,12 @@ from fiddler.exceptions import HttpException
14
14
  from fiddler.libs.http_client import RequestClient
15
15
  from fiddler.schema.events import EventIngest, EventsIngest
16
16
  from fiddler.utils.compatibility_helpers import (
17
- project_id_compat,
18
17
  model_id_compat,
18
+ project_id_compat,
19
19
  update_event_compat,
20
20
  )
21
21
  from fiddler.utils.decorators import handle_api_error_response
22
+ from fiddler.utils.helpers import match_semver
22
23
  from fiddler.utils.logger import get_logger
23
24
  from fiddler.utils.response_handler import APIResponseHandler
24
25
 
@@ -235,7 +236,7 @@ class EventsMixin:
235
236
  timestamp_field=timestamp_field,
236
237
  timestamp_format=timestamp_format,
237
238
  group_by=group_by,
238
- file_type=FileType.CSV,
239
+ file_type=file_type,
239
240
  wait=wait,
240
241
  )
241
242
  else:
@@ -368,14 +369,23 @@ class EventsMixin:
368
369
  'The batch provided is empty. Please retry with at least one row of data.'
369
370
  )
370
371
 
371
- file_type = FileType.CSV
372
- with tempfile.NamedTemporaryFile(suffix=file_type) as temp:
373
- events_df.to_csv(temp, index=False)
374
- events_path = Path(temp.name)
372
+ if self.server_info and match_semver(
373
+ self.server_info.server_version, '>=23.4.0'
374
+ ):
375
+ file_type = FileType.PARQUET
376
+ else:
377
+ file_type = FileType.CSV
378
+
379
+ with tempfile.NamedTemporaryFile(suffix=file_type) as temp_file:
380
+ if file_type == FileType.PARQUET:
381
+ events_df.to_parquet(temp_file.name, index=False)
382
+ else:
383
+ events_df.to_csv(temp_file.name, index=False)
384
+
375
385
  return self.publish_events_batch(
376
386
  project_name=project_name,
377
387
  model_name=model_name,
378
- events_path=events_path,
388
+ events_path=Path(temp_file.name),
379
389
  batch_id=batch_id,
380
390
  id_field=id_field,
381
391
  is_update=is_update,
@@ -383,6 +393,7 @@ class EventsMixin:
383
393
  timestamp_format=timestamp_format,
384
394
  group_by=group_by,
385
395
  wait=wait,
396
+ file_type=file_type,
386
397
  )
387
398
 
388
399
  @handle_api_error_response
@@ -0,0 +1,121 @@
1
+ from http import HTTPStatus
2
+ from typing import List, Optional
3
+
4
+ from pydantic import parse_obj_as
5
+
6
+ from fiddler.libs.http_client import RequestClient
7
+ from fiddler.schema.webhook import Webhook
8
+ from fiddler.utils.decorators import handle_api_error_response
9
+ from fiddler.utils.logger import get_logger
10
+ from fiddler.utils.response_handler import (
11
+ APIResponseHandler,
12
+ PaginatedResponseHandler,
13
+ )
14
+
15
+ logger = get_logger(__name__)
16
+
17
+
18
+ class WebhookMixin:
19
+ client: RequestClient
20
+ organization_name: str
21
+
22
+ @handle_api_error_response
23
+ def add_webhook(self, name:str, url:str, provider:str) -> Webhook:
24
+ """
25
+ Add a new `Webhook`.
26
+
27
+ :params name: name of webhook
28
+ :params url: webhook url
29
+ :params provider: Either 'SLACK' or 'OTHER'
30
+
31
+ :returns: Created `Webhook` object.
32
+ """
33
+ request_body = {
34
+ 'name': name,
35
+ 'url': url,
36
+ 'provider': provider,
37
+ }
38
+ response = self.client.post(
39
+ url='webhooks',
40
+ params={'organization_name': self.organization_name},
41
+ data=request_body,
42
+ )
43
+ if response.status_code == HTTPStatus.OK:
44
+ logger.info(f'Webhook created successfully.')
45
+ else:
46
+ logger.info('Webhook creation unsuccessful')
47
+ return Webhook.deserialize(APIResponseHandler(response))
48
+
49
+ @handle_api_error_response
50
+ def delete_webhook(self, uuid: str = None) -> None:
51
+ """
52
+ Delete a webhook
53
+
54
+ :params uuid: uuid of the Webhook to delete
55
+ :returns: None
56
+ """
57
+ response = self.client.delete(
58
+ url=f'webhooks/{uuid}'
59
+ )
60
+ if response.status_code == HTTPStatus.OK:
61
+ logger.info(f'Webhook {uuid} deleted successfully.')
62
+ else:
63
+ logger.info('Webhook deletion unsuccessful')
64
+
65
+ @handle_api_error_response
66
+ def get_webhook(self, uuid:str) -> List[Webhook]:
67
+ """
68
+ Get a webhook
69
+
70
+ :params uuid: UUID belongs to the Webhook
71
+ :returns: `Webhook` object
72
+ """
73
+ response = self.client.get(
74
+ url=f'webhooks/{uuid}',
75
+ )
76
+ return Webhook.deserialize(APIResponseHandler(response))
77
+
78
+ @handle_api_error_response
79
+ def update_webhook(self, uuid: str, name:str, url:str, provider:str) -> Webhook:
80
+ """
81
+ Update a webhook, by changing one or more of name, url or provider.
82
+ :params name: name of webhook
83
+ :params url: webhook url
84
+ :params provider: Either 'SLACK' or 'OTHER'
85
+
86
+ :returns: Updated `Webhook` object.
87
+ """
88
+ request_body = Webhook(
89
+ name=name, url=url, provider=provider
90
+ ).dict()
91
+ response = self.client.patch(
92
+ url=f'webhooks/{uuid}',
93
+ data=request_body,
94
+ )
95
+ if response.status_code == HTTPStatus.OK:
96
+ logger.info(f'Webhook {uuid} updated successfully.')
97
+ else:
98
+ logger.info('Webhook updation unsuccessful')
99
+ return Webhook.deserialize(APIResponseHandler(response))
100
+
101
+ @handle_api_error_response
102
+ def get_webhooks(self, limit: int = 300, offset: int = 0) -> List[Webhook]:
103
+ """
104
+ Get a list of all webhooks in the organization
105
+
106
+ :params limit: Number of webhooks to fetch in a call
107
+ :params offset: Number of rows to skip before any rows are retrived
108
+ :returns: List of `Webhook` object
109
+ """
110
+ response = self.client.get(
111
+ url='webhooks',
112
+ params={
113
+ 'organization_name': self.organization_name,
114
+ 'limit': limit,
115
+ 'offset': offset,
116
+ },
117
+ )
118
+ items = PaginatedResponseHandler(response).get_pagination_items()
119
+ return parse_obj_as(List[Webhook], items)
120
+
121
+
@@ -24,7 +24,12 @@ import numpy as np
24
24
  import pandas as pd
25
25
  import pandas.api.types
26
26
 
27
- from fiddler.schemas.custom_features import CustomFeature
27
+ from fiddler.schemas.custom_features import (
28
+ CustomFeature,
29
+ ImageEmbedding,
30
+ TextEmbedding,
31
+ VectorFeature,
32
+ )
28
33
  from fiddler.utils.formatting import prettyprint_number, validate_sanitized_names
29
34
  from fiddler.utils.logger import get_logger
30
35
  from fiddler.utils.pandas_helper import is_datetime, is_list, is_vector_value
@@ -199,6 +204,7 @@ class ModelTask(enum.Enum):
199
204
  MULTICLASS_CLASSIFICATION = 'multiclass_classification'
200
205
  REGRESSION = 'regression'
201
206
  RANKING = 'ranking'
207
+ NOT_SET = 'not_set'
202
208
 
203
209
  def is_classification(self):
204
210
  return self.value in (
@@ -1235,6 +1241,9 @@ class ModelInfo:
1235
1241
  for k, v in numeric_cols.items()
1236
1242
  if v in (DataType.INTEGER.value, DataType.FLOAT.value)
1237
1243
  ]
1244
+ valid_vector_cols = [
1245
+ input.name for input in self.inputs if input.data_type.is_vector()
1246
+ ]
1238
1247
 
1239
1248
  unique_cf_names = []
1240
1249
  for feature in self.custom_features:
@@ -1256,17 +1265,17 @@ class ModelInfo:
1256
1265
  else:
1257
1266
  unique_cf_names.append(feature.name)
1258
1267
 
1259
- if isinstance(feature.columns, list):
1268
+ if isinstance(feature, (TextEmbedding, ImageEmbedding, VectorFeature)):
1269
+ if not feature.column in valid_vector_cols:
1270
+ raise ValueError(
1271
+ f"Custom features '{feature.name}' defined on column '{feature.column}' is not found"
1272
+ )
1273
+ else:
1260
1274
  for col in feature.columns:
1261
1275
  if col not in valid_col_names:
1262
1276
  raise ValueError(
1263
1277
  f"Custom features '{feature.name}' defined on column '{col}' is not found or not of type int/float."
1264
1278
  )
1265
- else:
1266
- if feature.columns not in valid_col_names:
1267
- raise ValueError(
1268
- f"Custom features '{feature.name}' defined on column '{feature.columns}' is not found or not of type int/float."
1269
- )
1270
1279
 
1271
1280
  def warn_deprecated_parameter(self, param_name: str, from_version: str) -> None:
1272
1281
  warnings.warn(
@@ -1814,14 +1823,9 @@ class ModelInfo:
1814
1823
  # todo (pradhuman): replace categorical_target_class_details with target_class_order
1815
1824
 
1816
1825
  if not model_task:
1817
- model_task = cls.infer_model_task(
1818
- dataset_info=dataset_info,
1819
- target=target,
1820
- outputs=outputs,
1821
- )
1822
- LOG.warning(
1823
- f'Fiddler inferred your model as a {model_task.value} model. '
1824
- f'If this is wrong, please specify your model task.'
1826
+ raise ValueError(
1827
+ 'model_task is required to create a model info. Please specify a value '
1828
+ 'using the ModelTask enum.'
1825
1829
  )
1826
1830
 
1827
1831
  (
@@ -2290,42 +2294,6 @@ class ModelInfo:
2290
2294
  )
2291
2295
  return is_binary_ranking_model, top_k, bin_class_threshold
2292
2296
 
2293
- @classmethod
2294
- def infer_model_task(
2295
- cls,
2296
- dataset_info: DatasetInfo,
2297
- target: Optional[str],
2298
- outputs: Optional[List[str]],
2299
- ) -> ModelTask:
2300
- """
2301
- Inference assuming user gave all right parameters.
2302
- After, we run ModelInfoValidator to check all parameters.
2303
- :param dataset_info: dataset info object
2304
- :param target: target column name
2305
- :param outputs: list of output column name(s)
2306
- :return: Inferred Model task when possible
2307
- """
2308
- if not outputs or not target:
2309
- raise ValueError(
2310
- f'Fiddler cannot infer your model task because target and/or outputs '
2311
- f'are not specified. Please specify your model task.'
2312
- )
2313
- if len(outputs) > 1:
2314
- return ModelTask.MULTICLASS_CLASSIFICATION
2315
-
2316
- target_col = dataset_info[target]
2317
- output_col = dataset_info[outputs[0]]
2318
-
2319
- if ModelInfo.check_binary_target(target_column=target_col):
2320
- if output_col.value_range_min >= 0.0 and output_col.value_range_max <= 1.0:
2321
- return ModelTask.BINARY_CLASSIFICATION
2322
- return ModelTask.RANKING
2323
-
2324
- if not target_col.data_type.is_numeric():
2325
- return ModelTask.RANKING
2326
-
2327
- return ModelTask.REGRESSION
2328
-
2329
2297
  @classmethod
2330
2298
  def validate_model_task(
2331
2299
  cls,
@@ -2402,7 +2370,7 @@ class ModelInfo:
2402
2370
  target_column: Column,
2403
2371
  ) -> Optional[List[Union[str, bool, float, int]]]:
2404
2372
 
2405
- if model_task.value == ModelTask.REGRESSION.value:
2373
+ if model_task.value in [ModelTask.REGRESSION.value, ModelTask.NOT_SET.value]:
2406
2374
  return None
2407
2375
 
2408
2376
  if isinstance(target_class_order, (str, int, float, bool)):
@@ -1,6 +1,7 @@
1
1
  import enum
2
2
  from typing import Any, Dict, List, Optional, Union
3
3
 
4
+ from ast import literal_eval
4
5
  from pydantic import Field, root_validator
5
6
 
6
7
  from fiddler.schema.base import BaseDataSchema
@@ -140,6 +141,7 @@ class AlertRulePayload(BaseDataSchema):
140
141
  alert_type: Optional[AlertType]
141
142
  metric: Metric
142
143
  metric_id: Union[Metric, str]
144
+ feature_name: Optional[str]
143
145
  feature_names: Optional[List[str]]
144
146
  priority: Priority
145
147
  compare_to: CompareTo
@@ -161,7 +163,8 @@ class AlertRule(BaseDataSchema):
161
163
  name: Optional[str]
162
164
  alert_type: Optional[AlertType]
163
165
  metric: str
164
- columns: Optional[List[str]] = Field(alias='feature_names')
166
+ column: Optional[str] = Field(alias='feature_name', default=None)
167
+ columns: Optional[List[str]] = Field(alias='feature_names', default=None)
165
168
  baseline_name: Optional[str]
166
169
  priority: Priority
167
170
  compare_to: CompareTo
@@ -172,7 +175,15 @@ class AlertRule(BaseDataSchema):
172
175
  bin_size: Optional[str]
173
176
  time_bucket: Optional[int]
174
177
 
175
-
178
+ @root_validator(pre=True)
179
+ def set_feature_names(cls, values) -> dict:
180
+ if 'feature_names' in values and type(values['feature_names']) == str:
181
+ # in release 23.3 feature_names is stringified list. 23.4 onwards its List[str]
182
+ try:
183
+ values['feature_names'] = literal_eval(values['feature_names'])
184
+ except SyntaxError:
185
+ values['feature_names'] = None
186
+ return values
176
187
 
177
188
  class TriggeredAlerts(BaseDataSchema):
178
189
  id: int
@@ -180,10 +191,12 @@ class TriggeredAlerts(BaseDataSchema):
180
191
  alert_rule_uuid: str = Field(alias='alert_config_uuid')
181
192
  alert_run_start_time: int
182
193
  alert_time_bucket: int
183
- alert_value: Dict[str, float]
194
+ alert_value: Union[float, Dict[str, float]]
184
195
  baseline_time_bucket: Optional[int]
185
196
  baseline_value: Optional[float]
186
197
  is_alert: bool
187
198
  severity: Optional[str]
188
199
  failure_reason: str
189
200
  message: str
201
+ multi_col_values: Optional[Dict[str, float]]
202
+ feature_name: Optional[str]
@@ -0,0 +1,10 @@
1
+ from fiddler.schema.base import BaseDataSchema
2
+
3
+
4
+ class Webhook(BaseDataSchema):
5
+ uuid: str
6
+ name: str
7
+ organization_name: str
8
+ url: str
9
+ # provider is 'SLACK' or 'OTHER' as of Aug 2023.
10
+ provider: str
@@ -0,0 +1,96 @@
1
+ from enum import Enum
2
+ from typing import Any, Dict, List, Optional, Type, TypeVar
3
+
4
+ from pydantic import BaseModel
5
+
6
+ CustomFeatureTypeVar = TypeVar('CustomFeatureTypeVar', bound='CustomFeature')
7
+ DEFAULT_NUM_CLUSTERS = 5
8
+ DEFAULT_NUM_TAGS = 5
9
+
10
+
11
+ class CustomFeatureType(str, Enum):
12
+ FROM_COLUMNS = 'FROM_COLUMNS'
13
+ FROM_VECTOR = 'FROM_VECTOR'
14
+ FROM_TEXT_EMBEDDING = 'FROM_TEXT_EMBEDDING'
15
+ FROM_IMAGE_EMBEDDING = 'FROM_IMAGE_EMBEDDING'
16
+
17
+
18
+ class CustomFeature(BaseModel):
19
+ name: str
20
+ type: CustomFeatureType
21
+ n_clusters: Optional[int] = DEFAULT_NUM_CLUSTERS
22
+ centroids: Optional[List] = None
23
+
24
+ class Config:
25
+ allow_mutation = False
26
+
27
+ @classmethod
28
+ def from_columns(
29
+ cls, custom_name: str, cols: List[str], n_clusters: int = DEFAULT_NUM_CLUSTERS
30
+ ) -> 'Multivariate':
31
+ return Multivariate(
32
+ name=custom_name,
33
+ columns=cols,
34
+ n_clusters=n_clusters,
35
+ )
36
+
37
+ @classmethod
38
+ def from_dict(
39
+ cls: Type[CustomFeatureTypeVar], deserialized_json: dict
40
+ ) -> CustomFeatureTypeVar:
41
+ feature_type = CustomFeatureType(deserialized_json['type'])
42
+ if feature_type == CustomFeatureType.FROM_COLUMNS:
43
+ return Multivariate.parse_obj(deserialized_json)
44
+ elif feature_type == CustomFeatureType.FROM_VECTOR:
45
+ return VectorFeature.parse_obj(deserialized_json)
46
+ elif feature_type == CustomFeatureType.FROM_TEXT_EMBEDDING:
47
+ return TextEmbedding.parse_obj(deserialized_json)
48
+ elif feature_type == CustomFeatureType.FROM_IMAGE_EMBEDDING:
49
+ return ImageEmbedding.parse_obj(deserialized_json)
50
+ else:
51
+ raise ValueError(f'Unsupported feature type: {feature_type}')
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ return_dict = {
55
+ 'name': self.name,
56
+ 'type': self.type,
57
+ 'n_clusters': self.n_clusters,
58
+ }
59
+ if self.type == CustomFeatureType.FROM_COLUMNS:
60
+ return_dict['columns'] = self.columns
61
+ elif self.type == CustomFeatureType.FROM_VECTOR:
62
+ return_dict['column'] = self.column
63
+ elif self.type in (
64
+ CustomFeatureType.FROM_TEXT_EMBEDDING,
65
+ CustomFeatureType.FROM_IMAGE_EMBEDDING,
66
+ ):
67
+ return_dict['source_column'] = self.source_column
68
+ return_dict['column'] = self.column
69
+
70
+ if self.type == CustomFeatureType.FROM_TEXT_EMBEDDING:
71
+ return_dict['n_tags'] = self.n_tags
72
+ else:
73
+ raise ValueError(f'Unsupported feature type: {self.type}')
74
+
75
+ return return_dict
76
+
77
+
78
+ class Multivariate(CustomFeature):
79
+ type: CustomFeatureType = CustomFeatureType.FROM_COLUMNS
80
+ columns: List[str]
81
+ monitor_components: bool = False
82
+
83
+
84
+ class VectorFeature(CustomFeature):
85
+ type: CustomFeatureType = CustomFeatureType.FROM_VECTOR
86
+ source_column: Optional[str] = None
87
+ column: str
88
+
89
+
90
+ class TextEmbedding(VectorFeature):
91
+ type: CustomFeatureType = CustomFeatureType.FROM_TEXT_EMBEDDING
92
+ n_tags: Optional[int] = DEFAULT_NUM_TAGS
93
+
94
+
95
+ class ImageEmbedding(VectorFeature):
96
+ type: CustomFeatureType = CustomFeatureType.FROM_IMAGE_EMBEDDING
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fiddler-client
3
- Version: 2.0.0.dev9
3
+ Version: 2.0.0.dev10
4
4
  Summary: Python client for Fiddler Service
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler Labs
@@ -47,6 +47,15 @@ Description: Fiddler Client
47
47
  - Add `monitor_components` as an attribute of `CustomFeature`. Default to `False`
48
48
  - Remove `column` as a parameter in `add_alert_rule` and `get_alert_rules` functions
49
49
 
50
+ ### 1.8.4
51
+ - #### **New Features**
52
+ - New DeploymentType enum for MANUAL deployment
53
+
54
+ ### 1.8.3
55
+ - ### **Modifications**
56
+ - New `columns` parameter in add_alert_rule and get_alert_rules to support multiple columns to be used for server version >= 23.3.0
57
+ - get_triggered_alerts supports `alert_value` as a float as well as a dict
58
+
50
59
  ### 1.8.2
51
60
  - #### **Modifications**
52
61
  - Fixed a bug where `min` and `max` for columns of type `float` in `dataset_info` are cast into `int` after uploaded