mlrun 1.7.0rc5__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 (75) hide show
  1. mlrun/artifacts/base.py +2 -1
  2. mlrun/artifacts/plots.py +9 -5
  3. mlrun/common/constants.py +6 -0
  4. mlrun/common/schemas/__init__.py +2 -0
  5. mlrun/common/schemas/model_monitoring/__init__.py +4 -0
  6. mlrun/common/schemas/model_monitoring/constants.py +35 -18
  7. mlrun/common/schemas/project.py +1 -0
  8. mlrun/common/types.py +7 -1
  9. mlrun/config.py +19 -6
  10. mlrun/data_types/data_types.py +4 -0
  11. mlrun/datastore/alibaba_oss.py +130 -0
  12. mlrun/datastore/azure_blob.py +4 -5
  13. mlrun/datastore/base.py +22 -16
  14. mlrun/datastore/datastore.py +4 -0
  15. mlrun/datastore/google_cloud_storage.py +1 -1
  16. mlrun/datastore/sources.py +7 -7
  17. mlrun/db/base.py +14 -6
  18. mlrun/db/factory.py +1 -1
  19. mlrun/db/httpdb.py +61 -56
  20. mlrun/db/nopdb.py +3 -0
  21. mlrun/launcher/__init__.py +1 -1
  22. mlrun/launcher/base.py +1 -1
  23. mlrun/launcher/client.py +1 -1
  24. mlrun/launcher/factory.py +1 -1
  25. mlrun/launcher/local.py +1 -1
  26. mlrun/launcher/remote.py +1 -1
  27. mlrun/model.py +1 -0
  28. mlrun/model_monitoring/__init__.py +1 -1
  29. mlrun/model_monitoring/api.py +104 -301
  30. mlrun/model_monitoring/application.py +21 -21
  31. mlrun/model_monitoring/applications/histogram_data_drift.py +130 -40
  32. mlrun/model_monitoring/controller.py +26 -33
  33. mlrun/model_monitoring/db/__init__.py +16 -0
  34. mlrun/model_monitoring/{stores → db/stores}/__init__.py +43 -34
  35. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  36. mlrun/model_monitoring/{stores/model_endpoint_store.py → db/stores/base/store.py} +47 -6
  37. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  38. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +49 -0
  39. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/base.py +76 -3
  40. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +68 -0
  41. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/sqlite.py +13 -1
  42. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +662 -0
  43. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  44. mlrun/model_monitoring/{stores/kv_model_endpoint_store.py → db/stores/v3io_kv/kv_store.py} +134 -3
  45. mlrun/model_monitoring/features_drift_table.py +34 -22
  46. mlrun/model_monitoring/helpers.py +45 -6
  47. mlrun/model_monitoring/stream_processing.py +43 -9
  48. mlrun/model_monitoring/tracking_policy.py +7 -1
  49. mlrun/model_monitoring/writer.py +4 -36
  50. mlrun/projects/pipelines.py +13 -1
  51. mlrun/projects/project.py +279 -117
  52. mlrun/run.py +72 -74
  53. mlrun/runtimes/__init__.py +35 -0
  54. mlrun/runtimes/base.py +7 -1
  55. mlrun/runtimes/nuclio/api_gateway.py +188 -61
  56. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  57. mlrun/runtimes/nuclio/application/application.py +283 -0
  58. mlrun/runtimes/nuclio/application/reverse_proxy.go +87 -0
  59. mlrun/runtimes/nuclio/function.py +53 -1
  60. mlrun/runtimes/nuclio/serving.py +28 -32
  61. mlrun/runtimes/pod.py +27 -1
  62. mlrun/serving/server.py +4 -6
  63. mlrun/serving/states.py +41 -33
  64. mlrun/utils/helpers.py +34 -0
  65. mlrun/utils/version/version.json +2 -2
  66. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/METADATA +14 -5
  67. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/RECORD +71 -64
  68. mlrun/model_monitoring/batch.py +0 -974
  69. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  70. mlrun/model_monitoring/stores/models/mysql.py +0 -34
  71. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
  72. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/LICENSE +0 -0
  73. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/WHEEL +0 -0
  74. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/entry_points.txt +0 -0
  75. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.0rc7.dist-info}/top_level.txt +0 -0
mlrun/run.py CHANGED
@@ -34,7 +34,6 @@ import mlrun.common.schemas
34
34
  import mlrun.errors
35
35
  import mlrun.utils.helpers
36
36
  from mlrun.kfpops import format_summary_from_kfp_run, show_kfp_run
37
- from mlrun.runtimes.nuclio.serving import serving_subkind
38
37
 
39
38
  from .common.helpers import parse_versioned_object_uri
40
39
  from .config import config as mlconf
@@ -58,6 +57,7 @@ from .runtimes import (
58
57
  )
59
58
  from .runtimes.databricks_job.databricks_runtime import DatabricksRuntime
60
59
  from .runtimes.funcdoc import update_function_entry_points
60
+ from .runtimes.nuclio.application import ApplicationRuntime
61
61
  from .runtimes.utils import add_code_metadata, global_context
62
62
  from .utils import (
63
63
  extend_hub_uri_if_needed,
@@ -425,19 +425,19 @@ def import_function_to_dict(url, secrets=None):
425
425
 
426
426
 
427
427
  def new_function(
428
- name: str = "",
429
- project: str = "",
430
- tag: str = "",
431
- kind: str = "",
432
- command: str = "",
433
- image: str = "",
434
- args: list = None,
435
- runtime=None,
436
- mode=None,
437
- handler: str = None,
438
- source: str = None,
428
+ name: Optional[str] = "",
429
+ project: Optional[str] = "",
430
+ tag: Optional[str] = "",
431
+ kind: Optional[str] = "",
432
+ command: Optional[str] = "",
433
+ image: Optional[str] = "",
434
+ args: Optional[list] = None,
435
+ runtime: Optional[Union[mlrun.runtimes.BaseRuntime, dict]] = None,
436
+ mode: Optional[str] = None,
437
+ handler: Optional[str] = None,
438
+ source: Optional[str] = None,
439
439
  requirements: Union[str, list[str]] = None,
440
- kfp=None,
440
+ kfp: Optional[bool] = None,
441
441
  requirements_file: str = "",
442
442
  ):
443
443
  """Create a new ML function from base properties
@@ -535,9 +535,9 @@ def new_function(
535
535
  if source:
536
536
  runner.spec.build.source = source
537
537
  if handler:
538
- if kind == RuntimeKinds.serving:
538
+ if kind in [RuntimeKinds.serving, RuntimeKinds.application]:
539
539
  raise MLRunInvalidArgumentError(
540
- "cannot set the handler for serving runtime"
540
+ f"Handler is not supported for {kind} runtime"
541
541
  )
542
542
  elif kind in RuntimeKinds.nuclio_runtimes():
543
543
  runner.spec.function_handler = handler
@@ -575,22 +575,22 @@ def _process_runtime(command, runtime, kind):
575
575
 
576
576
 
577
577
  def code_to_function(
578
- name: str = "",
579
- project: str = "",
580
- tag: str = "",
581
- filename: str = "",
582
- handler: str = "",
583
- kind: str = "",
584
- image: str = None,
585
- code_output: str = "",
578
+ name: Optional[str] = "",
579
+ project: Optional[str] = "",
580
+ tag: Optional[str] = "",
581
+ filename: Optional[str] = "",
582
+ handler: Optional[str] = "",
583
+ kind: Optional[str] = "",
584
+ image: Optional[str] = None,
585
+ code_output: Optional[str] = "",
586
586
  embed_code: bool = True,
587
- description: str = "",
588
- requirements: Union[str, list[str]] = None,
589
- categories: list[str] = None,
590
- labels: dict[str, str] = None,
591
- with_doc: bool = True,
592
- ignored_tags=None,
593
- requirements_file: str = "",
587
+ description: Optional[str] = "",
588
+ requirements: Optional[Union[str, list[str]]] = None,
589
+ categories: Optional[list[str]] = None,
590
+ labels: Optional[dict[str, str]] = None,
591
+ with_doc: Optional[bool] = True,
592
+ ignored_tags: Optional[str] = None,
593
+ requirements_file: Optional[str] = "",
594
594
  ) -> Union[
595
595
  MpiRuntimeV1Alpha1,
596
596
  MpiRuntimeV1,
@@ -602,6 +602,7 @@ def code_to_function(
602
602
  Spark3Runtime,
603
603
  RemoteSparkRuntime,
604
604
  DatabricksRuntime,
605
+ ApplicationRuntime,
605
606
  ]:
606
607
  """Convenience function to insert code and configure an mlrun runtime.
607
608
 
@@ -718,35 +719,34 @@ def code_to_function(
718
719
  fn.metadata.categories = categories
719
720
  fn.metadata.labels = labels or fn.metadata.labels
720
721
 
721
- def resolve_nuclio_subkind(kind):
722
- is_nuclio = kind.startswith("nuclio")
723
- subkind = kind[kind.find(":") + 1 :] if is_nuclio and ":" in kind else None
724
- if kind == RuntimeKinds.serving:
725
- is_nuclio = True
726
- subkind = serving_subkind
727
- return is_nuclio, subkind
728
-
729
722
  if (
730
723
  not embed_code
731
724
  and not code_output
732
725
  and (not filename or filename.endswith(".ipynb"))
733
726
  ):
734
727
  raise ValueError(
735
- "a valid code file must be specified "
728
+ "A valid code file must be specified "
736
729
  "when not using the embed_code option"
737
730
  )
738
731
 
739
732
  if kind == RuntimeKinds.databricks and not embed_code:
740
- raise ValueError("databricks tasks only support embed_code=True")
733
+ raise ValueError("Databricks tasks only support embed_code=True")
741
734
 
742
- is_nuclio, subkind = resolve_nuclio_subkind(kind)
735
+ if kind == RuntimeKinds.application:
736
+ if handler:
737
+ raise MLRunInvalidArgumentError(
738
+ "Handler is not supported for application runtime"
739
+ )
740
+ filename, handler = ApplicationRuntime.get_filename_and_handler()
741
+
742
+ is_nuclio, sub_kind = RuntimeKinds.resolve_nuclio_sub_kind(kind)
743
743
  code_origin = add_name(add_code_metadata(filename), name)
744
744
 
745
745
  name, spec, code = nuclio.build_file(
746
746
  filename,
747
747
  name=name,
748
748
  handler=handler or "handler",
749
- kind=subkind,
749
+ kind=sub_kind,
750
750
  ignored_tags=ignored_tags,
751
751
  )
752
752
  spec["spec"]["env"].append(
@@ -759,14 +759,14 @@ def code_to_function(
759
759
  if not kind and spec_kind not in ["", "Function"]:
760
760
  kind = spec_kind.lower()
761
761
 
762
- # if its a nuclio subkind, redo nb parsing
763
- is_nuclio, subkind = resolve_nuclio_subkind(kind)
762
+ # if its a nuclio sub kind, redo nb parsing
763
+ is_nuclio, sub_kind = RuntimeKinds.resolve_nuclio_sub_kind(kind)
764
764
  if is_nuclio:
765
765
  name, spec, code = nuclio.build_file(
766
766
  filename,
767
767
  name=name,
768
768
  handler=handler or "handler",
769
- kind=subkind,
769
+ kind=sub_kind,
770
770
  ignored_tags=ignored_tags,
771
771
  )
772
772
 
@@ -780,33 +780,29 @@ def code_to_function(
780
780
  raise ValueError("code_output option is only used with notebooks")
781
781
 
782
782
  if is_nuclio:
783
- if subkind == serving_subkind:
784
- r = ServingRuntime()
785
- else:
786
- r = RemoteRuntime()
787
- r.spec.function_kind = subkind
788
- # default_handler is only used in :mlrun subkind, determine the handler to invoke in function.run()
789
- r.spec.default_handler = handler if subkind == "mlrun" else ""
790
- r.spec.function_handler = (
783
+ runtime = RuntimeKinds.resolve_nuclio_runtime(kind, sub_kind)
784
+ # default_handler is only used in :mlrun sub kind, determine the handler to invoke in function.run()
785
+ runtime.spec.default_handler = handler if sub_kind == "mlrun" else ""
786
+ runtime.spec.function_handler = (
791
787
  handler if handler and ":" in handler else get_in(spec, "spec.handler")
792
788
  )
793
789
  if not embed_code:
794
- r.spec.source = filename
790
+ runtime.spec.source = filename
795
791
  nuclio_runtime = get_in(spec, "spec.runtime")
796
792
  if nuclio_runtime and not nuclio_runtime.startswith("py"):
797
- r.spec.nuclio_runtime = nuclio_runtime
793
+ runtime.spec.nuclio_runtime = nuclio_runtime
798
794
  if not name:
799
- raise ValueError("name must be specified")
800
- r.metadata.name = name
801
- r.spec.build.code_origin = code_origin
802
- r.spec.build.origin_filename = filename or (name + ".ipynb")
803
- update_common(r, spec)
804
- return r
795
+ raise ValueError("Missing required parameter: name")
796
+ runtime.metadata.name = name
797
+ runtime.spec.build.code_origin = code_origin
798
+ runtime.spec.build.origin_filename = filename or (name + ".ipynb")
799
+ update_common(runtime, spec)
800
+ return runtime
805
801
 
806
802
  if kind is None or kind in ["", "Function"]:
807
803
  raise ValueError("please specify the function kind")
808
804
  elif kind in RuntimeKinds.all():
809
- r = get_runtime_class(kind)()
805
+ runtime = get_runtime_class(kind)()
810
806
  else:
811
807
  raise ValueError(f"unsupported runtime ({kind})")
812
808
 
@@ -815,10 +811,10 @@ def code_to_function(
815
811
  if not name:
816
812
  raise ValueError("name must be specified")
817
813
  h = get_in(spec, "spec.handler", "").split(":")
818
- r.handler = h[0] if len(h) <= 1 else h[1]
819
- r.metadata = get_in(spec, "spec.metadata")
820
- r.metadata.name = name
821
- build = r.spec.build
814
+ runtime.handler = h[0] if len(h) <= 1 else h[1]
815
+ runtime.metadata = get_in(spec, "spec.metadata")
816
+ runtime.metadata.name = name
817
+ build = runtime.spec.build
822
818
  build.code_origin = code_origin
823
819
  build.origin_filename = filename or (name + ".ipynb")
824
820
  build.extra = get_in(spec, "spec.build.extra")
@@ -826,18 +822,18 @@ def code_to_function(
826
822
  build.builder_env = get_in(spec, "spec.build.builder_env")
827
823
  if not embed_code:
828
824
  if code_output:
829
- r.spec.command = code_output
825
+ runtime.spec.command = code_output
830
826
  else:
831
- r.spec.command = filename
827
+ runtime.spec.command = filename
832
828
 
833
829
  build.image = get_in(spec, "spec.build.image")
834
- update_common(r, spec)
835
- r.prepare_image_for_deploy()
830
+ update_common(runtime, spec)
831
+ runtime.prepare_image_for_deploy()
836
832
 
837
833
  if with_doc:
838
- update_function_entry_points(r, code)
839
- r.spec.default_handler = handler
840
- return r
834
+ update_function_entry_points(runtime, code)
835
+ runtime.spec.default_handler = handler
836
+ return runtime
841
837
 
842
838
 
843
839
  def _run_pipeline(
@@ -851,6 +847,7 @@ def _run_pipeline(
851
847
  ops=None,
852
848
  url=None,
853
849
  cleanup_ttl=None,
850
+ timeout=60,
854
851
  ):
855
852
  """remote KubeFlow pipeline execution
856
853
 
@@ -888,6 +885,7 @@ def _run_pipeline(
888
885
  ops=ops,
889
886
  artifact_path=artifact_path,
890
887
  cleanup_ttl=cleanup_ttl,
888
+ timeout=timeout,
891
889
  )
892
890
  logger.info(f"Pipeline run id={pipeline_run_id}, check UI for progress")
893
891
  return pipeline_run_id
@@ -965,7 +963,7 @@ def wait_for_pipeline_completion(
965
963
  show_kfp_run(resp)
966
964
 
967
965
  status = resp["run"]["status"] if resp else "unknown"
968
- message = resp["run"].get("message", "")
966
+ message = resp["run"].get("message", "") if resp else ""
969
967
  if expected_statuses:
970
968
  if status not in expected_statuses:
971
969
  raise RuntimeError(
@@ -43,6 +43,8 @@ from .nuclio import (
43
43
  new_v2_model_server,
44
44
  nuclio_init_hook,
45
45
  )
46
+ from .nuclio.application import ApplicationRuntime
47
+ from .nuclio.serving import serving_subkind
46
48
  from .remotesparkjob import RemoteSparkRuntime
47
49
  from .sparkjob import Spark3Runtime
48
50
 
@@ -101,6 +103,7 @@ class RuntimeKinds:
101
103
  local = "local"
102
104
  handler = "handler"
103
105
  databricks = "databricks"
106
+ application = "application"
104
107
 
105
108
  @staticmethod
106
109
  def all():
@@ -115,6 +118,7 @@ class RuntimeKinds:
115
118
  RuntimeKinds.mpijob,
116
119
  RuntimeKinds.local,
117
120
  RuntimeKinds.databricks,
121
+ RuntimeKinds.application,
118
122
  ]
119
123
 
120
124
  @staticmethod
@@ -147,6 +151,7 @@ class RuntimeKinds:
147
151
  RuntimeKinds.remote,
148
152
  RuntimeKinds.nuclio,
149
153
  RuntimeKinds.serving,
154
+ RuntimeKinds.application,
150
155
  ]
151
156
 
152
157
  @staticmethod
@@ -211,6 +216,35 @@ class RuntimeKinds:
211
216
  # both spark and remote spark uses different mechanism for assigning images
212
217
  return kind not in [RuntimeKinds.spark, RuntimeKinds.remotespark]
213
218
 
219
+ @staticmethod
220
+ def resolve_nuclio_runtime(kind: str, sub_kind: str):
221
+ kind = kind.split(":")[0]
222
+ if kind not in RuntimeKinds.nuclio_runtimes():
223
+ raise ValueError(
224
+ f"Kind {kind} is not a nuclio runtime, available runtimes are {RuntimeKinds.nuclio_runtimes()}"
225
+ )
226
+
227
+ if sub_kind == serving_subkind:
228
+ return ServingRuntime()
229
+
230
+ if kind == RuntimeKinds.application:
231
+ return ApplicationRuntime()
232
+
233
+ runtime = RemoteRuntime()
234
+ runtime.spec.function_kind = sub_kind
235
+ return runtime
236
+
237
+ @staticmethod
238
+ def resolve_nuclio_sub_kind(kind):
239
+ is_nuclio = kind.startswith("nuclio")
240
+ sub_kind = kind[kind.find(":") + 1 :] if is_nuclio and ":" in kind else None
241
+ if kind == RuntimeKinds.serving:
242
+ is_nuclio = True
243
+ sub_kind = serving_subkind
244
+ elif kind == RuntimeKinds.application:
245
+ is_nuclio = True
246
+ return is_nuclio, sub_kind
247
+
214
248
 
215
249
  def get_runtime_class(kind: str):
216
250
  if kind == RuntimeKinds.mpijob:
@@ -228,6 +262,7 @@ def get_runtime_class(kind: str):
228
262
  RuntimeKinds.local: LocalRuntime,
229
263
  RuntimeKinds.remotespark: RemoteSparkRuntime,
230
264
  RuntimeKinds.databricks: DatabricksRuntime,
265
+ RuntimeKinds.application: ApplicationRuntime,
231
266
  }
232
267
 
233
268
  return kind_runtime_map[kind]
mlrun/runtimes/base.py CHANGED
@@ -786,7 +786,7 @@ class BaseRuntime(ModelObj):
786
786
  requirements: Optional[list[str]] = None,
787
787
  overwrite: bool = False,
788
788
  prepare_image_for_deploy: bool = True,
789
- requirements_file: str = "",
789
+ requirements_file: Optional[str] = "",
790
790
  ):
791
791
  """add package requirements from file or list to build spec.
792
792
 
@@ -840,6 +840,12 @@ class BaseRuntime(ModelObj):
840
840
  or (build.source and not build.load_source_on_run)
841
841
  )
842
842
 
843
+ def enrich_runtime_spec(
844
+ self,
845
+ project_node_selector: dict[str, str],
846
+ ):
847
+ pass
848
+
843
849
  def prepare_image_for_deploy(self):
844
850
  """
845
851
  if a function has a 'spec.image' it is considered to be deployed,