mlrun 1.8.0rc25__py3-none-any.whl → 1.8.0rc27__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.

mlrun/__main__.py CHANGED
@@ -772,10 +772,11 @@ def get(kind, name, selector, namespace, uid, project, tag, db, extra_args):
772
772
 
773
773
  runs = run_db.list_runs(uid=uid, project=project, labels=selector)
774
774
  df = runs.to_df()[
775
- ["name", "uid", "iter", "start", "state", "parameters", "results"]
775
+ ["name", "uid", "iter", "start", "end", "state", "parameters", "results"]
776
776
  ]
777
777
  # df['uid'] = df['uid'].apply(lambda x: f'..{x[-6:]}')
778
- df["start"] = df["start"].apply(time_str)
778
+ for time_column in ["start", "end"]:
779
+ df[time_column] = df[time_column].apply(time_str)
779
780
  df["parameters"] = df["parameters"].apply(dict_to_str)
780
781
  df["results"] = df["results"].apply(dict_to_str)
781
782
  print(tabulate(df, headers="keys"))
@@ -228,30 +228,8 @@ class MLRunLoader:
228
228
  @staticmethod
229
229
  def artifact_key_instance(artifact_key: str, src_path: str) -> str:
230
230
  if "%%" in artifact_key:
231
- pattern = mlrun.utils.regex.artifact_key[0]
232
- # Convert anchored pattern (^...$) to non-anchored version for finditer
233
- search_pattern = pattern.strip("^$")
234
- result = []
235
- current_pos = 0
236
-
237
- # Find all valid sequences
238
- for match in re.finditer(search_pattern, src_path):
239
- # Add hex values for characters between matches
240
- for char in src_path[current_pos : match.start()]:
241
- result.append(hex(ord(char))[2:].zfill(2))
242
-
243
- # Add the valid sequence
244
- result.append(match.group())
245
- current_pos = match.end()
246
-
247
- # Handle any remaining characters after the last match
248
- for char in src_path[current_pos:]:
249
- result.append(hex(ord(char))[2:].zfill(2))
250
-
251
- resolved_path = "".join(result)
252
-
231
+ resolved_path = DocumentArtifact.key_from_source(src_path)
253
232
  artifact_key = artifact_key.replace("%%", resolved_path)
254
-
255
233
  return artifact_key
256
234
 
257
235
 
@@ -260,6 +238,41 @@ class DocumentArtifact(Artifact):
260
238
  A specific artifact class inheriting from generic artifact, used to maintain Document meta-data.
261
239
  """
262
240
 
241
+ @staticmethod
242
+ def key_from_source(src_path: str) -> str:
243
+ """Convert a source path into a valid artifact key by replacing invalid characters with underscores.
244
+ Args:
245
+ src_path (str): The source path to be converted into a valid artifact key
246
+ Returns:
247
+ str: A modified version of the source path where all invalid characters are replaced
248
+ with underscores while preserving valid sequences in their original positions
249
+ Examples:
250
+ >>> DocumentArtifact.key_from_source("data/file-name(v1).txt")
251
+ "data_file-name_v1__txt"
252
+ """
253
+ pattern = mlrun.utils.regex.artifact_key[0]
254
+ # Convert anchored pattern (^...$) to non-anchored version for finditer
255
+ search_pattern = pattern.strip("^$")
256
+ result = []
257
+ current_pos = 0
258
+
259
+ # Find all valid sequences
260
+ for match in re.finditer(search_pattern, src_path):
261
+ # Add '_' values for characters between matches
262
+ for char in src_path[current_pos : match.start()]:
263
+ result.append("_")
264
+
265
+ # Add the valid sequence
266
+ result.append(match.group())
267
+ current_pos = match.end()
268
+
269
+ # Handle any remaining characters after the last match
270
+ for char in src_path[current_pos:]:
271
+ result.append("_")
272
+
273
+ resolved_path = "".join(result)
274
+ return resolved_path
275
+
263
276
  class DocumentArtifactSpec(ArtifactSpec):
264
277
  _dict_fields = ArtifactSpec._dict_fields + [
265
278
  "document_loader",
@@ -384,7 +397,7 @@ class DocumentArtifact(Artifact):
384
397
  metadata[self.METADATA_ORIGINAL_SOURCE_KEY] = self.spec.original_source
385
398
  metadata[self.METADATA_SOURCE_KEY] = self.get_source()
386
399
  metadata[self.METADATA_ARTIFACT_TAG] = self.tag or "latest"
387
- metadata[self.METADATA_ARTIFACT_KEY] = self.key
400
+ metadata[self.METADATA_ARTIFACT_KEY] = self.db_key
388
401
  metadata[self.METADATA_ARTIFACT_PROJECT] = self.metadata.project
389
402
 
390
403
  if self.get_target_path():
mlrun/artifacts/model.py CHANGED
@@ -30,6 +30,7 @@ from ..utils import StorePrefix, is_relative_path
30
30
  from .base import Artifact, ArtifactSpec, upload_extra_data
31
31
 
32
32
  model_spec_filename = "model_spec.yaml"
33
+ MODEL_OPTIONAL_SUFFIXES = [".tar.gz", ".pkl", ".bin", ".pickle"]
33
34
 
34
35
 
35
36
  class ModelArtifactSpec(ArtifactSpec):
@@ -426,7 +427,17 @@ def get_model(model_dir, suffix=""):
426
427
  model_file = ""
427
428
  model_spec = None
428
429
  extra_dataitems = {}
429
- suffix = suffix or ".pkl"
430
+ default_suffix = ".pkl"
431
+
432
+ alternative_suffix = next(
433
+ (
434
+ optional_suffix
435
+ for optional_suffix in MODEL_OPTIONAL_SUFFIXES
436
+ if model_dir.lower().endswith(optional_suffix)
437
+ ),
438
+ None,
439
+ )
440
+
430
441
  if hasattr(model_dir, "artifact_url"):
431
442
  model_dir = model_dir.artifact_url
432
443
 
@@ -440,15 +451,19 @@ def get_model(model_dir, suffix=""):
440
451
  target, model_spec.model_target_file or model_spec.model_file
441
452
  )
442
453
  extra_dataitems = _get_extra(target, model_spec.extra_data)
443
-
454
+ suffix = suffix or default_suffix
444
455
  elif model_dir.lower().endswith(".yaml"):
445
456
  model_spec = _load_model_spec(model_dir)
446
457
  model_file = _get_file_path(model_dir, model_spec.model_file)
447
458
  extra_dataitems = _get_extra(model_dir, model_spec.extra_data)
448
-
449
- elif model_dir.endswith(suffix):
459
+ suffix = suffix or default_suffix
460
+ elif suffix and model_dir.endswith(suffix):
461
+ model_file = model_dir
462
+ elif not suffix and alternative_suffix:
463
+ suffix = alternative_suffix
450
464
  model_file = model_dir
451
465
  else:
466
+ suffix = suffix or default_suffix
452
467
  dirobj = mlrun.datastore.store_manager.object(url=model_dir)
453
468
  model_dir_list = dirobj.listdir()
454
469
  if model_spec_filename in model_dir_list:
@@ -33,6 +33,7 @@ class FeatureSetFormat(ObjectFormat, mlrun.common.types.StrEnum):
33
33
  "metadata.name",
34
34
  "metadata.project",
35
35
  "metadata.tag",
36
+ "metadata.updated",
36
37
  "metadata.uid",
37
38
  "metadata.labels",
38
39
  "spec.entities",
@@ -47,9 +47,9 @@ def parse_monitoring_stream_path(
47
47
  function_name is None
48
48
  or function_name == mm_constants.MonitoringFunctionNames.STREAM
49
49
  ):
50
- stream_uri += f"?topic=monitoring_stream_{project}"
50
+ stream_uri += f"?topic=monitoring_stream_{project}_v1"
51
51
  else:
52
- stream_uri += f"?topic=monitoring_stream_{project}_{function_name}"
52
+ stream_uri += f"?topic=monitoring_stream_{project}_{function_name}_v1"
53
53
 
54
54
  return stream_uri
55
55
 
@@ -146,7 +146,6 @@ class EventFieldType:
146
146
 
147
147
  class FeatureSetFeatures(MonitoringStrEnum):
148
148
  LATENCY = EventFieldType.LATENCY
149
- ERROR_COUNT = EventFieldType.ERROR_COUNT
150
149
  METRICS = EventFieldType.METRICS
151
150
 
152
151
  @classmethod
@@ -328,6 +327,7 @@ class V3IOTSDBTables(MonitoringStrEnum):
328
327
  METRICS = "metrics"
329
328
  EVENTS = "events"
330
329
  ERRORS = "errors"
330
+ PREDICTIONS = "predictions"
331
331
 
332
332
 
333
333
  class TDEngineSuperTables(MonitoringStrEnum):
@@ -62,3 +62,4 @@ class EngineType(StrEnum):
62
62
  LOCAL = "local"
63
63
  REMOTE = "remote"
64
64
  KFP = "kfp"
65
+ REMOTE_KFP = "remote:kfp"
mlrun/config.py CHANGED
@@ -1304,7 +1304,7 @@ class Config:
1304
1304
  project=project,
1305
1305
  kind=kind
1306
1306
  if function_name is None
1307
- else f"{kind}-{function_name.lower()}",
1307
+ else f"{kind}-{function_name.lower()}-v1",
1308
1308
  )
1309
1309
  elif (
1310
1310
  kind == "stream"
@@ -1313,19 +1313,23 @@ class Config:
1313
1313
  ):
1314
1314
  return mlrun.mlconf.model_endpoint_monitoring.store_prefixes.user_space.format(
1315
1315
  project=project,
1316
- kind=kind,
1316
+ kind=f"{kind}-v1",
1317
1317
  )
1318
- else:
1319
- if (
1320
- function_name
1321
- == mlrun.common.schemas.model_monitoring.constants.MonitoringFunctionNames.APPLICATION_CONTROLLER
1322
- ):
1323
- kind = function_name
1318
+ elif (
1319
+ function_name
1320
+ == mlrun.common.schemas.model_monitoring.constants.MonitoringFunctionNames.APPLICATION_CONTROLLER
1321
+ and kind == "stream"
1322
+ ):
1324
1323
  return mlrun.mlconf.model_endpoint_monitoring.store_prefixes.default.format(
1325
1324
  project=project,
1326
- kind=kind,
1325
+ kind=f"{kind}-{function_name.lower()}-v1",
1327
1326
  )
1328
1327
 
1328
+ return mlrun.mlconf.model_endpoint_monitoring.store_prefixes.default.format(
1329
+ project=project,
1330
+ kind=kind,
1331
+ )
1332
+
1329
1333
  # Get the current offline path from the configuration
1330
1334
  file_path = mlrun.mlconf.model_endpoint_monitoring.offline_storage_path.format(
1331
1335
  project=project, kind=kind
mlrun/db/base.py CHANGED
@@ -108,6 +108,8 @@ class RunDBInterface(ABC):
108
108
  start_time_to: Optional[datetime.datetime] = None,
109
109
  last_update_time_from: Optional[datetime.datetime] = None,
110
110
  last_update_time_to: Optional[datetime.datetime] = None,
111
+ end_time_from: Optional[datetime.datetime] = None,
112
+ end_time_to: Optional[datetime.datetime] = None,
111
113
  partition_by: Union[mlrun.common.schemas.RunPartitionByField, str] = None,
112
114
  rows_per_partition: int = 1,
113
115
  partition_sort_by: Union[mlrun.common.schemas.SortField, str] = None,
mlrun/db/httpdb.py CHANGED
@@ -763,7 +763,6 @@ class HTTPRunDB(RunDBInterface):
763
763
  :returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
764
764
  """
765
765
  project = project or config.default_project
766
-
767
766
  response = self.api_call(
768
767
  "POST",
769
768
  path=f"projects/{project}/runs/{uid}/push-notifications",
@@ -906,6 +905,8 @@ class HTTPRunDB(RunDBInterface):
906
905
  start_time_to: Optional[datetime] = None,
907
906
  last_update_time_from: Optional[datetime] = None,
908
907
  last_update_time_to: Optional[datetime] = None,
908
+ end_time_from: Optional[datetime] = None,
909
+ end_time_to: Optional[datetime] = None,
909
910
  partition_by: Optional[
910
911
  Union[mlrun.common.schemas.RunPartitionByField, str]
911
912
  ] = None,
@@ -952,6 +953,8 @@ class HTTPRunDB(RunDBInterface):
952
953
  :param last_update_time_from: Filter by run last update time in ``(last_update_time_from,
953
954
  last_update_time_to)``.
954
955
  :param last_update_time_to: Filter by run last update time in ``(last_update_time_from, last_update_time_to)``.
956
+ :param end_time_from: Filter by run end time in ``[end_time_from, end_time_to]``.
957
+ :param end_time_to: Filter by run end time in ``[end_time_from, end_time_to]``.
955
958
  :param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
956
959
  parameter must be provided as well.
957
960
  :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
@@ -977,6 +980,8 @@ class HTTPRunDB(RunDBInterface):
977
980
  start_time_to=start_time_to,
978
981
  last_update_time_from=last_update_time_from,
979
982
  last_update_time_to=last_update_time_to,
983
+ end_time_from=end_time_from,
984
+ end_time_to=end_time_to,
980
985
  partition_by=partition_by,
981
986
  rows_per_partition=rows_per_partition,
982
987
  partition_sort_by=partition_sort_by,
@@ -5227,6 +5232,8 @@ class HTTPRunDB(RunDBInterface):
5227
5232
  start_time_to: Optional[datetime] = None,
5228
5233
  last_update_time_from: Optional[datetime] = None,
5229
5234
  last_update_time_to: Optional[datetime] = None,
5235
+ end_time_from: Optional[datetime] = None,
5236
+ end_time_to: Optional[datetime] = None,
5230
5237
  partition_by: Optional[
5231
5238
  Union[mlrun.common.schemas.RunPartitionByField, str]
5232
5239
  ] = None,
@@ -5278,6 +5285,8 @@ class HTTPRunDB(RunDBInterface):
5278
5285
  and not start_time_to
5279
5286
  and not last_update_time_from
5280
5287
  and not last_update_time_to
5288
+ and not end_time_from
5289
+ and not end_time_to
5281
5290
  and not partition_by
5282
5291
  and not partition_sort_by
5283
5292
  and not iter
@@ -5302,6 +5311,8 @@ class HTTPRunDB(RunDBInterface):
5302
5311
  "start_time_to": datetime_to_iso(start_time_to),
5303
5312
  "last_update_time_from": datetime_to_iso(last_update_time_from),
5304
5313
  "last_update_time_to": datetime_to_iso(last_update_time_to),
5314
+ "end_time_from": datetime_to_iso(end_time_from),
5315
+ "end_time_to": datetime_to_iso(end_time_to),
5305
5316
  "with-notifications": with_notifications,
5306
5317
  "page": page,
5307
5318
  "page-size": page_size,
mlrun/db/nopdb.py CHANGED
@@ -138,6 +138,8 @@ class NopDB(RunDBInterface):
138
138
  start_time_to: Optional[datetime.datetime] = None,
139
139
  last_update_time_from: Optional[datetime.datetime] = None,
140
140
  last_update_time_to: Optional[datetime.datetime] = None,
141
+ end_time_from: Optional[datetime.datetime] = None,
142
+ end_time_to: Optional[datetime.datetime] = None,
141
143
  partition_by: Union[mlrun.common.schemas.RunPartitionByField, str] = None,
142
144
  rows_per_partition: int = 1,
143
145
  partition_sort_by: Union[mlrun.common.schemas.SortField, str] = None,
mlrun/execution.py CHANGED
@@ -876,7 +876,7 @@ class MLClientCtx:
876
876
 
877
877
  def log_document(
878
878
  self,
879
- key: str,
879
+ key: str = "",
880
880
  tag: str = "",
881
881
  local_path: str = "",
882
882
  artifact_path: Optional[str] = None,
@@ -890,7 +890,8 @@ class MLClientCtx:
890
890
  """
891
891
  Log a document as an artifact.
892
892
 
893
- :param key: Artifact key
893
+ :param key: Optional artifact key. If not provided, will be derived from local_path
894
+ or target_path using DocumentArtifact.key_from_source()
894
895
  :param tag: Version tag
895
896
  :param local_path: path to the local file we upload, will also be use
896
897
  as the destination subpath (under "artifact_path")
@@ -923,7 +924,6 @@ class MLClientCtx:
923
924
  Example:
924
925
  >>> # Log a PDF document with custom loader
925
926
  >>> project.log_document(
926
- ... key="my_doc",
927
927
  ... local_path="path/to/doc.pdf",
928
928
  ... document_loader_spec=DocumentLoaderSpec(
929
929
  ... loader_class_name="langchain_community.document_loaders.PDFLoader",
@@ -932,6 +932,14 @@ class MLClientCtx:
932
932
  ... ),
933
933
  ... )
934
934
  """
935
+
936
+ if not key and not local_path and not target_path:
937
+ raise ValueError(
938
+ "Must provide either 'key' parameter or 'local_path'/'target_path' to derive the key from"
939
+ )
940
+ if not key:
941
+ key = DocumentArtifact.key_from_source(local_path or target_path)
942
+
935
943
  doc_artifact = DocumentArtifact(
936
944
  key=key,
937
945
  original_source=local_path or target_path,
mlrun/launcher/local.py CHANGED
@@ -281,5 +281,9 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
281
281
  # once the run is completed, and we can just push the notifications.
282
282
  # Only push from jupyter, not from the CLI.
283
283
  # "handler" and "dask" kinds are special cases of local runs which don't set local=True
284
- if self._is_run_local or runtime.kind in ["handler", "dask"]:
284
+ if self._is_run_local or runtime.kind in ["handler"]:
285
285
  mlrun.utils.notifications.NotificationPusher([runobj]).push()
286
+ elif runtime.kind in ["dask"]:
287
+ runtime._get_db().push_run_notifications(
288
+ uid=runobj.metadata.uid, project=runobj.metadata.project
289
+ )
mlrun/lists.py CHANGED
@@ -29,6 +29,7 @@ list_header = [
29
29
  "uid",
30
30
  "iter",
31
31
  "start",
32
+ "end",
32
33
  "state",
33
34
  "kind",
34
35
  "name",
@@ -58,6 +59,7 @@ class RunList(list):
58
59
  get_in(run, "metadata.uid", ""),
59
60
  get_in(run, "metadata.iteration", ""),
60
61
  get_in(run, "status.start_time", ""),
62
+ get_in(run, "status.end_time", ""),
61
63
  get_in(run, "status.state", ""),
62
64
  get_in(run, "step_kind", get_in(run, "kind", "")),
63
65
  get_in(run, "metadata.name", ""),
@@ -103,7 +105,8 @@ class RunList(list):
103
105
  return self._df
104
106
  rows = self.to_rows(extend_iterations=extend_iterations)
105
107
  df = pd.DataFrame(rows[1:], columns=rows[0]) # .set_index('iter')
106
- df["start"] = pd.to_datetime(df["start"])
108
+ for time_column in ["start", "end"]:
109
+ df[time_column] = pd.to_datetime(df[time_column])
107
110
 
108
111
  if flat:
109
112
  df = flatten(df, "labels")
mlrun/model.py CHANGED
@@ -1284,6 +1284,7 @@ class RunStatus(ModelObj):
1284
1284
  results=None,
1285
1285
  artifacts=None,
1286
1286
  start_time=None,
1287
+ end_time=None,
1287
1288
  last_update=None,
1288
1289
  iterations=None,
1289
1290
  ui_url=None,
@@ -1299,6 +1300,7 @@ class RunStatus(ModelObj):
1299
1300
  self.results = results
1300
1301
  self._artifacts = artifacts
1301
1302
  self.start_time = start_time
1303
+ self.end_time = end_time
1302
1304
  self.last_update = last_update
1303
1305
  self.iterations = iterations
1304
1306
  self.ui_url = ui_url
@@ -135,7 +135,7 @@ class V3IOTSDBConnector(TSDBConnector):
135
135
  monitoring_predictions_full_path = (
136
136
  mlrun.mlconf.get_model_monitoring_file_target_path(
137
137
  project=self.project,
138
- kind=mm_schemas.FileTargetKind.PREDICTIONS,
138
+ kind=mm_schemas.V3IOTSDBTables.PREDICTIONS,
139
139
  )
140
140
  )
141
141
  (
@@ -145,7 +145,7 @@ class V3IOTSDBConnector(TSDBConnector):
145
145
  ) = mlrun.common.model_monitoring.helpers.parse_model_endpoint_store_prefix(
146
146
  monitoring_predictions_full_path
147
147
  )
148
- self.tables[mm_schemas.FileTargetKind.PREDICTIONS] = monitoring_predictions_path
148
+ self.tables[mm_schemas.V3IOTSDBTables.PREDICTIONS] = monitoring_predictions_path
149
149
 
150
150
  def create_tables(self) -> None:
151
151
  """
@@ -226,7 +226,7 @@ class V3IOTSDBConnector(TSDBConnector):
226
226
  "storey.TSDBTarget",
227
227
  name="tsdb_predictions",
228
228
  after="FilterNOP",
229
- path=f"{self.container}/{self.tables[mm_schemas.FileTargetKind.PREDICTIONS]}",
229
+ path=f"{self.container}/{self.tables[mm_schemas.V3IOTSDBTables.PREDICTIONS]}",
230
230
  rate="1/s",
231
231
  time_col=mm_schemas.EventFieldType.TIMESTAMP,
232
232
  container=self.container,
@@ -740,7 +740,7 @@ class V3IOTSDBConnector(TSDBConnector):
740
740
  "both or neither of `aggregation_window` and `agg_funcs` must be provided"
741
741
  )
742
742
  df = self._get_records(
743
- table=mm_schemas.FileTargetKind.PREDICTIONS,
743
+ table=mm_schemas.V3IOTSDBTables.PREDICTIONS,
744
744
  start=start,
745
745
  end=end,
746
746
  columns=[mm_schemas.EventFieldType.ESTIMATED_PREDICTION_COUNT],
@@ -782,7 +782,7 @@ class V3IOTSDBConnector(TSDBConnector):
782
782
  filter_query = self._get_endpoint_filter(endpoint_id=endpoint_ids)
783
783
  start, end = self._get_start_end(start, end)
784
784
  df = self._get_records(
785
- table=mm_schemas.FileTargetKind.PREDICTIONS,
785
+ table=mm_schemas.V3IOTSDBTables.PREDICTIONS,
786
786
  start=start,
787
787
  end=end,
788
788
  filter_query=filter_query,
@@ -919,7 +919,7 @@ class V3IOTSDBConnector(TSDBConnector):
919
919
  start = start or (mlrun.utils.datetime_now() - timedelta(hours=24))
920
920
  start, end = self._get_start_end(start, end)
921
921
  df = self._get_records(
922
- table=mm_schemas.FileTargetKind.PREDICTIONS,
922
+ table=mm_schemas.V3IOTSDBTables.PREDICTIONS,
923
923
  start=start,
924
924
  end=end,
925
925
  columns=[mm_schemas.EventFieldType.LATENCY],
@@ -109,7 +109,7 @@ def filter_results_by_regex(
109
109
  result_name_filters=validated_filters,
110
110
  ):
111
111
  filtered_metrics_names.append(existing_result_name)
112
- return filtered_metrics_names
112
+ return list(set(filtered_metrics_names))
113
113
 
114
114
 
115
115
  def get_stream_path(
@@ -12,7 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import collections
16
15
  import datetime
17
16
  import os
18
17
  import typing
@@ -373,9 +372,6 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
373
372
  self.first_request: dict[str, str] = dict()
374
373
  self.last_request: dict[str, str] = dict()
375
374
 
376
- # Number of errors (value) per endpoint (key)
377
- self.error_count: dict[str, int] = collections.defaultdict(int)
378
-
379
375
  # Set of endpoints in the current events
380
376
  self.endpoints: set[str] = set()
381
377
 
@@ -417,10 +413,9 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
417
413
  predictions = event.get("resp", {}).get("outputs")
418
414
 
419
415
  if not self.is_valid(
420
- endpoint_id,
421
- is_not_none,
422
- timestamp,
423
- ["when"],
416
+ validation_function=is_not_none,
417
+ field=timestamp,
418
+ dict_path=["when"],
424
419
  ):
425
420
  return None
426
421
 
@@ -432,31 +427,27 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
432
427
  self.last_request[endpoint_id] = timestamp
433
428
 
434
429
  if not self.is_valid(
435
- endpoint_id,
436
- is_not_none,
437
- request_id,
438
- ["request", "id"],
430
+ validation_function=is_not_none,
431
+ field=request_id,
432
+ dict_path=["request", "id"],
439
433
  ):
440
434
  return None
441
435
  if not self.is_valid(
442
- endpoint_id,
443
- is_not_none,
444
- latency,
445
- ["microsec"],
436
+ validation_function=is_not_none,
437
+ field=latency,
438
+ dict_path=["microsec"],
446
439
  ):
447
440
  return None
448
441
  if not self.is_valid(
449
- endpoint_id,
450
- is_not_none,
451
- features,
452
- ["request", "inputs"],
442
+ validation_function=is_not_none,
443
+ field=features,
444
+ dict_path=["request", "inputs"],
453
445
  ):
454
446
  return None
455
447
  if not self.is_valid(
456
- endpoint_id,
457
- is_not_none,
458
- predictions,
459
- ["resp", "outputs"],
448
+ validation_function=is_not_none,
449
+ field=predictions,
450
+ dict_path=["resp", "outputs"],
460
451
  ):
461
452
  return None
462
453
 
@@ -514,7 +505,6 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
514
505
  EventFieldType.LAST_REQUEST_TIMESTAMP: mlrun.utils.enrich_datetime_with_tz_info(
515
506
  self.last_request[endpoint_id]
516
507
  ).timestamp(),
517
- EventFieldType.ERROR_COUNT: self.error_count[endpoint_id],
518
508
  EventFieldType.LABELS: event.get(EventFieldType.LABELS, {}),
519
509
  EventFieldType.METRICS: event.get(EventFieldType.METRICS, {}),
520
510
  EventFieldType.ENTITIES: event.get("request", {}).get(
@@ -545,7 +535,7 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
545
535
  .flat_dict()
546
536
  )
547
537
 
548
- # If model endpoint found, get first_request, last_request and error_count values
538
+ # If model endpoint found, get first_request & last_request values
549
539
  if endpoint_record:
550
540
  first_request = endpoint_record.get(EventFieldType.FIRST_REQUEST)
551
541
 
@@ -556,24 +546,18 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
556
546
  if last_request:
557
547
  self.last_request[endpoint_id] = last_request
558
548
 
559
- error_count = endpoint_record.get(EventFieldType.ERROR_COUNT)
560
-
561
- if error_count:
562
- self.error_count[endpoint_id] = int(error_count)
563
-
564
549
  # add endpoint to endpoints set
565
550
  self.endpoints.add(endpoint_id)
566
551
 
567
552
  def is_valid(
568
553
  self,
569
- endpoint_id: str,
570
554
  validation_function,
571
555
  field: typing.Any,
572
556
  dict_path: list[str],
573
557
  ):
574
558
  if validation_function(field, dict_path):
575
559
  return True
576
- self.error_count[endpoint_id] += 1
560
+
577
561
  return False
578
562
 
579
563
  @staticmethod
mlrun/projects/project.py CHANGED
@@ -1913,7 +1913,7 @@ class MlrunProject(ModelObj):
1913
1913
 
1914
1914
  def log_document(
1915
1915
  self,
1916
- key: str,
1916
+ key: str = "",
1917
1917
  tag: str = "",
1918
1918
  local_path: str = "",
1919
1919
  artifact_path: Optional[str] = None,
@@ -1926,7 +1926,8 @@ class MlrunProject(ModelObj):
1926
1926
  """
1927
1927
  Log a document as an artifact.
1928
1928
 
1929
- :param key: Artifact key
1929
+ :param key: Optional artifact key. If not provided, will be derived from local_path
1930
+ or target_path using DocumentArtifact.key_from_source()
1930
1931
  :param tag: Version tag
1931
1932
  :param local_path: path to the local file we upload, will also be use
1932
1933
  as the destination subpath (under "artifact_path")
@@ -1955,7 +1956,6 @@ class MlrunProject(ModelObj):
1955
1956
  Example:
1956
1957
  >>> # Log a PDF document with custom loader
1957
1958
  >>> project.log_document(
1958
- ... key="my_doc",
1959
1959
  ... local_path="path/to/doc.pdf",
1960
1960
  ... document_loader=DocumentLoaderSpec(
1961
1961
  ... loader_class_name="langchain_community.document_loaders.PDFLoader",
@@ -1965,6 +1965,13 @@ class MlrunProject(ModelObj):
1965
1965
  ... )
1966
1966
 
1967
1967
  """
1968
+ if not key and not local_path and not target_path:
1969
+ raise ValueError(
1970
+ "Must provide either 'key' parameter or 'local_path'/'target_path' to derive the key from"
1971
+ )
1972
+ if not key:
1973
+ key = DocumentArtifact.key_from_source(local_path or target_path)
1974
+
1968
1975
  document_loader_spec = document_loader_spec or DocumentLoaderSpec()
1969
1976
  if not document_loader_spec.download_object and upload:
1970
1977
  raise ValueError(
@@ -2119,8 +2126,9 @@ class MlrunProject(ModelObj):
2119
2126
  """
2120
2127
  :param name: AlertConfig name.
2121
2128
  :param summary: Summary of the alert, will be sent in the generated notifications
2122
- :param endpoints: The endpoints from which to retrieve the metrics that the
2123
- alerts will be based on.
2129
+ :param endpoints: The endpoints from which metrics will be retrieved to configure the alerts.
2130
+ This `ModelEndpointList` object obtained via the `list_model_endpoints`
2131
+ method or created manually using `ModelEndpoint` objects.
2124
2132
  :param events: AlertTrigger event types (EventKind).
2125
2133
  :param notifications: List of notifications to invoke once the alert is triggered
2126
2134
  :param result_names: Optional. Filters the result names used to create the alert configuration,
@@ -2129,6 +2137,8 @@ class MlrunProject(ModelObj):
2129
2137
  For example:
2130
2138
  [`app1.result-*`, `*.result1`]
2131
2139
  will match "mep1.app1.result.result-1" and "mep1.app2.result.result1".
2140
+ A specific result_name (not a wildcard) will always create a new alert
2141
+ config, regardless of whether the result name exists.
2132
2142
  :param severity: Severity of the alert.
2133
2143
  :param criteria: When the alert will be triggered based on the
2134
2144
  specified number of events within the defined time period.
@@ -2139,6 +2149,11 @@ class MlrunProject(ModelObj):
2139
2149
  """
2140
2150
  db = mlrun.db.get_run_db(secrets=self._secrets)
2141
2151
  matching_results = []
2152
+ specific_result_names = [
2153
+ result_name
2154
+ for result_name in result_names
2155
+ if result_name.count(".") == 3 and "*" not in result_name
2156
+ ]
2142
2157
  alerts = []
2143
2158
  endpoint_ids = [endpoint.metadata.uid for endpoint in endpoints.endpoints]
2144
2159
  # using separation to group by endpoint IDs:
@@ -2162,7 +2177,14 @@ class MlrunProject(ModelObj):
2162
2177
  existing_result_names=results_fqn_by_endpoint,
2163
2178
  result_name_filters=result_names,
2164
2179
  )
2165
- for result_fqn in matching_results:
2180
+ for specific_result_name in specific_result_names:
2181
+ if specific_result_name not in matching_results:
2182
+ logger.warning(
2183
+ f"The specific result name '{specific_result_name}' was"
2184
+ f" not found in the existing endpoint results. Adding alert configuration anyway."
2185
+ )
2186
+ alert_result_names = list(set(specific_result_names + matching_results))
2187
+ for result_fqn in alert_result_names:
2166
2188
  alerts.append(
2167
2189
  mlrun.alerts.alert.AlertConfig(
2168
2190
  project=self.name,
@@ -4639,6 +4661,8 @@ class MlrunProject(ModelObj):
4639
4661
  start_time_to: Optional[datetime.datetime] = None,
4640
4662
  last_update_time_from: Optional[datetime.datetime] = None,
4641
4663
  last_update_time_to: Optional[datetime.datetime] = None,
4664
+ end_time_from: Optional[datetime.datetime] = None,
4665
+ end_time_to: Optional[datetime.datetime] = None,
4642
4666
  **kwargs,
4643
4667
  ) -> mlrun.lists.RunList:
4644
4668
  """Retrieve a list of runs.
@@ -4682,6 +4706,8 @@ class MlrunProject(ModelObj):
4682
4706
  :param last_update_time_from: Filter by run last update time in ``(last_update_time_from,
4683
4707
  last_update_time_to)``.
4684
4708
  :param last_update_time_to: Filter by run last update time in ``(last_update_time_from, last_update_time_to)``.
4709
+ :param end_time_from: Filter by run end time in ``[end_time_from, end_time_to]``.
4710
+ :param end_time_to: Filter by run end time in ``[end_time_from, end_time_to]``.
4685
4711
  """
4686
4712
  if state:
4687
4713
  # TODO: Remove this in 1.9.0
@@ -4708,6 +4734,8 @@ class MlrunProject(ModelObj):
4708
4734
  start_time_to=start_time_to,
4709
4735
  last_update_time_from=last_update_time_from,
4710
4736
  last_update_time_to=last_update_time_to,
4737
+ end_time_from=end_time_from,
4738
+ end_time_to=end_time_to,
4711
4739
  **kwargs,
4712
4740
  )
4713
4741
 
@@ -756,7 +756,7 @@ class ServingRuntime(RemoteRuntime):
756
756
  namespace=namespace,
757
757
  logger=logger,
758
758
  is_mock=True,
759
- monitoring_mock=track_models,
759
+ monitoring_mock=self.spec.track_models,
760
760
  )
761
761
 
762
762
  if workdir:
@@ -789,7 +789,7 @@ class Spark3Runtime(KubejobRuntime):
789
789
  Spark itself uses the spec.[executor|driver].cores parameter to set the parallelism of tasks and cores
790
790
  assigned to each task within the pod. This function sets the .cores parameters for the job executed.
791
791
 
792
- See https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/issues/581 for a discussion about those
792
+ See https://github.com/kubeflow/spark-operator/issues/581 for a discussion about those
793
793
  parameters and their meaning in Spark operator.
794
794
 
795
795
  :param executor_cores: Number of cores to use for executor (spark.executor.cores)
mlrun/serving/states.py CHANGED
@@ -325,6 +325,9 @@ class BaseStep(ModelObj):
325
325
  full_event: Optional[bool] = None,
326
326
  input_path: Optional[str] = None,
327
327
  result_path: Optional[str] = None,
328
+ model_endpoint_creation_strategy: Optional[
329
+ schemas.ModelEndpointCreationStrategy
330
+ ] = None,
328
331
  **class_args,
329
332
  ):
330
333
  """add a step right after this step and return the new step
@@ -352,6 +355,16 @@ class BaseStep(ModelObj):
352
355
  this require that the event body will behave like a dict, example:
353
356
  event: {"x": 5} , result_path="y" means the output of the step will be written
354
357
  to event["y"] resulting in {"x": 5, "y": <result>}
358
+ :param model_endpoint_creation_strategy: Strategy for creating or updating the model endpoint:
359
+ * **overwrite**:
360
+ 1. If model endpoints with the same name exist, delete the `latest` one.
361
+ 2. Create a new model endpoint entry and set it as `latest`.
362
+ * **inplace** (default):
363
+ 1. If model endpoints with the same name exist, update the `latest` entry.
364
+ 2. Otherwise, create a new entry.
365
+ * **archive**:
366
+ 1. If model endpoints with the same name exist, preserve them.
367
+ 2. Create a new model endpoint with the same name and set it to `latest`.
355
368
  :param class_args: class init arguments
356
369
  """
357
370
  if hasattr(self, "steps"):
@@ -373,6 +386,7 @@ class BaseStep(ModelObj):
373
386
  input_path=input_path,
374
387
  result_path=result_path,
375
388
  class_args=class_args,
389
+ model_endpoint_creation_strategy=model_endpoint_creation_strategy,
376
390
  )
377
391
  step = parent._steps.update(name, step)
378
392
  step.set_parent(parent)
@@ -1035,6 +1049,9 @@ class QueueStep(BaseStep):
1035
1049
  full_event: Optional[bool] = None,
1036
1050
  input_path: Optional[str] = None,
1037
1051
  result_path: Optional[str] = None,
1052
+ model_endpoint_creation_strategy: Optional[
1053
+ schemas.ModelEndpointCreationStrategy
1054
+ ] = None,
1038
1055
  **class_args,
1039
1056
  ):
1040
1057
  if not function:
@@ -1051,6 +1068,7 @@ class QueueStep(BaseStep):
1051
1068
  full_event,
1052
1069
  input_path,
1053
1070
  result_path,
1071
+ model_endpoint_creation_strategy,
1054
1072
  **class_args,
1055
1073
  )
1056
1074
 
@@ -1129,6 +1147,9 @@ class FlowStep(BaseStep):
1129
1147
  full_event: Optional[bool] = None,
1130
1148
  input_path: Optional[str] = None,
1131
1149
  result_path: Optional[str] = None,
1150
+ model_endpoint_creation_strategy: Optional[
1151
+ schemas.ModelEndpointCreationStrategy
1152
+ ] = None,
1132
1153
  **class_args,
1133
1154
  ):
1134
1155
  """add task, queue or router step/class to the flow
@@ -1160,6 +1181,16 @@ class FlowStep(BaseStep):
1160
1181
  this require that the event body will behave like a dict, example:
1161
1182
  event: {"x": 5} , result_path="y" means the output of the step will be written
1162
1183
  to event["y"] resulting in {"x": 5, "y": <result>}
1184
+ :param model_endpoint_creation_strategy: Strategy for creating or updating the model endpoint:
1185
+ * **overwrite**:
1186
+ 1. If model endpoints with the same name exist, delete the `latest` one.
1187
+ 2. Create a new model endpoint entry and set it as `latest`.
1188
+ * **inplace** (default):
1189
+ 1. If model endpoints with the same name exist, update the `latest` entry.
1190
+ 2. Otherwise, create a new entry.
1191
+ * **archive**:
1192
+ 1. If model endpoints with the same name exist, preserve them.
1193
+ 2. Create a new model endpoint with the same name and set it to `latest`.
1163
1194
  :param class_args: class init arguments
1164
1195
  """
1165
1196
 
@@ -1172,6 +1203,7 @@ class FlowStep(BaseStep):
1172
1203
  full_event=full_event,
1173
1204
  input_path=input_path,
1174
1205
  result_path=result_path,
1206
+ model_endpoint_creation_strategy=model_endpoint_creation_strategy,
1175
1207
  class_args=class_args,
1176
1208
  )
1177
1209
 
@@ -149,16 +149,24 @@ class V2ModelServer(StepToDict):
149
149
  if not self.context.is_mock and not self.model_spec:
150
150
  self.get_model()
151
151
  if not self.context.is_mock or self.context.monitoring_mock:
152
- self.model_endpoint = mlrun.get_run_db().get_model_endpoint(
153
- project=server.project,
154
- name=self.name,
155
- function_name=server.function_name,
156
- function_tag=server.function_tag or "latest",
157
- )
158
- self.model_endpoint_uid = self.model_endpoint.metadata.uid
152
+ try:
153
+ self.model_endpoint = mlrun.get_run_db().get_model_endpoint(
154
+ project=server.project,
155
+ name=self.name,
156
+ function_name=server.function_name,
157
+ function_tag=server.function_tag or "latest",
158
+ )
159
+ self.model_endpoint_uid = self.model_endpoint.metadata.uid
160
+ except mlrun.errors.MLRunNotFoundError:
161
+ logger.info(
162
+ "Model Endpoint not found for this step we will not monitor this model",
163
+ function_name=server.function_name,
164
+ name=self.name,
165
+ )
166
+ self.model_endpoint, self.model_endpoint_uid = None, None
159
167
  self._model_logger = (
160
168
  _ModelLogPusher(self, self.context)
161
- if self.context and self.context.stream.enabled
169
+ if self.context and self.context.stream.enabled and self.model_endpoint_uid
162
170
  else None
163
171
  )
164
172
 
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "71de34eae245da0670aad9935e8729b9fbf9fc83",
3
- "version": "1.8.0-rc25"
2
+ "git_commit": "c482a37271171c5e81f9f977f8c1d584431826a7",
3
+ "version": "1.8.0-rc27"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mlrun
3
- Version: 1.8.0rc25
3
+ Version: 1.8.0rc27
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -51,7 +51,7 @@ Requires-Dist: setuptools>=75.2
51
51
  Requires-Dist: deprecated~=1.2
52
52
  Requires-Dist: jinja2>=3.1.3,~=3.1
53
53
  Requires-Dist: orjson<4,>=3.9.15
54
- Requires-Dist: mlrun-pipelines-kfp-common~=0.3.5
54
+ Requires-Dist: mlrun-pipelines-kfp-common~=0.3.6
55
55
  Requires-Dist: mlrun-pipelines-kfp-v1-8~=0.3.5; python_version < "3.11"
56
56
  Requires-Dist: docstring_parser~=0.16
57
57
  Requires-Dist: aiosmtplib~=3.0
@@ -1,12 +1,12 @@
1
1
  mlrun/__init__.py,sha256=zS40Lp5ZKivLBlNDkv-OQmVvwDib7C-cCdtD6UKXe28,8808
2
- mlrun/__main__.py,sha256=3CJdwbSQGpbEhnAnVN_-CkQmLOPUUXTKhMf7xIWNQrc,46138
3
- mlrun/config.py,sha256=zzR_qbNuA-lLIScx5GLRIF21eNJIoiVeBU-JS_movKo,71711
2
+ mlrun/__main__.py,sha256=ysteSDo1LYe_YOXVdIVEJ3BhLPOfBngkEfRg5iaGGg4,46202
3
+ mlrun/config.py,sha256=4m3fSgKZyYNXw15rJFzEXLFj4ZgEOaTiNTZ4iEly6PE,71882
4
4
  mlrun/errors.py,sha256=LkcbXTLANGdsgo2CRX2pdbyNmt--lMsjGv0XZMgP-Nc,8222
5
- mlrun/execution.py,sha256=0Lvs_kgUUbAyxnU8uABy4iRKLiTr7hcwhtWM79hrT28,49136
5
+ mlrun/execution.py,sha256=TIrCxh-FC2VYyVaz_-xVUfOkY3jJh26NUaFt0ZGlIto,49548
6
6
  mlrun/features.py,sha256=ReBaNGsBYXqcbgI012n-SO_j6oHIbk_Vpv0CGPXbUmo,15842
7
7
  mlrun/k8s_utils.py,sha256=mRQMs6NzPq36vx1n5_2BfFapXysc8wv3NcrZ77_2ANA,8949
8
- mlrun/lists.py,sha256=1hFv3Iyu5DVX1kdBGJmwUoY0CqrzauhKdSq9g3piHb4,8442
9
- mlrun/model.py,sha256=Qmj0UH5H0GKd6ZwxugxCvoqSP3O5q0LV0wSlHIzkyIM,85312
8
+ mlrun/lists.py,sha256=-nbmqScRia0v2IdSHt6Pd0fLRLSEtdB9bSxyD92BWvs,8562
9
+ mlrun/model.py,sha256=Fh8aoMVDiWY7CiMsuLGaA2zCv17DklmW2dbTp3ZpG7M,85368
10
10
  mlrun/render.py,sha256=940H9fBBFeghH4dlifbURvtjlvw4GlWdAXezN6ky4rI,13275
11
11
  mlrun/run.py,sha256=ht5tg-Sge_IYHILd55ym_HJTSmimu6sjBvSc5JzVqJc,45151
12
12
  mlrun/secrets.py,sha256=dZPdkc_zzfscVQepOHUwmzFqnBavDCBXV9DQoH_eIYM,7800
@@ -16,9 +16,9 @@ mlrun/api/schemas/__init__.py,sha256=fEWH4I8hr5AdRJ7yoW44RlFB6NHkYDxyomP5J6ct1z4
16
16
  mlrun/artifacts/__init__.py,sha256=ofC2extBCOC1wg1YtdTzWzH3eeG_f-sFBUkHjYtZJpk,1175
17
17
  mlrun/artifacts/base.py,sha256=nz2ZqC74JGfWN0M6_hOXXQj3bXSTxNp4eUgvWHVcdvY,29979
18
18
  mlrun/artifacts/dataset.py,sha256=QTot5vCgLHatlIWwNnKbWdZ8HHTxaZ7wk4gWQDoqQ2k,16655
19
- mlrun/artifacts/document.py,sha256=KQy_wC8QouE_EU_t3vK24Du4bkKBhmxacSssJk_yXLw,16571
19
+ mlrun/artifacts/document.py,sha256=O2nZhM47y6-miy47cIEBzLZyW92ZT2rxa-TMCAJlNY0,17181
20
20
  mlrun/artifacts/manager.py,sha256=bXb70mKF6wIGs7syCiFfGnjalqx4g9bO_J5DaVzUUKw,16163
21
- mlrun/artifacts/model.py,sha256=jeOjUq_iZSHoNqlPyGgOz6acwje1Yqpg1yZwF9GbyG8,21615
21
+ mlrun/artifacts/model.py,sha256=H5g7rINXol_aTcYIQaKRx1CO90b1h_3aajsItqef4-w,22144
22
22
  mlrun/artifacts/plots.py,sha256=dS0mHGt1b20tN2JyEH9H5o5I0oMKZkzn3Uz_3Hf4WjU,4813
23
23
  mlrun/common/__init__.py,sha256=xY3wHC4TEJgez7qtnn1pQvHosi8-5UJOCtyGBS7FcGE,571
24
24
  mlrun/common/constants.py,sha256=14xMUX9C5BB-LxsTlMTJQf_Xz2DyRjaK9yeR5dadcDU,3426
@@ -30,14 +30,14 @@ mlrun/common/db/sql_session.py,sha256=J6b-0xrnFb-8n_xdksPXeA8kArSMfAiSDN4n7iOhtu
30
30
  mlrun/common/formatters/__init__.py,sha256=lHcGFKKXx4vcCgJ0n2KHYD5sY5p5MvPz3DO9RbUoEOM,891
31
31
  mlrun/common/formatters/artifact.py,sha256=8oet2n5_bZlUALNXIjeYCTPDYKRB1h3gu_NWNK2lEig,1425
32
32
  mlrun/common/formatters/base.py,sha256=LHwWWnQJCmvlnOCCmG8YtJ_xzs0xBI8PujYDL5Ky9H4,4101
33
- mlrun/common/formatters/feature_set.py,sha256=1RdIkPRYTi8wGHNcAGTa3aCcj8cNV-GKk8IeMzvc0jE,1496
33
+ mlrun/common/formatters/feature_set.py,sha256=hC4Yh0TTUzOk2tSPPRXmb0ynjrfaxYZGv578QfQKgC4,1536
34
34
  mlrun/common/formatters/function.py,sha256=-DnfHThAcoizqJhTELeAltjsmlKRLnCaa1uKbWI0Eaw,1495
35
35
  mlrun/common/formatters/model_endpoint.py,sha256=MQPNpj6lQbitvsT9tIm-XZbH18HDv0X4OR3SAG5MPDI,906
36
36
  mlrun/common/formatters/pipeline.py,sha256=oATD3znsuq3s7LipPnZivDPelTX0hJ0MFeeXOQmwwLw,1762
37
37
  mlrun/common/formatters/project.py,sha256=0G4lhcTAsxQCxd40dKC4894cMH8nKt03BcGyp9wQO14,2102
38
38
  mlrun/common/formatters/run.py,sha256=Gcf9lVDqxPMNfWcPX0RJasjTC_N_U0yTBkQ02jOPJ7A,1062
39
39
  mlrun/common/model_monitoring/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
40
- mlrun/common/model_monitoring/helpers.py,sha256=lV86teJYoE3MNDx4yhpbzO1KylWmvDbuNODw5yGZwgs,2943
40
+ mlrun/common/model_monitoring/helpers.py,sha256=wNIvaLMtUAu875JPxTnOzmBpkFGamKBDAAdBsZEd6lQ,2949
41
41
  mlrun/common/runtimes/constants.py,sha256=07wD1g8QjXZe1fm2hSMOxZG19aAUsEZM8WeXnyoBd6Q,12127
42
42
  mlrun/common/schemas/__init__.py,sha256=PBuIAhXSkVEVxxKcv5hR_xvTwNAUqxOXHVPugOoWTyM,5386
43
43
  mlrun/common/schemas/alert.py,sha256=tRsjHEQTjCb-83GS0mprsu5junvqL4aQjWN2Rt_yAaM,10183
@@ -70,9 +70,9 @@ mlrun/common/schemas/runtime_resource.py,sha256=74EGmk1iODg-wV0cn2ew44ZX20nqJMow
70
70
  mlrun/common/schemas/schedule.py,sha256=LTWdZ4FvKDGkmmfyqKoBQ36VFqnnyIYLnq1I6qrTPyo,4292
71
71
  mlrun/common/schemas/secret.py,sha256=CCxFYiPwJtDxwg2VVJH9nUG9cAZ2a34IjeuaWv-BYlc,1487
72
72
  mlrun/common/schemas/tag.py,sha256=HRZi5QZ4vVGaCr2AMk9eJgcNiAIXmH4YDc8a4fvF770,893
73
- mlrun/common/schemas/workflow.py,sha256=rwYzDJYxpE9k4kC88j_eUCmqK4ZsWV_h-_nli7Fs7Ow,2078
73
+ mlrun/common/schemas/workflow.py,sha256=6u9niXfXpV-_c2rZL97gFIdAnOfM5WK-OCbrM5Kk34s,2108
74
74
  mlrun/common/schemas/model_monitoring/__init__.py,sha256=jz0fvdn8BEecgUCKhiSNH6QtFhSW4O19Ql9KXo0AxOg,1900
75
- mlrun/common/schemas/model_monitoring/constants.py,sha256=aSc-yVMWxn54LTmI16gOluYK0TB-XE4fGIuxGn_xttU,12604
75
+ mlrun/common/schemas/model_monitoring/constants.py,sha256=Yjzj8XQ95QLOCQwWt1-sTRdZdDDSLJutz5vWqPItOAM,12591
76
76
  mlrun/common/schemas/model_monitoring/grafana.py,sha256=Rq10KKOyyUYr7qOQFZfwGZtUim0LY9O0LQ5uc9jmIVQ,1562
77
77
  mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=0gBH-KnDDbGLOkiqHtk0_iNIdW-NPVy0TKJnZ1fDcEQ,11807
78
78
  mlrun/data_types/__init__.py,sha256=unRo9GGwCmj0hBKBRsXJ2P4BzpQaddlQTvIrVQaKluI,984
@@ -107,10 +107,10 @@ mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev
107
107
  mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
108
108
  mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
109
109
  mlrun/db/auth_utils.py,sha256=hpg8D2r82oN0BWabuWN04BTNZ7jYMAF242YSUpK7LFM,5211
110
- mlrun/db/base.py,sha256=hYxV5VIz7EbnOA7AXIfWv52ABueCka07xM6xpH2hbto,30600
110
+ mlrun/db/base.py,sha256=JQMligePluOeS2c3XX0IAk91k92U13-qCC-ZY61y0Ps,30716
111
111
  mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
112
- mlrun/db/httpdb.py,sha256=yOnMVLLm4ZigKdtsXXqe6i9IIVzQ-hKMEIKoVexzdhg,231100
113
- mlrun/db/nopdb.py,sha256=8nAuIn52NAfrKmk8EnE9kewLeGWOR29PxqVmfLxhhUw,27035
112
+ mlrun/db/httpdb.py,sha256=ijCMWi60dIdIP3jSQAxsQqj9EjnC_abDv3kGfDDjm-w,231735
113
+ mlrun/db/nopdb.py,sha256=I_0SkOY0pi5aTdNSiEaNcPSLENT8CBBy1OVRKCTGsvw,27151
114
114
  mlrun/feature_store/__init__.py,sha256=AVnY2AFUNc2dKxLLUMx2K3Wo1eGviv0brDcYlDnmtf4,1506
115
115
  mlrun/feature_store/api.py,sha256=qkojZpzqGAn3r9ww0ynBRKOs8ji8URaK4DSYD4SE-CE,50395
116
116
  mlrun/feature_store/common.py,sha256=Z7USI-d1fo0iwBMsqMBtJflJfyuiV3BLoDXQPSAoBAs,12826
@@ -213,14 +213,14 @@ mlrun/launcher/__init__.py,sha256=JL8qkT1lLr1YvW6iP0hmwDTaSR2RfrMDx0-1gWRhTOE,57
213
213
  mlrun/launcher/base.py,sha256=uZaUpwjy9_Z137aQ4b1JsuYqD01ZVRxytAxZSFKSu6U,16480
214
214
  mlrun/launcher/client.py,sha256=lJ3y9brmPspgwAZrUPAeu3Dn5B7mh9k3MhrbFKhNDvw,6286
215
215
  mlrun/launcher/factory.py,sha256=RW7mfzEFi8fR0M-4W1JQg1iq3_muUU6OTqT_3l4Ubrk,2338
216
- mlrun/launcher/local.py,sha256=9zNiuswHnSINDj4yYP2Vd192b5d4FUtSA8O2ICKjsKo,11279
216
+ mlrun/launcher/local.py,sha256=775HY-8S9LFUX5ubGXrLO0N1lVh8bn-DHFmNYuNqQPA,11451
217
217
  mlrun/launcher/remote.py,sha256=rLJW4UAnUT5iUb4BsGBOAV3K4R29a0X4lFtRkVKlyYU,7709
218
218
  mlrun/model_monitoring/__init__.py,sha256=ELy7njEtZnz09Dc6PGZSFFEGtnwI15bJNWM3Pj4_YIs,753
219
219
  mlrun/model_monitoring/api.py,sha256=nH5aEUkmUEJF0CurrWJxmxVv1tQed2yzCLhQByG1L00,28561
220
220
  mlrun/model_monitoring/controller.py,sha256=1SdrYC3n9nDOOM6G2dE0RgWnaq0o7u7sw2U2gJTpBPs,26516
221
221
  mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
222
- mlrun/model_monitoring/helpers.py,sha256=EX9i1JCY4NKHqUFptGU_xOIpGjQQ--3GytrEhDxIZ-4,18317
223
- mlrun/model_monitoring/stream_processing.py,sha256=EEix1rY0UMsaqadK9NsKMNJqcVPqGQq0vhuRCoKro2M,35526
222
+ mlrun/model_monitoring/helpers.py,sha256=nJhR7pQGzDGQDjGybV-pUyo4Eyt4OAeqqZ1aSEgs2lI,18328
223
+ mlrun/model_monitoring/stream_processing.py,sha256=xBN8LZ_MYkdAyXruRRYDysbkRlCMoI4XIXJlMgVqaGw,35092
224
224
  mlrun/model_monitoring/tracking_policy.py,sha256=PBIGrUYWrwcE5gwXupBIVzOb0QRRwPJsgQm_yLGQxB4,5595
225
225
  mlrun/model_monitoring/writer.py,sha256=vbL7bqTyNu8q4bNcebX72sUMybVDAoTWg-CXq4fov3Y,8429
226
226
  mlrun/model_monitoring/applications/__init__.py,sha256=QYvzgCutFdAkzqKPD3mvkX_3c1X4tzd-kW8ojUOE9ic,889
@@ -242,7 +242,7 @@ mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py,sha256=Uadj0UvAmln
242
242
  mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=eLi5kB1kFR8svukACnuYABaKOI4rof_SKMX61XXN5hI,30350
243
243
  mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
244
244
  mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=_-zo9relCDtjGgievxAcAP9gVN9nDWs8BzGtFwTjb9M,6284
245
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=oiro-fEmeVQe39hPmeNfi0DI4EKS59jwcr6Wx_eyuFI,37032
245
+ mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=w7k0HoA7lSRkxFWRpk56YL1x9jVKQTjTq9Eu38fKX5Y,37032
246
246
  mlrun/model_monitoring/metrics/__init__.py,sha256=6CsTXAxeLbbf8yfCADTaxmiavqwrLEdYFJ-qc5kgDAY,569
247
247
  mlrun/model_monitoring/metrics/histogram_distance.py,sha256=E9_WIl2vd6qNvoHVHoFcnuQk3ekbFWOdi8aU7sHrfk4,4724
248
248
  mlrun/package/__init__.py,sha256=v7VDyK9kDOOuDvFo4oiGV2fx-vM1KL7fdN9pGLakhUQ,7008
@@ -267,7 +267,7 @@ mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13
267
267
  mlrun/projects/__init__.py,sha256=0Krf0WIKfnZa71WthYOg0SoaTodGg3sV_hK3f_OlTPI,1220
268
268
  mlrun/projects/operations.py,sha256=VXUlMrouFTls-I-bMhdN5pPfQ34TR7bFQ-NUSWNvl84,20029
269
269
  mlrun/projects/pipelines.py,sha256=3UmjPKKAKKttdAOFnv_3vF0YLU1LHKQqUO2xp0K5yng,47915
270
- mlrun/projects/project.py,sha256=R928WXngIo_KJ-Ayxod2C2cmsHz2_yor8a3W7phDf_0,233046
270
+ mlrun/projects/project.py,sha256=xf4YbbzVaFh8Z4c8PfKxPTv7sgd2c7pwEsQYmfLjxFE,234809
271
271
  mlrun/runtimes/__init__.py,sha256=J9Sy2HiyMlztNv6VUurMzF5H2XzttNil8nRsWDsqLyg,8923
272
272
  mlrun/runtimes/base.py,sha256=Yt2l7srrXjK783cunBEKH0yQxQZRH8lkedXNOXuLbbo,37841
273
273
  mlrun/runtimes/daskjob.py,sha256=JwuGvOiPsxEDHHMMUS4Oie4hLlYYIZwihAl6DjroTY0,19521
@@ -291,22 +291,22 @@ mlrun/runtimes/nuclio/__init__.py,sha256=gx1kizzKv8pGT5TNloN1js1hdbxqDw3rM90sLVY
291
291
  mlrun/runtimes/nuclio/api_gateway.py,sha256=vH9ClKVP4Mb24rvA67xPuAvAhX-gAv6vVtjVxyplhdc,26969
292
292
  mlrun/runtimes/nuclio/function.py,sha256=Bff8Veg-eaqNrQ7yn20HpRhwAO4OA7FTnzXnAyoaBPU,52365
293
293
  mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha6E,2942
294
- mlrun/runtimes/nuclio/serving.py,sha256=Cc8MHi8gdJwkwLhaqO1KWU-UY36m-9zKUBFVa8JSGio,31987
294
+ mlrun/runtimes/nuclio/serving.py,sha256=ycRbZysdaEcpHZVqzSqGZys9ZjdGFrAECBfJATQfzfo,31997
295
295
  mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
296
296
  mlrun/runtimes/nuclio/application/application.py,sha256=HlEq4A6hbFqr3Ba3TL4m7nbmfMYI06Zb_NAKGjzkEFU,29242
297
297
  mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=JIIYae6bXzCLf3jXuu49KWPQYoXr_FDQ2Rbo1OWKAd0,3150
298
298
  mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
299
- mlrun/runtimes/sparkjob/spark3job.py,sha256=0ipkgAjDYDJDlcuvt379zonjhepCspsQQXMrz_tZfHo,41628
299
+ mlrun/runtimes/sparkjob/spark3job.py,sha256=E777WdlSe7Yx2kpg1bK0zZokn93bOQiUbtvtbcHV7ig,41610
300
300
  mlrun/serving/__init__.py,sha256=FhOlOCnBC5HFXOHzSDe4NHBs6mNUDP_Qqy6WMNsCwws,1307
301
301
  mlrun/serving/merger.py,sha256=qtPJacx94Tsz_-8L3J_-aS2NEsTdechZkQzJmyHjmig,6195
302
302
  mlrun/serving/remote.py,sha256=gxJkj_J3j-sZcVUbUzbAmJafP6t6y4NVFsu0kWmYngA,18818
303
303
  mlrun/serving/routers.py,sha256=A_R34_N6uYw2veK58WpffEp1NsFwq0XbNU9is2Nd7s8,50901
304
304
  mlrun/serving/server.py,sha256=dh8WQ0yEAhDvun1VA_DI5HBfywsACCrxBKn06bIjm1c,22843
305
305
  mlrun/serving/serving_wrapper.py,sha256=R670-S6PX_d5ER6jiHtRvacuPyFzQH0mEf2K0sBIIOM,836
306
- mlrun/serving/states.py,sha256=SD1xNqscHJO6aKEcZ3YCMnTlMDz3ipTSok0Qy2-vQTg,68583
306
+ mlrun/serving/states.py,sha256=8-hXWNK3kJj3FH5AKAfYr93br3og6xb53jzTR6hKVEU,70443
307
307
  mlrun/serving/utils.py,sha256=k2EIYDWHUGkE-IBI6T0UNT32fw-KySsccIJM_LObI00,4171
308
308
  mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
309
- mlrun/serving/v2_serving.py,sha256=Nm-mPa40JlhpAFH5JuaS4Kc38g_o70cBPGgrqo7zDRM,22525
309
+ mlrun/serving/v2_serving.py,sha256=pN49K7HOh1C1pAwAo_89FGB2HsLw0BO38unmUF3jE48,22956
310
310
  mlrun/track/__init__.py,sha256=yVXbT52fXvGKRlc_ByHqIVt7-9L3DRE634RSeQwgXtU,665
311
311
  mlrun/track/tracker.py,sha256=CyTU6Qd3_5GGEJ_hpocOj71wvV65EuFYUjaYEUKAL6Q,3575
312
312
  mlrun/track/tracker_manager.py,sha256=IYBl99I62IC6VCCmG1yt6JoHNOQXa53C4DURJ2sWgio,5726
@@ -337,11 +337,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
337
337
  mlrun/utils/notifications/notification/slack.py,sha256=eQvmctTh6wIG5xVOesLLV9S1-UUCu5UEQ9JIJOor3ts,7183
338
338
  mlrun/utils/notifications/notification/webhook.py,sha256=NeyIMSBojjjTJaUHmPbxMByp34GxYkl1-16NqzU27fU,4943
339
339
  mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
340
- mlrun/utils/version/version.json,sha256=MTyj1mgVxV_xX2d-zAZ65wss0XsoFXkn-u5mvdrLu00,89
340
+ mlrun/utils/version/version.json,sha256=-9Zh51rFvpmQCmLL4-Xi7uSMkjBw-RasTJKe24YTvss,89
341
341
  mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
342
- mlrun-1.8.0rc25.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
343
- mlrun-1.8.0rc25.dist-info/METADATA,sha256=QBiS1ES5J3LU6NX_Q5djlz1z9ediStIi10fHxVGE2qY,25888
344
- mlrun-1.8.0rc25.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
345
- mlrun-1.8.0rc25.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
346
- mlrun-1.8.0rc25.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
347
- mlrun-1.8.0rc25.dist-info/RECORD,,
342
+ mlrun-1.8.0rc27.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
343
+ mlrun-1.8.0rc27.dist-info/METADATA,sha256=Oav6I7kIOoc-SJd3JvSEp_x1LE6VWlyW8KfM4hLWxWM,25888
344
+ mlrun-1.8.0rc27.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
345
+ mlrun-1.8.0rc27.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
346
+ mlrun-1.8.0rc27.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
347
+ mlrun-1.8.0rc27.dist-info/RECORD,,