mlrun 1.8.0rc5__py3-none-any.whl → 1.8.0rc9__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.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

Files changed (74) hide show
  1. mlrun/__init__.py +1 -0
  2. mlrun/artifacts/__init__.py +1 -1
  3. mlrun/artifacts/base.py +21 -1
  4. mlrun/artifacts/document.py +62 -39
  5. mlrun/artifacts/manager.py +12 -5
  6. mlrun/common/constants.py +1 -0
  7. mlrun/common/model_monitoring/__init__.py +0 -2
  8. mlrun/common/model_monitoring/helpers.py +0 -28
  9. mlrun/common/schemas/__init__.py +2 -4
  10. mlrun/common/schemas/alert.py +77 -1
  11. mlrun/common/schemas/client_spec.py +0 -1
  12. mlrun/common/schemas/model_monitoring/__init__.py +0 -6
  13. mlrun/common/schemas/model_monitoring/constants.py +11 -9
  14. mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
  15. mlrun/common/schemas/notification.py +6 -0
  16. mlrun/common/schemas/project.py +3 -0
  17. mlrun/config.py +2 -3
  18. mlrun/datastore/datastore_profile.py +57 -17
  19. mlrun/datastore/sources.py +1 -2
  20. mlrun/datastore/store_resources.py +7 -2
  21. mlrun/datastore/vectorstore.py +99 -62
  22. mlrun/db/base.py +34 -20
  23. mlrun/db/httpdb.py +249 -163
  24. mlrun/db/nopdb.py +40 -17
  25. mlrun/execution.py +14 -7
  26. mlrun/feature_store/api.py +1 -0
  27. mlrun/model.py +3 -0
  28. mlrun/model_monitoring/__init__.py +3 -2
  29. mlrun/model_monitoring/api.py +64 -53
  30. mlrun/model_monitoring/applications/_application_steps.py +3 -1
  31. mlrun/model_monitoring/applications/base.py +115 -15
  32. mlrun/model_monitoring/applications/context.py +42 -24
  33. mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
  34. mlrun/model_monitoring/controller.py +43 -37
  35. mlrun/model_monitoring/db/__init__.py +0 -2
  36. mlrun/model_monitoring/db/tsdb/base.py +2 -1
  37. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
  38. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
  39. mlrun/model_monitoring/helpers.py +78 -66
  40. mlrun/model_monitoring/stream_processing.py +83 -270
  41. mlrun/model_monitoring/writer.py +1 -10
  42. mlrun/projects/pipelines.py +37 -1
  43. mlrun/projects/project.py +173 -70
  44. mlrun/run.py +40 -0
  45. mlrun/runtimes/nuclio/function.py +7 -6
  46. mlrun/runtimes/nuclio/serving.py +9 -4
  47. mlrun/serving/routers.py +158 -145
  48. mlrun/serving/server.py +6 -0
  49. mlrun/serving/states.py +21 -7
  50. mlrun/serving/v2_serving.py +94 -68
  51. mlrun/utils/helpers.py +23 -33
  52. mlrun/utils/notifications/notification/mail.py +17 -6
  53. mlrun/utils/notifications/notification_pusher.py +9 -5
  54. mlrun/utils/regex.py +8 -1
  55. mlrun/utils/version/version.json +2 -2
  56. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/METADATA +2 -2
  57. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/RECORD +61 -74
  58. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
  59. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  60. mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
  61. mlrun/model_monitoring/db/stores/base/store.py +0 -154
  62. mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
  63. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
  64. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
  65. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
  66. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
  67. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
  68. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
  69. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
  70. mlrun/model_monitoring/model_endpoint.py +0 -120
  71. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/LICENSE +0 -0
  72. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/WHEEL +0 -0
  73. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/entry_points.txt +0 -0
  74. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/top_level.txt +0 -0
@@ -1,464 +0,0 @@
1
- # Copyright 2023 Iguazio
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- import json
16
- import typing
17
- from dataclasses import dataclass
18
-
19
- import v3io.dataplane
20
- import v3io.dataplane.output
21
- import v3io.dataplane.response
22
- from v3io.dataplane import Client as V3IOClient
23
-
24
- import mlrun.common.model_monitoring.helpers
25
- import mlrun.common.schemas.model_monitoring as mm_schemas
26
- import mlrun.utils.v3io_clients
27
- from mlrun.model_monitoring.db import StoreBase
28
- from mlrun.utils import logger
29
-
30
- # Fields to encode before storing in the KV table or to decode after retrieving
31
- fields_to_encode_decode = [
32
- mm_schemas.EventFieldType.FEATURE_STATS,
33
- mm_schemas.EventFieldType.CURRENT_STATS,
34
- ]
35
-
36
-
37
- class SchemaField(typing.TypedDict):
38
- name: str
39
- type: str
40
- nullable: bool
41
-
42
-
43
- @dataclass
44
- class SchemaParams:
45
- key: str
46
- fields: list[SchemaField]
47
-
48
-
49
- _EXCLUDE_SCHEMA_FILTER_EXPRESSION = '__name!=".#schema"'
50
-
51
-
52
- class KVStoreBase(StoreBase):
53
- type: typing.ClassVar[str] = "v3io-nosql"
54
- """
55
- Handles the DB operations when the DB target is from type KV. For the KV operations, we use an instance of V3IO
56
- client and usually the KV table can be found under v3io:///users/pipelines/project-name/model-endpoints/endpoints/.
57
- """
58
-
59
- def __init__(
60
- self,
61
- project: str,
62
- ) -> None:
63
- super().__init__(project=project)
64
- self._client = None
65
- # Get the KV table path and container
66
- self.path, self.container = self._get_path_and_container()
67
-
68
- @property
69
- def client(self) -> V3IOClient:
70
- if not self._client:
71
- self._client = mlrun.utils.v3io_clients.get_v3io_client(
72
- endpoint=mlrun.mlconf.v3io_api,
73
- )
74
- return self._client
75
-
76
- def write_model_endpoint(self, endpoint: dict[str, typing.Any]):
77
- """
78
- Create a new endpoint record in the KV table.
79
-
80
- :param endpoint: model endpoint dictionary that will be written into the DB.
81
- """
82
-
83
- for field in fields_to_encode_decode:
84
- if field in endpoint:
85
- # Encode to binary data
86
- endpoint[field] = self._encode_field(endpoint[field])
87
-
88
- self.client.kv.put(
89
- container=self.container,
90
- table_path=self.path,
91
- key=endpoint[mm_schemas.EventFieldType.UID],
92
- attributes=endpoint,
93
- )
94
-
95
- self._infer_kv_schema()
96
-
97
- def update_model_endpoint(
98
- self, endpoint_id: str, attributes: dict[str, typing.Any]
99
- ):
100
- """
101
- Update a model endpoint record with a given attributes.
102
-
103
- :param endpoint_id: The unique id of the model endpoint.
104
- :param attributes: Dictionary of attributes that will be used for update the model endpoint. Note that the keys
105
- of the attributes dictionary should exist in the KV table.
106
-
107
- """
108
-
109
- for field in fields_to_encode_decode:
110
- if field in attributes:
111
- # Encode to binary data
112
- attributes[field] = self._encode_field(attributes[field])
113
-
114
- self.client.kv.update(
115
- container=self.container,
116
- table_path=self.path,
117
- key=endpoint_id,
118
- attributes=attributes,
119
- )
120
-
121
- def delete_model_endpoint(
122
- self,
123
- endpoint_id: str,
124
- ):
125
- """
126
- Deletes the KV record of a given model endpoint id.
127
-
128
- :param endpoint_id: The unique id of the model endpoint.
129
- """
130
-
131
- self.client.kv.delete(
132
- container=self.container,
133
- table_path=self.path,
134
- key=endpoint_id,
135
- )
136
-
137
- def get_model_endpoint(
138
- self,
139
- endpoint_id: str,
140
- ) -> dict[str, typing.Any]:
141
- """
142
- Get a single model endpoint record.
143
-
144
- :param endpoint_id: The unique id of the model endpoint.
145
-
146
- :return: A model endpoint record as a dictionary.
147
-
148
- :raise MLRunNotFoundError: If the endpoint was not found.
149
- """
150
-
151
- # Getting the raw data from the KV table
152
- endpoint = self.client.kv.get(
153
- container=self.container,
154
- table_path=self.path,
155
- key=endpoint_id,
156
- raise_for_status=v3io.dataplane.RaiseForStatus.never,
157
- )
158
- endpoint = endpoint.output.item
159
-
160
- for field in fields_to_encode_decode:
161
- if field in endpoint:
162
- # Decode binary data
163
- endpoint[field] = self._decode_field(endpoint[field])
164
-
165
- if not endpoint:
166
- raise mlrun.errors.MLRunNotFoundError(f"Endpoint {endpoint_id} not found")
167
-
168
- # For backwards compatability: replace null values for `error_count` and `metrics`
169
- self.validate_old_schema_fields(endpoint=endpoint)
170
-
171
- return endpoint
172
-
173
- def _get_path_and_container(self):
174
- """Getting path and container based on the model monitoring configurations"""
175
- path = mlrun.mlconf.model_endpoint_monitoring.store_prefixes.default.format(
176
- project=self.project,
177
- kind=mm_schemas.ModelMonitoringStoreKinds.ENDPOINTS,
178
- )
179
- (
180
- _,
181
- container,
182
- path,
183
- ) = mlrun.common.model_monitoring.helpers.parse_model_endpoint_store_prefix(
184
- path
185
- )
186
- return path, container
187
-
188
- def list_model_endpoints(
189
- self,
190
- model: typing.Optional[str] = None,
191
- function: typing.Optional[str] = None,
192
- labels: typing.Optional[list[str]] = None,
193
- top_level: typing.Optional[bool] = None,
194
- uids: typing.Optional[list] = None,
195
- include_stats: typing.Optional[bool] = None,
196
- ) -> list[dict[str, typing.Any]]:
197
- # # Initialize an empty model endpoints list
198
- endpoint_list = []
199
-
200
- # Retrieve the raw data from the KV table and get the endpoint ids
201
- try:
202
- cursor = self.client.kv.new_cursor(
203
- container=self.container,
204
- table_path=self.path,
205
- filter_expression=self._build_kv_cursor_filter_expression(
206
- self.project,
207
- function,
208
- model,
209
- top_level,
210
- ),
211
- raise_for_status=v3io.dataplane.RaiseForStatus.never,
212
- )
213
- items = cursor.all()
214
-
215
- except Exception as exc:
216
- logger.warning(
217
- "Failed retrieving raw data from kv table",
218
- exc=mlrun.errors.err_to_str(exc),
219
- )
220
- return endpoint_list
221
- # Create a list of model endpoints unique ids
222
- if uids is None:
223
- uids = []
224
- for item in items:
225
- if mm_schemas.EventFieldType.UID not in item:
226
- # This is kept for backwards compatibility - in old versions the key column named endpoint_id
227
- uids.append(item[mm_schemas.EventFieldType.ENDPOINT_ID])
228
- else:
229
- uids.append(item[mm_schemas.EventFieldType.UID])
230
-
231
- # Add each relevant model endpoint to the model endpoints list
232
- for endpoint_id in uids:
233
- endpoint_dict = self.get_model_endpoint(
234
- endpoint_id=endpoint_id,
235
- )
236
- if not include_stats:
237
- # Exclude these fields when listing model endpoints to avoid returning too much data (ML-6594)
238
- endpoint_dict.pop(mm_schemas.EventFieldType.FEATURE_STATS)
239
- endpoint_dict.pop(mm_schemas.EventFieldType.CURRENT_STATS)
240
-
241
- if labels and not self._validate_labels(
242
- endpoint_dict=endpoint_dict, labels=labels
243
- ):
244
- continue
245
-
246
- endpoint_list.append(endpoint_dict)
247
-
248
- return endpoint_list
249
-
250
- def delete_model_endpoints_resources(self):
251
- """
252
- Delete all model endpoints resources in V3IO KV.
253
- """
254
- logger.debug(
255
- "Deleting model monitoring endpoints resources in V3IO KV",
256
- project=self.project,
257
- )
258
-
259
- endpoints = self.list_model_endpoints()
260
-
261
- # Delete model endpoint record from KV table
262
- for endpoint_dict in endpoints:
263
- if mm_schemas.EventFieldType.UID not in endpoint_dict:
264
- # This is kept for backwards compatibility - in old versions the key column named endpoint_id
265
- endpoint_id = endpoint_dict[mm_schemas.EventFieldType.ENDPOINT_ID]
266
- else:
267
- endpoint_id = endpoint_dict[mm_schemas.EventFieldType.UID]
268
-
269
- logger.debug(
270
- "Deleting model endpoint resources from the V3IO KV table",
271
- endpoint_id=endpoint_id,
272
- project=self.project,
273
- )
274
-
275
- self.delete_model_endpoint(
276
- endpoint_id,
277
- )
278
-
279
- logger.debug(
280
- "Successfully deleted model monitoring endpoints from the V3IO KV table",
281
- project=self.project,
282
- )
283
-
284
- # Delete remain records in the KV
285
- all_records = self.client.kv.new_cursor(
286
- container=self.container,
287
- table_path=self.path,
288
- raise_for_status=v3io.dataplane.RaiseForStatus.never,
289
- ).all()
290
-
291
- all_records = [r["__name"] for r in all_records]
292
-
293
- # Cleanup KV
294
- for record in all_records:
295
- self.client.kv.delete(
296
- container=self.container,
297
- table_path=self.path,
298
- key=record,
299
- raise_for_status=v3io.dataplane.RaiseForStatus.never,
300
- )
301
-
302
- def _generate_tsdb_paths(self) -> tuple[str, str]:
303
- """Generate a short path to the TSDB resources and a filtered path for the frames object
304
- :return: A tuple of:
305
- [0] = Short path to the TSDB resources
306
- [1] = Filtered path to TSDB events without schema and container
307
- """
308
- # Full path for the time series DB events
309
- full_path = (
310
- mlrun.mlconf.model_endpoint_monitoring.store_prefixes.default.format(
311
- project=self.project,
312
- kind=mm_schemas.ModelMonitoringStoreKinds.EVENTS,
313
- )
314
- )
315
-
316
- # Generate the main directory with the TSDB resources
317
- tsdb_path = (
318
- mlrun.common.model_monitoring.helpers.parse_model_endpoint_project_prefix(
319
- full_path, self.project
320
- )
321
- )
322
-
323
- # Generate filtered path without schema and container as required by the frames object
324
- (
325
- _,
326
- _,
327
- filtered_path,
328
- ) = mlrun.common.model_monitoring.helpers.parse_model_endpoint_store_prefix(
329
- full_path
330
- )
331
- return tsdb_path, filtered_path
332
-
333
- def _infer_kv_schema(self):
334
- """
335
- Create KV schema file if not exist. This schema is being used by the Grafana dashboards.
336
- """
337
-
338
- schema_file = self.client.kv.new_cursor(
339
- container=self.container,
340
- table_path=self.path,
341
- filter_expression='__name==".#schema"',
342
- )
343
-
344
- if not schema_file.all():
345
- logger.info("Generate a new V3IO KV schema file", kv_table_path=self.path)
346
- frames_client = self._get_frames_client()
347
- frames_client.execute(backend="kv", table=self.path, command="infer_schema")
348
-
349
- def _get_frames_client(self):
350
- return mlrun.utils.v3io_clients.get_frames_client(
351
- address=mlrun.mlconf.v3io_framesd,
352
- container=self.container,
353
- )
354
-
355
- @staticmethod
356
- def _build_kv_cursor_filter_expression(
357
- project: str,
358
- function: typing.Optional[str] = None,
359
- model: typing.Optional[str] = None,
360
- top_level: bool = False,
361
- ) -> str:
362
- """
363
- Convert the provided filters into a valid filter expression. The expected filter expression includes different
364
- conditions, divided by ' AND '.
365
-
366
- :param project: The name of the project.
367
- :param model: The name of the model to filter by.
368
- :param function: The name of the function to filter by.
369
- :param top_level: If True will return only routers and endpoint that are NOT children of any router.
370
-
371
- :return: A valid filter expression as a string.
372
-
373
- :raise MLRunInvalidArgumentError: If project value is None.
374
- """
375
-
376
- if not project:
377
- raise mlrun.errors.MLRunInvalidArgumentError("project can't be empty")
378
-
379
- # Add project filter
380
- filter_expression = [f"{mm_schemas.EventFieldType.PROJECT}=='{project}'"]
381
-
382
- # Add function and model filters
383
- if function:
384
- function_uri = f"{project}/{function}" if function else None
385
- filter_expression.append(
386
- f"{mm_schemas.EventFieldType.FUNCTION_URI}=='{function_uri}'"
387
- )
388
- if model:
389
- model = model if ":" in model else f"{model}:latest"
390
- filter_expression.append(f"{mm_schemas.EventFieldType.MODEL}=='{model}'")
391
-
392
- # Apply top_level filter (remove endpoints that considered a child of a router)
393
- if top_level:
394
- filter_expression.append(
395
- f"(endpoint_type=='{str(mm_schemas.EndpointType.NODE_EP.value)}' "
396
- f"OR endpoint_type=='{str(mm_schemas.EndpointType.ROUTER.value)}')"
397
- )
398
-
399
- return " AND ".join(filter_expression)
400
-
401
- @staticmethod
402
- def validate_old_schema_fields(endpoint: dict):
403
- """
404
- Replace default null values for `error_count` and `metrics` for users that logged a model endpoint before 1.3.0.
405
- In addition, this function also validates that the key name of the endpoint unique id is `uid` and not
406
- `endpoint_id` that has been used before 1.3.0.
407
-
408
- Leaving here for backwards compatibility which related to the model endpoint schema.
409
-
410
- :param endpoint: An endpoint flattened dictionary.
411
- """
412
-
413
- # Validate default value for `error_count`
414
- # For backwards compatibility reasons, we validate that the model endpoint includes the `error_count` key
415
- if (
416
- mm_schemas.EventFieldType.ERROR_COUNT in endpoint
417
- and endpoint[mm_schemas.EventFieldType.ERROR_COUNT] == "null"
418
- ):
419
- endpoint[mm_schemas.EventFieldType.ERROR_COUNT] = "0"
420
-
421
- # Validate default value for `metrics`
422
- # For backwards compatibility reasons, we validate that the model endpoint includes the `metrics` key
423
- if (
424
- mm_schemas.EventFieldType.METRICS in endpoint
425
- and endpoint[mm_schemas.EventFieldType.METRICS] == "null"
426
- ):
427
- endpoint[mm_schemas.EventFieldType.METRICS] = json.dumps(
428
- {
429
- mm_schemas.EventKeyMetrics.GENERIC: {
430
- mm_schemas.EventLiveStats.LATENCY_AVG_1H: 0,
431
- mm_schemas.EventLiveStats.PREDICTIONS_PER_SECOND: 0,
432
- }
433
- }
434
- )
435
- # Validate key `uid` instead of `endpoint_id`
436
- # For backwards compatibility reasons, we replace the `endpoint_id` with `uid` which is the updated key name
437
- if mm_schemas.EventFieldType.ENDPOINT_ID in endpoint:
438
- endpoint[mm_schemas.EventFieldType.UID] = endpoint[
439
- mm_schemas.EventFieldType.ENDPOINT_ID
440
- ]
441
-
442
- @staticmethod
443
- def _encode_field(field: typing.Union[str, bytes]) -> bytes:
444
- """Encode a provided field. Mainly used when storing data in the KV table."""
445
-
446
- if isinstance(field, str):
447
- return field.encode("ascii")
448
- return field
449
-
450
- @staticmethod
451
- def _decode_field(field: typing.Union[str, bytes]) -> str:
452
- """Decode a provided field. Mainly used when retrieving data from the KV table."""
453
-
454
- if isinstance(field, bytes):
455
- return field.decode()
456
- return field
457
-
458
- @staticmethod
459
- def get_v3io_monitoring_apps_container(project_name: str) -> str:
460
- return f"users/pipelines/{project_name}/monitoring-apps"
461
-
462
- @staticmethod
463
- def _get_monitoring_schedules_container(project_name: str) -> str:
464
- return f"users/pipelines/{project_name}/monitoring-schedules/functions"
@@ -1,120 +0,0 @@
1
- # Copyright 2023 Iguazio
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
- #
15
-
16
- from dataclasses import dataclass, field
17
- from typing import Any, Optional
18
-
19
- import mlrun.model
20
- from mlrun.common.model_monitoring.helpers import FeatureStats
21
- from mlrun.common.schemas.model_monitoring.constants import (
22
- EndpointType,
23
- EventKeyMetrics,
24
- EventLiveStats,
25
- ModelMonitoringMode,
26
- )
27
-
28
-
29
- @dataclass
30
- class ModelEndpointSpec(mlrun.model.ModelObj):
31
- function_uri: str = "" # <project_name>/<function_name>:<tag>
32
- model: str = "" # <model_name>:<version>
33
- model_class: str = ""
34
- model_uri: str = ""
35
- feature_names: list[str] = field(default_factory=list)
36
- label_names: list[str] = field(default_factory=list)
37
- stream_path: str = ""
38
- algorithm: str = ""
39
- monitor_configuration: dict = field(default_factory=dict)
40
- active: bool = True
41
- monitoring_mode: ModelMonitoringMode = ModelMonitoringMode.disabled
42
-
43
-
44
- @dataclass
45
- class ModelEndpointStatus(mlrun.model.ModelObj):
46
- feature_stats: FeatureStats = field(default_factory=dict)
47
- current_stats: FeatureStats = field(default_factory=dict)
48
- first_request: str = ""
49
- last_request: str = ""
50
- error_count: int = 0
51
- drift_status: str = ""
52
- drift_measures: dict = field(default_factory=dict)
53
- metrics: dict[str, dict[str, Any]] = field(
54
- default_factory=lambda: {
55
- EventKeyMetrics.GENERIC: {
56
- EventLiveStats.LATENCY_AVG_1H: 0,
57
- EventLiveStats.PREDICTIONS_PER_SECOND: 0,
58
- }
59
- }
60
- )
61
- features: list[dict[str, Any]] = field(default_factory=list)
62
- children: list[str] = field(default_factory=list)
63
- children_uids: list[str] = field(default_factory=list)
64
- endpoint_type: EndpointType = EndpointType.NODE_EP
65
- monitoring_feature_set_uri: str = ""
66
- state: str = ""
67
-
68
-
69
- class ModelEndpoint(mlrun.model.ModelObj):
70
- kind = "model-endpoint"
71
- _dict_fields = ["kind", "metadata", "spec", "status"]
72
-
73
- def __init__(self):
74
- self._status: ModelEndpointStatus = ModelEndpointStatus()
75
- self._spec: ModelEndpointSpec = ModelEndpointSpec()
76
- self._metadata: mlrun.model.VersionedObjMetadata = (
77
- mlrun.model.VersionedObjMetadata()
78
- )
79
-
80
- @property
81
- def status(self) -> ModelEndpointStatus:
82
- return self._status
83
-
84
- @status.setter
85
- def status(self, status):
86
- self._status = self._verify_dict(status, "status", ModelEndpointStatus)
87
-
88
- @property
89
- def spec(self) -> ModelEndpointSpec:
90
- return self._spec
91
-
92
- @spec.setter
93
- def spec(self, spec):
94
- self._spec = self._verify_dict(spec, "spec", ModelEndpointSpec)
95
-
96
- @property
97
- def metadata(self) -> mlrun.model.VersionedObjMetadata:
98
- return self._metadata
99
-
100
- @metadata.setter
101
- def metadata(self, metadata):
102
- self._metadata = self._verify_dict(
103
- metadata, "metadata", mlrun.model.VersionedObjMetadata
104
- )
105
-
106
- @classmethod
107
- def from_flat_dict(
108
- cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
109
- ):
110
- new_obj = cls()
111
- new_obj._metadata = mlrun.model.VersionedObjMetadata().from_dict(
112
- struct=struct, fields=fields, deprecated_fields=deprecated_fields
113
- )
114
- new_obj._status = ModelEndpointStatus().from_dict(
115
- struct=struct, fields=fields, deprecated_fields=deprecated_fields
116
- )
117
- new_obj._spec = ModelEndpointSpec().from_dict(
118
- struct=struct, fields=fields, deprecated_fields=deprecated_fields
119
- )
120
- return new_obj