mlrun 1.10.0rc40__py3-none-any.whl → 1.11.0rc16__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/__init__.py +3 -2
- mlrun/__main__.py +0 -4
- mlrun/artifacts/dataset.py +2 -2
- mlrun/artifacts/plots.py +1 -1
- mlrun/{model_monitoring/db/tsdb/tdengine → auth}/__init__.py +2 -3
- mlrun/auth/nuclio.py +89 -0
- mlrun/auth/providers.py +429 -0
- mlrun/auth/utils.py +415 -0
- mlrun/common/constants.py +7 -0
- mlrun/common/model_monitoring/helpers.py +41 -4
- mlrun/common/runtimes/constants.py +28 -0
- mlrun/common/schemas/__init__.py +13 -3
- mlrun/common/schemas/alert.py +2 -2
- mlrun/common/schemas/api_gateway.py +3 -0
- mlrun/common/schemas/auth.py +10 -10
- mlrun/common/schemas/client_spec.py +4 -0
- mlrun/common/schemas/constants.py +25 -0
- mlrun/common/schemas/frontend_spec.py +1 -8
- mlrun/common/schemas/function.py +24 -0
- mlrun/common/schemas/hub.py +3 -2
- mlrun/common/schemas/model_monitoring/__init__.py +1 -1
- mlrun/common/schemas/model_monitoring/constants.py +2 -2
- mlrun/common/schemas/secret.py +17 -2
- mlrun/common/secrets.py +95 -1
- mlrun/common/types.py +10 -10
- mlrun/config.py +53 -15
- mlrun/data_types/infer.py +2 -2
- mlrun/datastore/__init__.py +2 -3
- mlrun/datastore/base.py +274 -10
- mlrun/datastore/datastore.py +1 -1
- mlrun/datastore/datastore_profile.py +49 -17
- mlrun/datastore/model_provider/huggingface_provider.py +6 -2
- mlrun/datastore/model_provider/model_provider.py +2 -2
- mlrun/datastore/model_provider/openai_provider.py +2 -2
- mlrun/datastore/s3.py +15 -16
- mlrun/datastore/sources.py +1 -1
- mlrun/datastore/store_resources.py +4 -4
- mlrun/datastore/storeytargets.py +16 -10
- mlrun/datastore/targets.py +1 -1
- mlrun/datastore/utils.py +16 -3
- mlrun/datastore/v3io.py +1 -1
- mlrun/db/base.py +36 -12
- mlrun/db/httpdb.py +316 -101
- mlrun/db/nopdb.py +29 -11
- mlrun/errors.py +4 -2
- mlrun/execution.py +11 -12
- mlrun/feature_store/api.py +1 -1
- mlrun/feature_store/common.py +1 -1
- mlrun/feature_store/feature_vector_utils.py +1 -1
- mlrun/feature_store/steps.py +8 -6
- mlrun/frameworks/_common/utils.py +3 -3
- mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +2 -1
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_ml_common/utils.py +2 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +4 -3
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +2 -1
- mlrun/frameworks/onnx/dataset.py +2 -1
- mlrun/frameworks/onnx/mlrun_interface.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +5 -4
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +2 -1
- mlrun/frameworks/pytorch/utils.py +2 -1
- mlrun/frameworks/sklearn/metric.py +2 -1
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +5 -4
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +2 -1
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +2 -1
- mlrun/hub/__init__.py +37 -0
- mlrun/hub/base.py +142 -0
- mlrun/hub/module.py +67 -76
- mlrun/hub/step.py +113 -0
- mlrun/launcher/base.py +2 -1
- mlrun/launcher/local.py +2 -1
- mlrun/model.py +12 -2
- mlrun/model_monitoring/__init__.py +0 -1
- mlrun/model_monitoring/api.py +2 -2
- mlrun/model_monitoring/applications/base.py +20 -6
- mlrun/model_monitoring/applications/context.py +1 -0
- mlrun/model_monitoring/controller.py +7 -17
- mlrun/model_monitoring/db/_schedules.py +2 -16
- mlrun/model_monitoring/db/_stats.py +2 -13
- mlrun/model_monitoring/db/tsdb/__init__.py +9 -7
- mlrun/model_monitoring/db/tsdb/base.py +2 -4
- mlrun/model_monitoring/db/tsdb/preaggregate.py +234 -0
- mlrun/model_monitoring/db/tsdb/stream_graph_steps.py +63 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_metrics_queries.py +414 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_predictions_queries.py +376 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_results_queries.py +590 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connection.py +434 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connector.py +541 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_operations.py +808 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_schema.py +502 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream.py +163 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream_graph_steps.py +60 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_dataframe_processor.py +141 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_query_builder.py +585 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/writer_graph_steps.py +73 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +4 -6
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +147 -79
- mlrun/model_monitoring/features_drift_table.py +2 -1
- mlrun/model_monitoring/helpers.py +2 -1
- mlrun/model_monitoring/stream_processing.py +18 -16
- mlrun/model_monitoring/writer.py +4 -3
- mlrun/package/__init__.py +2 -1
- mlrun/platforms/__init__.py +0 -44
- mlrun/platforms/iguazio.py +1 -1
- mlrun/projects/operations.py +11 -10
- mlrun/projects/project.py +81 -82
- mlrun/run.py +4 -7
- mlrun/runtimes/__init__.py +2 -204
- mlrun/runtimes/base.py +89 -21
- mlrun/runtimes/constants.py +225 -0
- mlrun/runtimes/daskjob.py +4 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +2 -1
- mlrun/runtimes/mounts.py +5 -0
- mlrun/runtimes/nuclio/__init__.py +12 -8
- mlrun/runtimes/nuclio/api_gateway.py +36 -6
- mlrun/runtimes/nuclio/application/application.py +200 -32
- mlrun/runtimes/nuclio/function.py +154 -49
- mlrun/runtimes/nuclio/serving.py +55 -42
- mlrun/runtimes/pod.py +59 -10
- mlrun/secrets.py +46 -2
- mlrun/serving/__init__.py +2 -0
- mlrun/serving/remote.py +5 -5
- mlrun/serving/routers.py +3 -3
- mlrun/serving/server.py +46 -43
- mlrun/serving/serving_wrapper.py +6 -2
- mlrun/serving/states.py +554 -207
- mlrun/serving/steps.py +1 -1
- mlrun/serving/system_steps.py +42 -33
- mlrun/track/trackers/mlflow_tracker.py +29 -31
- mlrun/utils/helpers.py +89 -16
- mlrun/utils/http.py +9 -2
- mlrun/utils/notifications/notification/git.py +1 -1
- mlrun/utils/notifications/notification/mail.py +39 -16
- mlrun/utils/notifications/notification_pusher.py +2 -2
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +3 -4
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/METADATA +39 -49
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/RECORD +144 -130
- mlrun/db/auth_utils.py +0 -152
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +0 -343
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +0 -75
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py +0 -281
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +0 -1368
- mlrun/model_monitoring/db/tsdb/tdengine/writer_graph_steps.py +0 -51
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/WHEEL +0 -0
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc40.dist-info → mlrun-1.11.0rc16.dist-info}/top_level.txt +0 -0
mlrun/errors.py
CHANGED
|
@@ -264,12 +264,14 @@ class MLRunFatalFailureError(Exception):
|
|
|
264
264
|
|
|
265
265
|
|
|
266
266
|
class ModelRunnerError(MLRunBaseError):
|
|
267
|
-
def __init__(self, models_errors: dict[str
|
|
267
|
+
def __init__(self, models_errors: dict[str, str], *args) -> None:
|
|
268
268
|
self.models_errors = models_errors
|
|
269
269
|
super().__init__(self.__repr__(), *args)
|
|
270
270
|
|
|
271
271
|
def __repr__(self):
|
|
272
|
-
return
|
|
272
|
+
return "ModelRunnerError: " + ";\n".join(
|
|
273
|
+
f"{model} {msg}" for model, msg in self.models_errors.items()
|
|
274
|
+
)
|
|
273
275
|
|
|
274
276
|
def __copy__(self):
|
|
275
277
|
return type(self)(models_errors=self.models_errors)
|
mlrun/execution.py
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
17
|
import uuid
|
|
18
|
-
import warnings
|
|
19
18
|
from copy import deepcopy
|
|
20
19
|
from typing import Optional, Union, cast
|
|
21
20
|
|
|
@@ -101,6 +100,7 @@ class MLClientCtx:
|
|
|
101
100
|
self._node_selector = {}
|
|
102
101
|
self._tolerations = {}
|
|
103
102
|
self._affinity = {}
|
|
103
|
+
self._auth = {}
|
|
104
104
|
|
|
105
105
|
self._function = ""
|
|
106
106
|
self._parameters = {}
|
|
@@ -234,6 +234,11 @@ class MLClientCtx:
|
|
|
234
234
|
"""Dictionary with node selectors (read-only)"""
|
|
235
235
|
return deepcopy(self._node_selector)
|
|
236
236
|
|
|
237
|
+
@property
|
|
238
|
+
def auth(self):
|
|
239
|
+
"""Dictionary with auth (read-only)"""
|
|
240
|
+
return deepcopy(self._auth)
|
|
241
|
+
|
|
237
242
|
@property
|
|
238
243
|
def tolerations(self):
|
|
239
244
|
"""Dictionary with tolerations (read-only)"""
|
|
@@ -437,6 +442,7 @@ class MLClientCtx:
|
|
|
437
442
|
self._affinity = spec.get("affinity", self._affinity)
|
|
438
443
|
self._reset_on_run = spec.get("reset_on_run", self._reset_on_run)
|
|
439
444
|
self._retry_spec = spec.get("retry", self._retry_spec)
|
|
445
|
+
self._auth = spec.get("auth", self._auth)
|
|
440
446
|
|
|
441
447
|
self._init_dbs(rundb)
|
|
442
448
|
|
|
@@ -1141,14 +1147,6 @@ class MLClientCtx:
|
|
|
1141
1147
|
self._update_run()
|
|
1142
1148
|
return item
|
|
1143
1149
|
|
|
1144
|
-
def get_cached_artifact(self, key):
|
|
1145
|
-
"""Return a logged artifact from cache (for potential updates)"""
|
|
1146
|
-
warnings.warn(
|
|
1147
|
-
"get_cached_artifact is deprecated in 1.8.0 and will be removed in 1.11.0. Use get_artifact instead.",
|
|
1148
|
-
FutureWarning,
|
|
1149
|
-
)
|
|
1150
|
-
return self.get_artifact(key)
|
|
1151
|
-
|
|
1152
1150
|
def get_artifact(
|
|
1153
1151
|
self, key, tag=None, iter=None, tree=None, uid=None
|
|
1154
1152
|
) -> Optional[Artifact]:
|
|
@@ -1310,6 +1308,7 @@ class MLClientCtx:
|
|
|
1310
1308
|
"node_selector": self._node_selector,
|
|
1311
1309
|
"tolerations": self._tolerations,
|
|
1312
1310
|
"affinity": self._affinity,
|
|
1311
|
+
"auth": self._auth,
|
|
1313
1312
|
"retry": self._retry_spec,
|
|
1314
1313
|
},
|
|
1315
1314
|
"status": {
|
|
@@ -1511,15 +1510,15 @@ class MLClientCtx:
|
|
|
1511
1510
|
|
|
1512
1511
|
|
|
1513
1512
|
def _cast_result(value):
|
|
1514
|
-
if isinstance(value,
|
|
1513
|
+
if isinstance(value, int | str | float):
|
|
1515
1514
|
return value
|
|
1516
1515
|
if isinstance(value, list):
|
|
1517
1516
|
return [_cast_result(v) for v in value]
|
|
1518
1517
|
if isinstance(value, dict):
|
|
1519
1518
|
return {k: _cast_result(v) for k, v in value.items()}
|
|
1520
|
-
if isinstance(value,
|
|
1519
|
+
if isinstance(value, np.int64 | np.integer):
|
|
1521
1520
|
return int(value)
|
|
1522
|
-
if isinstance(value,
|
|
1521
|
+
if isinstance(value, np.floating | np.float64):
|
|
1523
1522
|
return float(value)
|
|
1524
1523
|
if isinstance(value, np.ndarray):
|
|
1525
1524
|
return value.tolist()
|
mlrun/feature_store/api.py
CHANGED
|
@@ -361,7 +361,7 @@ def _ingest(
|
|
|
361
361
|
import pyspark.sql
|
|
362
362
|
|
|
363
363
|
if (
|
|
364
|
-
isinstance(source,
|
|
364
|
+
isinstance(source, pd.DataFrame | pyspark.sql.DataFrame)
|
|
365
365
|
and run_config is not None
|
|
366
366
|
):
|
|
367
367
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
mlrun/feature_store/common.py
CHANGED
|
@@ -256,7 +256,7 @@ class RunConfig:
|
|
|
256
256
|
@function.setter
|
|
257
257
|
def function(self, function):
|
|
258
258
|
if function and not (
|
|
259
|
-
isinstance(function,
|
|
259
|
+
isinstance(function, str | FunctionReference) or hasattr(function, "apply")
|
|
260
260
|
):
|
|
261
261
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
262
262
|
"function must be a uri (string) or mlrun function object/reference"
|
|
@@ -370,7 +370,7 @@ class OnlineVectorService:
|
|
|
370
370
|
if (
|
|
371
371
|
not entity_rows
|
|
372
372
|
or not isinstance(entity_rows, list)
|
|
373
|
-
or not isinstance(entity_rows[0],
|
|
373
|
+
or not isinstance(entity_rows[0], list | dict)
|
|
374
374
|
):
|
|
375
375
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
376
376
|
f"input data is of type {type(entity_rows)}. must be a list of lists or list of dicts"
|
mlrun/feature_store/steps.py
CHANGED
|
@@ -279,11 +279,11 @@ class MapValues(StepToDict, MLRunStep):
|
|
|
279
279
|
new_col_type = df.schema[new_column_name].dataType
|
|
280
280
|
# in order to avoid exception at isna on non-decimal/float columns -
|
|
281
281
|
# we need to check their types before filtering.
|
|
282
|
-
if isinstance(col_type,
|
|
282
|
+
if isinstance(col_type, FloatType | DoubleType | DecimalType):
|
|
283
283
|
column_filter = (~isnull(col(column))) & (~isnan(col(column)))
|
|
284
284
|
else:
|
|
285
285
|
column_filter = ~isnull(col(column))
|
|
286
|
-
if isinstance(new_col_type,
|
|
286
|
+
if isinstance(new_col_type, FloatType | DoubleType | DecimalType):
|
|
287
287
|
new_column_filter = isnull(col(new_column_name)) | isnan(
|
|
288
288
|
col(new_column_name)
|
|
289
289
|
)
|
|
@@ -295,7 +295,7 @@ class MapValues(StepToDict, MLRunStep):
|
|
|
295
295
|
for k, v in column_map.items()
|
|
296
296
|
if v is None
|
|
297
297
|
or (
|
|
298
|
-
isinstance(v,
|
|
298
|
+
isinstance(v, float | np.float64 | np.float32 | np.float16)
|
|
299
299
|
and math.isnan(v)
|
|
300
300
|
)
|
|
301
301
|
]
|
|
@@ -338,7 +338,7 @@ class MapValues(StepToDict, MLRunStep):
|
|
|
338
338
|
for val in column_map.values()
|
|
339
339
|
if type(val) is not None
|
|
340
340
|
and not (
|
|
341
|
-
isinstance(val,
|
|
341
|
+
isinstance(val, float | np.float64 | np.float32 | np.float16)
|
|
342
342
|
and math.isnan(val)
|
|
343
343
|
)
|
|
344
344
|
)
|
|
@@ -358,7 +358,9 @@ class MapValues(StepToDict, MLRunStep):
|
|
|
358
358
|
and val != "-inf"
|
|
359
359
|
and val != "inf"
|
|
360
360
|
and not (
|
|
361
|
-
isinstance(
|
|
361
|
+
isinstance(
|
|
362
|
+
val, float | np.float64 | np.float32 | np.float16
|
|
363
|
+
)
|
|
362
364
|
and math.isnan(val)
|
|
363
365
|
)
|
|
364
366
|
)
|
|
@@ -443,7 +445,7 @@ class OneHotEncoder(StepToDict, MLRunStep):
|
|
|
443
445
|
self.mapping = mapping
|
|
444
446
|
for key, values in mapping.items():
|
|
445
447
|
for val in values:
|
|
446
|
-
if not (isinstance(val, str) or isinstance(val,
|
|
448
|
+
if not (isinstance(val, str) or isinstance(val, int | np.integer)):
|
|
447
449
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
448
450
|
"For OneHotEncoder you must provide int or string mapping list"
|
|
449
451
|
)
|
|
@@ -97,9 +97,9 @@ class CommonUtils(ABC):
|
|
|
97
97
|
"""
|
|
98
98
|
if isinstance(dataset, np.ndarray):
|
|
99
99
|
return dataset
|
|
100
|
-
if isinstance(dataset,
|
|
100
|
+
if isinstance(dataset, pd.DataFrame | pd.Series):
|
|
101
101
|
return dataset.to_numpy()
|
|
102
|
-
if isinstance(dataset,
|
|
102
|
+
if isinstance(dataset, list | tuple):
|
|
103
103
|
return np.array(dataset)
|
|
104
104
|
if isinstance(dataset, dict):
|
|
105
105
|
return np.array(list(dataset.values()))
|
|
@@ -133,7 +133,7 @@ class CommonUtils(ABC):
|
|
|
133
133
|
"""
|
|
134
134
|
if isinstance(dataset, pd.DataFrame):
|
|
135
135
|
return dataset
|
|
136
|
-
if isinstance(dataset,
|
|
136
|
+
if isinstance(dataset, np.ndarray | pd.Series | list | tuple | dict):
|
|
137
137
|
return pd.DataFrame(dataset)
|
|
138
138
|
try:
|
|
139
139
|
# SciPy is not in MLRun's requirements but common to all frameworks.
|
|
@@ -281,7 +281,7 @@ class Logger:
|
|
|
281
281
|
"""
|
|
282
282
|
for parameter_name, parameter_value in self._context.parameters.items():
|
|
283
283
|
# Check if the parameter is a trackable value:
|
|
284
|
-
if isinstance(parameter_value,
|
|
284
|
+
if isinstance(parameter_value, str | bool | float | int):
|
|
285
285
|
self.log_static_hyperparameter(
|
|
286
286
|
parameter_name=parameter_name, value=parameter_value
|
|
287
287
|
)
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
from abc import abstractmethod
|
|
17
|
+
from collections.abc import Callable
|
|
17
18
|
from datetime import datetime
|
|
18
|
-
from typing import Any,
|
|
19
|
+
from typing import Any, Generic, Optional, Union
|
|
19
20
|
|
|
20
21
|
import yaml
|
|
21
22
|
|
|
@@ -73,7 +73,7 @@ class MLRunLogger(Logger):
|
|
|
73
73
|
"""
|
|
74
74
|
for parameter_name, parameter_value in self._context.parameters.items():
|
|
75
75
|
# Check if the parameter is a trackable value:
|
|
76
|
-
if isinstance(parameter_value,
|
|
76
|
+
if isinstance(parameter_value, str | bool | float | int):
|
|
77
77
|
self.log_static_hyperparameter(
|
|
78
78
|
parameter_name=parameter_name, value=parameter_value
|
|
79
79
|
)
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from abc import ABC
|
|
16
|
+
from collections.abc import Callable
|
|
16
17
|
from enum import Enum
|
|
17
|
-
from typing import
|
|
18
|
+
from typing import Union
|
|
18
19
|
|
|
19
20
|
import pandas as pd
|
|
20
21
|
from sklearn.base import is_classifier, is_regressor
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import mlrun
|
|
18
19
|
from mlrun.artifacts import get_model
|
|
@@ -58,7 +59,7 @@ def get_framework_by_instance(model: CommonTypes.ModelType) -> str:
|
|
|
58
59
|
|
|
59
60
|
from mlrun.frameworks.xgboost import XGBoostModelHandler
|
|
60
61
|
|
|
61
|
-
if isinstance(model,
|
|
62
|
+
if isinstance(model, XGBModel | Booster):
|
|
62
63
|
return XGBoostModelHandler.FRAMEWORK_NAME
|
|
63
64
|
except ModuleNotFoundError:
|
|
64
65
|
pass
|
|
@@ -69,7 +70,7 @@ def get_framework_by_instance(model: CommonTypes.ModelType) -> str:
|
|
|
69
70
|
|
|
70
71
|
from mlrun.frameworks.lgbm import LGBMModelHandler
|
|
71
72
|
|
|
72
|
-
if isinstance(model,
|
|
73
|
+
if isinstance(model, LGBMModel | Booster):
|
|
73
74
|
return LGBMModelHandler.FRAMEWORK_NAME
|
|
74
75
|
except ModuleNotFoundError:
|
|
75
76
|
pass
|
mlrun/frameworks/onnx/dataset.py
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import onnx
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
from torch import Tensor
|
|
@@ -496,7 +497,7 @@ class LoggingCallback(Callback):
|
|
|
496
497
|
value = self._objects[source]
|
|
497
498
|
for key in key_chain:
|
|
498
499
|
try:
|
|
499
|
-
if isinstance(value,
|
|
500
|
+
if isinstance(value, dict | list | tuple):
|
|
500
501
|
value = value[key]
|
|
501
502
|
else:
|
|
502
503
|
value = getattr(value, key)
|
|
@@ -507,7 +508,7 @@ class LoggingCallback(Callback):
|
|
|
507
508
|
)
|
|
508
509
|
|
|
509
510
|
# Parse the value:
|
|
510
|
-
if isinstance(value,
|
|
511
|
+
if isinstance(value, Tensor | Parameter):
|
|
511
512
|
if value.numel() == 1:
|
|
512
513
|
value = float(value)
|
|
513
514
|
else:
|
|
@@ -523,7 +524,7 @@ class LoggingCallback(Callback):
|
|
|
523
524
|
f"The parameter with the following key chain: {key_chain} is a numpy.ndarray with {value.size} "
|
|
524
525
|
f"elements. numpy arrays are trackable only if they have 1 element."
|
|
525
526
|
)
|
|
526
|
-
elif not isinstance(value,
|
|
527
|
+
elif not isinstance(value, float | int | str | bool):
|
|
527
528
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
528
529
|
f"The parameter with the following key chain: {key_chain} is of type '{type(value)}'. "
|
|
529
530
|
f"The only trackable types are: float, int, str and bool."
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import torch
|
|
18
19
|
from torch import Tensor
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from collections.abc import Callable
|
|
15
16
|
from datetime import datetime
|
|
16
|
-
from typing import
|
|
17
|
+
from typing import Optional, Union
|
|
17
18
|
|
|
18
19
|
import torch
|
|
19
20
|
from torch import Tensor
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Union
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import torch
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import tensorflow as tf
|
|
@@ -441,8 +442,8 @@ class LoggingCallback(Callback):
|
|
|
441
442
|
)
|
|
442
443
|
|
|
443
444
|
# Parse the value:
|
|
444
|
-
if isinstance(value,
|
|
445
|
-
is_keras_3() and isinstance(value,
|
|
445
|
+
if isinstance(value, tf.Tensor | tf.Variable) or (
|
|
446
|
+
is_keras_3() and isinstance(value, keras.KerasTensor | keras.Variable)
|
|
446
447
|
):
|
|
447
448
|
if int(tf.size(value)) == 1:
|
|
448
449
|
value = float(value)
|
|
@@ -459,7 +460,7 @@ class LoggingCallback(Callback):
|
|
|
459
460
|
f"The parameter with the following key chain: {key_chain} is a numpy.ndarray with {value.size} "
|
|
460
461
|
f"elements. numpy arrays are trackable only if they have 1 element."
|
|
461
462
|
)
|
|
462
|
-
elif not (isinstance(value,
|
|
463
|
+
elif not (isinstance(value, float | int | str | bool)):
|
|
463
464
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
464
465
|
f"The parameter with the following key chain: {key_chain} is of type '{type(value)}'. The only "
|
|
465
466
|
f"trackable types are: float, int, str and bool."
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import mlrun
|
|
18
19
|
from mlrun.artifacts import Artifact
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from collections.abc import Callable
|
|
15
16
|
from datetime import datetime
|
|
16
|
-
from typing import
|
|
17
|
+
from typing import Optional, Union
|
|
17
18
|
|
|
18
19
|
import tensorflow as tf
|
|
19
20
|
from packaging import version
|
mlrun/hub/__init__.py
CHANGED
|
@@ -11,5 +11,42 @@
|
|
|
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
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
import mlrun
|
|
17
|
+
from mlrun.common.schemas.hub import HubSourceType
|
|
14
18
|
|
|
15
19
|
from .module import get_hub_module, import_module
|
|
20
|
+
from .step import get_hub_step
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_hub_item(
|
|
24
|
+
source_name: str,
|
|
25
|
+
item_name: str,
|
|
26
|
+
version: Optional[str] = None,
|
|
27
|
+
tag: Optional[str] = "latest",
|
|
28
|
+
force_refresh: bool = False,
|
|
29
|
+
item_type: HubSourceType = HubSourceType.functions,
|
|
30
|
+
) -> mlrun.common.schemas.hub.HubItem:
|
|
31
|
+
"""
|
|
32
|
+
Retrieve a specific hub item.
|
|
33
|
+
|
|
34
|
+
:param source_name: Name of source.
|
|
35
|
+
:param item_name: Name of the item to retrieve, as it appears in the hub catalog.
|
|
36
|
+
:param version: Get a specific version of the item. Default is ``None``.
|
|
37
|
+
:param tag: Get a specific version of the item identified by tag. Default is ``latest``.
|
|
38
|
+
:param force_refresh: Make the server fetch the information from the actual hub
|
|
39
|
+
source, rather than
|
|
40
|
+
rely on cached information. Default is ``False``.
|
|
41
|
+
:param item_type: The type of item to retrieve from the hub source (e.g: functions, modules).
|
|
42
|
+
:returns: :py:class:`~mlrun.common.schemas.hub.HubItem`.
|
|
43
|
+
"""
|
|
44
|
+
db = mlrun.get_run_db()
|
|
45
|
+
return db.get_hub_item(
|
|
46
|
+
source_name=source_name,
|
|
47
|
+
item_name=item_name,
|
|
48
|
+
version=version,
|
|
49
|
+
tag=tag,
|
|
50
|
+
force_refresh=force_refresh,
|
|
51
|
+
item_type=item_type,
|
|
52
|
+
)
|
mlrun/hub/base.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
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
|
+
import os
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import ClassVar, Optional
|
|
20
|
+
|
|
21
|
+
from mlrun.common.schemas.hub import HubSourceType
|
|
22
|
+
from mlrun.run import function_to_module, get_object
|
|
23
|
+
from mlrun.utils import logger
|
|
24
|
+
|
|
25
|
+
from ..errors import MLRunBadRequestError
|
|
26
|
+
from ..model import ModelObj
|
|
27
|
+
from ..utils import extend_hub_uri_if_needed
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class HubAsset(ModelObj):
|
|
31
|
+
ASSET_TYPE: ClassVar[HubSourceType]
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
name: str,
|
|
36
|
+
version: str,
|
|
37
|
+
description: Optional[str] = None,
|
|
38
|
+
categories: Optional[list] = None,
|
|
39
|
+
requirements: Optional[list] = None,
|
|
40
|
+
local_path: Optional[Path] = None,
|
|
41
|
+
filename: Optional[str] = None,
|
|
42
|
+
example: Optional[str] = None,
|
|
43
|
+
url: Optional[str] = None,
|
|
44
|
+
**kwargs,
|
|
45
|
+
):
|
|
46
|
+
self.name: str = name
|
|
47
|
+
self.version: str = version
|
|
48
|
+
self.description: str = description or ""
|
|
49
|
+
self.categories: list = categories or []
|
|
50
|
+
self.requirements: list = requirements or []
|
|
51
|
+
self.local_path: Optional[Path] = local_path
|
|
52
|
+
self.filename: str = filename or name
|
|
53
|
+
self.example: str = example or ""
|
|
54
|
+
self.url: str = url or ""
|
|
55
|
+
|
|
56
|
+
def module(self):
|
|
57
|
+
"""Import the code of the asset as a module."""
|
|
58
|
+
try:
|
|
59
|
+
return function_to_module(code=self.filename, workdir=self.local_path)
|
|
60
|
+
except Exception as e:
|
|
61
|
+
raise MLRunBadRequestError(
|
|
62
|
+
f"Failed to import module from {self.get_src_file_path()}: {e}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def install_requirements(self) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Install pip-style requirements of the asset (e.g., ["pandas>=2.0.0", "requests==2.31.0"]).
|
|
68
|
+
"""
|
|
69
|
+
if not self.requirements or len(self.requirements) == 0:
|
|
70
|
+
logger.info("No requirements to install.")
|
|
71
|
+
return
|
|
72
|
+
for req in self.requirements:
|
|
73
|
+
logger.info(f"Installing {req} ...")
|
|
74
|
+
try:
|
|
75
|
+
subprocess.run(
|
|
76
|
+
[sys.executable, "-m", "pip", "install", req], check=True, text=True
|
|
77
|
+
)
|
|
78
|
+
logger.info(f"Installed {req}")
|
|
79
|
+
except subprocess.CalledProcessError as e:
|
|
80
|
+
logger.error(f"Failed to install {req} (exit code {e.returncode})")
|
|
81
|
+
|
|
82
|
+
def download_files(
|
|
83
|
+
self,
|
|
84
|
+
local_path: Optional[str] = None,
|
|
85
|
+
download_example: bool = True,
|
|
86
|
+
):
|
|
87
|
+
"""
|
|
88
|
+
Download this hub asset’s files (code file and, if available and requested, an example notebook) to the target
|
|
89
|
+
directory specified by `local_path` (defaults to the current working directory).
|
|
90
|
+
This path will be used later to locate the code file when calling module().
|
|
91
|
+
"""
|
|
92
|
+
self.local_path = self.verify_directory(path=local_path)
|
|
93
|
+
source_url, _ = extend_hub_uri_if_needed(
|
|
94
|
+
uri=self.url, asset_type=self.ASSET_TYPE, file=self.filename
|
|
95
|
+
)
|
|
96
|
+
self._download_object(obj_url=source_url, target_name=self.filename)
|
|
97
|
+
if download_example and self.example:
|
|
98
|
+
example_url, _ = extend_hub_uri_if_needed(
|
|
99
|
+
uri=self.url, asset_type=self.ASSET_TYPE, file=self.example
|
|
100
|
+
)
|
|
101
|
+
self._download_object(obj_url=example_url, target_name=self.example)
|
|
102
|
+
|
|
103
|
+
def _download_object(self, obj_url, target_name, secrets=None):
|
|
104
|
+
data = get_object(url=obj_url, secrets=secrets)
|
|
105
|
+
target_filepath = os.path.join(self.local_path, target_name)
|
|
106
|
+
with open(target_filepath, "wb") as f:
|
|
107
|
+
f.write(data)
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def verify_directory(path: Optional[str] = None) -> Path:
|
|
111
|
+
"""
|
|
112
|
+
Validate that the given path is an existing directory.
|
|
113
|
+
If no path has been provided, returns current working directory.
|
|
114
|
+
"""
|
|
115
|
+
if path:
|
|
116
|
+
path = Path(path)
|
|
117
|
+
if not path.exists():
|
|
118
|
+
raise ValueError(f"Path does not exist: {path}")
|
|
119
|
+
if not path.is_dir():
|
|
120
|
+
raise ValueError(f"Path is not a directory: {path}")
|
|
121
|
+
return path
|
|
122
|
+
return Path(os.getcwd())
|
|
123
|
+
|
|
124
|
+
def get_src_file_path(self) -> str:
|
|
125
|
+
"""Get the full path to the asset's code file."""
|
|
126
|
+
if not self.local_path:
|
|
127
|
+
raise MLRunBadRequestError(
|
|
128
|
+
f"Local path not set. Call download_files() first to download the asset files, or "
|
|
129
|
+
f"set_local_path() with the directory containing {self.filename}"
|
|
130
|
+
)
|
|
131
|
+
src_path = Path(self.local_path) / self.filename
|
|
132
|
+
if not src_path.exists():
|
|
133
|
+
raise FileNotFoundError(
|
|
134
|
+
f"File {self.filename} not found in {self.local_path}. Call download_files() first to download the "
|
|
135
|
+
f"asset files, or set_local_path() with the directory containing {self.filename}"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return str(src_path)
|
|
139
|
+
|
|
140
|
+
def set_local_path(self, path: str):
|
|
141
|
+
"""Set the local path where the asset's files are stored."""
|
|
142
|
+
self.local_path = self.verify_directory(path=path)
|