mlrun 1.7.0rc39__py3-none-any.whl → 1.7.0rc42__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/common/constants.py +3 -0
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/helpers.py +0 -1
- mlrun/common/schemas/api_gateway.py +6 -6
- mlrun/common/schemas/common.py +4 -4
- mlrun/common/schemas/model_monitoring/model_endpoints.py +0 -1
- mlrun/config.py +1 -1
- mlrun/data_types/to_pandas.py +12 -12
- mlrun/datastore/alibaba_oss.py +1 -0
- mlrun/datastore/azure_blob.py +1 -6
- mlrun/datastore/base.py +12 -0
- mlrun/datastore/dbfs_store.py +1 -5
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +1 -9
- mlrun/datastore/redis.py +1 -0
- mlrun/datastore/s3.py +1 -0
- mlrun/datastore/storeytargets.py +147 -0
- mlrun/datastore/targets.py +67 -69
- mlrun/datastore/v3io.py +1 -0
- mlrun/errors.py +7 -4
- mlrun/feature_store/feature_vector.py +3 -1
- mlrun/feature_store/retrieval/job.py +3 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/model.py +1 -1
- mlrun/model_monitoring/api.py +1 -2
- mlrun/model_monitoring/applications/_application_steps.py +25 -43
- mlrun/model_monitoring/applications/context.py +206 -70
- mlrun/model_monitoring/controller.py +0 -1
- mlrun/model_monitoring/db/stores/__init__.py +3 -3
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +17 -8
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +14 -4
- mlrun/model_monitoring/db/tsdb/__init__.py +3 -3
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +18 -10
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -23
- mlrun/model_monitoring/helpers.py +38 -1
- mlrun/model_monitoring/stream_processing.py +8 -26
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/projects/project.py +17 -16
- mlrun/runtimes/funcdoc.py +1 -1
- mlrun/runtimes/nuclio/api_gateway.py +9 -0
- mlrun/runtimes/nuclio/application/application.py +131 -55
- mlrun/runtimes/nuclio/function.py +4 -10
- mlrun/runtimes/nuclio/serving.py +2 -2
- mlrun/runtimes/sparkjob/spark3job.py +1 -1
- mlrun/runtimes/utils.py +16 -0
- mlrun/serving/routers.py +1 -1
- mlrun/serving/server.py +19 -5
- mlrun/serving/states.py +8 -0
- mlrun/serving/v2_serving.py +34 -26
- mlrun/utils/helpers.py +12 -2
- mlrun/utils/v3io_clients.py +2 -2
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/METADATA +2 -2
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/RECORD +58 -57
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/WHEEL +1 -1
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc39.dist-info → mlrun-1.7.0rc42.dist-info}/top_level.txt +0 -0
|
@@ -24,6 +24,7 @@ import mlrun.common.model_monitoring
|
|
|
24
24
|
import mlrun.common.schemas.model_monitoring as mm_schemas
|
|
25
25
|
import mlrun.feature_store.steps
|
|
26
26
|
import mlrun.utils.v3io_clients
|
|
27
|
+
from mlrun.common.schemas import EventFieldType
|
|
27
28
|
from mlrun.model_monitoring.db import TSDBConnector
|
|
28
29
|
from mlrun.model_monitoring.helpers import get_invocations_fqn
|
|
29
30
|
from mlrun.utils import logger
|
|
@@ -64,14 +65,17 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
64
65
|
self.container = container
|
|
65
66
|
|
|
66
67
|
self.v3io_framesd = v3io_framesd or mlrun.mlconf.v3io_framesd
|
|
67
|
-
self._frames_client: v3io_frames.client.ClientBase =
|
|
68
|
-
self._get_v3io_frames_client(self.container)
|
|
69
|
-
)
|
|
70
|
-
|
|
68
|
+
self._frames_client: Optional[v3io_frames.client.ClientBase] = None
|
|
71
69
|
self._init_tables_path()
|
|
70
|
+
self._create_table = create_table
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
@property
|
|
73
|
+
def frames_client(self) -> v3io_frames.client.ClientBase:
|
|
74
|
+
if not self._frames_client:
|
|
75
|
+
self._frames_client = self._get_v3io_frames_client(self.container)
|
|
76
|
+
if self._create_table:
|
|
77
|
+
self.create_tables()
|
|
78
|
+
return self._frames_client
|
|
75
79
|
|
|
76
80
|
def _init_tables_path(self):
|
|
77
81
|
self.tables = {}
|
|
@@ -151,7 +155,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
151
155
|
for table_name in application_tables:
|
|
152
156
|
logger.info("Creating table in V3IO TSDB", table_name=table_name)
|
|
153
157
|
table = self.tables[table_name]
|
|
154
|
-
self.
|
|
158
|
+
self.frames_client.create(
|
|
155
159
|
backend=_TSDB_BE,
|
|
156
160
|
table=table,
|
|
157
161
|
if_exists=v3io_frames.IGNORE,
|
|
@@ -161,8 +165,9 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
161
165
|
def apply_monitoring_stream_steps(
|
|
162
166
|
self,
|
|
163
167
|
graph,
|
|
164
|
-
tsdb_batching_max_events: int =
|
|
165
|
-
tsdb_batching_timeout_secs: int =
|
|
168
|
+
tsdb_batching_max_events: int = 1000,
|
|
169
|
+
tsdb_batching_timeout_secs: int = 30,
|
|
170
|
+
sample_window: int = 10,
|
|
166
171
|
):
|
|
167
172
|
"""
|
|
168
173
|
Apply TSDB steps on the provided monitoring graph. Throughout these steps, the graph stores live data of
|
|
@@ -173,6 +178,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
173
178
|
- endpoint_features (Prediction and feature names and values)
|
|
174
179
|
- custom_metrics (user-defined metrics)
|
|
175
180
|
"""
|
|
181
|
+
|
|
176
182
|
# Write latency per prediction, labeled by endpoint ID only
|
|
177
183
|
graph.add_step(
|
|
178
184
|
"storey.TSDBTarget",
|
|
@@ -197,17 +203,23 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
197
203
|
key=mm_schemas.EventFieldType.ENDPOINT_ID,
|
|
198
204
|
)
|
|
199
205
|
|
|
206
|
+
# Emits the event in window size of events based on sample_window size (10 by default)
|
|
207
|
+
graph.add_step(
|
|
208
|
+
"storey.steps.SampleWindow",
|
|
209
|
+
name="sample",
|
|
210
|
+
after="Rename",
|
|
211
|
+
window_size=sample_window,
|
|
212
|
+
key=EventFieldType.ENDPOINT_ID,
|
|
213
|
+
)
|
|
214
|
+
|
|
200
215
|
# Before writing data to TSDB, create dictionary of 2-3 dictionaries that contains
|
|
201
216
|
# stats and details about the events
|
|
202
217
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
apply_process_before_tsdb()
|
|
218
|
+
graph.add_step(
|
|
219
|
+
"mlrun.model_monitoring.db.tsdb.v3io.stream_graph_steps.ProcessBeforeTSDB",
|
|
220
|
+
name="ProcessBeforeTSDB",
|
|
221
|
+
after="sample",
|
|
222
|
+
)
|
|
211
223
|
|
|
212
224
|
# Unpacked keys from each dictionary and write to TSDB target
|
|
213
225
|
def apply_filter_and_unpacked_keys(name, keys):
|
|
@@ -273,8 +285,8 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
273
285
|
def handle_model_error(
|
|
274
286
|
self,
|
|
275
287
|
graph,
|
|
276
|
-
tsdb_batching_max_events: int =
|
|
277
|
-
tsdb_batching_timeout_secs: int =
|
|
288
|
+
tsdb_batching_max_events: int = 1000,
|
|
289
|
+
tsdb_batching_timeout_secs: int = 30,
|
|
278
290
|
**kwargs,
|
|
279
291
|
) -> None:
|
|
280
292
|
graph.add_step(
|
|
@@ -333,7 +345,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
333
345
|
raise ValueError(f"Invalid {kind = }")
|
|
334
346
|
|
|
335
347
|
try:
|
|
336
|
-
self.
|
|
348
|
+
self.frames_client.write(
|
|
337
349
|
backend=_TSDB_BE,
|
|
338
350
|
table=table,
|
|
339
351
|
dfs=pd.DataFrame.from_records([event]),
|
|
@@ -360,7 +372,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
360
372
|
tables = mm_schemas.V3IOTSDBTables.list()
|
|
361
373
|
for table_to_delete in tables:
|
|
362
374
|
try:
|
|
363
|
-
self.
|
|
375
|
+
self.frames_client.delete(backend=_TSDB_BE, table=table_to_delete)
|
|
364
376
|
except v3io_frames.DeleteError as e:
|
|
365
377
|
logger.warning(
|
|
366
378
|
f"Failed to delete TSDB table '{table}'",
|
|
@@ -476,7 +488,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
476
488
|
aggregators = ",".join(agg_funcs) if agg_funcs else None
|
|
477
489
|
table_path = self.tables[table]
|
|
478
490
|
try:
|
|
479
|
-
df = self.
|
|
491
|
+
df = self.frames_client.read(
|
|
480
492
|
backend=_TSDB_BE,
|
|
481
493
|
table=table_path,
|
|
482
494
|
start=start,
|
|
@@ -579,7 +591,7 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
579
591
|
|
|
580
592
|
logger.debug("Querying V3IO TSDB", query=query)
|
|
581
593
|
|
|
582
|
-
df: pd.DataFrame = self.
|
|
594
|
+
df: pd.DataFrame = self.frames_client.read(
|
|
583
595
|
backend=_TSDB_BE,
|
|
584
596
|
start=start,
|
|
585
597
|
end=end,
|
|
@@ -19,9 +19,11 @@ import numpy as np
|
|
|
19
19
|
import pandas as pd
|
|
20
20
|
|
|
21
21
|
import mlrun
|
|
22
|
+
import mlrun.artifacts
|
|
22
23
|
import mlrun.common.model_monitoring.helpers
|
|
23
24
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
24
25
|
import mlrun.data_types.infer
|
|
26
|
+
import mlrun.model_monitoring
|
|
25
27
|
from mlrun.common.schemas.model_monitoring.model_endpoints import (
|
|
26
28
|
ModelEndpointMonitoringMetric,
|
|
27
29
|
ModelEndpointMonitoringMetricType,
|
|
@@ -253,7 +255,7 @@ def calculate_inputs_statistics(
|
|
|
253
255
|
)
|
|
254
256
|
|
|
255
257
|
# Recalculate the histograms over the bins that are set in the sample-set of the end point:
|
|
256
|
-
for feature in inputs_statistics
|
|
258
|
+
for feature in list(inputs_statistics):
|
|
257
259
|
if feature in sample_set_statistics:
|
|
258
260
|
counts, bins = np.histogram(
|
|
259
261
|
inputs[feature].to_numpy(),
|
|
@@ -270,6 +272,9 @@ def calculate_inputs_statistics(
|
|
|
270
272
|
inputs_statistics[feature]["hist"]
|
|
271
273
|
)
|
|
272
274
|
)
|
|
275
|
+
else:
|
|
276
|
+
# If the feature is not in the sample set and doesn't have a histogram, remove it from the statistics:
|
|
277
|
+
inputs_statistics.pop(feature)
|
|
273
278
|
|
|
274
279
|
return inputs_statistics
|
|
275
280
|
|
|
@@ -322,3 +327,35 @@ def get_invocations_metric(project: str) -> ModelEndpointMonitoringMetric:
|
|
|
322
327
|
name=mm_constants.PredictionsQueryConstants.INVOCATIONS,
|
|
323
328
|
full_name=get_invocations_fqn(project),
|
|
324
329
|
)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def enrich_model_endpoint_with_model_uri(
|
|
333
|
+
model_endpoint: ModelEndpoint,
|
|
334
|
+
model_obj: mlrun.artifacts.ModelArtifact,
|
|
335
|
+
):
|
|
336
|
+
"""
|
|
337
|
+
Enrich the model endpoint object with the model uri from the model object. We will use a unique reference
|
|
338
|
+
to the model object that includes the project, db_key, iter, and tree.
|
|
339
|
+
In addition, we verify that the model object is of type `ModelArtifact`.
|
|
340
|
+
|
|
341
|
+
:param model_endpoint: An object representing the model endpoint that will be enriched with the model uri.
|
|
342
|
+
:param model_obj: An object representing the model artifact.
|
|
343
|
+
|
|
344
|
+
:raise: `MLRunInvalidArgumentError` if the model object is not of type `ModelArtifact`.
|
|
345
|
+
"""
|
|
346
|
+
mlrun.utils.helpers.verify_field_of_type(
|
|
347
|
+
field_name="model_endpoint.spec.model_uri",
|
|
348
|
+
field_value=model_obj,
|
|
349
|
+
expected_type=mlrun.artifacts.ModelArtifact,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Update model_uri with a unique reference to handle future changes
|
|
353
|
+
model_artifact_uri = mlrun.utils.helpers.generate_artifact_uri(
|
|
354
|
+
project=model_endpoint.metadata.project,
|
|
355
|
+
key=model_obj.db_key,
|
|
356
|
+
iter=model_obj.iter,
|
|
357
|
+
tree=model_obj.tree,
|
|
358
|
+
)
|
|
359
|
+
model_endpoint.spec.model_uri = mlrun.datastore.get_store_uri(
|
|
360
|
+
kind=mlrun.utils.helpers.StorePrefix.Model, uri=model_artifact_uri
|
|
361
|
+
)
|
|
@@ -37,6 +37,7 @@ from mlrun.common.schemas.model_monitoring.constants import (
|
|
|
37
37
|
ModelEndpointTarget,
|
|
38
38
|
ProjectSecretKeys,
|
|
39
39
|
)
|
|
40
|
+
from mlrun.model_monitoring.db import StoreBase, TSDBConnector
|
|
40
41
|
from mlrun.utils import logger
|
|
41
42
|
|
|
42
43
|
|
|
@@ -48,14 +49,12 @@ class EventStreamProcessor:
|
|
|
48
49
|
parquet_batching_max_events: int,
|
|
49
50
|
parquet_batching_timeout_secs: int,
|
|
50
51
|
parquet_target: str,
|
|
51
|
-
sample_window: int = 10,
|
|
52
52
|
aggregate_windows: typing.Optional[list[str]] = None,
|
|
53
|
-
aggregate_period: str = "
|
|
53
|
+
aggregate_period: str = "5m",
|
|
54
54
|
model_monitoring_access_key: str = None,
|
|
55
55
|
):
|
|
56
56
|
# General configurations, mainly used for the storey steps in the future serving graph
|
|
57
57
|
self.project = project
|
|
58
|
-
self.sample_window = sample_window
|
|
59
58
|
self.aggregate_windows = aggregate_windows or ["5m", "1h"]
|
|
60
59
|
self.aggregate_period = aggregate_period
|
|
61
60
|
|
|
@@ -133,7 +132,8 @@ class EventStreamProcessor:
|
|
|
133
132
|
def apply_monitoring_serving_graph(
|
|
134
133
|
self,
|
|
135
134
|
fn: mlrun.runtimes.ServingRuntime,
|
|
136
|
-
|
|
135
|
+
tsdb_connector: TSDBConnector,
|
|
136
|
+
endpoint_store: StoreBase,
|
|
137
137
|
) -> None:
|
|
138
138
|
"""
|
|
139
139
|
Apply monitoring serving graph to a given serving function. The following serving graph includes about 4 main
|
|
@@ -161,8 +161,8 @@ class EventStreamProcessor:
|
|
|
161
161
|
using CE, the parquet target path is based on the defined MLRun artifact path.
|
|
162
162
|
|
|
163
163
|
:param fn: A serving function.
|
|
164
|
-
:param
|
|
165
|
-
|
|
164
|
+
:param tsdb_connector: Time series database connector.
|
|
165
|
+
:param endpoint_store: KV/SQL store used for endpoint data.
|
|
166
166
|
"""
|
|
167
167
|
|
|
168
168
|
graph = typing.cast(
|
|
@@ -190,10 +190,6 @@ class EventStreamProcessor:
|
|
|
190
190
|
_fn="(event.get('error') is not None)",
|
|
191
191
|
)
|
|
192
192
|
|
|
193
|
-
tsdb_connector = mlrun.model_monitoring.get_tsdb_connector(
|
|
194
|
-
project=self.project, secret_provider=secret_provider
|
|
195
|
-
)
|
|
196
|
-
|
|
197
193
|
tsdb_connector.handle_model_error(
|
|
198
194
|
graph,
|
|
199
195
|
)
|
|
@@ -306,24 +302,9 @@ class EventStreamProcessor:
|
|
|
306
302
|
table=self.kv_path,
|
|
307
303
|
)
|
|
308
304
|
|
|
309
|
-
|
|
310
|
-
project=self.project, secret_provider=secret_provider
|
|
311
|
-
)
|
|
312
|
-
if store_object.type == ModelEndpointTarget.V3IO_NOSQL:
|
|
305
|
+
if endpoint_store.type == ModelEndpointTarget.V3IO_NOSQL:
|
|
313
306
|
apply_infer_schema()
|
|
314
307
|
|
|
315
|
-
# Emits the event in window size of events based on sample_window size (10 by default)
|
|
316
|
-
def apply_storey_sample_window():
|
|
317
|
-
graph.add_step(
|
|
318
|
-
"storey.steps.SampleWindow",
|
|
319
|
-
name="sample",
|
|
320
|
-
after="Rename",
|
|
321
|
-
window_size=self.sample_window,
|
|
322
|
-
key=EventFieldType.ENDPOINT_ID,
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
apply_storey_sample_window()
|
|
326
|
-
|
|
327
308
|
tsdb_connector.apply_monitoring_stream_steps(graph=graph)
|
|
328
309
|
|
|
329
310
|
# Parquet branch
|
|
@@ -353,6 +334,7 @@ class EventStreamProcessor:
|
|
|
353
334
|
index_cols=[EventFieldType.ENDPOINT_ID],
|
|
354
335
|
key_bucketing_number=0,
|
|
355
336
|
time_partitioning_granularity="hour",
|
|
337
|
+
time_field=EventFieldType.TIMESTAMP,
|
|
356
338
|
partition_cols=["$key", "$year", "$month", "$day", "$hour"],
|
|
357
339
|
)
|
|
358
340
|
|
|
@@ -34,7 +34,7 @@ class _DefaultPackagerMeta(ABCMeta):
|
|
|
34
34
|
dynamically generated docstring that will include a summary of the packager.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
def __new__(
|
|
37
|
+
def __new__(cls, name: str, bases: tuple, namespace: dict, **kwargs):
|
|
38
38
|
"""
|
|
39
39
|
Create a new DefaultPackager metaclass that saves the original packager docstring to another attribute named
|
|
40
40
|
`_packager_doc`.
|
|
@@ -48,7 +48,7 @@ class _DefaultPackagerMeta(ABCMeta):
|
|
|
48
48
|
namespace["_packager_doc"] = namespace.get("__doc__", "")
|
|
49
49
|
|
|
50
50
|
# Continue creating the metaclass:
|
|
51
|
-
return super().__new__(
|
|
51
|
+
return super().__new__(cls, name, bases, namespace, **kwargs)
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
54
|
def __doc__(cls: type["DefaultPackager"]) -> str:
|
mlrun/projects/project.py
CHANGED
|
@@ -1557,15 +1557,15 @@ class MlrunProject(ModelObj):
|
|
|
1557
1557
|
self,
|
|
1558
1558
|
item,
|
|
1559
1559
|
body=None,
|
|
1560
|
-
tag="",
|
|
1561
|
-
local_path="",
|
|
1562
|
-
artifact_path=None,
|
|
1563
|
-
format=None,
|
|
1564
|
-
upload=None,
|
|
1565
|
-
labels=None,
|
|
1566
|
-
target_path=None,
|
|
1560
|
+
tag: str = "",
|
|
1561
|
+
local_path: str = "",
|
|
1562
|
+
artifact_path: Optional[str] = None,
|
|
1563
|
+
format: Optional[str] = None,
|
|
1564
|
+
upload: Optional[bool] = None,
|
|
1565
|
+
labels: Optional[dict[str, str]] = None,
|
|
1566
|
+
target_path: Optional[str] = None,
|
|
1567
1567
|
**kwargs,
|
|
1568
|
-
):
|
|
1568
|
+
) -> Artifact:
|
|
1569
1569
|
"""Log an output artifact and optionally upload it to datastore
|
|
1570
1570
|
|
|
1571
1571
|
If the artifact already exists with the same key and tag, it will be overwritten.
|
|
@@ -1664,7 +1664,7 @@ class MlrunProject(ModelObj):
|
|
|
1664
1664
|
stats=None,
|
|
1665
1665
|
target_path="",
|
|
1666
1666
|
extra_data=None,
|
|
1667
|
-
label_column: str = None,
|
|
1667
|
+
label_column: Optional[str] = None,
|
|
1668
1668
|
**kwargs,
|
|
1669
1669
|
) -> DatasetArtifact:
|
|
1670
1670
|
"""
|
|
@@ -1741,15 +1741,15 @@ class MlrunProject(ModelObj):
|
|
|
1741
1741
|
artifact_path=None,
|
|
1742
1742
|
upload=None,
|
|
1743
1743
|
labels=None,
|
|
1744
|
-
inputs: list[Feature] = None,
|
|
1745
|
-
outputs: list[Feature] = None,
|
|
1746
|
-
feature_vector: str = None,
|
|
1747
|
-
feature_weights: list = None,
|
|
1744
|
+
inputs: Optional[list[Feature]] = None,
|
|
1745
|
+
outputs: Optional[list[Feature]] = None,
|
|
1746
|
+
feature_vector: Optional[str] = None,
|
|
1747
|
+
feature_weights: Optional[list] = None,
|
|
1748
1748
|
training_set=None,
|
|
1749
1749
|
label_column=None,
|
|
1750
1750
|
extra_data=None,
|
|
1751
1751
|
**kwargs,
|
|
1752
|
-
):
|
|
1752
|
+
) -> ModelArtifact:
|
|
1753
1753
|
"""Log a model artifact and optionally upload it to datastore
|
|
1754
1754
|
|
|
1755
1755
|
If the model already exists with the same key and tag, it will be overwritten.
|
|
@@ -3040,8 +3040,9 @@ class MlrunProject(ModelObj):
|
|
|
3040
3040
|
"Remote repo is not defined, use .create_remote() + push()"
|
|
3041
3041
|
)
|
|
3042
3042
|
|
|
3043
|
-
if engine not in ["remote"]:
|
|
3044
|
-
#
|
|
3043
|
+
if engine not in ["remote"] and not schedule:
|
|
3044
|
+
# For remote/scheduled runs we don't require the functions to be synced as they can be loaded dynamically
|
|
3045
|
+
# during run
|
|
3045
3046
|
self.sync_functions(always=sync)
|
|
3046
3047
|
if not self.spec._function_objects:
|
|
3047
3048
|
raise ValueError(
|
mlrun/runtimes/funcdoc.py
CHANGED
|
@@ -578,6 +578,15 @@ class APIGateway(ModelObj):
|
|
|
578
578
|
"true"
|
|
579
579
|
)
|
|
580
580
|
|
|
581
|
+
def with_gateway_timeout(self, gateway_timeout: int):
|
|
582
|
+
"""
|
|
583
|
+
Set gateway proxy connect/read/send timeout annotations
|
|
584
|
+
:param gateway_timeout: The timeout in seconds
|
|
585
|
+
"""
|
|
586
|
+
mlrun.runtimes.utils.enrich_gateway_timeout_annotations(
|
|
587
|
+
self.metadata.annotations, gateway_timeout
|
|
588
|
+
)
|
|
589
|
+
|
|
581
590
|
@classmethod
|
|
582
591
|
def from_scheme(cls, api_gateway: schemas.APIGateway):
|
|
583
592
|
project = api_gateway.metadata.labels.get(
|