mlrun 1.7.0rc6__py3-none-any.whl → 1.7.0rc7__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 (59) hide show
  1. mlrun/common/constants.py +6 -0
  2. mlrun/common/schemas/__init__.py +2 -0
  3. mlrun/common/schemas/model_monitoring/__init__.py +4 -0
  4. mlrun/common/schemas/model_monitoring/constants.py +35 -18
  5. mlrun/common/schemas/project.py +1 -0
  6. mlrun/common/types.py +7 -1
  7. mlrun/config.py +11 -4
  8. mlrun/data_types/data_types.py +4 -0
  9. mlrun/datastore/alibaba_oss.py +130 -0
  10. mlrun/datastore/azure_blob.py +4 -5
  11. mlrun/datastore/base.py +22 -16
  12. mlrun/datastore/datastore.py +4 -0
  13. mlrun/datastore/google_cloud_storage.py +1 -1
  14. mlrun/datastore/sources.py +2 -3
  15. mlrun/db/base.py +14 -6
  16. mlrun/db/httpdb.py +61 -56
  17. mlrun/db/nopdb.py +3 -0
  18. mlrun/model.py +1 -0
  19. mlrun/model_monitoring/__init__.py +1 -1
  20. mlrun/model_monitoring/api.py +104 -295
  21. mlrun/model_monitoring/controller.py +25 -25
  22. mlrun/model_monitoring/db/__init__.py +16 -0
  23. mlrun/model_monitoring/{stores → db/stores}/__init__.py +43 -34
  24. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  25. mlrun/model_monitoring/{stores/model_endpoint_store.py → db/stores/base/store.py} +47 -6
  26. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  27. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +49 -0
  28. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/base.py +76 -3
  29. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +68 -0
  30. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/sqlite.py +13 -1
  31. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +662 -0
  32. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  33. mlrun/model_monitoring/{stores/kv_model_endpoint_store.py → db/stores/v3io_kv/kv_store.py} +134 -3
  34. mlrun/model_monitoring/helpers.py +0 -2
  35. mlrun/model_monitoring/stream_processing.py +41 -9
  36. mlrun/model_monitoring/tracking_policy.py +7 -1
  37. mlrun/model_monitoring/writer.py +4 -36
  38. mlrun/projects/pipelines.py +13 -1
  39. mlrun/projects/project.py +109 -101
  40. mlrun/run.py +3 -1
  41. mlrun/runtimes/base.py +6 -0
  42. mlrun/runtimes/nuclio/api_gateway.py +188 -61
  43. mlrun/runtimes/nuclio/function.py +3 -0
  44. mlrun/runtimes/nuclio/serving.py +28 -32
  45. mlrun/runtimes/pod.py +26 -0
  46. mlrun/serving/server.py +4 -6
  47. mlrun/serving/states.py +34 -14
  48. mlrun/utils/helpers.py +34 -0
  49. mlrun/utils/version/version.json +2 -2
  50. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/METADATA +14 -5
  51. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/RECORD +55 -51
  52. mlrun/model_monitoring/batch.py +0 -933
  53. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  54. mlrun/model_monitoring/stores/models/mysql.py +0 -34
  55. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
  56. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/LICENSE +0 -0
  57. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/WHEEL +0 -0
  58. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/entry_points.txt +0 -0
  59. {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc7.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2024 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,60 +16,54 @@
16
16
 
17
17
  import enum
18
18
  import typing
19
+ import warnings
19
20
 
20
21
  import mlrun.common.schemas.secret
21
22
  import mlrun.errors
22
23
 
23
- from .model_endpoint_store import ModelEndpointStore
24
+ from .base import StoreBase
24
25
 
25
26
 
26
- class ModelEndpointStoreType(enum.Enum):
27
- """Enum class to handle the different store type values for saving a model endpoint record."""
27
+ class ObjectStoreFactory(enum.Enum):
28
+ """Enum class to handle the different store type values for saving model monitoring records."""
28
29
 
29
30
  v3io_nosql = "v3io-nosql"
30
31
  SQL = "sql"
31
32
 
32
- def to_endpoint_store(
33
+ def to_object_store(
33
34
  self,
34
35
  project: str,
35
36
  access_key: str = None,
36
- endpoint_store_connection: str = None,
37
37
  secret_provider: typing.Callable = None,
38
- ) -> ModelEndpointStore:
38
+ ) -> StoreBase:
39
39
  """
40
- Return a ModelEndpointStore object based on the provided enum value.
41
-
42
- :param project: The name of the project.
43
- :param access_key: Access key with permission to the DB table. Note that if access key is None
44
- and the endpoint target is from type KV then the access key will be
45
- retrieved from the environment variable.
46
- :param endpoint_store_connection: A valid connection string for model endpoint target. Contains several
47
- key-value pairs that required for the database connection.
48
- e.g. A root user with password 1234, tries to connect a schema called
49
- mlrun within a local MySQL DB instance:
50
- 'mysql+pymysql://root:1234@localhost:3306/mlrun'.
40
+ Return a StoreBase object based on the provided enum value.
41
+
42
+ :param project: The name of the project.
43
+ :param access_key: Access key with permission to the DB table. Note that if access key is None
44
+ and the endpoint target is from type KV then the access key will be
45
+ retrieved from the environment variable.
51
46
  :param secret_provider: An optional secret provider to get the connection string secret.
52
47
 
53
- :return: `ModelEndpointStore` object.
48
+ :return: `StoreBase` object.
54
49
 
55
50
  """
56
51
 
57
- if self.value == ModelEndpointStoreType.v3io_nosql.value:
58
- from .kv_model_endpoint_store import KVModelEndpointStore
52
+ if self == self.v3io_nosql:
53
+ from mlrun.model_monitoring.db.stores.v3io_kv.kv_store import KVStoreBase
59
54
 
60
55
  # Get V3IO access key from env
61
56
  access_key = access_key or mlrun.mlconf.get_v3io_access_key()
62
57
 
63
- return KVModelEndpointStore(project=project, access_key=access_key)
58
+ return KVStoreBase(project=project, access_key=access_key)
64
59
 
65
60
  # Assuming SQL store target if store type is not KV.
66
61
  # Update these lines once there are more than two store target types.
67
62
 
68
- from .sql_model_endpoint_store import SQLModelEndpointStore
63
+ from mlrun.model_monitoring.db.stores.sqldb.sql_store import SQLStoreBase
69
64
 
70
- return SQLModelEndpointStore(
65
+ return SQLStoreBase(
71
66
  project=project,
72
- sql_connection_string=endpoint_store_connection,
73
67
  secret_provider=secret_provider,
74
68
  )
75
69
 
@@ -88,7 +82,24 @@ def get_model_endpoint_store(
88
82
  project: str,
89
83
  access_key: str = None,
90
84
  secret_provider: typing.Callable = None,
91
- ) -> ModelEndpointStore:
85
+ ) -> StoreBase:
86
+ # Leaving here for backwards compatibility
87
+ warnings.warn(
88
+ "The 'get_model_endpoint_store' function is deprecated and will be removed in 1.9.0. "
89
+ "Please use `get_store_object` instead.",
90
+ # TODO: remove in 1.9.0
91
+ FutureWarning,
92
+ )
93
+ return get_store_object(
94
+ project=project, access_key=access_key, secret_provider=secret_provider
95
+ )
96
+
97
+
98
+ def get_store_object(
99
+ project: str,
100
+ access_key: str = None,
101
+ secret_provider: typing.Callable = None,
102
+ ) -> StoreBase:
92
103
  """
93
104
  Getting the DB target type based on mlrun.config.model_endpoint_monitoring.store_type.
94
105
 
@@ -96,16 +107,14 @@ def get_model_endpoint_store(
96
107
  :param access_key: Access key with permission to the DB table.
97
108
  :param secret_provider: An optional secret provider to get the connection string secret.
98
109
 
99
- :return: `ModelEndpointStore` object. Using this object, the user can apply different operations on the
100
- model endpoint record such as write, update, get and delete.
110
+ :return: `StoreBase` object. Using this object, the user can apply different operations on the
111
+ model monitoring record such as write, update, get and delete a model endpoint.
101
112
  """
102
113
 
103
- # Get store type value from ModelEndpointStoreType enum class
104
- model_endpoint_store_type = ModelEndpointStoreType(
105
- mlrun.mlconf.model_endpoint_monitoring.store_type
106
- )
114
+ # Get store type value from ObjectStoreFactory enum class
115
+ store_type = ObjectStoreFactory(mlrun.mlconf.model_endpoint_monitoring.store_type)
107
116
 
108
- # Convert into model endpoint store target object
109
- return model_endpoint_store_type.to_endpoint_store(
117
+ # Convert into store target object
118
+ return store_type.to_object_store(
110
119
  project=project, access_key=access_key, secret_provider=secret_provider
111
120
  )
@@ -0,0 +1,15 @@
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
+ from .store import StoreBase
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2024 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -11,22 +11,21 @@
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
- #
15
14
 
16
15
  import typing
17
16
  from abc import ABC, abstractmethod
18
17
 
19
18
 
20
- class ModelEndpointStore(ABC):
19
+ class StoreBase(ABC):
21
20
  """
22
- An abstract class to handle the model endpoint in the DB target.
21
+ An abstract class to handle the store object in the DB target.
23
22
  """
24
23
 
25
24
  def __init__(self, project: str):
26
25
  """
27
- Initialize a new model endpoint target.
26
+ Initialize a new store target.
28
27
 
29
- :param project: The name of the project.
28
+ :param project: The name of the project.
30
29
  """
31
30
  self.project = project
32
31
 
@@ -143,3 +142,45 @@ class ModelEndpointStore(ABC):
143
142
  """
144
143
 
145
144
  pass
145
+
146
+ @abstractmethod
147
+ def write_application_result(self, event: dict[str, typing.Any]):
148
+ """
149
+ Write a new application result event in the target table.
150
+
151
+ :param event: An event dictionary that represents the application result, should be corresponded to the
152
+ schema defined in the :py:class:`~mlrun.common.schemas.model_monitoring.constants.WriterEvent`
153
+ object.
154
+ """
155
+ pass
156
+
157
+ @abstractmethod
158
+ def get_last_analyzed(self, endpoint_id: str, application_name: str) -> int:
159
+ """
160
+ Get the last analyzed time for the provided model endpoint and application.
161
+
162
+ :param endpoint_id: The unique id of the model endpoint.
163
+ :param application_name: Registered application name.
164
+
165
+ :return: Timestamp as a Unix time.
166
+ :raise: MLRunNotFoundError if last analyzed value is not found.
167
+ """
168
+ pass
169
+
170
+ @abstractmethod
171
+ def update_last_analyzed(
172
+ self,
173
+ endpoint_id: str,
174
+ application_name: str,
175
+ last_analyzed: int,
176
+ ):
177
+ """
178
+ Update the last analyzed time for the provided model endpoint and application.
179
+
180
+ :param endpoint_id: The unique id of the model endpoint.
181
+ :param application_name: Registered application name.
182
+ :param last_analyzed: Timestamp as a Unix time that represents the last analyzed time of a certain
183
+ application and model endpoint.
184
+
185
+ """
186
+ pass
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,49 @@
1
+ # Copyright 2023 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Optional, Union
16
+
17
+ from .mysql import ApplicationResultTable as MySQLApplicationResultTable
18
+ from .mysql import ModelEndpointsTable as MySQLModelEndpointsTable
19
+ from .mysql import MonitoringSchedulesTable as MySQLMonitoringSchedulesTable
20
+ from .sqlite import ApplicationResultTable as SQLiteApplicationResultTable
21
+ from .sqlite import ModelEndpointsTable as SQLiteModelEndpointsTable
22
+ from .sqlite import MonitoringSchedulesTable as SQLiteMonitoringSchedulesTable
23
+
24
+
25
+ def _get_model_endpoints_table(
26
+ connection_string: Optional[str] = None,
27
+ ) -> Union[type[MySQLModelEndpointsTable], type[SQLiteModelEndpointsTable]]:
28
+ """Return ModelEndpointsTable based on the provided connection string"""
29
+ if connection_string and "mysql:" in connection_string:
30
+ return MySQLModelEndpointsTable
31
+ return SQLiteModelEndpointsTable
32
+
33
+
34
+ def _get_application_result_table(
35
+ connection_string: Optional[str] = None,
36
+ ) -> Union[type[MySQLApplicationResultTable], type[SQLiteApplicationResultTable]]:
37
+ """Return ModelEndpointsTable based on the provided connection string"""
38
+ if connection_string and "mysql:" in connection_string:
39
+ return MySQLApplicationResultTable
40
+ return SQLiteApplicationResultTable
41
+
42
+
43
+ def _get_monitoring_schedules_table(
44
+ connection_string: Optional[str] = None,
45
+ ) -> Union[type[MySQLMonitoringSchedulesTable], type[SQLiteMonitoringSchedulesTable]]:
46
+ """Return ModelEndpointsTable based on the provided connection string"""
47
+ if connection_string and "mysql:" in connection_string:
48
+ return MySQLMonitoringSchedulesTable
49
+ return SQLiteMonitoringSchedulesTable
@@ -11,10 +11,22 @@
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 sqlalchemy import (
15
+ TIMESTAMP,
16
+ Boolean,
17
+ Column,
18
+ Float,
19
+ Integer,
20
+ String,
21
+ Text,
22
+ )
14
23
 
15
- from sqlalchemy import TIMESTAMP, Boolean, Column, Integer, String, Text
16
-
17
- from mlrun.common.schemas.model_monitoring import EventFieldType
24
+ from mlrun.common.schemas.model_monitoring import (
25
+ EventFieldType,
26
+ FileTargetKind,
27
+ SchedulingKeys,
28
+ WriterEvent,
29
+ )
18
30
  from mlrun.utils.db import BaseModel
19
31
 
20
32
 
@@ -82,3 +94,64 @@ class ModelEndpointsBaseTable(BaseModel):
82
94
  EventFieldType.LAST_REQUEST,
83
95
  TIMESTAMP,
84
96
  )
97
+
98
+
99
+ class ApplicationResultBaseTable(BaseModel):
100
+ __tablename__ = FileTargetKind.APP_RESULTS
101
+
102
+ uid = Column(EventFieldType.UID, String(120), primary_key=True)
103
+
104
+ application_name = Column(
105
+ WriterEvent.APPLICATION_NAME,
106
+ String(40),
107
+ nullable=True,
108
+ )
109
+
110
+ endpoint_id = Column(
111
+ WriterEvent.ENDPOINT_ID,
112
+ String(40),
113
+ nullable=True,
114
+ )
115
+
116
+ result_name = Column(
117
+ WriterEvent.RESULT_NAME,
118
+ String(40),
119
+ )
120
+
121
+ start_infer_time = Column(
122
+ WriterEvent.START_INFER_TIME,
123
+ TIMESTAMP(timezone=True),
124
+ )
125
+ end_infer_time = Column(
126
+ WriterEvent.END_INFER_TIME,
127
+ TIMESTAMP(timezone=True),
128
+ )
129
+
130
+ result_status = Column(WriterEvent.RESULT_STATUS, String(10))
131
+ result_kind = Column(WriterEvent.RESULT_KIND, String(40))
132
+ result_value = Column(WriterEvent.RESULT_VALUE, Float)
133
+ result_extra_data = Column(WriterEvent.RESULT_EXTRA_DATA, Text)
134
+ current_stats = Column(WriterEvent.CURRENT_STATS, Text)
135
+
136
+
137
+ class MonitoringSchedulesBaseTable(BaseModel):
138
+ __tablename__ = FileTargetKind.MONITORING_SCHEDULES
139
+
140
+ uid = Column(SchedulingKeys.UID, String(32), primary_key=True)
141
+
142
+ application_name = Column(
143
+ SchedulingKeys.APPLICATION_NAME,
144
+ String(40),
145
+ nullable=False,
146
+ )
147
+
148
+ endpoint_id = Column(
149
+ SchedulingKeys.ENDPOINT_ID,
150
+ String(40),
151
+ nullable=False,
152
+ )
153
+
154
+ last_analyzed = Column(
155
+ SchedulingKeys.LAST_ANALYZED,
156
+ Integer,
157
+ )
@@ -0,0 +1,68 @@
1
+ # Copyright 2023 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 sqlalchemy.dialects.mysql
16
+ from sqlalchemy import Column, ForeignKey, String
17
+ from sqlalchemy.ext.declarative import declarative_base, declared_attr
18
+
19
+ from mlrun.common.schemas.model_monitoring import (
20
+ EventFieldType,
21
+ WriterEvent,
22
+ )
23
+
24
+ from .base import (
25
+ ApplicationResultBaseTable,
26
+ ModelEndpointsBaseTable,
27
+ MonitoringSchedulesBaseTable,
28
+ )
29
+
30
+ Base = declarative_base()
31
+
32
+
33
+ class ModelEndpointsTable(Base, ModelEndpointsBaseTable):
34
+ first_request = Column(
35
+ EventFieldType.FIRST_REQUEST,
36
+ sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
37
+ )
38
+ last_request = Column(
39
+ EventFieldType.LAST_REQUEST,
40
+ sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
41
+ )
42
+
43
+
44
+ class ApplicationResultTable(Base, ApplicationResultBaseTable):
45
+ start_infer_time = Column(
46
+ WriterEvent.START_INFER_TIME,
47
+ sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
48
+ )
49
+ end_infer_time = Column(
50
+ WriterEvent.END_INFER_TIME,
51
+ sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
52
+ )
53
+
54
+ @declared_attr
55
+ def endpoint_id(cls):
56
+ return Column(
57
+ String(40),
58
+ ForeignKey(f"{EventFieldType.MODEL_ENDPOINTS}.{EventFieldType.UID}"),
59
+ )
60
+
61
+
62
+ class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
63
+ @declared_attr
64
+ def endpoint_id(cls):
65
+ return Column(
66
+ String(40),
67
+ ForeignKey(f"{EventFieldType.MODEL_ENDPOINTS}.{EventFieldType.UID}"),
68
+ )
@@ -14,10 +14,22 @@
14
14
 
15
15
  from sqlalchemy.ext.declarative import declarative_base
16
16
 
17
- from .base import ModelEndpointsBaseTable
17
+ from .base import (
18
+ ApplicationResultBaseTable,
19
+ ModelEndpointsBaseTable,
20
+ MonitoringSchedulesBaseTable,
21
+ )
18
22
 
19
23
  Base = declarative_base()
20
24
 
21
25
 
22
26
  class ModelEndpointsTable(Base, ModelEndpointsBaseTable):
23
27
  pass
28
+
29
+
30
+ class ApplicationResultTable(Base, ApplicationResultBaseTable):
31
+ pass
32
+
33
+
34
+ class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
35
+ pass