mlrun 1.10.0rc17__py3-none-any.whl → 1.10.0rc19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (32) hide show
  1. mlrun/__init__.py +21 -2
  2. mlrun/common/constants.py +1 -0
  3. mlrun/common/formatters/artifact.py +1 -0
  4. mlrun/common/schemas/model_monitoring/constants.py +14 -6
  5. mlrun/config.py +14 -0
  6. mlrun/datastore/__init__.py +9 -1
  7. mlrun/datastore/datastore.py +4 -4
  8. mlrun/datastore/datastore_profile.py +26 -0
  9. mlrun/datastore/model_provider/huggingface_provider.py +182 -0
  10. mlrun/datastore/model_provider/model_provider.py +57 -56
  11. mlrun/datastore/model_provider/openai_provider.py +34 -20
  12. mlrun/datastore/utils.py +6 -0
  13. mlrun/launcher/base.py +13 -0
  14. mlrun/model_monitoring/api.py +5 -3
  15. mlrun/model_monitoring/applications/base.py +107 -28
  16. mlrun/model_monitoring/applications/results.py +4 -7
  17. mlrun/run.py +4 -2
  18. mlrun/runtimes/base.py +5 -2
  19. mlrun/runtimes/daskjob.py +1 -0
  20. mlrun/runtimes/nuclio/application/application.py +84 -5
  21. mlrun/runtimes/nuclio/function.py +3 -1
  22. mlrun/serving/server.py +1 -0
  23. mlrun/serving/states.py +5 -2
  24. mlrun/utils/helpers.py +16 -1
  25. mlrun/utils/logger.py +3 -1
  26. mlrun/utils/version/version.json +2 -2
  27. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/METADATA +2 -2
  28. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/RECORD +32 -31
  29. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/WHEEL +0 -0
  30. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/entry_points.txt +0 -0
  31. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/licenses/LICENSE +0 -0
  32. {mlrun-1.10.0rc17.dist-info → mlrun-1.10.0rc19.dist-info}/top_level.txt +0 -0
@@ -11,13 +11,17 @@
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
- from typing import Callable, Optional, TypeVar, Union
16
+ from typing import TYPE_CHECKING, Any, Callable, Optional, 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
- T = TypeVar("T")
22
+ if TYPE_CHECKING:
23
+ from openai._models import BaseModel # noqa
24
+ from openai.types.chat.chat_completion import ChatCompletion
21
25
 
22
26
 
23
27
  class OpenAIProvider(ModelProvider):
@@ -68,10 +72,6 @@ class OpenAIProvider(ModelProvider):
68
72
  subpath = ""
69
73
  return endpoint, subpath
70
74
 
71
- @property
72
- def model(self) -> Optional[str]:
73
- return self.endpoint
74
-
75
75
  def load_client(self) -> None:
76
76
  """
77
77
  Initializes the OpenAI SDK client using the provided options.
@@ -103,8 +103,8 @@ class OpenAIProvider(ModelProvider):
103
103
  return self._sanitize_options(res)
104
104
 
105
105
  def custom_invoke(
106
- self, operation: Optional[Callable[..., T]] = None, **invoke_kwargs
107
- ) -> Optional[T]:
106
+ self, operation: Optional[Callable] = None, **invoke_kwargs
107
+ ) -> Union["ChatCompletion", "BaseModel"]:
108
108
  """
109
109
  OpenAI-specific implementation of `ModelProvider.custom_invoke`.
110
110
 
@@ -126,18 +126,24 @@ class OpenAIProvider(ModelProvider):
126
126
 
127
127
  """
128
128
  invoke_kwargs = self.get_invoke_kwargs(invoke_kwargs)
129
+ model_kwargs = {"model": invoke_kwargs.pop("model", None) or self.model}
130
+
129
131
  if operation:
130
- return operation(**invoke_kwargs, model=self.model)
132
+ if not callable(operation):
133
+ raise mlrun.errors.MLRunInvalidArgumentError(
134
+ "OpenAI custom_invoke operation must be a callable"
135
+ )
136
+ if not accepts_param(operation, "model"):
137
+ model_kwargs = {}
138
+ return operation(**invoke_kwargs, **model_kwargs)
131
139
  else:
132
- return self.client.chat.completions.create(
133
- **invoke_kwargs, model=self.model
134
- )
140
+ return self.client.chat.completions.create(**invoke_kwargs, **model_kwargs)
135
141
 
136
142
  async def async_custom_invoke(
137
143
  self,
138
- operation: Optional[Callable[..., Awaitable[T]]] = None,
144
+ operation: Optional[Callable[..., Awaitable[Any]]] = None,
139
145
  **invoke_kwargs,
140
- ) -> Optional[T]:
146
+ ) -> Union["ChatCompletion", "BaseModel"]:
141
147
  """
142
148
  OpenAI-specific implementation of `ModelProvider.async_custom_invoke`.
143
149
 
@@ -145,25 +151,33 @@ class OpenAIProvider(ModelProvider):
145
151
  `ModelProvider.async_custom_invoke`.
146
152
 
147
153
  Example:
148
- ```python
154
+ ```python
149
155
  result = openai_model_provider.invoke(
150
156
  openai_model_provider.async_client.images.generate,
151
157
  prompt="A futuristic cityscape at sunset",
152
158
  n=1,
153
159
  size="1024x1024",
154
160
  )
155
- ```
161
+ ```
162
+
156
163
  :param operation: Same as ModelProvider.async_custom_invoke.
157
164
  :param invoke_kwargs: Same as ModelProvider.async_custom_invoke.
158
165
  :return: Same as ModelProvider.async_custom_invoke.
159
166
 
160
167
  """
161
168
  invoke_kwargs = self.get_invoke_kwargs(invoke_kwargs)
169
+ model_kwargs = {"model": invoke_kwargs.pop("model", None) or self.model}
162
170
  if operation:
163
- return await operation(**invoke_kwargs, model=self.model)
171
+ if not inspect.iscoroutinefunction(operation):
172
+ raise mlrun.errors.MLRunInvalidArgumentError(
173
+ "OpenAI async_custom_invoke operation must be a coroutine function"
174
+ )
175
+ if not accepts_param(operation, "model"):
176
+ model_kwargs = {}
177
+ return await operation(**invoke_kwargs, **model_kwargs)
164
178
  else:
165
179
  return await self.async_client.chat.completions.create(
166
- **invoke_kwargs, model=self.model
180
+ **invoke_kwargs, **model_kwargs
167
181
  )
168
182
 
169
183
  def invoke(
@@ -171,7 +185,7 @@ class OpenAIProvider(ModelProvider):
171
185
  messages: Optional[list[dict]] = None,
172
186
  as_str: bool = False,
173
187
  **invoke_kwargs,
174
- ) -> Optional[Union[str, T]]:
188
+ ) -> Union[str, "ChatCompletion"]:
175
189
  """
176
190
  OpenAI-specific implementation of `ModelProvider.invoke`.
177
191
  Invokes an OpenAI model operation using the sync client.
@@ -200,7 +214,7 @@ class OpenAIProvider(ModelProvider):
200
214
  messages: Optional[list[dict]] = None,
201
215
  as_str: bool = False,
202
216
  **invoke_kwargs,
203
- ) -> str:
217
+ ) -> Union[str, "ChatCompletion"]:
204
218
  """
205
219
  OpenAI-specific implementation of `ModelProvider.async_invoke`.
206
220
  Invokes an OpenAI model operation using the async client.
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
mlrun/launcher/base.py CHANGED
@@ -157,6 +157,19 @@ class BaseLauncher(abc.ABC):
157
157
  ]:
158
158
  mlrun.utils.helpers.warn_on_deprecated_image(image)
159
159
 
160
+ # Raise an error if retry is configured for a runtime that doesn't support retries.
161
+ # For local runs, we intentionally skip this validation and allow the run to proceed, since they are typically
162
+ # used for debugging purposes, and in such cases we avoid blocking their execution.
163
+ if (
164
+ not mlrun.runtimes.RuntimeKinds.is_local_runtime(runtime.kind)
165
+ and run.spec.retry.count
166
+ and runtime.kind not in mlrun.runtimes.RuntimeKinds.retriable_runtimes()
167
+ ):
168
+ raise mlrun.errors.MLRunInvalidArgumentError(
169
+ f"Retry is not supported for {runtime.kind} runtime, supported runtimes are: "
170
+ f"{mlrun.runtimes.RuntimeKinds.retriable_runtimes()}"
171
+ )
172
+
160
173
  @staticmethod
161
174
  def _validate_output_path(
162
175
  runtime: "mlrun.runtimes.BaseRuntime",
@@ -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
@@ -365,7 +365,7 @@ def import_function(url="", secrets=None, db="", project=None, new_name=None):
365
365
  def import_function_to_dict(url, secrets=None):
366
366
  """Load function spec from local/remote YAML file"""
367
367
  obj = get_object(url, secrets)
368
- runtime = yaml.load(obj, Loader=yaml.FullLoader)
368
+ runtime = yaml.safe_load(obj)
369
369
  remote = "://" in url
370
370
 
371
371
  code = get_in(runtime, "spec.build.functionSourceCode")
@@ -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/runtimes/base.py CHANGED
@@ -447,14 +447,17 @@ class BaseRuntime(ModelObj):
447
447
  :return: Dictionary with all the variables that could be parsed
448
448
  """
449
449
  runtime_env = {
450
- "MLRUN_ACTIVE_PROJECT": self.metadata.project or config.active_project
450
+ mlrun_constants.MLRUN_ACTIVE_PROJECT: self.metadata.project
451
+ or config.active_project
451
452
  }
452
453
  if runobj:
453
454
  runtime_env["MLRUN_EXEC_CONFIG"] = runobj.to_json(
454
455
  exclude_notifications_params=True
455
456
  )
456
457
  if runobj.metadata.project:
457
- runtime_env["MLRUN_ACTIVE_PROJECT"] = runobj.metadata.project
458
+ runtime_env[mlrun_constants.MLRUN_ACTIVE_PROJECT] = (
459
+ runobj.metadata.project
460
+ )
458
461
  if runobj.spec.verbose:
459
462
  runtime_env["MLRUN_LOG_LEVEL"] = "DEBUG"
460
463
  if config.httpdb.api_url:
mlrun/runtimes/daskjob.py CHANGED
@@ -541,6 +541,7 @@ class DaskCluster(KubejobRuntime):
541
541
  notifications=notifications,
542
542
  returns=returns,
543
543
  state_thresholds=state_thresholds,
544
+ retry=retry,
544
545
  **launcher_kwargs,
545
546
  )
546
547