mlrun 1.3.2rc1__py3-none-any.whl → 1.3.2rc2__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 (93) hide show
  1. mlrun/api/api/deps.py +14 -1
  2. mlrun/api/api/endpoints/frontend_spec.py +0 -2
  3. mlrun/api/api/endpoints/functions.py +15 -27
  4. mlrun/api/api/endpoints/grafana_proxy.py +435 -74
  5. mlrun/api/api/endpoints/healthz.py +5 -18
  6. mlrun/api/api/endpoints/model_endpoints.py +33 -37
  7. mlrun/api/api/utils.py +6 -13
  8. mlrun/api/crud/__init__.py +14 -16
  9. mlrun/api/crud/logs.py +5 -7
  10. mlrun/api/crud/model_monitoring/__init__.py +2 -2
  11. mlrun/api/crud/model_monitoring/model_endpoint_store.py +847 -0
  12. mlrun/api/crud/model_monitoring/model_endpoints.py +105 -328
  13. mlrun/api/crud/pipelines.py +2 -3
  14. mlrun/api/db/sqldb/models/models_mysql.py +52 -19
  15. mlrun/api/db/sqldb/models/models_sqlite.py +52 -19
  16. mlrun/api/db/sqldb/session.py +19 -26
  17. mlrun/api/schemas/__init__.py +2 -0
  18. mlrun/api/schemas/constants.py +0 -13
  19. mlrun/api/schemas/frontend_spec.py +0 -1
  20. mlrun/api/schemas/model_endpoints.py +38 -195
  21. mlrun/api/schemas/schedule.py +2 -2
  22. mlrun/api/utils/clients/log_collector.py +5 -0
  23. mlrun/builder.py +9 -41
  24. mlrun/config.py +1 -76
  25. mlrun/data_types/__init__.py +1 -6
  26. mlrun/data_types/data_types.py +1 -3
  27. mlrun/datastore/__init__.py +2 -9
  28. mlrun/datastore/sources.py +20 -25
  29. mlrun/datastore/store_resources.py +1 -1
  30. mlrun/datastore/targets.py +34 -67
  31. mlrun/datastore/utils.py +4 -26
  32. mlrun/db/base.py +2 -4
  33. mlrun/db/filedb.py +5 -13
  34. mlrun/db/httpdb.py +32 -64
  35. mlrun/db/sqldb.py +2 -4
  36. mlrun/errors.py +0 -5
  37. mlrun/execution.py +0 -2
  38. mlrun/feature_store/api.py +8 -24
  39. mlrun/feature_store/feature_set.py +6 -28
  40. mlrun/feature_store/feature_vector.py +0 -2
  41. mlrun/feature_store/ingestion.py +11 -8
  42. mlrun/feature_store/retrieval/base.py +43 -271
  43. mlrun/feature_store/retrieval/dask_merger.py +153 -55
  44. mlrun/feature_store/retrieval/job.py +3 -12
  45. mlrun/feature_store/retrieval/local_merger.py +130 -48
  46. mlrun/feature_store/retrieval/spark_merger.py +125 -126
  47. mlrun/features.py +2 -7
  48. mlrun/model_monitoring/constants.py +6 -48
  49. mlrun/model_monitoring/helpers.py +35 -118
  50. mlrun/model_monitoring/model_monitoring_batch.py +260 -293
  51. mlrun/model_monitoring/stream_processing_fs.py +253 -220
  52. mlrun/platforms/iguazio.py +0 -33
  53. mlrun/projects/project.py +72 -34
  54. mlrun/runtimes/base.py +0 -5
  55. mlrun/runtimes/daskjob.py +0 -2
  56. mlrun/runtimes/function.py +3 -29
  57. mlrun/runtimes/kubejob.py +15 -39
  58. mlrun/runtimes/local.py +45 -7
  59. mlrun/runtimes/mpijob/abstract.py +0 -2
  60. mlrun/runtimes/mpijob/v1.py +0 -2
  61. mlrun/runtimes/pod.py +0 -2
  62. mlrun/runtimes/remotesparkjob.py +0 -2
  63. mlrun/runtimes/serving.py +0 -6
  64. mlrun/runtimes/sparkjob/abstract.py +2 -39
  65. mlrun/runtimes/sparkjob/spark3job.py +0 -2
  66. mlrun/serving/__init__.py +1 -2
  67. mlrun/serving/routers.py +35 -35
  68. mlrun/serving/server.py +12 -22
  69. mlrun/serving/states.py +30 -162
  70. mlrun/serving/v2_serving.py +10 -13
  71. mlrun/utils/clones.py +1 -1
  72. mlrun/utils/model_monitoring.py +96 -122
  73. mlrun/utils/version/version.json +2 -2
  74. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/METADATA +27 -23
  75. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/RECORD +79 -92
  76. mlrun/api/crud/model_monitoring/grafana.py +0 -427
  77. mlrun/datastore/spark_udf.py +0 -40
  78. mlrun/model_monitoring/__init__.py +0 -44
  79. mlrun/model_monitoring/common.py +0 -112
  80. mlrun/model_monitoring/model_endpoint.py +0 -141
  81. mlrun/model_monitoring/stores/__init__.py +0 -106
  82. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -448
  83. mlrun/model_monitoring/stores/model_endpoint_store.py +0 -147
  84. mlrun/model_monitoring/stores/models/__init__.py +0 -23
  85. mlrun/model_monitoring/stores/models/base.py +0 -18
  86. mlrun/model_monitoring/stores/models/mysql.py +0 -100
  87. mlrun/model_monitoring/stores/models/sqlite.py +0 -98
  88. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -375
  89. mlrun/utils/db.py +0 -52
  90. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/LICENSE +0 -0
  91. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/WHEEL +0 -0
  92. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/entry_points.txt +0 -0
  93. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/top_level.txt +0 -0
@@ -1,427 +0,0 @@
1
- # Copyright 2018 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 typing import Any, Dict, List, Optional, Set
17
-
18
- import numpy as np
19
- import pandas as pd
20
- from fastapi.concurrency import run_in_threadpool
21
- from sqlalchemy.orm import Session
22
-
23
- import mlrun.api.crud
24
- import mlrun.api.schemas
25
- import mlrun.api.utils.auth.verifier
26
- import mlrun.model_monitoring
27
- from mlrun.api.schemas import (
28
- GrafanaColumn,
29
- GrafanaDataPoint,
30
- GrafanaNumberColumn,
31
- GrafanaTable,
32
- GrafanaTimeSeriesTarget,
33
- ProjectsFormat,
34
- )
35
- from mlrun.api.utils.singletons.project_member import get_project_member
36
- from mlrun.errors import MLRunBadRequestError
37
- from mlrun.utils import config, logger
38
- from mlrun.utils.model_monitoring import parse_model_endpoint_store_prefix
39
- from mlrun.utils.v3io_clients import get_frames_client
40
-
41
-
42
- def grafana_list_projects(
43
- db_session: Session,
44
- auth_info: mlrun.api.schemas.AuthInfo,
45
- query_parameters: Dict[str, str],
46
- ) -> List[str]:
47
- """
48
- List available project names. Will be used as a filter in each grafana dashboard.
49
-
50
- :param db_session: A session that manages the current dialog with the database.
51
- :param auth_info: The auth info of the request.
52
- :param query_parameters: Dictionary of query parameters attached to the request. Note that this parameter is
53
- required by the API even though it is not being used in this function.
54
-
55
- :return: List of available project names.
56
- """
57
-
58
- projects_output = get_project_member().list_projects(
59
- db_session, format_=ProjectsFormat.name_only, leader_session=auth_info.session
60
- )
61
- return projects_output.projects
62
-
63
-
64
- # TODO: remove in 1.5.0 the following functions: grafana_list_endpoints, grafana_individual_feature_analysis,
65
- # grafana_overall_feature_analysis, grafana_income_features, parse_query_parameters, drop_grafana_escape_chars,
66
-
67
-
68
- async def grafana_list_endpoints(
69
- body: Dict[str, Any],
70
- query_parameters: Dict[str, str],
71
- auth_info: mlrun.api.schemas.AuthInfo,
72
- ) -> List[GrafanaTable]:
73
- project = query_parameters.get("project")
74
-
75
- # Filters
76
- model = query_parameters.get("model", None)
77
- function = query_parameters.get("function", None)
78
- labels = query_parameters.get("labels", "")
79
- labels = labels.split(",") if labels else []
80
-
81
- # Metrics to include
82
- metrics = query_parameters.get("metrics", "")
83
- metrics = metrics.split(",") if metrics else []
84
-
85
- # Time range for metrics
86
- start = body.get("rangeRaw", {}).get("start", "now-1h")
87
- end = body.get("rangeRaw", {}).get("end", "now")
88
-
89
- if project:
90
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_permissions(
91
- project,
92
- mlrun.api.schemas.AuthorizationAction.read,
93
- auth_info,
94
- )
95
- endpoint_list = await run_in_threadpool(
96
- mlrun.api.crud.ModelEndpoints().list_model_endpoints,
97
- auth_info=auth_info,
98
- project=project,
99
- model=model,
100
- function=function,
101
- labels=labels,
102
- metrics=metrics,
103
- start=start,
104
- end=end,
105
- )
106
- allowed_endpoints = await mlrun.api.utils.auth.verifier.AuthVerifier().filter_project_resources_by_permissions(
107
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
108
- endpoint_list.endpoints,
109
- lambda _endpoint: (
110
- _endpoint.metadata.project,
111
- _endpoint.metadata.uid,
112
- ),
113
- auth_info,
114
- )
115
- endpoint_list.endpoints = allowed_endpoints
116
-
117
- columns = [
118
- GrafanaColumn(text="endpoint_id", type="string"),
119
- GrafanaColumn(text="endpoint_function", type="string"),
120
- GrafanaColumn(text="endpoint_model", type="string"),
121
- GrafanaColumn(text="endpoint_model_class", type="string"),
122
- GrafanaColumn(text="first_request", type="time"),
123
- GrafanaColumn(text="last_request", type="time"),
124
- GrafanaColumn(text="accuracy", type="number"),
125
- GrafanaColumn(text="error_count", type="number"),
126
- GrafanaColumn(text="drift_status", type="number"),
127
- GrafanaColumn(text="predictions_per_second", type="number"),
128
- GrafanaColumn(text="latency_avg_1h", type="number"),
129
- ]
130
-
131
- table = GrafanaTable(columns=columns)
132
- for endpoint in endpoint_list.endpoints:
133
- row = [
134
- endpoint.metadata.uid,
135
- endpoint.spec.function_uri,
136
- endpoint.spec.model,
137
- endpoint.spec.model_class,
138
- endpoint.status.first_request,
139
- endpoint.status.last_request,
140
- "N/A", # Leaving here for backwards compatibility
141
- endpoint.status.error_count,
142
- endpoint.status.drift_status,
143
- ]
144
-
145
- if (
146
- endpoint.status.metrics
147
- and mlrun.model_monitoring.EventKeyMetrics.GENERIC
148
- in endpoint.status.metrics
149
- ):
150
- row.extend(
151
- [
152
- endpoint.status.metrics[
153
- mlrun.model_monitoring.EventKeyMetrics.GENERIC
154
- ][mlrun.model_monitoring.EventLiveStats.PREDICTIONS_PER_SECOND],
155
- endpoint.status.metrics[
156
- mlrun.model_monitoring.EventKeyMetrics.GENERIC
157
- ][mlrun.model_monitoring.EventLiveStats.LATENCY_AVG_1H],
158
- ]
159
- )
160
-
161
- table.add_row(*row)
162
-
163
- return [table]
164
-
165
-
166
- async def grafana_individual_feature_analysis(
167
- body: Dict[str, Any],
168
- query_parameters: Dict[str, str],
169
- auth_info: mlrun.api.schemas.AuthInfo,
170
- ):
171
- endpoint_id = query_parameters.get("endpoint_id")
172
- project = query_parameters.get("project")
173
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
174
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
175
- project,
176
- endpoint_id,
177
- mlrun.api.schemas.AuthorizationAction.read,
178
- auth_info,
179
- )
180
-
181
- endpoint = await run_in_threadpool(
182
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
183
- auth_info=auth_info,
184
- project=project,
185
- endpoint_id=endpoint_id,
186
- feature_analysis=True,
187
- )
188
-
189
- # Load JSON data from KV, make sure not to fail if a field is missing
190
- feature_stats = endpoint.status.feature_stats or {}
191
- current_stats = endpoint.status.current_stats or {}
192
- drift_measures = endpoint.status.drift_measures or {}
193
-
194
- table = GrafanaTable(
195
- columns=[
196
- GrafanaColumn(text="feature_name", type="string"),
197
- GrafanaColumn(text="actual_min", type="number"),
198
- GrafanaColumn(text="actual_mean", type="number"),
199
- GrafanaColumn(text="actual_max", type="number"),
200
- GrafanaColumn(text="expected_min", type="number"),
201
- GrafanaColumn(text="expected_mean", type="number"),
202
- GrafanaColumn(text="expected_max", type="number"),
203
- GrafanaColumn(text="tvd", type="number"),
204
- GrafanaColumn(text="hellinger", type="number"),
205
- GrafanaColumn(text="kld", type="number"),
206
- ]
207
- )
208
-
209
- for feature, base_stat in feature_stats.items():
210
- current_stat = current_stats.get(feature, {})
211
- drift_measure = drift_measures.get(feature, {})
212
-
213
- table.add_row(
214
- feature,
215
- current_stat.get("min"),
216
- current_stat.get("mean"),
217
- current_stat.get("max"),
218
- base_stat.get("min"),
219
- base_stat.get("mean"),
220
- base_stat.get("max"),
221
- drift_measure.get("tvd"),
222
- drift_measure.get("hellinger"),
223
- drift_measure.get("kld"),
224
- )
225
-
226
- return [table]
227
-
228
-
229
- async def grafana_overall_feature_analysis(
230
- body: Dict[str, Any],
231
- query_parameters: Dict[str, str],
232
- auth_info: mlrun.api.schemas.AuthInfo,
233
- ):
234
- endpoint_id = query_parameters.get("endpoint_id")
235
- project = query_parameters.get("project")
236
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
237
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
238
- project,
239
- endpoint_id,
240
- mlrun.api.schemas.AuthorizationAction.read,
241
- auth_info,
242
- )
243
- endpoint = await run_in_threadpool(
244
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
245
- auth_info=auth_info,
246
- project=project,
247
- endpoint_id=endpoint_id,
248
- feature_analysis=True,
249
- )
250
-
251
- table = GrafanaTable(
252
- columns=[
253
- GrafanaNumberColumn(text="tvd_sum"),
254
- GrafanaNumberColumn(text="tvd_mean"),
255
- GrafanaNumberColumn(text="hellinger_sum"),
256
- GrafanaNumberColumn(text="hellinger_mean"),
257
- GrafanaNumberColumn(text="kld_sum"),
258
- GrafanaNumberColumn(text="kld_mean"),
259
- ]
260
- )
261
-
262
- if endpoint.status.drift_measures:
263
- table.add_row(
264
- endpoint.status.drift_measures.get("tvd_sum"),
265
- endpoint.status.drift_measures.get("tvd_mean"),
266
- endpoint.status.drift_measures.get("hellinger_sum"),
267
- endpoint.status.drift_measures.get("hellinger_mean"),
268
- endpoint.status.drift_measures.get("kld_sum"),
269
- endpoint.status.drift_measures.get("kld_mean"),
270
- )
271
-
272
- return [table]
273
-
274
-
275
- async def grafana_incoming_features(
276
- body: Dict[str, Any],
277
- query_parameters: Dict[str, str],
278
- auth_info: mlrun.api.schemas.AuthInfo,
279
- ):
280
- endpoint_id = query_parameters.get("endpoint_id")
281
- project = query_parameters.get("project")
282
- start = body.get("rangeRaw", {}).get("from", "now-1h")
283
- end = body.get("rangeRaw", {}).get("to", "now")
284
-
285
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
286
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
287
- project,
288
- endpoint_id,
289
- mlrun.api.schemas.AuthorizationAction.read,
290
- auth_info,
291
- )
292
-
293
- endpoint = await run_in_threadpool(
294
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
295
- auth_info=auth_info,
296
- project=project,
297
- endpoint_id=endpoint_id,
298
- )
299
-
300
- time_series = []
301
-
302
- feature_names = endpoint.spec.feature_names
303
-
304
- if not feature_names:
305
- logger.warn(
306
- "'feature_names' is either missing or not initialized in endpoint record",
307
- endpoint_id=endpoint.metadata.uid,
308
- )
309
- return time_series
310
-
311
- path = config.model_endpoint_monitoring.store_prefixes.default.format(
312
- project=project, kind=mlrun.api.schemas.ModelMonitoringStoreKinds.EVENTS
313
- )
314
- _, container, path = parse_model_endpoint_store_prefix(path)
315
-
316
- client = get_frames_client(
317
- token=auth_info.data_session,
318
- address=config.v3io_framesd,
319
- container=container,
320
- )
321
-
322
- data: pd.DataFrame = await run_in_threadpool(
323
- client.read,
324
- backend="tsdb",
325
- table=path,
326
- columns=feature_names,
327
- filter=f"endpoint_id=='{endpoint_id}'",
328
- start=start,
329
- end=end,
330
- )
331
-
332
- data.drop(["endpoint_id"], axis=1, inplace=True, errors="ignore")
333
- data.index = data.index.astype(np.int64) // 10**6
334
-
335
- for feature, indexed_values in data.to_dict().items():
336
- target = GrafanaTimeSeriesTarget(target=feature)
337
- for index, value in indexed_values.items():
338
- data_point = GrafanaDataPoint(value=float(value), timestamp=index)
339
- target.add_data_point(data_point)
340
- time_series.append(target)
341
-
342
- return time_series
343
-
344
-
345
- def parse_query_parameters(request_body: Dict[str, Any]) -> Dict[str, str]:
346
- """
347
- This function searches for the target field in Grafana's SimpleJson json. Once located, the target string is
348
- parsed by splitting on semi-colons (;). Each part in the resulting list is then split by an equal sign (=) to be
349
- read as key-value pairs.
350
- """
351
-
352
- # Try to get the target
353
- targets = request_body.get("targets", [])
354
-
355
- if len(targets) > 1:
356
- logger.warn(
357
- f"The 'targets' list contains more then one element ({len(targets)}), all targets except the first one are "
358
- f"ignored."
359
- )
360
-
361
- target_obj = targets[0] if targets else {}
362
- target_query = target_obj.get("target") if target_obj else ""
363
-
364
- if not target_query:
365
- raise MLRunBadRequestError(f"Target missing in request body:\n {request_body}")
366
-
367
- parameters = _parse_parameters(target_query)
368
-
369
- return parameters
370
-
371
-
372
- def parse_search_parameters(request_body: Dict[str, Any]) -> Dict[str, str]:
373
- """
374
- This function searches for the target field in Grafana's SimpleJson json. Once located, the target string is
375
- parsed by splitting on semi-colons (;). Each part in the resulting list is then split by an equal sign (=) to be
376
- read as key-value pairs.
377
- """
378
-
379
- # Try to get the target
380
- target = request_body.get("target")
381
-
382
- if not target:
383
- raise MLRunBadRequestError(f"Target missing in request body:\n {request_body}")
384
-
385
- parameters = _parse_parameters(target)
386
-
387
- return parameters
388
-
389
-
390
- def _parse_parameters(target_query):
391
- parameters = {}
392
- for query in filter(lambda q: q, target_query.split(";")):
393
- query_parts = query.split("=")
394
- if len(query_parts) < 2:
395
- raise MLRunBadRequestError(
396
- f"Query must contain both query key and query value. Expected query_key=query_value, found {query} "
397
- f"instead."
398
- )
399
- parameters[query_parts[0]] = query_parts[1]
400
- return parameters
401
-
402
-
403
- def drop_grafana_escape_chars(query_parameters: Dict[str, str]):
404
- query_parameters = dict(query_parameters)
405
- endpoint_id = query_parameters.get("endpoint_id")
406
- if endpoint_id is not None:
407
- query_parameters["endpoint_id"] = endpoint_id.replace("\\", "")
408
- return query_parameters
409
-
410
-
411
- def validate_query_parameters(
412
- query_parameters: Dict[str, str], supported_endpoints: Optional[Set[str]] = None
413
- ):
414
- """Validates the parameters sent via Grafana's SimpleJson query"""
415
- if "target_endpoint" not in query_parameters:
416
- raise MLRunBadRequestError(
417
- f"Expected 'target_endpoint' field in query, found {query_parameters} instead"
418
- )
419
-
420
- if (
421
- supported_endpoints is not None
422
- and query_parameters["target_endpoint"] not in supported_endpoints
423
- ):
424
- raise MLRunBadRequestError(
425
- f"{query_parameters['target_endpoint']} unsupported in query parameters: {query_parameters}. "
426
- f"Currently supports: {','.join(supported_endpoints)}"
427
- )
@@ -1,40 +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
- import hashlib
15
-
16
- from pyspark.sql.functions import udf
17
- from pyspark.sql.types import StringType
18
-
19
-
20
- def _hash_list(*list_to_hash):
21
- list_to_hash = [str(element) for element in list_to_hash]
22
- str_concatted = "".join(list_to_hash)
23
- sha1 = hashlib.sha1()
24
- sha1.update(str_concatted.encode("utf8"))
25
- return sha1.hexdigest()
26
-
27
-
28
- def _redis_stringify_key(key_list):
29
- suffix = "}:static"
30
- if isinstance(key_list, list):
31
- if len(key_list) >= 2:
32
- return str(key_list[0]) + "." + _hash_list(key_list[1:]) + suffix
33
- if len(key_list) == 2:
34
- return str(key_list[0]) + "." + str(key_list[1]) + suffix
35
- return str(key_list[0]) + suffix
36
- return str(key_list) + suffix
37
-
38
-
39
- hash_and_concat_v3io_udf = udf(_hash_list, StringType())
40
- hash_and_concat_redis_udf = udf(_redis_stringify_key, StringType())
@@ -1,44 +0,0 @@
1
- # Copyright 2018 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
- # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
- # for backwards compatibility
17
-
18
- __all__ = [
19
- "ModelEndpoint",
20
- "ModelMonitoringMode",
21
- "EndpointType",
22
- "create_model_endpoint_uid",
23
- "EventFieldType",
24
- "EventLiveStats",
25
- "EventKeyMetrics",
26
- "TimeSeriesTarget",
27
- "ModelEndpointTarget",
28
- "FileTargetKind",
29
- "ProjectSecretKeys",
30
- "ModelMonitoringStoreKinds",
31
- ]
32
-
33
- from .common import EndpointType, ModelMonitoringMode, create_model_endpoint_uid
34
- from .constants import (
35
- EventFieldType,
36
- EventKeyMetrics,
37
- EventLiveStats,
38
- FileTargetKind,
39
- ModelEndpointTarget,
40
- ModelMonitoringStoreKinds,
41
- ProjectSecretKeys,
42
- TimeSeriesTarget,
43
- )
44
- from .model_endpoint import ModelEndpoint
@@ -1,112 +0,0 @@
1
- # Copyright 2018 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
- import enum
17
- import hashlib
18
- from dataclasses import dataclass
19
- from typing import Optional
20
-
21
- import mlrun.utils
22
-
23
-
24
- class ModelMonitoringMode(str, enum.Enum):
25
- enabled = "enabled"
26
- disabled = "disabled"
27
-
28
-
29
- class EndpointType(enum.IntEnum):
30
- NODE_EP = 1 # end point that is not a child of a router
31
- ROUTER = 2 # endpoint that is router
32
- LEAF_EP = 3 # end point that is a child of a router
33
-
34
-
35
- def create_model_endpoint_uid(function_uri: str, versioned_model: str):
36
- function_uri = FunctionURI.from_string(function_uri)
37
- versioned_model = VersionedModel.from_string(versioned_model)
38
-
39
- if (
40
- not function_uri.project
41
- or not function_uri.function
42
- or not versioned_model.model
43
- ):
44
- raise ValueError("Both function_uri and versioned_model have to be initialized")
45
-
46
- uid = EndpointUID(
47
- function_uri.project,
48
- function_uri.function,
49
- function_uri.tag,
50
- function_uri.hash_key,
51
- versioned_model.model,
52
- versioned_model.version,
53
- )
54
-
55
- return uid
56
-
57
-
58
- @dataclass
59
- class FunctionURI:
60
- project: str
61
- function: str
62
- tag: Optional[str] = None
63
- hash_key: Optional[str] = None
64
-
65
- @classmethod
66
- def from_string(cls, function_uri):
67
- project, uri, tag, hash_key = mlrun.utils.parse_versioned_object_uri(
68
- function_uri
69
- )
70
- return cls(
71
- project=project,
72
- function=uri,
73
- tag=tag or None,
74
- hash_key=hash_key or None,
75
- )
76
-
77
-
78
- @dataclass
79
- class VersionedModel:
80
- model: str
81
- version: Optional[str]
82
-
83
- @classmethod
84
- def from_string(cls, model):
85
- try:
86
- model, version = model.split(":")
87
- except ValueError:
88
- model, version = model, None
89
-
90
- return cls(model, version)
91
-
92
-
93
- @dataclass
94
- class EndpointUID:
95
- project: str
96
- function: str
97
- function_tag: str
98
- function_hash_key: str
99
- model: str
100
- model_version: str
101
- uid: Optional[str] = None
102
-
103
- def __post_init__(self):
104
- function_ref = (
105
- f"{self.function}_{self.function_tag or self.function_hash_key or 'N/A'}"
106
- )
107
- versioned_model = f"{self.model}_{self.model_version or 'N/A'}"
108
- unique_string = f"{self.project}_{function_ref}_{versioned_model}"
109
- self.uid = hashlib.sha1(unique_string.encode("utf-8")).hexdigest()
110
-
111
- def __str__(self):
112
- return self.uid