mlrun 1.6.4rc2__py3-none-any.whl → 1.7.0rc20__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 (291) hide show
  1. mlrun/__init__.py +11 -1
  2. mlrun/__main__.py +26 -112
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/api/schemas/__init__.py +5 -4
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +46 -257
  8. mlrun/artifacts/dataset.py +11 -192
  9. mlrun/artifacts/manager.py +47 -48
  10. mlrun/artifacts/model.py +31 -159
  11. mlrun/artifacts/plots.py +23 -380
  12. mlrun/common/constants.py +69 -0
  13. mlrun/common/db/sql_session.py +2 -3
  14. mlrun/common/formatters/__init__.py +19 -0
  15. mlrun/common/formatters/artifact.py +21 -0
  16. mlrun/common/formatters/base.py +78 -0
  17. mlrun/common/formatters/function.py +41 -0
  18. mlrun/common/formatters/pipeline.py +53 -0
  19. mlrun/common/formatters/project.py +51 -0
  20. mlrun/common/helpers.py +1 -2
  21. mlrun/common/model_monitoring/helpers.py +9 -5
  22. mlrun/{runtimes → common/runtimes}/constants.py +37 -9
  23. mlrun/common/schemas/__init__.py +24 -4
  24. mlrun/common/schemas/alert.py +203 -0
  25. mlrun/common/schemas/api_gateway.py +148 -0
  26. mlrun/common/schemas/artifact.py +18 -8
  27. mlrun/common/schemas/auth.py +11 -5
  28. mlrun/common/schemas/background_task.py +1 -1
  29. mlrun/common/schemas/client_spec.py +4 -1
  30. mlrun/common/schemas/feature_store.py +16 -16
  31. mlrun/common/schemas/frontend_spec.py +8 -7
  32. mlrun/common/schemas/function.py +5 -1
  33. mlrun/common/schemas/hub.py +11 -18
  34. mlrun/common/schemas/memory_reports.py +2 -2
  35. mlrun/common/schemas/model_monitoring/__init__.py +18 -3
  36. mlrun/common/schemas/model_monitoring/constants.py +83 -26
  37. mlrun/common/schemas/model_monitoring/grafana.py +13 -9
  38. mlrun/common/schemas/model_monitoring/model_endpoints.py +99 -16
  39. mlrun/common/schemas/notification.py +4 -4
  40. mlrun/common/schemas/object.py +2 -2
  41. mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
  42. mlrun/common/schemas/pipeline.py +1 -10
  43. mlrun/common/schemas/project.py +24 -23
  44. mlrun/common/schemas/runtime_resource.py +8 -12
  45. mlrun/common/schemas/schedule.py +3 -3
  46. mlrun/common/schemas/tag.py +1 -2
  47. mlrun/common/schemas/workflow.py +2 -2
  48. mlrun/common/types.py +7 -1
  49. mlrun/config.py +54 -17
  50. mlrun/data_types/to_pandas.py +10 -12
  51. mlrun/datastore/__init__.py +5 -8
  52. mlrun/datastore/alibaba_oss.py +130 -0
  53. mlrun/datastore/azure_blob.py +17 -5
  54. mlrun/datastore/base.py +62 -39
  55. mlrun/datastore/datastore.py +28 -9
  56. mlrun/datastore/datastore_profile.py +146 -20
  57. mlrun/datastore/filestore.py +0 -1
  58. mlrun/datastore/google_cloud_storage.py +6 -2
  59. mlrun/datastore/hdfs.py +56 -0
  60. mlrun/datastore/inmem.py +2 -2
  61. mlrun/datastore/redis.py +6 -2
  62. mlrun/datastore/s3.py +9 -0
  63. mlrun/datastore/snowflake_utils.py +43 -0
  64. mlrun/datastore/sources.py +201 -96
  65. mlrun/datastore/spark_utils.py +1 -2
  66. mlrun/datastore/store_resources.py +7 -7
  67. mlrun/datastore/targets.py +358 -104
  68. mlrun/datastore/utils.py +72 -58
  69. mlrun/datastore/v3io.py +5 -1
  70. mlrun/db/base.py +185 -35
  71. mlrun/db/factory.py +1 -1
  72. mlrun/db/httpdb.py +614 -179
  73. mlrun/db/nopdb.py +210 -26
  74. mlrun/errors.py +12 -1
  75. mlrun/execution.py +41 -24
  76. mlrun/feature_store/__init__.py +0 -2
  77. mlrun/feature_store/api.py +40 -72
  78. mlrun/feature_store/common.py +1 -1
  79. mlrun/feature_store/feature_set.py +76 -55
  80. mlrun/feature_store/feature_vector.py +28 -30
  81. mlrun/feature_store/ingestion.py +7 -6
  82. mlrun/feature_store/retrieval/base.py +16 -11
  83. mlrun/feature_store/retrieval/conversion.py +11 -13
  84. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  85. mlrun/feature_store/retrieval/job.py +9 -3
  86. mlrun/feature_store/retrieval/local_merger.py +2 -0
  87. mlrun/feature_store/retrieval/spark_merger.py +34 -24
  88. mlrun/feature_store/steps.py +37 -34
  89. mlrun/features.py +9 -20
  90. mlrun/frameworks/_common/artifacts_library.py +9 -9
  91. mlrun/frameworks/_common/mlrun_interface.py +5 -5
  92. mlrun/frameworks/_common/model_handler.py +48 -48
  93. mlrun/frameworks/_common/plan.py +2 -3
  94. mlrun/frameworks/_common/producer.py +3 -4
  95. mlrun/frameworks/_common/utils.py +5 -5
  96. mlrun/frameworks/_dl_common/loggers/logger.py +6 -7
  97. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +9 -9
  98. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +23 -47
  99. mlrun/frameworks/_ml_common/artifacts_library.py +1 -2
  100. mlrun/frameworks/_ml_common/loggers/logger.py +3 -4
  101. mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +4 -5
  102. mlrun/frameworks/_ml_common/model_handler.py +24 -24
  103. mlrun/frameworks/_ml_common/pkl_model_server.py +2 -2
  104. mlrun/frameworks/_ml_common/plan.py +1 -1
  105. mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +2 -3
  106. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +2 -3
  107. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  108. mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +3 -3
  109. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  110. mlrun/frameworks/_ml_common/utils.py +4 -4
  111. mlrun/frameworks/auto_mlrun/auto_mlrun.py +9 -9
  112. mlrun/frameworks/huggingface/model_server.py +4 -4
  113. mlrun/frameworks/lgbm/__init__.py +33 -33
  114. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  115. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -5
  116. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -5
  117. mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -3
  118. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +6 -6
  119. mlrun/frameworks/lgbm/model_handler.py +10 -10
  120. mlrun/frameworks/lgbm/model_server.py +6 -6
  121. mlrun/frameworks/lgbm/utils.py +5 -5
  122. mlrun/frameworks/onnx/dataset.py +8 -8
  123. mlrun/frameworks/onnx/mlrun_interface.py +3 -3
  124. mlrun/frameworks/onnx/model_handler.py +6 -6
  125. mlrun/frameworks/onnx/model_server.py +7 -7
  126. mlrun/frameworks/parallel_coordinates.py +4 -3
  127. mlrun/frameworks/pytorch/__init__.py +18 -18
  128. mlrun/frameworks/pytorch/callbacks/callback.py +4 -5
  129. mlrun/frameworks/pytorch/callbacks/logging_callback.py +17 -17
  130. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +11 -11
  131. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +23 -29
  132. mlrun/frameworks/pytorch/callbacks_handler.py +38 -38
  133. mlrun/frameworks/pytorch/mlrun_interface.py +20 -20
  134. mlrun/frameworks/pytorch/model_handler.py +17 -17
  135. mlrun/frameworks/pytorch/model_server.py +7 -7
  136. mlrun/frameworks/sklearn/__init__.py +13 -13
  137. mlrun/frameworks/sklearn/estimator.py +4 -4
  138. mlrun/frameworks/sklearn/metrics_library.py +14 -14
  139. mlrun/frameworks/sklearn/mlrun_interface.py +3 -6
  140. mlrun/frameworks/sklearn/model_handler.py +2 -2
  141. mlrun/frameworks/tf_keras/__init__.py +10 -7
  142. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +15 -15
  143. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +11 -11
  144. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +19 -23
  145. mlrun/frameworks/tf_keras/mlrun_interface.py +9 -11
  146. mlrun/frameworks/tf_keras/model_handler.py +14 -14
  147. mlrun/frameworks/tf_keras/model_server.py +6 -6
  148. mlrun/frameworks/xgboost/__init__.py +13 -13
  149. mlrun/frameworks/xgboost/model_handler.py +6 -6
  150. mlrun/k8s_utils.py +14 -16
  151. mlrun/launcher/__init__.py +1 -1
  152. mlrun/launcher/base.py +16 -15
  153. mlrun/launcher/client.py +8 -6
  154. mlrun/launcher/factory.py +1 -1
  155. mlrun/launcher/local.py +17 -11
  156. mlrun/launcher/remote.py +16 -10
  157. mlrun/lists.py +7 -6
  158. mlrun/model.py +238 -73
  159. mlrun/model_monitoring/__init__.py +1 -1
  160. mlrun/model_monitoring/api.py +138 -315
  161. mlrun/model_monitoring/application.py +5 -296
  162. mlrun/model_monitoring/applications/__init__.py +24 -0
  163. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  164. mlrun/model_monitoring/applications/base.py +282 -0
  165. mlrun/model_monitoring/applications/context.py +214 -0
  166. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  167. mlrun/model_monitoring/applications/histogram_data_drift.py +349 -0
  168. mlrun/model_monitoring/applications/results.py +99 -0
  169. mlrun/model_monitoring/controller.py +104 -84
  170. mlrun/model_monitoring/controller_handler.py +13 -5
  171. mlrun/model_monitoring/db/__init__.py +18 -0
  172. mlrun/model_monitoring/{stores → db/stores}/__init__.py +43 -36
  173. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  174. mlrun/model_monitoring/{stores/model_endpoint_store.py → db/stores/base/store.py} +64 -40
  175. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  176. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
  177. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/base.py +109 -5
  178. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +88 -0
  179. mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
  180. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +684 -0
  181. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  182. mlrun/model_monitoring/{stores/kv_model_endpoint_store.py → db/stores/v3io_kv/kv_store.py} +310 -165
  183. mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
  184. mlrun/model_monitoring/db/tsdb/base.py +329 -0
  185. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  186. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  187. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
  188. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
  189. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +397 -0
  190. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  191. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  192. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +630 -0
  193. mlrun/model_monitoring/evidently_application.py +6 -118
  194. mlrun/model_monitoring/features_drift_table.py +134 -106
  195. mlrun/model_monitoring/helpers.py +127 -28
  196. mlrun/model_monitoring/metrics/__init__.py +13 -0
  197. mlrun/model_monitoring/metrics/histogram_distance.py +127 -0
  198. mlrun/model_monitoring/model_endpoint.py +3 -2
  199. mlrun/model_monitoring/prometheus.py +1 -4
  200. mlrun/model_monitoring/stream_processing.py +62 -231
  201. mlrun/model_monitoring/tracking_policy.py +9 -2
  202. mlrun/model_monitoring/writer.py +152 -124
  203. mlrun/package/__init__.py +6 -6
  204. mlrun/package/context_handler.py +5 -5
  205. mlrun/package/packager.py +7 -7
  206. mlrun/package/packagers/default_packager.py +6 -6
  207. mlrun/package/packagers/numpy_packagers.py +15 -15
  208. mlrun/package/packagers/pandas_packagers.py +5 -5
  209. mlrun/package/packagers/python_standard_library_packagers.py +10 -10
  210. mlrun/package/packagers_manager.py +19 -23
  211. mlrun/package/utils/_formatter.py +6 -6
  212. mlrun/package/utils/_pickler.py +2 -2
  213. mlrun/package/utils/_supported_format.py +4 -4
  214. mlrun/package/utils/log_hint_utils.py +2 -2
  215. mlrun/package/utils/type_hint_utils.py +4 -9
  216. mlrun/platforms/__init__.py +11 -10
  217. mlrun/platforms/iguazio.py +24 -203
  218. mlrun/projects/operations.py +35 -21
  219. mlrun/projects/pipelines.py +68 -99
  220. mlrun/projects/project.py +830 -266
  221. mlrun/render.py +3 -11
  222. mlrun/run.py +162 -166
  223. mlrun/runtimes/__init__.py +62 -7
  224. mlrun/runtimes/base.py +39 -32
  225. mlrun/runtimes/daskjob.py +8 -8
  226. mlrun/runtimes/databricks_job/databricks_cancel_task.py +1 -1
  227. mlrun/runtimes/databricks_job/databricks_runtime.py +7 -7
  228. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  229. mlrun/runtimes/funcdoc.py +0 -28
  230. mlrun/runtimes/function_reference.py +1 -1
  231. mlrun/runtimes/kubejob.py +28 -122
  232. mlrun/runtimes/local.py +6 -3
  233. mlrun/runtimes/mpijob/__init__.py +0 -20
  234. mlrun/runtimes/mpijob/abstract.py +9 -10
  235. mlrun/runtimes/mpijob/v1.py +1 -1
  236. mlrun/{model_monitoring/stores/models/sqlite.py → runtimes/nuclio/__init__.py} +7 -9
  237. mlrun/runtimes/nuclio/api_gateway.py +709 -0
  238. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  239. mlrun/runtimes/nuclio/application/application.py +523 -0
  240. mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
  241. mlrun/runtimes/{function.py → nuclio/function.py} +112 -73
  242. mlrun/runtimes/{nuclio.py → nuclio/nuclio.py} +6 -6
  243. mlrun/runtimes/{serving.py → nuclio/serving.py} +45 -51
  244. mlrun/runtimes/pod.py +286 -88
  245. mlrun/runtimes/remotesparkjob.py +2 -2
  246. mlrun/runtimes/sparkjob/spark3job.py +51 -34
  247. mlrun/runtimes/utils.py +7 -75
  248. mlrun/secrets.py +9 -5
  249. mlrun/serving/remote.py +2 -7
  250. mlrun/serving/routers.py +13 -10
  251. mlrun/serving/server.py +22 -26
  252. mlrun/serving/states.py +99 -25
  253. mlrun/serving/utils.py +3 -3
  254. mlrun/serving/v1_serving.py +6 -7
  255. mlrun/serving/v2_serving.py +59 -20
  256. mlrun/track/tracker.py +2 -1
  257. mlrun/track/tracker_manager.py +3 -3
  258. mlrun/track/trackers/mlflow_tracker.py +1 -2
  259. mlrun/utils/async_http.py +5 -7
  260. mlrun/utils/azure_vault.py +1 -1
  261. mlrun/utils/clones.py +1 -2
  262. mlrun/utils/condition_evaluator.py +3 -3
  263. mlrun/utils/db.py +3 -3
  264. mlrun/utils/helpers.py +183 -197
  265. mlrun/utils/http.py +2 -5
  266. mlrun/utils/logger.py +76 -14
  267. mlrun/utils/notifications/notification/__init__.py +17 -12
  268. mlrun/utils/notifications/notification/base.py +14 -2
  269. mlrun/utils/notifications/notification/console.py +2 -0
  270. mlrun/utils/notifications/notification/git.py +3 -1
  271. mlrun/utils/notifications/notification/ipython.py +3 -1
  272. mlrun/utils/notifications/notification/slack.py +101 -21
  273. mlrun/utils/notifications/notification/webhook.py +11 -1
  274. mlrun/utils/notifications/notification_pusher.py +155 -30
  275. mlrun/utils/retryer.py +208 -0
  276. mlrun/utils/singleton.py +1 -1
  277. mlrun/utils/v3io_clients.py +2 -4
  278. mlrun/utils/version/version.json +2 -2
  279. mlrun/utils/version/version.py +2 -6
  280. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/METADATA +31 -19
  281. mlrun-1.7.0rc20.dist-info/RECORD +353 -0
  282. mlrun/kfpops.py +0 -868
  283. mlrun/model_monitoring/batch.py +0 -1095
  284. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  285. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -384
  286. mlrun/platforms/other.py +0 -306
  287. mlrun-1.6.4rc2.dist-info/RECORD +0 -314
  288. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/LICENSE +0 -0
  289. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/WHEEL +0 -0
  290. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/entry_points.txt +0 -0
  291. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/top_level.txt +0 -0
@@ -12,299 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import dataclasses
16
- import json
17
- import re
18
- from abc import ABC, abstractmethod
19
- from typing import Any, Optional, Tuple, Union
20
-
21
- import numpy as np
22
- import pandas as pd
23
-
24
- import mlrun.common.helpers
25
- import mlrun.common.schemas.model_monitoring
26
- import mlrun.common.schemas.model_monitoring.constants as mm_constant
27
- import mlrun.utils.v3io_clients
28
- from mlrun.datastore import get_stream_pusher
29
- from mlrun.datastore.targets import ParquetTarget
30
- from mlrun.model_monitoring.helpers import get_stream_path
31
- from mlrun.serving.utils import StepToDict
32
- from mlrun.utils import logger
33
-
34
-
35
- @dataclasses.dataclass
36
- class ModelMonitoringApplicationResult:
37
- """
38
- Class representing the result of a custom model monitoring application.
39
-
40
- :param name: (str) Name of the application result. This name must be
41
- unique for each metric in a single application
42
- (name must be of the format [a-zA-Z_][a-zA-Z0-9_]*).
43
- :param value: (float) Value of the application result.
44
- :param kind: (ResultKindApp) Kind of application result.
45
- :param status: (ResultStatusApp) Status of the application result.
46
- :param extra_data: (dict) Extra data associated with the application result.
47
- """
48
-
49
- name: str
50
- value: float
51
- kind: mm_constant.ResultKindApp
52
- status: mm_constant.ResultStatusApp
53
- extra_data: dict = dataclasses.field(default_factory=dict)
54
-
55
- def __post_init__(self):
56
- pat = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
57
- if not re.fullmatch(pat, self.name):
58
- raise mlrun.errors.MLRunInvalidArgumentError(
59
- "Attribute name must be of the format [a-zA-Z_][a-zA-Z0-9_]*"
60
- )
61
-
62
- def to_dict(self):
63
- """
64
- Convert the object to a dictionary format suitable for writing.
65
-
66
- :returns: (dict) Dictionary representation of the result.
67
- """
68
- return {
69
- mm_constant.WriterEvent.RESULT_NAME: self.name,
70
- mm_constant.WriterEvent.RESULT_VALUE: self.value,
71
- mm_constant.WriterEvent.RESULT_KIND: self.kind,
72
- mm_constant.WriterEvent.RESULT_STATUS: self.status,
73
- mm_constant.WriterEvent.RESULT_EXTRA_DATA: json.dumps(self.extra_data),
74
- }
75
-
76
-
77
- class ModelMonitoringApplicationBase(StepToDict, ABC):
78
- """
79
- A base class for a model monitoring application.
80
- Inherit from this class to create a custom model monitoring application.
81
-
82
- example for very simple custom application::
83
- # mlrun: start-code
84
- class MyApp(ApplicationBase):
85
- def do_tracking(
86
- self,
87
- sample_df_stats: pd.DataFrame,
88
- feature_stats: pd.DataFrame,
89
- start_infer_time: pd.Timestamp,
90
- end_infer_time: pd.Timestamp,
91
- schedule_time: pd.Timestamp,
92
- latest_request: pd.Timestamp,
93
- endpoint_id: str,
94
- output_stream_uri: str,
95
- ) -> ModelMonitoringApplicationResult:
96
- self.context.log_artifact(TableArtifact("sample_df_stats", df=sample_df_stats))
97
- return ModelMonitoringApplicationResult(
98
- name="data_drift_test",
99
- value=0.5,
100
- kind=mm_constant.ResultKindApp.data_drift,
101
- status=mm_constant.ResultStatusApp.detected,
102
- )
103
-
104
- # mlrun: end-code
105
- """
106
-
107
- kind = "monitoring_application"
108
-
109
- def do(
110
- self, event: dict[str, Any]
111
- ) -> Tuple[list[ModelMonitoringApplicationResult], dict]:
112
- """
113
- Process the monitoring event and return application results.
114
-
115
- :param event: (dict) The monitoring event to process.
116
- :returns: (list[ModelMonitoringApplicationResult], dict) The application results
117
- and the original event for the application.
118
- """
119
- resolved_event = self._resolve_event(event)
120
- if not (
121
- hasattr(self, "context") and isinstance(self.context, mlrun.MLClientCtx)
122
- ):
123
- self._lazy_init(app_name=resolved_event[0])
124
- results = self.do_tracking(*resolved_event)
125
- results = results if isinstance(results, list) else [results]
126
- return results, event
127
-
128
- def _lazy_init(self, app_name: str):
129
- self.context = self._create_context_for_logging(app_name=app_name)
130
-
131
- @abstractmethod
132
- def do_tracking(
133
- self,
134
- application_name: str,
135
- sample_df_stats: pd.DataFrame,
136
- feature_stats: pd.DataFrame,
137
- sample_df: pd.DataFrame,
138
- start_infer_time: pd.Timestamp,
139
- end_infer_time: pd.Timestamp,
140
- latest_request: pd.Timestamp,
141
- endpoint_id: str,
142
- output_stream_uri: str,
143
- ) -> Union[
144
- ModelMonitoringApplicationResult, list[ModelMonitoringApplicationResult]
145
- ]:
146
- """
147
- Implement this method with your custom monitoring logic.
148
-
149
- :param application_name: (str) the app name
150
- :param sample_df_stats: (pd.DataFrame) The new sample distribution DataFrame.
151
- :param feature_stats: (pd.DataFrame) The train sample distribution DataFrame.
152
- :param sample_df: (pd.DataFrame) The new sample DataFrame.
153
- :param start_infer_time: (pd.Timestamp) Start time of the monitoring schedule.
154
- :param end_infer_time: (pd.Timestamp) End time of the monitoring schedule.
155
- :param latest_request: (pd.Timestamp) Timestamp of the latest request on this endpoint_id.
156
- :param endpoint_id: (str) ID of the monitored model endpoint
157
- :param output_stream_uri: (str) URI of the output stream for results
158
-
159
- :returns: (ModelMonitoringApplicationResult) or
160
- (list[ModelMonitoringApplicationResult]) of the application results.
161
- """
162
- raise NotImplementedError
163
-
164
- @classmethod
165
- def _resolve_event(
166
- cls,
167
- event: dict[str, Any],
168
- ) -> Tuple[
169
- str,
170
- pd.DataFrame,
171
- pd.DataFrame,
172
- pd.DataFrame,
173
- pd.Timestamp,
174
- pd.Timestamp,
175
- pd.Timestamp,
176
- str,
177
- str,
178
- ]:
179
- """
180
- Converting the event into a single tuple that will be used for passing the event arguments to the running
181
- application
182
-
183
- :param event: dictionary with all the incoming data
184
-
185
- :return: A tuple of:
186
- [0] = (str) application name
187
- [1] = (pd.DataFrame) current input statistics
188
- [2] = (pd.DataFrame) train statistics
189
- [3] = (pd.DataFrame) current input data
190
- [4] = (pd.Timestamp) start time of the monitoring schedule
191
- [5] = (pd.Timestamp) end time of the monitoring schedule
192
- [6] = (pd.Timestamp) timestamp of the latest request
193
- [7] = (str) endpoint id
194
- [8] = (str) output stream uri
195
- """
196
- start_time = pd.Timestamp(event[mm_constant.ApplicationEvent.START_INFER_TIME])
197
- end_time = pd.Timestamp(event[mm_constant.ApplicationEvent.END_INFER_TIME])
198
- return (
199
- event[mm_constant.ApplicationEvent.APPLICATION_NAME],
200
- cls._dict_to_histogram(
201
- json.loads(event[mm_constant.ApplicationEvent.CURRENT_STATS])
202
- ),
203
- cls._dict_to_histogram(
204
- json.loads(event[mm_constant.ApplicationEvent.FEATURE_STATS])
205
- ),
206
- ParquetTarget(
207
- path=event[mm_constant.ApplicationEvent.SAMPLE_PARQUET_PATH]
208
- ).as_df(start_time=start_time, end_time=end_time, time_column="timestamp"),
209
- start_time,
210
- end_time,
211
- pd.Timestamp(event[mm_constant.ApplicationEvent.LAST_REQUEST]),
212
- event[mm_constant.ApplicationEvent.ENDPOINT_ID],
213
- event[mm_constant.ApplicationEvent.OUTPUT_STREAM_URI],
214
- )
215
-
216
- @staticmethod
217
- def _create_context_for_logging(app_name: str):
218
- context = mlrun.get_or_create_ctx(
219
- f"{app_name}-logger",
220
- upload_artifacts=True,
221
- labels={"workflow": "model-monitoring-app-logger"},
222
- )
223
- return context
224
-
225
- @staticmethod
226
- def _dict_to_histogram(histogram_dict: dict[str, dict[str, Any]]) -> pd.DataFrame:
227
- """
228
- Convert histogram dictionary to pandas DataFrame with feature histograms as columns
229
-
230
- :param histogram_dict: Histogram dictionary
231
-
232
- :returns: Histogram dataframe
233
- """
234
-
235
- # Create a dictionary with feature histograms as values
236
- histograms = {}
237
- for feature, stats in histogram_dict.items():
238
- if "hist" in stats:
239
- # Normalize to probability distribution of each feature
240
- histograms[feature] = np.array(stats["hist"][0]) / stats["count"]
241
-
242
- # Convert the dictionary to pandas DataFrame
243
- histograms = pd.DataFrame(histograms)
244
-
245
- return histograms
246
-
247
-
248
- class PushToMonitoringWriter(StepToDict):
249
- kind = "monitoring_application_stream_pusher"
250
-
251
- def __init__(
252
- self,
253
- project: Optional[str] = None,
254
- writer_application_name: Optional[str] = None,
255
- stream_uri: Optional[str] = None,
256
- name: Optional[str] = None,
257
- ):
258
- """
259
- Class for pushing application results to the monitoring writer stream.
260
-
261
- :param project: Project name.
262
- :param writer_application_name: Writer application name.
263
- :param stream_uri: Stream URI for pushing results.
264
- :param name: Name of the PushToMonitoringWriter
265
- instance default to PushToMonitoringWriter.
266
- """
267
- self.project = project
268
- self.application_name_to_push = writer_application_name
269
- self.stream_uri = stream_uri or get_stream_path(
270
- project=self.project, application_name=self.application_name_to_push
271
- )
272
- self.output_stream = None
273
- self.name = name or "PushToMonitoringWriter"
274
-
275
- def do(self, event: Tuple[list[ModelMonitoringApplicationResult], dict]) -> None:
276
- """
277
- Push application results to the monitoring writer stream.
278
-
279
- :param event: Monitoring result(s) to push and the original event from the controller.
280
- """
281
- self._lazy_init()
282
- application_results, application_event = event
283
- metadata = {
284
- mm_constant.WriterEvent.APPLICATION_NAME: application_event[
285
- mm_constant.ApplicationEvent.APPLICATION_NAME
286
- ],
287
- mm_constant.WriterEvent.ENDPOINT_ID: application_event[
288
- mm_constant.ApplicationEvent.ENDPOINT_ID
289
- ],
290
- mm_constant.WriterEvent.START_INFER_TIME: application_event[
291
- mm_constant.ApplicationEvent.START_INFER_TIME
292
- ],
293
- mm_constant.WriterEvent.END_INFER_TIME: application_event[
294
- mm_constant.ApplicationEvent.END_INFER_TIME
295
- ],
296
- mm_constant.WriterEvent.CURRENT_STATS: json.dumps(
297
- application_event[mm_constant.ApplicationEvent.CURRENT_STATS]
298
- ),
299
- }
300
- for result in application_results:
301
- data = result.to_dict()
302
- data.update(metadata)
303
- logger.info(f"Pushing data = {data} \n to stream = {self.stream_uri}")
304
- self.output_stream.push([data])
305
-
306
- def _lazy_init(self):
307
- if self.output_stream is None:
308
- self.output_stream = get_stream_pusher(
309
- self.stream_uri,
310
- )
15
+ # TODO : delete this file in 1.9.0
16
+ from mlrun.model_monitoring.applications import ( # noqa: F401
17
+ ModelMonitoringApplicationBase,
18
+ ModelMonitoringApplicationResult,
19
+ )
@@ -0,0 +1,24 @@
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
+ from .base import ModelMonitoringApplicationBase, ModelMonitoringApplicationBaseV2
17
+ from .context import MonitoringApplicationContext
18
+ from .evidently_base import (
19
+ _HAS_EVIDENTLY,
20
+ SUPPORTED_EVIDENTLY_VERSION,
21
+ EvidentlyModelMonitoringApplicationBase,
22
+ EvidentlyModelMonitoringApplicationBaseV2,
23
+ )
24
+ from .results import ModelMonitoringApplicationMetric, ModelMonitoringApplicationResult
@@ -0,0 +1,157 @@
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
+ import json
15
+ import typing
16
+ from typing import Optional
17
+
18
+ import mlrun.common.helpers
19
+ import mlrun.common.model_monitoring.helpers
20
+ import mlrun.common.schemas.model_monitoring.constants as mm_constant
21
+ import mlrun.datastore
22
+ import mlrun.utils.v3io_clients
23
+ from mlrun.model_monitoring.helpers import get_stream_path
24
+ from mlrun.serving.utils import StepToDict
25
+ from mlrun.utils import logger
26
+
27
+ from .context import MonitoringApplicationContext
28
+ from .results import ModelMonitoringApplicationMetric, ModelMonitoringApplicationResult
29
+
30
+
31
+ class _PushToMonitoringWriter(StepToDict):
32
+ kind = "monitoring_application_stream_pusher"
33
+
34
+ def __init__(
35
+ self,
36
+ project: Optional[str] = None,
37
+ writer_application_name: Optional[str] = None,
38
+ stream_uri: Optional[str] = None,
39
+ name: Optional[str] = None,
40
+ ):
41
+ """
42
+ Class for pushing application results to the monitoring writer stream.
43
+
44
+ :param project: Project name.
45
+ :param writer_application_name: Writer application name.
46
+ :param stream_uri: Stream URI for pushing results.
47
+ :param name: Name of the PushToMonitoringWriter
48
+ instance default to PushToMonitoringWriter.
49
+ """
50
+ self.project = project
51
+ self.application_name_to_push = writer_application_name
52
+ self.stream_uri = stream_uri or get_stream_path(
53
+ project=self.project, function_name=self.application_name_to_push
54
+ )
55
+ self.output_stream = None
56
+ self.name = name or "PushToMonitoringWriter"
57
+
58
+ def do(
59
+ self,
60
+ event: tuple[
61
+ list[
62
+ typing.Union[
63
+ ModelMonitoringApplicationResult, ModelMonitoringApplicationMetric
64
+ ]
65
+ ],
66
+ MonitoringApplicationContext,
67
+ ],
68
+ ) -> None:
69
+ """
70
+ Push application results to the monitoring writer stream.
71
+
72
+ :param event: Monitoring result(s) to push and the original event from the controller.
73
+ """
74
+ self._lazy_init()
75
+ application_results, application_context = event
76
+ writer_event = {
77
+ mm_constant.WriterEvent.APPLICATION_NAME: application_context.application_name,
78
+ mm_constant.WriterEvent.ENDPOINT_ID: application_context.endpoint_id,
79
+ mm_constant.WriterEvent.START_INFER_TIME: application_context.start_infer_time.isoformat(
80
+ sep=" ", timespec="microseconds"
81
+ ),
82
+ mm_constant.WriterEvent.END_INFER_TIME: application_context.end_infer_time.isoformat(
83
+ sep=" ", timespec="microseconds"
84
+ ),
85
+ }
86
+ for result in application_results:
87
+ data = result.to_dict()
88
+ if isinstance(result, ModelMonitoringApplicationResult):
89
+ writer_event[mm_constant.WriterEvent.EVENT_KIND] = (
90
+ mm_constant.WriterEventKind.RESULT
91
+ )
92
+ data[mm_constant.ResultData.CURRENT_STATS] = json.dumps(
93
+ application_context.sample_df_stats
94
+ )
95
+ writer_event[mm_constant.WriterEvent.DATA] = json.dumps(data)
96
+ else:
97
+ writer_event[mm_constant.WriterEvent.EVENT_KIND] = (
98
+ mm_constant.WriterEventKind.METRIC
99
+ )
100
+ writer_event[mm_constant.WriterEvent.DATA] = json.dumps(data)
101
+
102
+ writer_event[mm_constant.WriterEvent.EVENT_KIND] = (
103
+ mm_constant.WriterEventKind.RESULT
104
+ if isinstance(result, ModelMonitoringApplicationResult)
105
+ else mm_constant.WriterEventKind.METRIC
106
+ )
107
+ logger.info(
108
+ f"Pushing data = {writer_event} \n to stream = {self.stream_uri}"
109
+ )
110
+ self.output_stream.push([writer_event])
111
+
112
+ def _lazy_init(self):
113
+ if self.output_stream is None:
114
+ self.output_stream = mlrun.datastore.get_stream_pusher(
115
+ self.stream_uri,
116
+ )
117
+
118
+
119
+ class _PrepareMonitoringEvent(StepToDict):
120
+ def __init__(self, application_name: str):
121
+ """
122
+ Class for preparing the application event for the application step.
123
+
124
+ :param application_name: Application name.
125
+ """
126
+
127
+ self.context = self._create_mlrun_context(application_name)
128
+ self.model_endpoints = {}
129
+
130
+ def do(self, event: dict[str, dict]) -> MonitoringApplicationContext:
131
+ """
132
+ Prepare the application event for the application step.
133
+
134
+ :param event: Application event.
135
+ :return: Application event.
136
+ """
137
+ if not event.get("mlrun_context"):
138
+ application_context = MonitoringApplicationContext().from_dict(
139
+ event,
140
+ context=self.context,
141
+ model_endpoint_dict=self.model_endpoints,
142
+ )
143
+ else:
144
+ application_context = MonitoringApplicationContext().from_dict(event)
145
+ self.model_endpoints.setdefault(
146
+ application_context.endpoint_id, application_context.model_endpoint
147
+ )
148
+ return application_context
149
+
150
+ @staticmethod
151
+ def _create_mlrun_context(app_name: str):
152
+ context = mlrun.get_or_create_ctx(
153
+ f"{app_name}-logger",
154
+ upload_artifacts=True,
155
+ )
156
+ context.__class__ = MonitoringApplicationContext
157
+ return context