mlrun 1.10.0rc17__py3-none-any.whl → 1.10.0rc18__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.
@@ -41,6 +41,7 @@ class ArtifactFormat(ObjectFormat, mlrun.common.types.StrEnum):
41
41
  "spec.metrics",
42
42
  "spec.target_path",
43
43
  "spec.parent_uri",
44
+ "spec.has_children",
44
45
  ]
45
46
  ),
46
47
  }[_format]
@@ -487,25 +487,33 @@ class ModelMonitoringLabels:
487
487
 
488
488
  _RESERVED_FUNCTION_NAMES = MonitoringFunctionNames.list() + [SpecialApps.MLRUN_INFRA]
489
489
 
490
+ _RESERVED_EVALUATE_FUNCTION_SUFFIX = "-batch"
491
+
490
492
 
491
493
  class ModelEndpointMonitoringMetricType(StrEnum):
492
494
  RESULT = "result"
493
495
  METRIC = "metric"
494
496
 
495
497
 
498
+ # refer to `mlrun.utils.regex.project_name`
499
+ _INNER_PROJECT_PATTERN = r"[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?"
500
+ PROJECT_PATTERN = rf"^{_INNER_PROJECT_PATTERN}$"
501
+
502
+ MODEL_ENDPOINT_ID_PATTERN = r"^[a-zA-Z0-9_-]+$"
503
+
496
504
  _FQN_PART_PATTERN = r"[a-zA-Z0-9_-]+"
505
+ _RESULT_NAME_PATTERN = r"[a-zA-Z_][a-zA-Z0-9_]*"
506
+
497
507
  FQN_PATTERN = (
498
- rf"^(?P<project>{_FQN_PART_PATTERN})\."
508
+ rf"^(?P<project>{_INNER_PROJECT_PATTERN})\."
499
509
  rf"(?P<app>{_FQN_PART_PATTERN})\."
500
510
  rf"(?P<type>{ModelEndpointMonitoringMetricType.RESULT}|{ModelEndpointMonitoringMetricType.METRIC})\."
501
- rf"(?P<name>{_FQN_PART_PATTERN})$"
511
+ rf"(?P<name>{_RESULT_NAME_PATTERN})$"
502
512
  )
503
513
  FQN_REGEX = re.compile(FQN_PATTERN)
514
+ APP_NAME_REGEX = re.compile(_FQN_PART_PATTERN)
515
+ RESULT_NAME_REGEX = re.compile(_RESULT_NAME_PATTERN)
504
516
 
505
- # refer to `mlrun.utils.regex.project_name`
506
- PROJECT_PATTERN = r"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
507
- MODEL_ENDPOINT_ID_PATTERN = r"^[a-zA-Z0-9_-]+$"
508
- RESULT_NAME_PATTERN = r"[a-zA-Z_][a-zA-Z0-9_]*"
509
517
 
510
518
  INTERSECT_DICT_KEYS = {
511
519
  ModelEndpointMonitoringMetricType.METRIC: "intersect_metrics",
mlrun/config.py CHANGED
@@ -194,6 +194,7 @@ default_config = {
194
194
  "v3io_framesd": "http://framesd:8080",
195
195
  "model_providers": {
196
196
  "openai_default_model": "gpt-4o",
197
+ "huggingface_default_model": "microsoft/Phi-3-mini-4k-instruct",
197
198
  },
198
199
  # default node selector to be applied to all functions - json string base64 encoded format
199
200
  "default_function_node_selector": "e30=",
@@ -1238,6 +1239,19 @@ class Config:
1238
1239
  """
1239
1240
  return self.is_running_on_iguazio()
1240
1241
 
1242
+ @staticmethod
1243
+ def get_run_retry_staleness_threshold_timedelta() -> timedelta:
1244
+ """
1245
+ Get the staleness threshold in timedelta for run retries.
1246
+ This is used to determine if a run is stale and should be retried.
1247
+
1248
+ :return: The staleness threshold in timedelta.
1249
+ """
1250
+ staleness_threshold = int(
1251
+ mlrun.mlconf.monitoring.runs.retry.staleness_threshold
1252
+ )
1253
+ return timedelta(minutes=staleness_threshold)
1254
+
1241
1255
  def to_dict(self):
1242
1256
  return copy.deepcopy(self._cfg)
1243
1257
 
@@ -38,6 +38,7 @@ from ..utils import DB_SCHEMA, RunKeys
38
38
  from .base import DataItem, DataStore, HttpStore
39
39
  from .filestore import FileStore
40
40
  from .inmem import InMemoryStore
41
+ from .model_provider.huggingface_provider import HuggingFaceProvider
41
42
  from .model_provider.openai_provider import OpenAIProvider
42
43
  from .store_resources import get_store_resource, is_store_uri
43
44
  from .v3io import V3ioStore
@@ -102,8 +103,7 @@ def schema_to_store(schema) -> DataStore.__subclasses__():
102
103
  def schema_to_model_provider(
103
104
  schema: str, raise_missing_schema_exception=True
104
105
  ) -> type[ModelProvider]:
105
- # TODO add hugging face and http
106
- schema_dict = {"openai": OpenAIProvider}
106
+ schema_dict = {"openai": OpenAIProvider, "huggingface": HuggingFaceProvider}
107
107
  provider_class = schema_dict.get(schema, None)
108
108
  if not provider_class:
109
109
  if raise_missing_schema_exception:
@@ -247,7 +247,7 @@ class StoreManager:
247
247
 
248
248
  if schema == "ds":
249
249
  datastore_profile = datastore_profile_read(url, project_name, secrets)
250
- secrets = merge(secrets or {}, datastore_profile.secrets() or {})
250
+ secrets = merge({}, secrets or {}, datastore_profile.secrets() or {})
251
251
  url = datastore_profile.url(subpath)
252
252
  schema, endpoint, parsed_url = parse_url(url)
253
253
  subpath = parsed_url.path
@@ -281,7 +281,7 @@ class StoreManager:
281
281
  endpoint, subpath
282
282
  )
283
283
  remote_client = remote_client_class(
284
- self, schema, cache_key, parsed_url.netloc, secrets=secrets, **kwargs
284
+ self, schema, cache_key, endpoint, secrets=secrets, **kwargs
285
285
  )
286
286
  if not secrets and not mlrun.config.is_running_as_api():
287
287
  cache[cache_key] = remote_client
@@ -486,6 +486,31 @@ class OpenAIProfile(DatastoreProfile):
486
486
  return f"{self.type}://{subpath.lstrip('/')}"
487
487
 
488
488
 
489
+ class HuggingFaceProfile(DatastoreProfile):
490
+ type: str = pydantic.v1.Field("huggingface")
491
+ _private_attributes = ("token", "model_kwargs")
492
+ task: typing.Optional[str] = None
493
+ token: typing.Optional[str] = None
494
+ device: typing.Optional[typing.Union[int, str]] = None
495
+ device_map: typing.Union[str, dict[str, typing.Union[int, str]], None] = None
496
+ trust_remote_code: bool = None
497
+ model_kwargs: typing.Optional[dict[str, typing.Any]] = None
498
+
499
+ def secrets(self) -> dict:
500
+ keys = {
501
+ "HF_TASK": self.task,
502
+ "HF_TOKEN": self.token,
503
+ "HF_DEVICE": self.device,
504
+ "HF_DEVICE_MAP": self.device_map,
505
+ "HF_TRUST_REMOTE_CODE": self.trust_remote_code,
506
+ "HF_MODEL_KWARGS": self.model_kwargs,
507
+ }
508
+ return {k: v for k, v in keys.items() if v}
509
+
510
+ def url(self, subpath):
511
+ return f"{self.type}://{subpath.lstrip('/')}"
512
+
513
+
489
514
  _DATASTORE_TYPE_TO_PROFILE_CLASS: dict[str, type[DatastoreProfile]] = {
490
515
  "v3io": DatastoreProfileV3io,
491
516
  "s3": DatastoreProfileS3,
@@ -500,6 +525,7 @@ _DATASTORE_TYPE_TO_PROFILE_CLASS: dict[str, type[DatastoreProfile]] = {
500
525
  "taosws": DatastoreProfileTDEngine,
501
526
  "config": ConfigProfile,
502
527
  "openai": OpenAIProfile,
528
+ "huggingface": HuggingFaceProfile,
503
529
  }
504
530
 
505
531
 
@@ -0,0 +1,183 @@
1
+ # Copyright 2025 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
+ from typing import TYPE_CHECKING, Optional, TypeVar, Union
16
+
17
+ import mlrun
18
+ from mlrun.datastore.model_provider.model_provider import ModelProvider
19
+
20
+ if TYPE_CHECKING:
21
+ from transformers.pipelines.base import Pipeline
22
+
23
+ T = TypeVar("T")
24
+ ChatType = list[dict[str, str]] # according to transformers.pipelines.text_generation
25
+
26
+
27
+ class HuggingFaceProvider(ModelProvider):
28
+ """
29
+ HuggingFaceProvider is a wrapper around the Hugging Face Transformers pipeline
30
+ that provides an interface for interacting with a wide range of Hugging Face models.
31
+
32
+ It supports synchronous operations, enabling flexible integration into various workflows.
33
+
34
+ This class extends the ModelProvider base class and implements Hugging Face-specific
35
+ functionality, including pipeline initialization, default text generation operations,
36
+ and custom operations tailored to the Hugging Face Transformers pipeline API.
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ parent,
42
+ schema,
43
+ name,
44
+ endpoint="",
45
+ secrets: Optional[dict] = None,
46
+ default_invoke_kwargs: Optional[dict] = None,
47
+ ):
48
+ endpoint = endpoint or mlrun.mlconf.model_providers.huggingface_default_model
49
+ if schema != "huggingface":
50
+ raise mlrun.errors.MLRunInvalidArgumentError(
51
+ "HuggingFaceProvider supports only 'huggingface' as the provider kind."
52
+ )
53
+ super().__init__(
54
+ parent=parent,
55
+ kind=schema,
56
+ name=name,
57
+ endpoint=endpoint,
58
+ secrets=secrets,
59
+ default_invoke_kwargs=default_invoke_kwargs,
60
+ )
61
+ self.options = self.get_client_options()
62
+ self._expected_operation_type = None
63
+ self.load_client()
64
+
65
+ @staticmethod
66
+ def _extract_string_output(result) -> str:
67
+ """
68
+ Extracts the first generated string from Hugging Face pipeline output,
69
+ regardless of whether it's plain text-generation or chat-style output.
70
+ """
71
+ if not isinstance(result, list) or len(result) == 0:
72
+ raise ValueError("Empty or invalid pipeline output")
73
+
74
+ return result[0].get("generated_text")
75
+
76
+ @classmethod
77
+ def parse_endpoint_and_path(cls, endpoint, subpath) -> (str, str):
78
+ if endpoint and subpath:
79
+ endpoint = endpoint + subpath
80
+ # In HuggingFace, "/" in a model name is part of the name — `subpath` is not used.
81
+ subpath = ""
82
+ return endpoint, subpath
83
+
84
+ def load_client(self) -> None:
85
+ """
86
+ Initializes the Hugging Face pipeline using the provided options.
87
+
88
+ This method imports the `pipeline` function from the `transformers` package,
89
+ creates a pipeline instance with the specified task and model (from `self.options`),
90
+ and assigns it to `self._client`.
91
+
92
+ Note: Hugging Face pipelines are synchronous and do not support async invocation.
93
+
94
+ Raises:
95
+ ImportError: If the `transformers` package is not installed.
96
+ """
97
+ try:
98
+ from transformers import pipeline, AutoModelForCausalLM # noqa
99
+ from transformers import AutoTokenizer # noqa
100
+ from transformers.pipelines.base import Pipeline # noqa
101
+
102
+ self._client = pipeline(model=self.model, **self.options)
103
+ self._expected_operation_type = Pipeline
104
+ except ImportError as exc:
105
+ raise ImportError("transformers package is not installed") from exc
106
+
107
+ def get_client_options(self):
108
+ res = dict(
109
+ task=self._get_secret_or_env("HF_TASK") or "text-generation",
110
+ token=self._get_secret_or_env("HF_TOKEN"),
111
+ device=self._get_secret_or_env("HF_DEVICE"),
112
+ device_map=self._get_secret_or_env("HF_DEVICE_MAP"),
113
+ trust_remote_code=self._get_secret_or_env("HF_TRUST_REMOTE_CODE"),
114
+ model_kwargs=self._get_secret_or_env("HF_MODEL_KWARGS"),
115
+ )
116
+ return self._sanitize_options(res)
117
+
118
+ def custom_invoke(
119
+ self, operation: Optional["Pipeline"] = None, **invoke_kwargs
120
+ ) -> Optional[T]:
121
+ """
122
+ HuggingFace implementation of `ModelProvider.custom_invoke`.
123
+ Use the default config in provider client/ user defined client:
124
+
125
+ Example:
126
+ ```python
127
+ image = Image.open(image_path)
128
+ pipeline_object = pipeline("image-classification", model="microsoft/resnet-50")
129
+ result = hf_provider.custom_invoke(
130
+ pipeline_object,
131
+ inputs=image,
132
+ )
133
+ ```
134
+
135
+
136
+ :param operation: A pipeline object
137
+ :param invoke_kwargs: Keyword arguments to pass to the operation.
138
+ :return: The full response returned by the operation.
139
+
140
+ """
141
+ invoke_kwargs = self.get_invoke_kwargs(invoke_kwargs)
142
+ if operation:
143
+ if not isinstance(operation, self._expected_operation_type):
144
+ raise mlrun.errors.MLRunInvalidArgumentError(
145
+ "Huggingface operation must inherit" " from 'Pipeline' object"
146
+ )
147
+ return operation(**invoke_kwargs)
148
+ else:
149
+ return self.client(**invoke_kwargs)
150
+
151
+ def invoke(
152
+ self,
153
+ messages: Union[str, list[str], ChatType, list[ChatType]] = None,
154
+ as_str: bool = False,
155
+ **invoke_kwargs,
156
+ ) -> Optional[Union[str, list, T]]:
157
+ """
158
+ HuggingFace-specific implementation of `ModelProvider.invoke`.
159
+ Invokes a HuggingFace model operation using the synchronous client.
160
+ For complete usage details, refer to `ModelProvider.invoke`.
161
+ :param messages:
162
+ Same as ModelProvider.invoke.
163
+
164
+ :param as_str:
165
+ If `True`, returns only the main content from a single response
166
+ (intended for single-response use cases).
167
+ If `False`, returns the full response object, whose type depends on
168
+ the client (e.g., `pipeline`).
169
+
170
+ :param invoke_kwargs:
171
+ Same as ModelProvider.invoke.
172
+ :return: Same as ModelProvider.invoke.
173
+ """
174
+ if self.client.task != "text-generation":
175
+ raise mlrun.errors.MLRunInvalidArgumentError(
176
+ "HuggingFaceProvider.invoke supports text-generation task only"
177
+ )
178
+ if as_str:
179
+ invoke_kwargs["return_full_text"] = False
180
+ response = self.custom_invoke(text_inputs=messages, **invoke_kwargs)
181
+ if as_str:
182
+ return self._extract_string_output(response)
183
+ return response
@@ -148,7 +148,12 @@ class ModelProvider(BaseRemoteClient):
148
148
 
149
149
  @property
150
150
  def model(self) -> Optional[str]:
151
- return None
151
+ """
152
+ Returns the model identifier used by the underlying SDK.
153
+
154
+ :return: A string representing the model ID, or None if not set.
155
+ """
156
+ return self.endpoint
152
157
 
153
158
  def get_invoke_kwargs(self, invoke_kwargs) -> dict:
154
159
  kwargs = self.default_invoke_kwargs.copy()
@@ -11,11 +11,13 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+ import inspect
14
15
  from collections.abc import Awaitable
15
16
  from typing import Callable, Optional, TypeVar, Union
16
17
 
17
18
  import mlrun
18
19
  from mlrun.datastore.model_provider.model_provider import ModelProvider
20
+ from mlrun.datastore.utils import accepts_param
19
21
 
20
22
  T = TypeVar("T")
21
23
 
@@ -68,10 +70,6 @@ class OpenAIProvider(ModelProvider):
68
70
  subpath = ""
69
71
  return endpoint, subpath
70
72
 
71
- @property
72
- def model(self) -> Optional[str]:
73
- return self.endpoint
74
-
75
73
  def load_client(self) -> None:
76
74
  """
77
75
  Initializes the OpenAI SDK client using the provided options.
@@ -126,12 +124,18 @@ class OpenAIProvider(ModelProvider):
126
124
 
127
125
  """
128
126
  invoke_kwargs = self.get_invoke_kwargs(invoke_kwargs)
127
+ model_kwargs = {"model": invoke_kwargs.pop("model", None) or self.model}
128
+
129
129
  if operation:
130
- return operation(**invoke_kwargs, model=self.model)
130
+ if not callable(operation):
131
+ raise mlrun.errors.MLRunInvalidArgumentError(
132
+ "OpenAI custom_invoke operation must be a callable"
133
+ )
134
+ if not accepts_param(operation, "model"):
135
+ model_kwargs = {}
136
+ return operation(**invoke_kwargs, **model_kwargs)
131
137
  else:
132
- return self.client.chat.completions.create(
133
- **invoke_kwargs, model=self.model
134
- )
138
+ return self.client.chat.completions.create(**invoke_kwargs, **model_kwargs)
135
139
 
136
140
  async def async_custom_invoke(
137
141
  self,
@@ -145,25 +149,33 @@ class OpenAIProvider(ModelProvider):
145
149
  `ModelProvider.async_custom_invoke`.
146
150
 
147
151
  Example:
148
- ```python
152
+ ```python
149
153
  result = openai_model_provider.invoke(
150
154
  openai_model_provider.async_client.images.generate,
151
155
  prompt="A futuristic cityscape at sunset",
152
156
  n=1,
153
157
  size="1024x1024",
154
158
  )
155
- ```
159
+ ```
160
+
156
161
  :param operation: Same as ModelProvider.async_custom_invoke.
157
162
  :param invoke_kwargs: Same as ModelProvider.async_custom_invoke.
158
163
  :return: Same as ModelProvider.async_custom_invoke.
159
164
 
160
165
  """
161
166
  invoke_kwargs = self.get_invoke_kwargs(invoke_kwargs)
167
+ model_kwargs = {"model": invoke_kwargs.pop("model", None) or self.model}
162
168
  if operation:
163
- return await operation(**invoke_kwargs, model=self.model)
169
+ if not inspect.iscoroutinefunction(operation):
170
+ raise mlrun.errors.MLRunInvalidArgumentError(
171
+ "OpenAI async_custom_invoke operation must be a coroutine function"
172
+ )
173
+ if not accepts_param(operation, "model"):
174
+ model_kwargs = {}
175
+ return await operation(**invoke_kwargs, **model_kwargs)
164
176
  else:
165
177
  return await self.async_client.chat.completions.create(
166
- **invoke_kwargs, model=self.model
178
+ **invoke_kwargs, **model_kwargs
167
179
  )
168
180
 
169
181
  def invoke(
mlrun/datastore/utils.py CHANGED
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import inspect
15
16
  import math
16
17
  import tarfile
17
18
  import tempfile
@@ -333,3 +334,8 @@ def parse_url(url):
333
334
  if parsed_url.port:
334
335
  endpoint += f":{parsed_url.port}"
335
336
  return schema, endpoint, parsed_url
337
+
338
+
339
+ def accepts_param(func: callable, param_name):
340
+ sig = inspect.signature(func)
341
+ return param_name in sig.parameters
@@ -19,8 +19,6 @@ from datetime import datetime
19
19
  import numpy as np
20
20
  import pandas as pd
21
21
 
22
- import mlrun.artifacts
23
- import mlrun.common.helpers
24
22
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
25
23
  import mlrun.datastore.base
26
24
  import mlrun.feature_store
@@ -538,10 +536,14 @@ def _create_model_monitoring_function_base(
538
536
  This function does not set the labels or mounts v3io.
539
537
  """
540
538
  if name in mm_constants._RESERVED_FUNCTION_NAMES:
541
- raise mlrun.errors.MLRunInvalidArgumentError(
539
+ raise mlrun.errors.MLRunValueError(
542
540
  "An application cannot have the following names: "
543
541
  f"{mm_constants._RESERVED_FUNCTION_NAMES}"
544
542
  )
543
+ if name and name.endswith(mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX):
544
+ raise mlrun.errors.MLRunValueError(
545
+ "Model monitoring application names cannot end with `-batch`"
546
+ )
545
547
  if func is None:
546
548
  func = ""
547
549
  func_obj = typing.cast(
@@ -25,6 +25,7 @@ import pandas as pd
25
25
 
26
26
  import mlrun
27
27
  import mlrun.common.constants as mlrun_constants
28
+ import mlrun.common.helpers
28
29
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
29
30
  import mlrun.datastore.datastore_profile as ds_profile
30
31
  import mlrun.errors
@@ -33,6 +34,7 @@ import mlrun.model_monitoring.applications.context as mm_context
33
34
  import mlrun.model_monitoring.applications.results as mm_results
34
35
  import mlrun.model_monitoring.db._schedules as mm_schedules
35
36
  import mlrun.model_monitoring.helpers as mm_helpers
37
+ import mlrun.utils
36
38
  from mlrun.serving.utils import MonitoringApplicationToDict
37
39
  from mlrun.utils import logger
38
40
 
@@ -194,7 +196,25 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
194
196
  Optional[mm_schedules.ModelMonitoringSchedulesFileApplication],
195
197
  ]
196
198
  ]:
197
- endpoints_output: dict[str, list[tuple]] = defaultdict(list)
199
+ endpoints_output: dict[
200
+ str,
201
+ list[
202
+ tuple[
203
+ mm_context.MonitoringApplicationContext,
204
+ Union[
205
+ mm_results.ModelMonitoringApplicationResult,
206
+ mm_results.ModelMonitoringApplicationMetric,
207
+ list[
208
+ Union[
209
+ mm_results.ModelMonitoringApplicationResult,
210
+ mm_results.ModelMonitoringApplicationMetric,
211
+ mm_results._ModelMonitoringApplicationStats,
212
+ ]
213
+ ],
214
+ ],
215
+ ]
216
+ ],
217
+ ] = defaultdict(list)
198
218
  application_schedules = nullcontext()
199
219
  if write_output:
200
220
  cls._check_writer_is_up(project)
@@ -220,11 +240,21 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
220
240
  profile=stream_profile,
221
241
  )
222
242
  for endpoint_id, outputs in endpoints_output.items():
243
+ writer_events = []
244
+ for ctx, res in outputs:
245
+ if isinstance(res, list):
246
+ writer_events.extend(
247
+ _serialize_context_and_result(
248
+ context=ctx, result=sub_res
249
+ )
250
+ for sub_res in res
251
+ )
252
+ else:
253
+ writer_events.append(
254
+ _serialize_context_and_result(context=ctx, result=res)
255
+ )
223
256
  writer_stream.push(
224
- [
225
- _serialize_context_and_result(context=ctx, result=res)
226
- for ctx, res in outputs
227
- ],
257
+ writer_events,
228
258
  partition_key=endpoint_id,
229
259
  )
230
260
  logger.debug(
@@ -238,6 +268,14 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
238
268
  )
239
269
  application_schedules.__exit__(None, None, None)
240
270
 
271
+ @classmethod
272
+ def _get_application_name(cls, context: "mlrun.MLClientCtx") -> str:
273
+ """Get the application name from the context via the function URI"""
274
+ _, application_name, _, _ = mlrun.common.helpers.parse_versioned_object_uri(
275
+ context.to_dict().get("spec", {}).get("function", "")
276
+ )
277
+ return application_name
278
+
241
279
  def _handler(
242
280
  self,
243
281
  context: "mlrun.MLClientCtx",
@@ -250,7 +288,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
250
288
  end: Optional[str] = None,
251
289
  base_period: Optional[int] = None,
252
290
  write_output: bool = False,
253
- allow_unordered_data: bool = False,
291
+ fail_on_overlap: bool = True,
254
292
  stream_profile: Optional[ds_profile.DatastoreProfile] = None,
255
293
  ):
256
294
  """
@@ -271,7 +309,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
271
309
  "working with endpoints, without any custom data-frame input"
272
310
  )
273
311
 
274
- application_name = self.__class__.__name__
312
+ application_name = self._get_application_name(context)
275
313
 
276
314
  feature_stats = (
277
315
  mm_api.get_sample_set_statistics(reference_data)
@@ -320,7 +358,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
320
358
  application_schedules=application_schedules,
321
359
  endpoint_id=endpoint_id,
322
360
  application_name=application_name,
323
- allow_unordered_data=allow_unordered_data,
361
+ fail_on_overlap=fail_on_overlap,
324
362
  ):
325
363
  result = call_do_tracking(
326
364
  event={
@@ -443,7 +481,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
443
481
  end_dt: datetime,
444
482
  base_period: Optional[int],
445
483
  application_name: str,
446
- allow_unordered_data: bool,
484
+ fail_on_overlap: bool,
447
485
  ) -> datetime:
448
486
  """Make sure that the (app, endpoint) pair doesn't write output before the last analyzed window"""
449
487
  if application_schedules:
@@ -452,7 +490,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
452
490
  )
453
491
  if last_analyzed:
454
492
  if start_dt < last_analyzed:
455
- if allow_unordered_data:
493
+ if not fail_on_overlap:
456
494
  if last_analyzed < end_dt and base_period is None:
457
495
  logger.warn(
458
496
  "Setting the start time to last_analyzed since the original start time precedes "
@@ -499,7 +537,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
499
537
  ],
500
538
  endpoint_id: str,
501
539
  application_name: str,
502
- allow_unordered_data: bool,
540
+ fail_on_overlap: bool,
503
541
  ) -> Iterator[tuple[Optional[datetime], Optional[datetime]]]:
504
542
  if start is None or end is None:
505
543
  # A single window based on the `sample_data` input - see `_handler`.
@@ -516,7 +554,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
516
554
  end_dt=end_dt,
517
555
  base_period=base_period,
518
556
  application_name=application_name,
519
- allow_unordered_data=allow_unordered_data,
557
+ fail_on_overlap=fail_on_overlap,
520
558
  )
521
559
 
522
560
  if base_period is None:
@@ -589,6 +627,42 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
589
627
  """
590
628
  return f"{handler_to_class}::{cls._handler.__name__}"
591
629
 
630
+ @classmethod
631
+ def _determine_job_name(
632
+ cls,
633
+ *,
634
+ func_name: Optional[str],
635
+ class_handler: Optional[str],
636
+ handler_to_class: str,
637
+ ) -> str:
638
+ """
639
+ Determine the batch app's job name. This name is used also as the application name,
640
+ which is retrieved in `_get_application_name`.
641
+ """
642
+ if func_name:
643
+ job_name = func_name
644
+ else:
645
+ if not class_handler:
646
+ class_name = cls.__name__
647
+ else:
648
+ class_name = handler_to_class.split(".")[-1].split("::")[0]
649
+
650
+ job_name = mlrun.utils.normalize_name(class_name, verbose=False)
651
+
652
+ if not mm_constants.APP_NAME_REGEX.fullmatch(job_name):
653
+ raise mlrun.errors.MLRunValueError(
654
+ "The function name does not comply with the required pattern "
655
+ f"`{mm_constants.APP_NAME_REGEX.pattern}`. "
656
+ "Please choose another `func_name`."
657
+ )
658
+ if not job_name.endswith(mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX):
659
+ job_name += mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX
660
+ mlrun.utils.logger.info(
661
+ 'Changing function name - adding `"-batch"` suffix', func_name=job_name
662
+ )
663
+
664
+ return job_name
665
+
592
666
  @classmethod
593
667
  def to_job(
594
668
  cls,
@@ -628,7 +702,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
628
702
  * ``end``, ``datetime``
629
703
  * ``base_period``, ``int``
630
704
  * ``write_output``, ``bool``
631
- * ``allow_unordered_data``, ``bool``
705
+ * ``fail_on_overlap``, ``bool``
632
706
 
633
707
  For Git sources, add the source archive to the returned job and change the handler:
634
708
 
@@ -647,7 +721,10 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
647
721
  :py:class:`~mlrun.model_monitoring.applications.ModelMonitoringApplicationBase`,
648
722
  is used.
649
723
  :param func_path: The path to the function. If ``None``, the current notebook is used.
650
- :param func_name: The name of the function. If not ``None``, the class name is used.
724
+ :param func_name: The name of the function. If ``None``, the normalized class name is used
725
+ (:py:meth:`mlrun.utils.helpers.normalize_name`).
726
+ A ``"-batch"`` suffix is guaranteed to be added if not already there.
727
+ The function name is also used as the application name to use for the results.
651
728
  :param tag: Tag for the function.
652
729
  :param image: Docker image to run the job on (when running remotely).
653
730
  :param with_repo: Whether to clone the current repo to the build source.
@@ -668,12 +745,11 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
668
745
  handler_to_class = class_handler or cls.__name__
669
746
  handler = cls.get_job_handler(handler_to_class)
670
747
 
671
- if not class_handler:
672
- class_name = cls.__name__
673
- else:
674
- class_name = handler_to_class.split(".")[-1].split("::")[-1]
675
-
676
- job_name = func_name if func_name else class_name
748
+ job_name = cls._determine_job_name(
749
+ func_name=func_name,
750
+ class_handler=class_handler,
751
+ handler_to_class=handler_to_class,
752
+ )
677
753
 
678
754
  job = cast(
679
755
  mlrun.runtimes.KubejobRuntime,
@@ -712,7 +788,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
712
788
  end: Optional[datetime] = None,
713
789
  base_period: Optional[int] = None,
714
790
  write_output: bool = False,
715
- allow_unordered_data: bool = False,
791
+ fail_on_overlap: bool = True,
716
792
  stream_profile: Optional[ds_profile.DatastoreProfile] = None,
717
793
  ) -> "mlrun.RunObject":
718
794
  """
@@ -724,7 +800,10 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
724
800
  data to the application.
725
801
 
726
802
  :param func_path: The path to the function. If ``None``, the current notebook is used.
727
- :param func_name: The name of the function. If not ``None``, the class name is used.
803
+ :param func_name: The name of the function. If ``None``, the normalized class name is used
804
+ (:py:meth:`mlrun.utils.helpers.normalize_name`).
805
+ A ``"-batch"`` suffix is guaranteed to be added if not already there.
806
+ The function name is also used as the application name to use for the results.
728
807
  :param tag: Tag for the function.
729
808
  :param run_local: Whether to run the function locally or remotely.
730
809
  :param auto_build: Whether to auto build the function.
@@ -777,11 +856,11 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
777
856
  :param write_output: Whether to write the results and metrics to the time-series DB. Can be ``True`` only
778
857
  if ``endpoints`` are passed.
779
858
  Note: the model monitoring infrastructure must be up for the writing to work.
780
- :param allow_unordered_data: Relevant only when writing outputs to the database. When ``False``, and the
781
- requested ``start`` time precedes the ``end`` time of a previous run that also
782
- wrote to the database - an error is raised.
783
- If ``True``, when the previously described situation occurs, the relevant time
784
- window is cut so that it starts at the earliest possible time after ``start``.
859
+ :param fail_on_overlap: Relevant only when ``write_output=True``. When ``True``, and the
860
+ requested ``start`` time precedes the ``end`` time of a previous run that also
861
+ wrote to the database - an error is raised.
862
+ If ``False``, when the previously described situation occurs, the relevant time
863
+ window is cut so that it starts at the earliest possible time after ``start``.
785
864
  :param stream_profile: The stream datastore profile. It should be provided only when running locally and
786
865
  writing the outputs to the database (i.e., when both ``run_local`` and
787
866
  ``write_output`` are set to ``True``).
@@ -821,7 +900,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
821
900
  params["end"] = end.isoformat() if isinstance(end, datetime) else end
822
901
  params["base_period"] = base_period
823
902
  params["write_output"] = write_output
824
- params["allow_unordered_data"] = allow_unordered_data
903
+ params["fail_on_overlap"] = fail_on_overlap
825
904
  if stream_profile:
826
905
  if not run_local:
827
906
  raise mlrun.errors.MLRunValueError(
@@ -14,16 +14,13 @@
14
14
 
15
15
  import dataclasses
16
16
  import json
17
- import re
18
17
  from abc import ABC, abstractmethod
19
18
 
20
19
  from pydantic.v1 import validator
21
20
  from pydantic.v1.dataclasses import dataclass
22
21
 
23
- import mlrun.common.helpers
24
- import mlrun.common.model_monitoring.helpers
25
22
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
26
- import mlrun.utils.v3io_clients
23
+ import mlrun.errors
27
24
  from mlrun.utils import logger
28
25
 
29
26
  _RESULT_EXTRA_DATA_MAX_SIZE = 998
@@ -33,10 +30,10 @@ class _ModelMonitoringApplicationDataRes(ABC):
33
30
  name: str
34
31
 
35
32
  def __post_init__(self):
36
- pat = re.compile(mm_constants.RESULT_NAME_PATTERN)
37
- if not re.fullmatch(pat, self.name):
33
+ if not mm_constants.RESULT_NAME_REGEX.fullmatch(self.name):
38
34
  raise mlrun.errors.MLRunValueError(
39
- f"Attribute name must comply with the regex `{mm_constants.RESULT_NAME_PATTERN}`"
35
+ "The application result or metric name must comply with the regex "
36
+ f"`{mm_constants.RESULT_NAME_REGEX.pattern}`"
40
37
  )
41
38
 
42
39
  @abstractmethod
mlrun/run.py CHANGED
@@ -1184,11 +1184,13 @@ def get_model_provider(
1184
1184
  raise_missing_schema_exception=True,
1185
1185
  ) -> ModelProvider:
1186
1186
  """get mlrun dataitem object (from path/url)"""
1187
- store_manager.set(secrets, db=db)
1187
+ # without caching secrets
1188
+ store_manager.set(db=db)
1188
1189
  return store_manager.model_provider_object(
1189
1190
  url=url,
1190
1191
  default_invoke_kwargs=default_invoke_kwargs,
1191
1192
  raise_missing_schema_exception=raise_missing_schema_exception,
1193
+ secrets=secrets,
1192
1194
  )
1193
1195
 
1194
1196
 
mlrun/serving/states.py CHANGED
@@ -1206,7 +1206,7 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
1206
1206
 
1207
1207
  class LLModel(Model):
1208
1208
  def __init__(
1209
- self, name: str, input_path: Optional[Union[str, list[str]]], **kwargs
1209
+ self, name: str, input_path: Optional[Union[str, list[str]]] = None, **kwargs
1210
1210
  ):
1211
1211
  super().__init__(name, **kwargs)
1212
1212
  self._input_path = split_path(input_path)
mlrun/utils/helpers.py CHANGED
@@ -800,7 +800,12 @@ def remove_tag_from_artifact_uri(uri: str) -> Optional[str]:
800
800
  "store://key:tag" => "store://key"
801
801
  "store://models/remote-model-project/my_model#0@tree" => unchanged (no tag)
802
802
  """
803
- return re.sub(r"(?<=/[^/:]\+):[^@^:\s]+(?=(@|\^|$))", "", uri)
803
+ add_store = False
804
+ if mlrun.datastore.is_store_uri(uri):
805
+ uri = uri.removeprefix(DB_SCHEMA + "://")
806
+ add_store = True
807
+ uri = re.sub(r"(#[^:@\s]*)?:[^@^:\s]+(?=(@|\^|$))", lambda m: m.group(1) or "", uri)
808
+ return uri if not add_store else DB_SCHEMA + "://" + uri
804
809
 
805
810
 
806
811
  def extend_hub_uri_if_needed(uri) -> tuple[str, bool]:
mlrun/utils/logger.py CHANGED
@@ -393,12 +393,14 @@ def resolve_formatter_by_kind(
393
393
 
394
394
 
395
395
  def create_test_logger(name: str = "mlrun", stream: IO[str] = stdout) -> Logger:
396
- return create_logger(
396
+ logger = create_logger(
397
397
  level="debug",
398
398
  formatter_kind=FormatterKinds.HUMAN_EXTENDED.name,
399
399
  name=name,
400
400
  stream=stream,
401
401
  )
402
+ logger._logger.propagate = True # pass records up to pytest’s handler
403
+ return logger
402
404
 
403
405
 
404
406
  def create_logger(
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "2e72ac795fbd5a2a1422956417d742f8dd9bcdb5",
3
- "version": "1.10.0-rc17"
2
+ "git_commit": "ef58f2d7ada676ba266aaf084b7a46714b95ba4e",
3
+ "version": "1.10.0-rc18"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.10.0rc17
3
+ Version: 1.10.0rc18
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -44,7 +44,7 @@ Requires-Dist: semver~=3.0
44
44
  Requires-Dist: dependency-injector~=4.41
45
45
  Requires-Dist: fsspec<2024.7,>=2023.9.2
46
46
  Requires-Dist: v3iofs~=0.1.17
47
- Requires-Dist: storey~=1.10.8
47
+ Requires-Dist: storey~=1.10.9
48
48
  Requires-Dist: inflection~=0.5.0
49
49
  Requires-Dist: python-dotenv~=1.0
50
50
  Requires-Dist: setuptools>=75.2
@@ -1,6 +1,6 @@
1
1
  mlrun/__init__.py,sha256=Y_AFhZV1hEx4vfiO-cyjup0aLGcp6R0SeL75GqLFQrc,7514
2
2
  mlrun/__main__.py,sha256=wQNaxW7QsqFBtWffnPkw-497fnpsrQzUnscBQQAP_UM,48364
3
- mlrun/config.py,sha256=c3F899B20Xe_wpO7cg9G5jEM7iMxfK92LaNxPKnQTyg,72306
3
+ mlrun/config.py,sha256=XAAb68MwEHpuPddPMtKBULtFk0hI9YC25DniYQk1DKk,72853
4
4
  mlrun/errors.py,sha256=bAk0t_qmCxQSPNK0TugOAfA5R6f0G6OYvEvXUWSJ_5U,9062
5
5
  mlrun/execution.py,sha256=dJ4PFwg5AlDHbCL2Q9dVDjWA_i64UTq2qBiF8kTU9tw,56922
6
6
  mlrun/features.py,sha256=jMEXo6NB36A6iaxNEJWzdtYwUmglYD90OIKTIEeWhE8,15841
@@ -8,7 +8,7 @@ mlrun/k8s_utils.py,sha256=mMnGyouHoJC93ZD2KGf9neJM1pD7mR9IXLnHOEwYVTQ,21469
8
8
  mlrun/lists.py,sha256=OlaV2QIFUzmenad9kxNJ3k4whlDyxI3zFbGwr6vpC5Y,8561
9
9
  mlrun/model.py,sha256=wHtM8LylSOEFk6Hxl95CVm8DOPhofjsANYdIvKHH6dw,88956
10
10
  mlrun/render.py,sha256=5DlhD6JtzHgmj5RVlpaYiHGhX84Q7qdi4RCEUj2UMgw,13195
11
- mlrun/run.py,sha256=_ban8NoNWfQHps3QIVyWh_Hn2S6usNrFBTUMObaeueo,46904
11
+ mlrun/run.py,sha256=6I4I_88Slpj27WzGnoq0c02SNpDaGsJllC8Y-2BED0E,46951
12
12
  mlrun/secrets.py,sha256=dZPdkc_zzfscVQepOHUwmzFqnBavDCBXV9DQoH_eIYM,7800
13
13
  mlrun/alerts/__init__.py,sha256=0gtG1BG0DXxFrXegIkjbM1XEN4sP9ODo0ucXrNld1hU,601
14
14
  mlrun/alerts/alert.py,sha256=QQFZGydQbx9RvAaSiaH-ALQZVcDKQX5lgizqj_rXW2k,15948
@@ -30,7 +30,7 @@ mlrun/common/types.py,sha256=1gxThbmC0Vd0U1ffIkEwz4T4S7JOgHt70rvw8TCO21c,1073
30
30
  mlrun/common/db/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
31
31
  mlrun/common/db/dialects.py,sha256=QN9bx7CTo32IIdJ2J3ZrsX8IUdp_BPxBtl0LyjMEC9g,868
32
32
  mlrun/common/formatters/__init__.py,sha256=au7S3M3wa9964RpQhFSvflk5-i5SWMeb3kek8Gvt4kg,889
33
- mlrun/common/formatters/artifact.py,sha256=NT2RPfReUGWVQ-Rhv1zexgXfLuKI5FvtneJDhihZK5g,1462
33
+ mlrun/common/formatters/artifact.py,sha256=JRs1B3nEvTdn4h69FLHjZZY_Dy40E9-BgvxfjcL_DKU,1503
34
34
  mlrun/common/formatters/base.py,sha256=85vQ0t4ZfqCs8b8QV1RLfRcEvANztKvTvsa__sD3zTo,4099
35
35
  mlrun/common/formatters/feature_set.py,sha256=SmSSiNYXZtmzQDCvQJhIpArtjOInmDN0g1xFqrDdWsw,1534
36
36
  mlrun/common/formatters/function.py,sha256=H8bHilWSn1NXm5WWlFH2dx8slomCGm3e8ghsmWOOh48,1493
@@ -75,7 +75,7 @@ mlrun/common/schemas/serving.py,sha256=4ek9JZDagkdeXyfkX6P6xp4deUNSf_kqXUaXcKSuv
75
75
  mlrun/common/schemas/tag.py,sha256=1wqEiAujsElojWb3qmuyfcaLFjXSNAAQdafkDx7fkn0,891
76
76
  mlrun/common/schemas/workflow.py,sha256=Y-FHJnxs5c86yetuOAPdEJPkne__tLPCxjSXSb4lrjo,2541
77
77
  mlrun/common/schemas/model_monitoring/__init__.py,sha256=FqFiFIDcylquQdY0XTBamB5kMzMrMFEpVYM_ecsVfLg,1925
78
- mlrun/common/schemas/model_monitoring/constants.py,sha256=spujh8a2GOb7pm8LksAQwndxPWSsjeyRub3ZVICdgNI,13685
78
+ mlrun/common/schemas/model_monitoring/constants.py,sha256=WhuUWgOwk91BI0dP5c1rm6X_W0V4UBV3l6KvRNHHE-E,13898
79
79
  mlrun/common/schemas/model_monitoring/functions.py,sha256=GpfSGp05D87wEKemECD3USL368pvnAM2WfS-nef5qOg,2210
80
80
  mlrun/common/schemas/model_monitoring/grafana.py,sha256=THQlLfPBevBksta8p5OaIsBaJtsNSXexLvHrDxOaVns,2095
81
81
  mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=aCrVqgoJsUEwvDJ84YFabDSy78CHcVBV3b0RdWj4JUw,13250
@@ -88,8 +88,8 @@ mlrun/datastore/__init__.py,sha256=UKGHkUfj5A9dqTiOeW4UScvwv0vq91NS_xs3-_QA7Jk,5
88
88
  mlrun/datastore/alibaba_oss.py,sha256=E0t0-e9Me2t2Mux2LWdC9riOG921TgNjhoy897JJX7o,4932
89
89
  mlrun/datastore/azure_blob.py,sha256=3LG7tOTwT97ZFBmyq-sfAIe5_SkuFgisRQtipv4kKUw,12779
90
90
  mlrun/datastore/base.py,sha256=yLdnFCL2k_rcasdbxXjnQr7Lwm-A79LnW9AITtn9-p4,25450
91
- mlrun/datastore/datastore.py,sha256=IbAUi2GZesWcmqPimURZD9iP5GpCB8se7GYA9afkAjA,13236
92
- mlrun/datastore/datastore_profile.py,sha256=fRR01v9mqC40UML49-6rdx-28b2FaRLj7iZeWJgSiT0,22842
91
+ mlrun/datastore/datastore.py,sha256=gOlMyPDelD9CRieoraDPYf1NNig_GrQRuuQxLmRq8Bo,13298
92
+ mlrun/datastore/datastore_profile.py,sha256=Y4VtaatIK4UXuTdpffCkAcsCBSxj5KOgnX7KlL-Yds8,23803
93
93
  mlrun/datastore/dbfs_store.py,sha256=CJwst1598qxiu63-Qa0c3e5E8LjeCv1XbMyWI7A6irY,6560
94
94
  mlrun/datastore/filestore.py,sha256=OcykjzhbUAZ6_Cb9bGAXRL2ngsOpxXSb4rR0lyogZtM,3773
95
95
  mlrun/datastore/google_cloud_storage.py,sha256=NREwZT7BCI0HfmOGkjpy5S3psiL_rgQSi43MaazJcKk,8711
@@ -105,12 +105,13 @@ mlrun/datastore/spark_utils.py,sha256=dn0RWpYzee-M8UZw-NVuHAdqlNAZ7VO-fNtI8ZiDky
105
105
  mlrun/datastore/store_resources.py,sha256=s2794zqkzy_mjRMvRedDNs_tycTLoF8wxTqsWRQphCE,6839
106
106
  mlrun/datastore/storeytargets.py,sha256=TvHbY3XS0qOg8ImXW1ET61UnjUPcYJbfSGAga3vgC-o,6492
107
107
  mlrun/datastore/targets.py,sha256=8dRnLy1wBYJbVyommYkpGeztdT1CsfFHZY6Zh7o8X-Q,79165
108
- mlrun/datastore/utils.py,sha256=7qhGMRos-IgV2o-dywWbMvCGQDlbRs_CZcwfvTxZTvw,11798
108
+ mlrun/datastore/utils.py,sha256=jxvq4lgQfgqb7dwKe4Kp51fYCCyOvitEdIfV2mzlqxg,11936
109
109
  mlrun/datastore/v3io.py,sha256=sMn5473k_bXyIJovNf0rahbVHRmO0YPdOwIhbs06clg,8201
110
110
  mlrun/datastore/vectorstore.py,sha256=k-yom5gfw20hnVG0Rg7aBEehuXwvAloZwn0cx0VGals,11708
111
111
  mlrun/datastore/model_provider/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
112
- mlrun/datastore/model_provider/model_provider.py,sha256=eDkTdwFsVxSFzTkYUwyXfl34d5IIulcQrLRjxWM2BFc,7911
113
- mlrun/datastore/model_provider/openai_provider.py,sha256=KmuE9i3EbeOc7QACvFLwnU2n3i_PmIw429BaZC0Y9Zw,8463
112
+ mlrun/datastore/model_provider/huggingface_provider.py,sha256=KTmErt_WHhAV9t8803_iCHoa7jO-0y-7bch7KMTMDKo,7264
113
+ mlrun/datastore/model_provider/model_provider.py,sha256=dJIc1R0wbExsk-uzWgpt9w_FK027mr4lTBxYpQx-icY,8083
114
+ mlrun/datastore/model_provider/openai_provider.py,sha256=Tl3HXLDOtHkp54rb0ZCddlCWU-gUruhFJwSC6ocbv1Y,9157
114
115
  mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev56Te4,1343
115
116
  mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
116
117
  mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
@@ -225,7 +226,7 @@ mlrun/launcher/factory.py,sha256=RW7mfzEFi8fR0M-4W1JQg1iq3_muUU6OTqT_3l4Ubrk,233
225
226
  mlrun/launcher/local.py,sha256=3gv-IQYoIChSmRaZ0vLUh0Tu26oLMCx9GbBYh4fWygQ,12161
226
227
  mlrun/launcher/remote.py,sha256=zFXE52Cq_7EkC8lfNKT0ceIbye0CfFiundF7O1YU4Xw,7810
227
228
  mlrun/model_monitoring/__init__.py,sha256=qDQnncjya9XPTlfvGyfWsZWiXc-glGZrrNja-5QmCZk,782
228
- mlrun/model_monitoring/api.py,sha256=lAsUp-gzqw8D1cpHVGA2_nPMYn5R4jdxk9UaGOiQ8fE,25945
229
+ mlrun/model_monitoring/api.py,sha256=9UsBIy8LYeAOoiIDTYthuD0mx1TYZxeGgaEM_H2qBkM,26092
229
230
  mlrun/model_monitoring/controller.py,sha256=FVckATzREAzldj68D1KxcnKSdilgKUDRdqhRUf9XpWU,39592
230
231
  mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
231
232
  mlrun/model_monitoring/helpers.py,sha256=0xhIYKzhaBrgyjLiA_ekCZsXzi3GBXpLyG40Bhj-PTY,23596
@@ -233,10 +234,10 @@ mlrun/model_monitoring/stream_processing.py,sha256=Mzn9Pelcblw8UzOFLGKb9oXOX0tkP
233
234
  mlrun/model_monitoring/writer.py,sha256=rGRFzSOkqZWvD3Y6sVk2H1Gepfnkzkp9ce00PsApTLo,8288
234
235
  mlrun/model_monitoring/applications/__init__.py,sha256=MaH_n4GiqqQvSkntM5yQ7_FCANtM_IfgK-IJTdo4G_E,757
235
236
  mlrun/model_monitoring/applications/_application_steps.py,sha256=t9LDIqQUGE10cyjyhlg0QqN1yVx0apD1HpERYLJfm8U,7409
236
- mlrun/model_monitoring/applications/base.py,sha256=nkJK0X3-7xEjcWGjtfLmvMomi5F14mmWs_M0_L8op5o,40547
237
+ mlrun/model_monitoring/applications/base.py,sha256=tfxXcE7WOvPEd68b6gbZWFG-8gkeeSaRRN0G0HYn0C8,43932
237
238
  mlrun/model_monitoring/applications/context.py,sha256=fAGFNCyNhSnVJPSIeJxv-XmEL2JhDmjK5Ouog9qyvdc,17035
238
239
  mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=2qgfFmrpHf-x0_EaHD-0T28piwSQzw-HH71aV1GwbZs,15389
239
- mlrun/model_monitoring/applications/results.py,sha256=_qmj6TWT0SR2bi7gUyRKBU418eGgGoLW2_hTJ7S-ock,5782
240
+ mlrun/model_monitoring/applications/results.py,sha256=LfBQOmkpKGvVGNrcj5QiXsRIG2IRgcv_Xqe4QJBmauk,5699
240
241
  mlrun/model_monitoring/applications/evidently/__init__.py,sha256=-DqdPnBSrjZhFvKOu_Ie3MiFvlur9sPTZpZ1u0_1AE8,690
241
242
  mlrun/model_monitoring/applications/evidently/base.py,sha256=shH9YwuFrGNWy1IDAbv622l-GE4o1z_u1bqhqTyTHDA,5661
242
243
  mlrun/model_monitoring/db/__init__.py,sha256=r47xPGZpIfMuv8J3PQCZTSqVPMhUta4sSJCZFKcS7FM,644
@@ -313,7 +314,7 @@ mlrun/serving/remote.py,sha256=Igha2FipK3-6rV_PZ1K464kTbiTu8rhc6SMm-HiEJ6o,18817
313
314
  mlrun/serving/routers.py,sha256=SmBOlHn7rT2gWTa-W8f16UB0UthgIFc4D1cPOZAA9ss,54003
314
315
  mlrun/serving/server.py,sha256=_P_SR4_7YKqruVzzDHgSPHWlNLGPG5-ksSUwuGhnmjg,38851
315
316
  mlrun/serving/serving_wrapper.py,sha256=UL9hhWCfMPcTJO_XrkvNaFvck1U1E7oS8trTZyak0cA,835
316
- mlrun/serving/states.py,sha256=nrwQcWC0q6A6xFSvTWvaDmtSVgv8Fva9TxCuBHGwZHs,124062
317
+ mlrun/serving/states.py,sha256=-eo1IGLm96Kd0bTrwj211nUcwomMizQ6MxrqtURNxAg,124069
317
318
  mlrun/serving/system_steps.py,sha256=tCxkJ54peOzRTMaqvHQCbcwx0ITqZkSpGXbtpRUEfzU,18463
318
319
  mlrun/serving/utils.py,sha256=Zbfqm8TKNcTE8zRBezVBzpvR2WKeKeIRN7otNIaiYEc,4170
319
320
  mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
@@ -328,9 +329,9 @@ mlrun/utils/async_http.py,sha256=8Olx8TNNeXB07nEGwlqhEgFgnFAD71vBU_bqaA9JW-w,122
328
329
  mlrun/utils/azure_vault.py,sha256=IEFizrDGDbAaoWwDr1WoA88S_EZ0T--vjYtY-i0cvYQ,3450
329
330
  mlrun/utils/clones.py,sha256=qbAGyEbSvlewn3Tw_DpQZP9z6MGzFhSaZfI1CblX8Fg,7515
330
331
  mlrun/utils/condition_evaluator.py,sha256=-nGfRmZzivn01rHTroiGY4rqEv8T1irMyhzxEei-sKc,1897
331
- mlrun/utils/helpers.py,sha256=ympa9GWzF_NMNemKSas29s8I0-2seHGhfErFT1b-6tY,82419
332
+ mlrun/utils/helpers.py,sha256=fMlwtYBzUK98nCTFCA5FGm1imqIdpJi0CuAPmO10YZs,82641
332
333
  mlrun/utils/http.py,sha256=5ZU2VpokaUM_DT3HBSqTm8xjUqTPjZN5fKkSIvKlTl0,8704
333
- mlrun/utils/logger.py,sha256=RG0m1rx6gfkJ-2C1r_p41MMpPiaDYqaYM2lYHDlNZEU,14767
334
+ mlrun/utils/logger.py,sha256=uaCgI_ezzaXf7nJDCy-1Nrjds8vSXqDbzmjmb3IyCQo,14864
334
335
  mlrun/utils/regex.py,sha256=FcRwWD8x9X3HLhCCU2F0AVKTFah784Pr7ZAe3a02jw8,5199
335
336
  mlrun/utils/retryer.py,sha256=SHddxyNdUjIyvNJ3idTDyBzXARihCSuo3zWlZj6fqB0,7852
336
337
  mlrun/utils/singleton.py,sha256=fNOfAUtha6OPCV_M1umWnGD0iabnnRwBke9otIspv30,868
@@ -347,11 +348,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
347
348
  mlrun/utils/notifications/notification/slack.py,sha256=kfhogR5keR7Zjh0VCjJNK3NR5_yXT7Cv-x9GdOUW4Z8,7294
348
349
  mlrun/utils/notifications/notification/webhook.py,sha256=zxh8CAlbPnTazsk6r05X5TKwqUZVOH5KBU2fJbzQlG4,5330
349
350
  mlrun/utils/version/__init__.py,sha256=YnzE6tlf24uOQ8y7Z7l96QLAI6-QEii7-77g8ynmzy0,613
350
- mlrun/utils/version/version.json,sha256=V37lX2OyNEzNPMQsoXG-KqHjDgxsQv-dFqRr2AHbFCk,90
351
+ mlrun/utils/version/version.json,sha256=1hAlhHbCP3fWtgQa3l5zk4ROJntlDhuVxmDS5HRBMiY,90
351
352
  mlrun/utils/version/version.py,sha256=M2hVhRrgkN3SxacZHs3ZqaOsqAA7B6a22ne324IQ1HE,1877
352
- mlrun-1.10.0rc17.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
353
- mlrun-1.10.0rc17.dist-info/METADATA,sha256=D6HN7BHzSm7-exb9kSE5N2h4m_dPOSsQc-PoM_5avj4,26195
354
- mlrun-1.10.0rc17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
355
- mlrun-1.10.0rc17.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
356
- mlrun-1.10.0rc17.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
357
- mlrun-1.10.0rc17.dist-info/RECORD,,
353
+ mlrun-1.10.0rc18.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
354
+ mlrun-1.10.0rc18.dist-info/METADATA,sha256=Rx-oVfq1W7TA73agpQeaFDhrevZ_RYVTXG6ormcXWvk,26195
355
+ mlrun-1.10.0rc18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
356
+ mlrun-1.10.0rc18.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
357
+ mlrun-1.10.0rc18.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
358
+ mlrun-1.10.0rc18.dist-info/RECORD,,