mlrun 1.7.2rc3__py3-none-any.whl → 1.8.0rc1__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 +14 -12
- mlrun/__main__.py +3 -3
- mlrun/alerts/alert.py +19 -12
- mlrun/artifacts/__init__.py +0 -2
- mlrun/artifacts/base.py +34 -11
- mlrun/artifacts/dataset.py +16 -16
- mlrun/artifacts/manager.py +13 -13
- mlrun/artifacts/model.py +66 -53
- mlrun/common/constants.py +6 -0
- mlrun/common/formatters/__init__.py +1 -0
- mlrun/common/formatters/feature_set.py +1 -0
- mlrun/common/formatters/function.py +1 -0
- mlrun/common/formatters/model_endpoint.py +30 -0
- mlrun/common/formatters/pipeline.py +1 -2
- mlrun/common/model_monitoring/__init__.py +0 -3
- mlrun/common/model_monitoring/helpers.py +1 -1
- mlrun/common/runtimes/constants.py +1 -2
- mlrun/common/schemas/__init__.py +4 -2
- mlrun/common/schemas/artifact.py +0 -6
- mlrun/common/schemas/common.py +50 -0
- mlrun/common/schemas/model_monitoring/__init__.py +8 -1
- mlrun/common/schemas/model_monitoring/constants.py +62 -12
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +149 -0
- mlrun/common/schemas/model_monitoring/model_endpoints.py +21 -5
- mlrun/common/schemas/partition.py +122 -0
- mlrun/config.py +43 -15
- mlrun/data_types/__init__.py +0 -2
- mlrun/data_types/data_types.py +0 -1
- mlrun/data_types/infer.py +3 -1
- mlrun/data_types/spark.py +4 -4
- mlrun/data_types/to_pandas.py +2 -11
- mlrun/datastore/__init__.py +0 -2
- mlrun/datastore/alibaba_oss.py +4 -1
- mlrun/datastore/azure_blob.py +4 -1
- mlrun/datastore/base.py +12 -4
- mlrun/datastore/datastore.py +9 -3
- mlrun/datastore/datastore_profile.py +1 -1
- mlrun/datastore/dbfs_store.py +4 -1
- mlrun/datastore/filestore.py +4 -1
- mlrun/datastore/google_cloud_storage.py +4 -1
- mlrun/datastore/hdfs.py +4 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +4 -1
- mlrun/datastore/s3.py +4 -1
- mlrun/datastore/sources.py +51 -49
- mlrun/datastore/store_resources.py +0 -2
- mlrun/datastore/targets.py +22 -23
- mlrun/datastore/utils.py +2 -2
- mlrun/datastore/v3io.py +4 -1
- mlrun/datastore/wasbfs/fs.py +13 -12
- mlrun/db/base.py +126 -62
- mlrun/db/factory.py +3 -0
- mlrun/db/httpdb.py +767 -231
- mlrun/db/nopdb.py +126 -57
- mlrun/errors.py +2 -2
- mlrun/execution.py +55 -29
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +40 -40
- mlrun/feature_store/common.py +9 -9
- mlrun/feature_store/feature_set.py +20 -18
- mlrun/feature_store/feature_vector.py +27 -24
- mlrun/feature_store/retrieval/base.py +14 -9
- mlrun/feature_store/retrieval/job.py +2 -1
- mlrun/feature_store/steps.py +2 -2
- mlrun/features.py +30 -13
- mlrun/frameworks/__init__.py +1 -2
- mlrun/frameworks/_common/__init__.py +1 -2
- mlrun/frameworks/_common/artifacts_library.py +2 -2
- mlrun/frameworks/_common/mlrun_interface.py +10 -6
- mlrun/frameworks/_common/model_handler.py +29 -27
- mlrun/frameworks/_common/producer.py +3 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
- mlrun/frameworks/_ml_common/__init__.py +1 -2
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_ml_common/model_handler.py +21 -21
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/auto_mlrun/__init__.py +1 -2
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
- mlrun/frameworks/huggingface/__init__.py +1 -2
- mlrun/frameworks/huggingface/model_server.py +9 -9
- mlrun/frameworks/lgbm/__init__.py +47 -44
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
- mlrun/frameworks/lgbm/model_handler.py +15 -11
- mlrun/frameworks/lgbm/model_server.py +11 -7
- mlrun/frameworks/lgbm/utils.py +2 -2
- mlrun/frameworks/onnx/__init__.py +1 -2
- mlrun/frameworks/onnx/dataset.py +3 -3
- mlrun/frameworks/onnx/mlrun_interface.py +2 -2
- mlrun/frameworks/onnx/model_handler.py +7 -5
- mlrun/frameworks/onnx/model_server.py +8 -6
- mlrun/frameworks/parallel_coordinates.py +11 -11
- mlrun/frameworks/pytorch/__init__.py +22 -23
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
- mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
- mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
- mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
- mlrun/frameworks/pytorch/model_handler.py +21 -17
- mlrun/frameworks/pytorch/model_server.py +13 -9
- mlrun/frameworks/sklearn/__init__.py +19 -18
- mlrun/frameworks/sklearn/estimator.py +2 -2
- mlrun/frameworks/sklearn/metric.py +3 -3
- mlrun/frameworks/sklearn/metrics_library.py +8 -6
- mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
- mlrun/frameworks/sklearn/model_handler.py +4 -3
- mlrun/frameworks/tf_keras/__init__.py +11 -12
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
- mlrun/frameworks/tf_keras/model_handler.py +17 -13
- mlrun/frameworks/tf_keras/model_server.py +12 -8
- mlrun/frameworks/xgboost/__init__.py +19 -18
- mlrun/frameworks/xgboost/model_handler.py +13 -9
- mlrun/launcher/base.py +3 -4
- mlrun/launcher/local.py +1 -1
- mlrun/launcher/remote.py +1 -1
- mlrun/lists.py +4 -3
- mlrun/model.py +108 -44
- mlrun/model_monitoring/__init__.py +1 -2
- mlrun/model_monitoring/api.py +6 -6
- mlrun/model_monitoring/applications/_application_steps.py +13 -15
- mlrun/model_monitoring/applications/histogram_data_drift.py +41 -15
- mlrun/model_monitoring/applications/results.py +55 -3
- mlrun/model_monitoring/controller.py +185 -223
- mlrun/model_monitoring/db/_schedules.py +156 -0
- mlrun/model_monitoring/db/_stats.py +189 -0
- mlrun/model_monitoring/db/stores/__init__.py +1 -1
- mlrun/model_monitoring/db/stores/base/store.py +6 -65
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -97
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +2 -58
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -15
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +6 -257
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +9 -271
- mlrun/model_monitoring/db/tsdb/base.py +74 -22
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +66 -35
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +284 -51
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -17
- mlrun/model_monitoring/helpers.py +97 -1
- mlrun/model_monitoring/model_endpoint.py +4 -2
- mlrun/model_monitoring/stream_processing.py +2 -2
- mlrun/model_monitoring/tracking_policy.py +10 -3
- mlrun/model_monitoring/writer.py +47 -26
- mlrun/package/__init__.py +3 -6
- mlrun/package/context_handler.py +1 -1
- mlrun/package/packager.py +12 -9
- mlrun/package/packagers/__init__.py +0 -2
- mlrun/package/packagers/default_packager.py +14 -11
- mlrun/package/packagers/numpy_packagers.py +16 -7
- mlrun/package/packagers/pandas_packagers.py +18 -18
- mlrun/package/packagers/python_standard_library_packagers.py +25 -11
- mlrun/package/packagers_manager.py +31 -14
- mlrun/package/utils/__init__.py +0 -3
- mlrun/package/utils/_pickler.py +6 -6
- mlrun/platforms/__init__.py +3 -3
- mlrun/platforms/iguazio.py +4 -1
- mlrun/projects/__init__.py +1 -6
- mlrun/projects/operations.py +27 -27
- mlrun/projects/pipelines.py +85 -215
- mlrun/projects/project.py +444 -158
- mlrun/run.py +9 -9
- mlrun/runtimes/__init__.py +1 -3
- mlrun/runtimes/base.py +13 -10
- mlrun/runtimes/daskjob.py +9 -9
- mlrun/runtimes/generators.py +2 -1
- mlrun/runtimes/kubejob.py +4 -5
- mlrun/runtimes/mpijob/__init__.py +0 -2
- mlrun/runtimes/mpijob/abstract.py +7 -6
- mlrun/runtimes/nuclio/api_gateway.py +7 -7
- mlrun/runtimes/nuclio/application/application.py +11 -11
- mlrun/runtimes/nuclio/function.py +14 -13
- mlrun/runtimes/nuclio/serving.py +9 -9
- mlrun/runtimes/pod.py +74 -29
- mlrun/runtimes/remotesparkjob.py +3 -2
- mlrun/runtimes/sparkjob/__init__.py +0 -2
- mlrun/runtimes/sparkjob/spark3job.py +21 -11
- mlrun/runtimes/utils.py +6 -5
- mlrun/serving/merger.py +6 -4
- mlrun/serving/remote.py +18 -17
- mlrun/serving/routers.py +27 -27
- mlrun/serving/server.py +1 -1
- mlrun/serving/states.py +76 -71
- mlrun/serving/utils.py +13 -2
- mlrun/serving/v1_serving.py +3 -2
- mlrun/serving/v2_serving.py +4 -4
- mlrun/track/__init__.py +1 -1
- mlrun/track/tracker.py +2 -2
- mlrun/track/trackers/mlflow_tracker.py +6 -5
- mlrun/utils/async_http.py +1 -1
- mlrun/utils/helpers.py +72 -28
- mlrun/utils/logger.py +104 -2
- mlrun/utils/notifications/notification/base.py +23 -4
- mlrun/utils/notifications/notification/console.py +1 -1
- mlrun/utils/notifications/notification/git.py +6 -6
- mlrun/utils/notifications/notification/ipython.py +5 -4
- mlrun/utils/notifications/notification/slack.py +1 -1
- mlrun/utils/notifications/notification/webhook.py +13 -17
- mlrun/utils/notifications/notification_pusher.py +23 -19
- mlrun/utils/regex.py +1 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/METADATA +186 -186
- mlrun-1.8.0rc1.dist-info/RECORD +356 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/WHEEL +1 -1
- mlrun-1.7.2rc3.dist-info/RECORD +0 -351
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/LICENSE +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/top_level.txt +0 -0
mlrun/__init__.py
CHANGED
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
|
-
|
|
17
15
|
__all__ = [
|
|
18
16
|
"get_version",
|
|
19
17
|
"set_environment",
|
|
@@ -29,8 +27,10 @@ __all__ = [
|
|
|
29
27
|
]
|
|
30
28
|
|
|
31
29
|
from os import environ, path
|
|
30
|
+
from typing import Optional
|
|
32
31
|
|
|
33
32
|
import dotenv
|
|
33
|
+
|
|
34
34
|
import mlrun_pipelines
|
|
35
35
|
|
|
36
36
|
from .config import config as mlconf
|
|
@@ -88,12 +88,12 @@ if "IGZ_NAMESPACE_DOMAIN" in environ:
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
def set_environment(
|
|
91
|
-
api_path: str = None,
|
|
91
|
+
api_path: Optional[str] = None,
|
|
92
92
|
artifact_path: str = "",
|
|
93
|
-
access_key: str = None,
|
|
94
|
-
username: str = None,
|
|
95
|
-
env_file: str = None,
|
|
96
|
-
mock_functions: str = None,
|
|
93
|
+
access_key: Optional[str] = None,
|
|
94
|
+
username: Optional[str] = None,
|
|
95
|
+
env_file: Optional[str] = None,
|
|
96
|
+
mock_functions: Optional[str] = None,
|
|
97
97
|
):
|
|
98
98
|
"""set and test default config for: api path, artifact_path and project
|
|
99
99
|
|
|
@@ -136,15 +136,16 @@ def set_environment(
|
|
|
136
136
|
if not mlconf.dbpath:
|
|
137
137
|
raise ValueError("DB/API path was not detected, please specify its address")
|
|
138
138
|
|
|
139
|
-
if mock_functions is not None:
|
|
140
|
-
mock_functions = "1" if mock_functions is True else mock_functions
|
|
141
|
-
mlconf.force_run_local = mock_functions
|
|
142
|
-
mlconf.mock_nuclio_deployment = mock_functions
|
|
143
|
-
|
|
144
139
|
# check connectivity and load remote defaults
|
|
145
140
|
get_run_db()
|
|
146
141
|
if api_path:
|
|
147
142
|
environ["MLRUN_DBPATH"] = mlconf.dbpath
|
|
143
|
+
mlconf.reload()
|
|
144
|
+
|
|
145
|
+
if mock_functions is not None:
|
|
146
|
+
mock_functions = "1" if mock_functions is True else mock_functions
|
|
147
|
+
mlconf.force_run_local = mock_functions
|
|
148
|
+
mlconf.mock_nuclio_deployment = mock_functions
|
|
148
149
|
|
|
149
150
|
if not mlconf.artifact_path and not artifact_path:
|
|
150
151
|
raise ValueError(
|
|
@@ -159,6 +160,7 @@ def set_environment(
|
|
|
159
160
|
"artifact_path must refer to an absolute path" " or a valid url"
|
|
160
161
|
)
|
|
161
162
|
mlconf.artifact_path = artifact_path
|
|
163
|
+
|
|
162
164
|
return mlconf.default_project, mlconf.artifact_path
|
|
163
165
|
|
|
164
166
|
|
mlrun/__main__.py
CHANGED
|
@@ -27,13 +27,13 @@ import click
|
|
|
27
27
|
import dotenv
|
|
28
28
|
import pandas as pd
|
|
29
29
|
import yaml
|
|
30
|
-
from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
|
|
31
30
|
from tabulate import tabulate
|
|
32
31
|
|
|
33
32
|
import mlrun
|
|
34
33
|
import mlrun.common.constants as mlrun_constants
|
|
35
34
|
import mlrun.common.schemas
|
|
36
35
|
from mlrun.common.helpers import parse_versioned_object_uri
|
|
36
|
+
from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
|
|
37
37
|
|
|
38
38
|
from .config import config as mlconf
|
|
39
39
|
from .db import get_run_db
|
|
@@ -1248,10 +1248,10 @@ def show_or_set_config(
|
|
|
1248
1248
|
}
|
|
1249
1249
|
for key, value in env_dict.items():
|
|
1250
1250
|
if value:
|
|
1251
|
-
dotenv.set_key(filename, key, value, quote_mode="")
|
|
1251
|
+
dotenv.set_key(filename, key, value, quote_mode="always")
|
|
1252
1252
|
if env_vars:
|
|
1253
1253
|
for key, value in list2dict(env_vars).items():
|
|
1254
|
-
dotenv.set_key(filename, key, value, quote_mode="")
|
|
1254
|
+
dotenv.set_key(filename, key, value, quote_mode="always")
|
|
1255
1255
|
if env_file:
|
|
1256
1256
|
# if its not the default file print the usage details
|
|
1257
1257
|
print(
|
mlrun/alerts/alert.py
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import Union
|
|
15
|
+
from typing import Optional, Union
|
|
16
16
|
|
|
17
17
|
import mlrun
|
|
18
18
|
import mlrun.common.schemas.alert as alert_objects
|
|
@@ -40,21 +40,21 @@ class AlertConfig(ModelObj):
|
|
|
40
40
|
|
|
41
41
|
def __init__(
|
|
42
42
|
self,
|
|
43
|
-
project: str = None,
|
|
44
|
-
name: str = None,
|
|
43
|
+
project: Optional[str] = None,
|
|
44
|
+
name: Optional[str] = None,
|
|
45
45
|
template: Union[alert_objects.AlertTemplate, str] = None,
|
|
46
|
-
description: str = None,
|
|
47
|
-
summary: str = None,
|
|
46
|
+
description: Optional[str] = None,
|
|
47
|
+
summary: Optional[str] = None,
|
|
48
48
|
severity: alert_objects.AlertSeverity = None,
|
|
49
49
|
trigger: alert_objects.AlertTrigger = None,
|
|
50
50
|
criteria: alert_objects.AlertCriteria = None,
|
|
51
51
|
reset_policy: alert_objects.ResetPolicy = None,
|
|
52
|
-
notifications: list[alert_objects.AlertNotification] = None,
|
|
52
|
+
notifications: Optional[list[alert_objects.AlertNotification]] = None,
|
|
53
53
|
entities: alert_objects.EventEntities = None,
|
|
54
|
-
id: int = None,
|
|
54
|
+
id: Optional[int] = None,
|
|
55
55
|
state: alert_objects.AlertActiveState = None,
|
|
56
|
-
created: str = None,
|
|
57
|
-
count: int = None,
|
|
56
|
+
created: Optional[str] = None,
|
|
57
|
+
count: Optional[int] = None,
|
|
58
58
|
):
|
|
59
59
|
"""Alert config object
|
|
60
60
|
|
|
@@ -142,7 +142,7 @@ class AlertConfig(ModelObj):
|
|
|
142
142
|
raise mlrun.errors.MLRunInvalidArgumentError("Alert name must be provided")
|
|
143
143
|
|
|
144
144
|
def _serialize_field(
|
|
145
|
-
self, struct: dict, field_name: str = None, strip: bool = False
|
|
145
|
+
self, struct: dict, field_name: Optional[str] = None, strip: bool = False
|
|
146
146
|
):
|
|
147
147
|
if field_name == "entities":
|
|
148
148
|
if self.entities:
|
|
@@ -179,7 +179,12 @@ class AlertConfig(ModelObj):
|
|
|
179
179
|
return None
|
|
180
180
|
return super()._serialize_field(struct, field_name, strip)
|
|
181
181
|
|
|
182
|
-
def to_dict(
|
|
182
|
+
def to_dict(
|
|
183
|
+
self,
|
|
184
|
+
fields: Optional[list] = None,
|
|
185
|
+
exclude: Optional[list] = None,
|
|
186
|
+
strip: bool = False,
|
|
187
|
+
):
|
|
183
188
|
if self.entities is None:
|
|
184
189
|
raise mlrun.errors.MLRunBadRequestError("Alert entity field is missing")
|
|
185
190
|
if not self.notifications:
|
|
@@ -189,7 +194,9 @@ class AlertConfig(ModelObj):
|
|
|
189
194
|
return super().to_dict(self._dict_fields)
|
|
190
195
|
|
|
191
196
|
@classmethod
|
|
192
|
-
def from_dict(
|
|
197
|
+
def from_dict(
|
|
198
|
+
cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
|
|
199
|
+
):
|
|
193
200
|
new_obj = super().from_dict(struct, fields=fields)
|
|
194
201
|
|
|
195
202
|
entity_data = struct.get("entities")
|
mlrun/artifacts/__init__.py
CHANGED
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
|
-
|
|
17
15
|
# Don't remove this, used by sphinx documentation
|
|
18
16
|
__all__ = ["get_model", "update_model"]
|
|
19
17
|
|
mlrun/artifacts/base.py
CHANGED
|
@@ -62,14 +62,21 @@ class ArtifactMetadata(ModelObj):
|
|
|
62
62
|
def base_dict(self):
|
|
63
63
|
return super().to_dict()
|
|
64
64
|
|
|
65
|
-
def to_dict(
|
|
65
|
+
def to_dict(
|
|
66
|
+
self,
|
|
67
|
+
fields: typing.Optional[list] = None,
|
|
68
|
+
exclude: typing.Optional[list] = None,
|
|
69
|
+
strip: bool = False,
|
|
70
|
+
):
|
|
66
71
|
"""return long dict form of the artifact"""
|
|
67
72
|
return super().to_dict(
|
|
68
73
|
self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
|
|
69
74
|
)
|
|
70
75
|
|
|
71
76
|
@classmethod
|
|
72
|
-
def from_dict(
|
|
77
|
+
def from_dict(
|
|
78
|
+
cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
|
|
79
|
+
):
|
|
73
80
|
fields = fields or cls._dict_fields + cls._extra_fields
|
|
74
81
|
return super().from_dict(
|
|
75
82
|
struct, fields=fields, deprecated_fields=deprecated_fields
|
|
@@ -109,7 +116,7 @@ class ArtifactSpec(ModelObj):
|
|
|
109
116
|
db_key=None,
|
|
110
117
|
extra_data=None,
|
|
111
118
|
body=None,
|
|
112
|
-
unpackaging_instructions: dict = None,
|
|
119
|
+
unpackaging_instructions: typing.Optional[dict] = None,
|
|
113
120
|
):
|
|
114
121
|
self.src_path = src_path
|
|
115
122
|
self.target_path = target_path
|
|
@@ -131,14 +138,21 @@ class ArtifactSpec(ModelObj):
|
|
|
131
138
|
def base_dict(self):
|
|
132
139
|
return super().to_dict()
|
|
133
140
|
|
|
134
|
-
def to_dict(
|
|
141
|
+
def to_dict(
|
|
142
|
+
self,
|
|
143
|
+
fields: typing.Optional[list] = None,
|
|
144
|
+
exclude: typing.Optional[list] = None,
|
|
145
|
+
strip: bool = False,
|
|
146
|
+
):
|
|
135
147
|
"""return long dict form of the artifact"""
|
|
136
148
|
return super().to_dict(
|
|
137
149
|
self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
|
|
138
150
|
)
|
|
139
151
|
|
|
140
152
|
@classmethod
|
|
141
|
-
def from_dict(
|
|
153
|
+
def from_dict(
|
|
154
|
+
cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
|
|
155
|
+
):
|
|
142
156
|
fields = fields or cls._dict_fields + cls._extra_fields
|
|
143
157
|
return super().from_dict(
|
|
144
158
|
struct, fields=fields, deprecated_fields=deprecated_fields
|
|
@@ -192,7 +206,7 @@ class Artifact(ModelObj):
|
|
|
192
206
|
size=None,
|
|
193
207
|
target_path=None,
|
|
194
208
|
project=None,
|
|
195
|
-
src_path: str = None,
|
|
209
|
+
src_path: typing.Optional[str] = None,
|
|
196
210
|
# All params up until here are legacy params for compatibility with legacy artifacts.
|
|
197
211
|
# TODO: remove them in 1.9.0.
|
|
198
212
|
metadata: ArtifactMetadata = None,
|
|
@@ -366,7 +380,7 @@ class Artifact(ModelObj):
|
|
|
366
380
|
struct[field] = val.base_dict()
|
|
367
381
|
return struct
|
|
368
382
|
|
|
369
|
-
def upload(self, artifact_path: str = None):
|
|
383
|
+
def upload(self, artifact_path: typing.Optional[str] = None):
|
|
370
384
|
"""
|
|
371
385
|
internal, upload to target store
|
|
372
386
|
:param artifact_path: required only for when generating target_path from artifact hash
|
|
@@ -379,7 +393,9 @@ class Artifact(ModelObj):
|
|
|
379
393
|
if src_path and os.path.isfile(src_path):
|
|
380
394
|
self._upload_file(source_path=src_path, artifact_path=artifact_path)
|
|
381
395
|
|
|
382
|
-
def _upload_body(
|
|
396
|
+
def _upload_body(
|
|
397
|
+
self, body, target=None, artifact_path: typing.Optional[str] = None
|
|
398
|
+
):
|
|
383
399
|
body_hash = None
|
|
384
400
|
if not target and not self.spec.target_path:
|
|
385
401
|
if not mlrun.mlconf.artifacts.generate_target_path_from_artifact_hash:
|
|
@@ -400,7 +416,10 @@ class Artifact(ModelObj):
|
|
|
400
416
|
)
|
|
401
417
|
|
|
402
418
|
def _upload_file(
|
|
403
|
-
self,
|
|
419
|
+
self,
|
|
420
|
+
source_path: str,
|
|
421
|
+
target_path: typing.Optional[str] = None,
|
|
422
|
+
artifact_path: typing.Optional[str] = None,
|
|
404
423
|
):
|
|
405
424
|
file_hash = None
|
|
406
425
|
if not target_path and not self.spec.target_path:
|
|
@@ -651,7 +670,7 @@ class DirArtifact(Artifact):
|
|
|
651
670
|
def is_dir(self):
|
|
652
671
|
return True
|
|
653
672
|
|
|
654
|
-
def upload(self, artifact_path: str = None):
|
|
673
|
+
def upload(self, artifact_path: typing.Optional[str] = None):
|
|
655
674
|
"""
|
|
656
675
|
internal, upload to target store
|
|
657
676
|
:param artifact_path: required only for when generating target_path from artifact hash
|
|
@@ -758,13 +777,17 @@ def upload_extra_data(
|
|
|
758
777
|
extra_data: dict,
|
|
759
778
|
prefix="",
|
|
760
779
|
update_spec=False,
|
|
761
|
-
artifact_path: str = None,
|
|
780
|
+
artifact_path: typing.Optional[str] = None,
|
|
762
781
|
):
|
|
763
782
|
"""upload extra data to the artifact store"""
|
|
764
783
|
if not extra_data:
|
|
765
784
|
return
|
|
766
785
|
target_path = artifact.target_path
|
|
767
786
|
for key, item in extra_data.items():
|
|
787
|
+
if item is ...:
|
|
788
|
+
# Skip future links (packagers feature for linking artifacts before they are logged)
|
|
789
|
+
continue
|
|
790
|
+
|
|
768
791
|
if isinstance(item, bytes):
|
|
769
792
|
if target_path:
|
|
770
793
|
target = os.path.join(target_path, prefix + key)
|
mlrun/artifacts/dataset.py
CHANGED
|
@@ -149,16 +149,16 @@ class DatasetArtifact(Artifact):
|
|
|
149
149
|
|
|
150
150
|
def __init__(
|
|
151
151
|
self,
|
|
152
|
-
key: str = None,
|
|
152
|
+
key: Optional[str] = None,
|
|
153
153
|
df=None,
|
|
154
|
-
preview: int = None,
|
|
154
|
+
preview: Optional[int] = None,
|
|
155
155
|
format: str = "", # TODO: should be changed to 'fmt'.
|
|
156
|
-
stats: bool = None,
|
|
157
|
-
target_path: str = None,
|
|
158
|
-
extra_data: dict = None,
|
|
159
|
-
column_metadata: dict = None,
|
|
156
|
+
stats: Optional[bool] = None,
|
|
157
|
+
target_path: Optional[str] = None,
|
|
158
|
+
extra_data: Optional[dict] = None,
|
|
159
|
+
column_metadata: Optional[dict] = None,
|
|
160
160
|
ignore_preview_limits: bool = False,
|
|
161
|
-
label_column: str = None,
|
|
161
|
+
label_column: Optional[str] = None,
|
|
162
162
|
**kwargs,
|
|
163
163
|
):
|
|
164
164
|
if key or format or target_path:
|
|
@@ -207,7 +207,7 @@ class DatasetArtifact(Artifact):
|
|
|
207
207
|
def spec(self, spec):
|
|
208
208
|
self._spec = self._verify_dict(spec, "spec", DatasetArtifactSpec)
|
|
209
209
|
|
|
210
|
-
def upload(self, artifact_path: str = None):
|
|
210
|
+
def upload(self, artifact_path: Optional[str] = None):
|
|
211
211
|
"""
|
|
212
212
|
internal, upload to target store
|
|
213
213
|
:param artifact_path: required only for when generating target_path from artifact hash
|
|
@@ -396,13 +396,13 @@ def get_df_stats(df):
|
|
|
396
396
|
def update_dataset_meta(
|
|
397
397
|
artifact,
|
|
398
398
|
from_df=None,
|
|
399
|
-
schema: dict = None,
|
|
400
|
-
header: list = None,
|
|
401
|
-
preview: list = None,
|
|
402
|
-
stats: dict = None,
|
|
403
|
-
extra_data: dict = None,
|
|
404
|
-
column_metadata: dict = None,
|
|
405
|
-
labels: dict = None,
|
|
399
|
+
schema: Optional[dict] = None,
|
|
400
|
+
header: Optional[list] = None,
|
|
401
|
+
preview: Optional[list] = None,
|
|
402
|
+
stats: Optional[dict] = None,
|
|
403
|
+
extra_data: Optional[dict] = None,
|
|
404
|
+
column_metadata: Optional[dict] = None,
|
|
405
|
+
labels: Optional[dict] = None,
|
|
406
406
|
ignore_preview_limits: bool = False,
|
|
407
407
|
):
|
|
408
408
|
"""Update dataset object attributes/metadata
|
|
@@ -495,4 +495,4 @@ def upload_dataframe(
|
|
|
495
495
|
size = target_class(path=target_path).write_dataframe(df, **kw)
|
|
496
496
|
return size, None
|
|
497
497
|
|
|
498
|
-
raise mlrun.errors.MLRunInvalidArgumentError(f"
|
|
498
|
+
raise mlrun.errors.MLRunInvalidArgumentError(f"Format {format} not implemented yet")
|
mlrun/artifacts/manager.py
CHANGED
|
@@ -124,7 +124,7 @@ class ArtifactManager:
|
|
|
124
124
|
|
|
125
125
|
self.artifact_db = db
|
|
126
126
|
self.input_artifacts = {}
|
|
127
|
-
self.
|
|
127
|
+
self.artifact_uris = {}
|
|
128
128
|
|
|
129
129
|
@staticmethod
|
|
130
130
|
def ensure_artifact_source_file_exists(item, path, body):
|
|
@@ -156,14 +156,12 @@ class ArtifactManager:
|
|
|
156
156
|
|
|
157
157
|
def artifact_list(self, full=False):
|
|
158
158
|
artifacts = []
|
|
159
|
-
for
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
for artifacts_uri in self.artifact_uris.values():
|
|
160
|
+
artifact: Artifact = mlrun.datastore.get_store_resource(artifacts_uri)
|
|
161
|
+
if full:
|
|
162
|
+
artifacts.append(artifact.to_dict())
|
|
162
163
|
else:
|
|
163
|
-
|
|
164
|
-
artifacts.append(artifact.to_dict())
|
|
165
|
-
else:
|
|
166
|
-
artifacts.append(artifact.base_dict())
|
|
164
|
+
artifacts.append(artifact.base_dict())
|
|
167
165
|
return artifacts
|
|
168
166
|
|
|
169
167
|
def log_artifact(
|
|
@@ -246,6 +244,8 @@ class ArtifactManager:
|
|
|
246
244
|
# otherwise, we do not want to override it.
|
|
247
245
|
# this is mainly relevant for imported artifacts that have an explicit db_key value already set
|
|
248
246
|
db_key = item.db_key or key
|
|
247
|
+
if db_key != key:
|
|
248
|
+
validate_artifact_key_name(db_key, "artifact.db_key")
|
|
249
249
|
item.db_key = db_key or ""
|
|
250
250
|
item.viewer = viewer or item.viewer
|
|
251
251
|
item.tree = producer.tag
|
|
@@ -304,7 +304,7 @@ class ArtifactManager:
|
|
|
304
304
|
item.target_path = target_path
|
|
305
305
|
|
|
306
306
|
item.before_log()
|
|
307
|
-
self.
|
|
307
|
+
self.artifact_uris[key] = item.uri
|
|
308
308
|
|
|
309
309
|
if ((upload is None and item.kind != "dir") or upload) and not item.is_inline():
|
|
310
310
|
# before uploading the item, we want to ensure that its tags are valid,
|
|
@@ -317,12 +317,12 @@ class ArtifactManager:
|
|
|
317
317
|
size = str(item.size) or "?"
|
|
318
318
|
db_str = "Y" if (self.artifact_db and db_key) else "N"
|
|
319
319
|
logger.debug(
|
|
320
|
-
f"
|
|
320
|
+
f"Log artifact {key} at {item.target_path}, size: {size}, db: {db_str}"
|
|
321
321
|
)
|
|
322
322
|
return item
|
|
323
323
|
|
|
324
|
-
def update_artifact(self, producer, item):
|
|
325
|
-
self.
|
|
324
|
+
def update_artifact(self, producer, item: Artifact):
|
|
325
|
+
self.artifact_uris[item.key] = item.uri
|
|
326
326
|
self._log_to_db(item.db_key, producer.project, producer.inputs, item)
|
|
327
327
|
|
|
328
328
|
def _log_to_db(self, key, project, sources, item, tag=None):
|
|
@@ -387,7 +387,7 @@ class ArtifactManager:
|
|
|
387
387
|
deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
|
|
388
388
|
mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
|
|
389
389
|
),
|
|
390
|
-
secrets: dict = None,
|
|
390
|
+
secrets: typing.Optional[dict] = None,
|
|
391
391
|
):
|
|
392
392
|
self.artifact_db.del_artifact(
|
|
393
393
|
key=item.db_key,
|
mlrun/artifacts/model.py
CHANGED
|
@@ -303,7 +303,7 @@ class ModelArtifact(Artifact):
|
|
|
303
303
|
self.metadata.labels = self.metadata.labels or {}
|
|
304
304
|
self.metadata.labels["framework"] = self.spec.framework
|
|
305
305
|
|
|
306
|
-
def upload(self, artifact_path: str = None):
|
|
306
|
+
def upload(self, artifact_path: Optional[str] = None):
|
|
307
307
|
"""
|
|
308
308
|
internal, upload to target store
|
|
309
309
|
:param artifact_path: required only for when generating target_path from artifact hash
|
|
@@ -324,9 +324,7 @@ class ModelArtifact(Artifact):
|
|
|
324
324
|
artifact=self, extra_data=self.spec.extra_data, artifact_path=artifact_path
|
|
325
325
|
)
|
|
326
326
|
|
|
327
|
-
|
|
328
|
-
# and the tag is not part of the model spec but the metadata of the model artifact
|
|
329
|
-
spec_body = _remove_tag_from_spec_yaml(self)
|
|
327
|
+
spec_body = _sanitize_and_serialize_model_spec_yaml(self)
|
|
330
328
|
spec_target_path = None
|
|
331
329
|
|
|
332
330
|
if mlrun.mlconf.artifacts.generate_target_path_from_artifact_hash:
|
|
@@ -355,7 +353,7 @@ class ModelArtifact(Artifact):
|
|
|
355
353
|
def _upload_body_or_file(
|
|
356
354
|
self,
|
|
357
355
|
artifact_path: str,
|
|
358
|
-
target_model_path: str = None,
|
|
356
|
+
target_model_path: Optional[str] = None,
|
|
359
357
|
):
|
|
360
358
|
body = self.spec.get_body()
|
|
361
359
|
if body:
|
|
@@ -403,12 +401,6 @@ class ModelArtifact(Artifact):
|
|
|
403
401
|
return mlrun.get_dataitem(target_model_path).get()
|
|
404
402
|
|
|
405
403
|
|
|
406
|
-
def _get_src_path(model_spec: ModelArtifact, filename):
|
|
407
|
-
if model_spec.src_path:
|
|
408
|
-
return path.join(model_spec.src_path, filename)
|
|
409
|
-
return filename
|
|
410
|
-
|
|
411
|
-
|
|
412
404
|
def get_model(model_dir, suffix=""):
|
|
413
405
|
"""return model file, model spec object, and list of extra data items
|
|
414
406
|
|
|
@@ -483,49 +475,20 @@ def get_model(model_dir, suffix=""):
|
|
|
483
475
|
return temp_path, model_spec, extra_dataitems
|
|
484
476
|
|
|
485
477
|
|
|
486
|
-
def _load_model_spec(spec_path):
|
|
487
|
-
data = mlrun.datastore.store_manager.object(url=spec_path).get()
|
|
488
|
-
spec = yaml.load(data, Loader=yaml.FullLoader)
|
|
489
|
-
return ModelArtifact.from_dict(spec)
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
def _get_file_path(base_path: str, name: str, isdir=False):
|
|
493
|
-
if not is_relative_path(name):
|
|
494
|
-
return name
|
|
495
|
-
if not isdir:
|
|
496
|
-
base_path = path.dirname(base_path)
|
|
497
|
-
return path.join(base_path, name).replace("\\", "/")
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
def _get_extra(target, extra_data, is_dir=False):
|
|
501
|
-
extra_dataitems = {}
|
|
502
|
-
for k, v in extra_data.items():
|
|
503
|
-
extra_dataitems[k] = mlrun.datastore.store_manager.object(
|
|
504
|
-
url=_get_file_path(target, v, isdir=is_dir), key=k
|
|
505
|
-
)
|
|
506
|
-
return extra_dataitems
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
def _remove_tag_from_spec_yaml(model_spec):
|
|
510
|
-
spec_dict = model_spec.to_dict()
|
|
511
|
-
spec_dict["metadata"].pop("tag", None)
|
|
512
|
-
return yaml.safe_dump(spec_dict)
|
|
513
|
-
|
|
514
|
-
|
|
515
478
|
def update_model(
|
|
516
479
|
model_artifact,
|
|
517
|
-
parameters: dict = None,
|
|
518
|
-
metrics: dict = None,
|
|
519
|
-
extra_data: dict = None,
|
|
520
|
-
inputs: list[Feature] = None,
|
|
521
|
-
outputs: list[Feature] = None,
|
|
522
|
-
feature_vector: str = None,
|
|
523
|
-
feature_weights: list = None,
|
|
480
|
+
parameters: Optional[dict] = None,
|
|
481
|
+
metrics: Optional[dict] = None,
|
|
482
|
+
extra_data: Optional[dict] = None,
|
|
483
|
+
inputs: Optional[list[Feature]] = None,
|
|
484
|
+
outputs: Optional[list[Feature]] = None,
|
|
485
|
+
feature_vector: Optional[str] = None,
|
|
486
|
+
feature_weights: Optional[list] = None,
|
|
524
487
|
key_prefix: str = "",
|
|
525
|
-
labels: dict = None,
|
|
488
|
+
labels: Optional[dict] = None,
|
|
526
489
|
write_spec_copy=True,
|
|
527
490
|
store_object: bool = True,
|
|
528
|
-
):
|
|
491
|
+
) -> ModelArtifact:
|
|
529
492
|
"""Update model object attributes
|
|
530
493
|
|
|
531
494
|
this method will edit or add attributes to a model object
|
|
@@ -593,10 +556,7 @@ def update_model(
|
|
|
593
556
|
|
|
594
557
|
if write_spec_copy:
|
|
595
558
|
spec_path = path.join(model_spec.target_path, model_spec_filename)
|
|
596
|
-
|
|
597
|
-
# the model spec yaml should not include the tag, as the same model can be used with different tags,
|
|
598
|
-
# and the tag is not part of the model spec but the metadata of the model artifact
|
|
599
|
-
model_spec_yaml = _remove_tag_from_spec_yaml(model_spec)
|
|
559
|
+
model_spec_yaml = _sanitize_and_serialize_model_spec_yaml(model_spec)
|
|
600
560
|
mlrun.datastore.store_manager.object(url=spec_path).put(model_spec_yaml)
|
|
601
561
|
|
|
602
562
|
model_spec.db_key = model_spec.db_key or model_spec.key
|
|
@@ -609,3 +569,56 @@ def update_model(
|
|
|
609
569
|
project=model_spec.project,
|
|
610
570
|
)
|
|
611
571
|
return model_spec
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def _get_src_path(model_spec: ModelArtifact, filename: str) -> str:
|
|
575
|
+
return path.join(model_spec.src_path, filename) if model_spec.src_path else filename
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def _load_model_spec(spec_path) -> ModelArtifact:
|
|
579
|
+
data = mlrun.datastore.store_manager.object(url=spec_path).get()
|
|
580
|
+
spec = yaml.load(data, Loader=yaml.FullLoader)
|
|
581
|
+
return ModelArtifact.from_dict(spec)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _get_file_path(base_path: str, name: str, isdir: bool = False) -> str:
|
|
585
|
+
if not is_relative_path(name):
|
|
586
|
+
return name
|
|
587
|
+
if not isdir:
|
|
588
|
+
base_path = path.dirname(base_path)
|
|
589
|
+
return path.join(base_path, name).replace("\\", "/")
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
def _get_extra(target: str, extra_data: dict, is_dir: bool = False) -> dict:
|
|
593
|
+
extra_dataitems = {}
|
|
594
|
+
for k, v in extra_data.items():
|
|
595
|
+
extra_dataitems[k] = mlrun.datastore.store_manager.object(
|
|
596
|
+
url=_get_file_path(target, v, isdir=is_dir), key=k
|
|
597
|
+
)
|
|
598
|
+
return extra_dataitems
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def _sanitize_and_serialize_model_spec_yaml(model: ModelArtifact) -> str:
|
|
602
|
+
model_dict = _sanitize_model_spec(model)
|
|
603
|
+
return _serialize_model_spec_yaml(model_dict)
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def _sanitize_model_spec(model: ModelArtifact) -> dict:
|
|
607
|
+
model_dict = model.to_dict()
|
|
608
|
+
|
|
609
|
+
# The model spec yaml should not include the tag, as the same model can be used with different tags,
|
|
610
|
+
# and the tag is not part of the model spec but the metadata of the model artifact
|
|
611
|
+
model_dict["metadata"].pop("tag", None)
|
|
612
|
+
|
|
613
|
+
# Remove future packaging links
|
|
614
|
+
if model_dict["spec"].get("extra_data"):
|
|
615
|
+
model_dict["spec"]["extra_data"] = {
|
|
616
|
+
key: item
|
|
617
|
+
for key, item in model_dict["spec"]["extra_data"].items()
|
|
618
|
+
if item is not ...
|
|
619
|
+
}
|
|
620
|
+
return model_dict
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def _serialize_model_spec_yaml(model_dict: dict) -> str:
|
|
624
|
+
return yaml.safe_dump(model_dict)
|
mlrun/common/constants.py
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
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 mlrun.common.types
|
|
14
15
|
|
|
15
16
|
IMAGE_NAME_ENRICH_REGISTRY_PREFIX = "." # prefix for image name to enrich with registry
|
|
16
17
|
MLRUN_SERVING_CONF = "serving-conf"
|
|
@@ -86,3 +87,8 @@ class MLRunInternalLabels:
|
|
|
86
87
|
for key, value in cls.__dict__.items()
|
|
87
88
|
if not key.startswith("__") and isinstance(value, str)
|
|
88
89
|
]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class DeployStatusTextKind(mlrun.common.types.StrEnum):
|
|
93
|
+
logs = "logs"
|
|
94
|
+
events = "events"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright 2024 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
import typing
|
|
17
|
+
|
|
18
|
+
import mlrun.common.types
|
|
19
|
+
|
|
20
|
+
from .base import ObjectFormat
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ModelEndpointFormat(ObjectFormat, mlrun.common.types.StrEnum):
|
|
24
|
+
full = "full"
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def format_method(_format: str) -> typing.Optional[typing.Callable]:
|
|
28
|
+
return {
|
|
29
|
+
ModelEndpointFormat.full: None,
|
|
30
|
+
}[_format]
|