mlrun 1.3.3__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +3 -3
- mlrun/__main__.py +79 -37
- mlrun/api/__init__.py +1 -1
- mlrun/api/api/__init__.py +1 -1
- mlrun/api/api/api.py +4 -4
- mlrun/api/api/deps.py +10 -21
- mlrun/api/api/endpoints/__init__.py +1 -1
- mlrun/api/api/endpoints/artifacts.py +64 -36
- mlrun/api/api/endpoints/auth.py +4 -4
- mlrun/api/api/endpoints/background_tasks.py +11 -11
- mlrun/api/api/endpoints/client_spec.py +5 -5
- mlrun/api/api/endpoints/clusterization_spec.py +6 -4
- mlrun/api/api/endpoints/feature_store.py +124 -115
- mlrun/api/api/endpoints/files.py +22 -14
- mlrun/api/api/endpoints/frontend_spec.py +28 -21
- mlrun/api/api/endpoints/functions.py +142 -87
- mlrun/api/api/endpoints/grafana_proxy.py +89 -442
- mlrun/api/api/endpoints/healthz.py +20 -7
- mlrun/api/api/endpoints/hub.py +320 -0
- mlrun/api/api/endpoints/internal/__init__.py +1 -1
- mlrun/api/api/endpoints/internal/config.py +1 -1
- mlrun/api/api/endpoints/internal/memory_reports.py +9 -9
- mlrun/api/api/endpoints/logs.py +11 -11
- mlrun/api/api/endpoints/model_endpoints.py +74 -70
- mlrun/api/api/endpoints/operations.py +13 -9
- mlrun/api/api/endpoints/pipelines.py +93 -88
- mlrun/api/api/endpoints/projects.py +35 -35
- mlrun/api/api/endpoints/runs.py +69 -27
- mlrun/api/api/endpoints/runtime_resources.py +28 -28
- mlrun/api/api/endpoints/schedules.py +98 -41
- mlrun/api/api/endpoints/secrets.py +37 -32
- mlrun/api/api/endpoints/submit.py +12 -12
- mlrun/api/api/endpoints/tags.py +20 -22
- mlrun/api/api/utils.py +251 -42
- mlrun/api/constants.py +1 -1
- mlrun/api/crud/__init__.py +18 -15
- mlrun/api/crud/artifacts.py +10 -10
- mlrun/api/crud/client_spec.py +4 -4
- mlrun/api/crud/clusterization_spec.py +3 -3
- mlrun/api/crud/feature_store.py +54 -46
- mlrun/api/crud/functions.py +3 -3
- mlrun/api/crud/hub.py +312 -0
- mlrun/api/crud/logs.py +11 -9
- mlrun/api/crud/model_monitoring/__init__.py +3 -3
- mlrun/api/crud/model_monitoring/grafana.py +435 -0
- mlrun/api/crud/model_monitoring/model_endpoints.py +352 -129
- mlrun/api/crud/notifications.py +149 -0
- mlrun/api/crud/pipelines.py +67 -52
- mlrun/api/crud/projects.py +51 -23
- mlrun/api/crud/runs.py +7 -5
- mlrun/api/crud/runtime_resources.py +13 -13
- mlrun/api/{db/filedb → crud/runtimes}/__init__.py +1 -1
- mlrun/api/crud/runtimes/nuclio/__init__.py +14 -0
- mlrun/api/crud/runtimes/nuclio/function.py +505 -0
- mlrun/api/crud/runtimes/nuclio/helpers.py +310 -0
- mlrun/api/crud/secrets.py +88 -46
- mlrun/api/crud/tags.py +5 -5
- mlrun/api/db/__init__.py +1 -1
- mlrun/api/db/base.py +102 -54
- mlrun/api/db/init_db.py +2 -3
- mlrun/api/db/session.py +4 -12
- mlrun/api/db/sqldb/__init__.py +1 -1
- mlrun/api/db/sqldb/db.py +439 -196
- mlrun/api/db/sqldb/helpers.py +1 -1
- mlrun/api/db/sqldb/models/__init__.py +3 -3
- mlrun/api/db/sqldb/models/models_mysql.py +82 -64
- mlrun/api/db/sqldb/models/models_sqlite.py +76 -64
- mlrun/api/db/sqldb/session.py +27 -20
- mlrun/api/initial_data.py +82 -24
- mlrun/api/launcher.py +196 -0
- mlrun/api/main.py +91 -22
- mlrun/api/middlewares.py +6 -5
- mlrun/api/migrations_mysql/env.py +1 -1
- mlrun/api/migrations_mysql/versions/28383af526f3_market_place_to_hub.py +40 -0
- mlrun/api/migrations_mysql/versions/32bae1b0e29c_increase_timestamp_fields_precision.py +1 -1
- mlrun/api/migrations_mysql/versions/4903aef6a91d_tag_foreign_key_and_cascades.py +1 -1
- mlrun/api/migrations_mysql/versions/5f1351c88a19_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_mysql/versions/88e656800d6a_add_requested_logs_column_and_index_to_.py +1 -1
- mlrun/api/migrations_mysql/versions/9d16de5f03a7_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_mysql/versions/b86f5b53f3d7_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_mysql/versions/c4af40b0bf61_init.py +1 -1
- mlrun/api/migrations_mysql/versions/c905d15bd91d_notifications.py +72 -0
- mlrun/api/migrations_mysql/versions/ee041e8fdaa0_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/env.py +1 -1
- mlrun/api/migrations_sqlite/versions/11f8dd2dc9fe_init.py +1 -1
- mlrun/api/migrations_sqlite/versions/1c954f8cb32d_schedule_last_run_uri.py +1 -1
- mlrun/api/migrations_sqlite/versions/2b6d23c715aa_adding_feature_sets.py +1 -1
- mlrun/api/migrations_sqlite/versions/4acd9430b093_market_place_to_hub.py +77 -0
- mlrun/api/migrations_sqlite/versions/6401142f2d7c_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/versions/64d90a1a69bc_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/803438ecd005_add_requested_logs_column_to_runs.py +1 -1
- mlrun/api/migrations_sqlite/versions/863114f0c659_refactoring_feature_set.py +1 -1
- mlrun/api/migrations_sqlite/versions/959ae00528ad_notifications.py +63 -0
- mlrun/api/migrations_sqlite/versions/accf9fc83d38_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/b68e8e897a28_schedule_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/bcd0c1f9720c_adding_project_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/cf21882f938e_schedule_id.py +1 -1
- mlrun/api/migrations_sqlite/versions/d781f58f607f_tag_object_name_string.py +1 -1
- mlrun/api/migrations_sqlite/versions/deac06871ace_adding_marketplace_sources_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/e1dd5983c06b_schedule_concurrency_limit.py +1 -1
- mlrun/api/migrations_sqlite/versions/e5594ed3ab53_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/f4249b4ba6fa_adding_feature_vectors.py +1 -1
- mlrun/api/migrations_sqlite/versions/f7b5a1a03629_adding_feature_labels.py +1 -1
- mlrun/api/schemas/__init__.py +216 -138
- mlrun/api/utils/__init__.py +1 -1
- mlrun/api/utils/asyncio.py +1 -1
- mlrun/api/utils/auth/__init__.py +1 -1
- mlrun/api/utils/auth/providers/__init__.py +1 -1
- mlrun/api/utils/auth/providers/base.py +7 -7
- mlrun/api/utils/auth/providers/nop.py +6 -7
- mlrun/api/utils/auth/providers/opa.py +17 -17
- mlrun/api/utils/auth/verifier.py +36 -34
- mlrun/api/utils/background_tasks.py +24 -24
- mlrun/{builder.py → api/utils/builder.py} +216 -123
- mlrun/api/utils/clients/__init__.py +1 -1
- mlrun/api/utils/clients/chief.py +19 -4
- mlrun/api/utils/clients/iguazio.py +106 -60
- mlrun/api/utils/clients/log_collector.py +1 -1
- mlrun/api/utils/clients/nuclio.py +23 -23
- mlrun/api/utils/clients/protocols/grpc.py +2 -2
- mlrun/api/utils/db/__init__.py +1 -1
- mlrun/api/utils/db/alembic.py +1 -1
- mlrun/api/utils/db/backup.py +1 -1
- mlrun/api/utils/db/mysql.py +24 -25
- mlrun/api/utils/db/sql_collation.py +1 -1
- mlrun/api/utils/db/sqlite_migration.py +2 -2
- mlrun/api/utils/events/__init__.py +14 -0
- mlrun/api/utils/events/base.py +57 -0
- mlrun/api/utils/events/events_factory.py +41 -0
- mlrun/api/utils/events/iguazio.py +217 -0
- mlrun/api/utils/events/nop.py +55 -0
- mlrun/api/utils/helpers.py +16 -13
- mlrun/api/utils/memory_reports.py +1 -1
- mlrun/api/utils/periodic.py +6 -3
- mlrun/api/utils/projects/__init__.py +1 -1
- mlrun/api/utils/projects/follower.py +33 -33
- mlrun/api/utils/projects/leader.py +36 -34
- mlrun/api/utils/projects/member.py +27 -27
- mlrun/api/utils/projects/remotes/__init__.py +1 -1
- mlrun/api/utils/projects/remotes/follower.py +13 -13
- mlrun/api/utils/projects/remotes/leader.py +10 -10
- mlrun/api/utils/projects/remotes/nop_follower.py +27 -21
- mlrun/api/utils/projects/remotes/nop_leader.py +17 -16
- mlrun/api/utils/scheduler.py +140 -51
- mlrun/api/utils/singletons/__init__.py +1 -1
- mlrun/api/utils/singletons/db.py +9 -15
- mlrun/api/utils/singletons/k8s.py +677 -5
- mlrun/api/utils/singletons/logs_dir.py +1 -1
- mlrun/api/utils/singletons/project_member.py +1 -1
- mlrun/api/utils/singletons/scheduler.py +1 -1
- mlrun/artifacts/__init__.py +2 -2
- mlrun/artifacts/base.py +8 -2
- mlrun/artifacts/dataset.py +5 -3
- mlrun/artifacts/manager.py +7 -1
- mlrun/artifacts/model.py +15 -4
- mlrun/artifacts/plots.py +1 -1
- mlrun/common/__init__.py +1 -1
- mlrun/common/constants.py +15 -0
- mlrun/common/model_monitoring.py +209 -0
- mlrun/common/schemas/__init__.py +167 -0
- mlrun/{api → common}/schemas/artifact.py +13 -14
- mlrun/{api → common}/schemas/auth.py +10 -8
- mlrun/{api → common}/schemas/background_task.py +3 -3
- mlrun/{api → common}/schemas/client_spec.py +1 -1
- mlrun/{api → common}/schemas/clusterization_spec.py +3 -3
- mlrun/{api → common}/schemas/constants.py +21 -8
- mlrun/common/schemas/events.py +36 -0
- mlrun/{api → common}/schemas/feature_store.py +2 -1
- mlrun/{api → common}/schemas/frontend_spec.py +7 -6
- mlrun/{api → common}/schemas/function.py +5 -5
- mlrun/{api → common}/schemas/http.py +3 -3
- mlrun/common/schemas/hub.py +134 -0
- mlrun/{api → common}/schemas/k8s.py +3 -3
- mlrun/{api → common}/schemas/memory_reports.py +1 -1
- mlrun/common/schemas/model_endpoints.py +342 -0
- mlrun/common/schemas/notification.py +57 -0
- mlrun/{api → common}/schemas/object.py +6 -6
- mlrun/{api → common}/schemas/pipeline.py +3 -3
- mlrun/{api → common}/schemas/project.py +6 -5
- mlrun/common/schemas/regex.py +24 -0
- mlrun/common/schemas/runs.py +30 -0
- mlrun/{api → common}/schemas/runtime_resource.py +3 -3
- mlrun/{api → common}/schemas/schedule.py +19 -7
- mlrun/{api → common}/schemas/secret.py +3 -3
- mlrun/{api → common}/schemas/tag.py +2 -2
- mlrun/common/types.py +25 -0
- mlrun/config.py +152 -20
- mlrun/data_types/__init__.py +7 -2
- mlrun/data_types/data_types.py +4 -2
- mlrun/data_types/infer.py +1 -1
- mlrun/data_types/spark.py +10 -3
- mlrun/datastore/__init__.py +10 -3
- mlrun/datastore/azure_blob.py +1 -1
- mlrun/datastore/base.py +185 -53
- mlrun/datastore/datastore.py +1 -1
- mlrun/datastore/filestore.py +1 -1
- mlrun/datastore/google_cloud_storage.py +1 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +1 -1
- mlrun/datastore/s3.py +1 -1
- mlrun/datastore/sources.py +192 -70
- mlrun/datastore/spark_udf.py +44 -0
- mlrun/datastore/store_resources.py +4 -4
- mlrun/datastore/targets.py +115 -45
- mlrun/datastore/utils.py +127 -5
- mlrun/datastore/v3io.py +1 -1
- mlrun/datastore/wasbfs/__init__.py +1 -1
- mlrun/datastore/wasbfs/fs.py +1 -1
- mlrun/db/__init__.py +7 -5
- mlrun/db/base.py +112 -68
- mlrun/db/httpdb.py +445 -277
- mlrun/db/nopdb.py +491 -0
- mlrun/db/sqldb.py +112 -65
- mlrun/errors.py +6 -1
- mlrun/execution.py +44 -22
- mlrun/feature_store/__init__.py +1 -1
- mlrun/feature_store/api.py +143 -95
- mlrun/feature_store/common.py +16 -20
- mlrun/feature_store/feature_set.py +42 -12
- mlrun/feature_store/feature_vector.py +32 -21
- mlrun/feature_store/ingestion.py +9 -12
- mlrun/feature_store/retrieval/__init__.py +3 -2
- mlrun/feature_store/retrieval/base.py +388 -66
- mlrun/feature_store/retrieval/dask_merger.py +63 -151
- mlrun/feature_store/retrieval/job.py +30 -12
- mlrun/feature_store/retrieval/local_merger.py +40 -133
- mlrun/feature_store/retrieval/spark_merger.py +129 -127
- mlrun/feature_store/retrieval/storey_merger.py +173 -0
- mlrun/feature_store/steps.py +132 -15
- mlrun/features.py +8 -3
- mlrun/frameworks/__init__.py +1 -1
- mlrun/frameworks/_common/__init__.py +1 -1
- mlrun/frameworks/_common/artifacts_library.py +1 -1
- mlrun/frameworks/_common/mlrun_interface.py +1 -1
- mlrun/frameworks/_common/model_handler.py +1 -1
- mlrun/frameworks/_common/plan.py +1 -1
- mlrun/frameworks/_common/producer.py +1 -1
- mlrun/frameworks/_common/utils.py +1 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +1 -1
- mlrun/frameworks/_dl_common/model_handler.py +1 -1
- mlrun/frameworks/_dl_common/utils.py +1 -1
- mlrun/frameworks/_ml_common/__init__.py +1 -1
- mlrun/frameworks/_ml_common/artifacts_library.py +1 -1
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_ml_common/loggers/logger.py +1 -1
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_ml_common/model_handler.py +1 -1
- mlrun/frameworks/_ml_common/pkl_model_server.py +13 -1
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -1
- mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +1 -6
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +1 -1
- mlrun/frameworks/_ml_common/producer.py +1 -1
- mlrun/frameworks/_ml_common/utils.py +1 -1
- mlrun/frameworks/auto_mlrun/__init__.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +1 -1
- mlrun/frameworks/huggingface/__init__.py +1 -1
- mlrun/frameworks/huggingface/model_server.py +1 -1
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/model_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/lgbm/model_server.py +1 -1
- mlrun/frameworks/lgbm/utils.py +1 -1
- mlrun/frameworks/onnx/__init__.py +1 -1
- mlrun/frameworks/onnx/dataset.py +1 -1
- mlrun/frameworks/onnx/mlrun_interface.py +1 -1
- mlrun/frameworks/onnx/model_handler.py +1 -1
- mlrun/frameworks/onnx/model_server.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +1 -1
- mlrun/frameworks/pytorch/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks_handler.py +1 -1
- mlrun/frameworks/pytorch/mlrun_interface.py +1 -1
- mlrun/frameworks/pytorch/model_handler.py +1 -1
- mlrun/frameworks/pytorch/model_server.py +1 -1
- mlrun/frameworks/pytorch/utils.py +1 -1
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/estimator.py +1 -1
- mlrun/frameworks/sklearn/metric.py +1 -1
- mlrun/frameworks/sklearn/metrics_library.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +1 -1
- mlrun/frameworks/sklearn/model_handler.py +1 -1
- mlrun/frameworks/sklearn/utils.py +1 -1
- mlrun/frameworks/tf_keras/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +1 -1
- mlrun/frameworks/tf_keras/model_handler.py +1 -1
- mlrun/frameworks/tf_keras/model_server.py +1 -1
- mlrun/frameworks/tf_keras/utils.py +1 -1
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/frameworks/xgboost/mlrun_interface.py +1 -1
- mlrun/frameworks/xgboost/model_handler.py +1 -1
- mlrun/frameworks/xgboost/utils.py +1 -1
- mlrun/k8s_utils.py +14 -765
- mlrun/kfpops.py +14 -17
- mlrun/launcher/__init__.py +13 -0
- mlrun/launcher/base.py +406 -0
- mlrun/launcher/client.py +159 -0
- mlrun/launcher/factory.py +50 -0
- mlrun/launcher/local.py +276 -0
- mlrun/launcher/remote.py +178 -0
- mlrun/lists.py +10 -2
- mlrun/mlutils/__init__.py +1 -1
- mlrun/mlutils/data.py +1 -1
- mlrun/mlutils/models.py +1 -1
- mlrun/mlutils/plots.py +1 -1
- mlrun/model.py +252 -14
- mlrun/model_monitoring/__init__.py +41 -0
- mlrun/model_monitoring/features_drift_table.py +1 -1
- mlrun/model_monitoring/helpers.py +123 -38
- mlrun/model_monitoring/model_endpoint.py +144 -0
- mlrun/model_monitoring/model_monitoring_batch.py +310 -259
- mlrun/model_monitoring/stores/__init__.py +106 -0
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +448 -0
- mlrun/model_monitoring/stores/model_endpoint_store.py +147 -0
- mlrun/model_monitoring/stores/models/__init__.py +23 -0
- mlrun/model_monitoring/stores/models/base.py +18 -0
- mlrun/model_monitoring/stores/models/mysql.py +100 -0
- mlrun/model_monitoring/stores/models/sqlite.py +98 -0
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +370 -0
- mlrun/model_monitoring/stream_processing_fs.py +239 -271
- mlrun/package/__init__.py +163 -0
- mlrun/package/context_handler.py +325 -0
- mlrun/package/errors.py +47 -0
- mlrun/package/packager.py +298 -0
- mlrun/{runtimes/package → package/packagers}/__init__.py +3 -1
- mlrun/package/packagers/default_packager.py +422 -0
- mlrun/package/packagers/numpy_packagers.py +612 -0
- mlrun/package/packagers/pandas_packagers.py +968 -0
- mlrun/package/packagers/python_standard_library_packagers.py +616 -0
- mlrun/package/packagers_manager.py +786 -0
- mlrun/package/utils/__init__.py +53 -0
- mlrun/package/utils/_archiver.py +226 -0
- mlrun/package/utils/_formatter.py +211 -0
- mlrun/package/utils/_pickler.py +234 -0
- mlrun/package/utils/_supported_format.py +71 -0
- mlrun/package/utils/log_hint_utils.py +93 -0
- mlrun/package/utils/type_hint_utils.py +298 -0
- mlrun/platforms/__init__.py +1 -1
- mlrun/platforms/iguazio.py +34 -2
- mlrun/platforms/other.py +1 -1
- mlrun/projects/__init__.py +1 -1
- mlrun/projects/operations.py +14 -9
- mlrun/projects/pipelines.py +31 -13
- mlrun/projects/project.py +762 -238
- mlrun/render.py +49 -19
- mlrun/run.py +57 -326
- mlrun/runtimes/__init__.py +3 -9
- mlrun/runtimes/base.py +247 -784
- mlrun/runtimes/constants.py +1 -1
- mlrun/runtimes/daskjob.py +45 -41
- mlrun/runtimes/funcdoc.py +43 -7
- mlrun/runtimes/function.py +66 -656
- mlrun/runtimes/function_reference.py +1 -1
- mlrun/runtimes/generators.py +1 -1
- mlrun/runtimes/kubejob.py +99 -116
- mlrun/runtimes/local.py +59 -66
- mlrun/runtimes/mpijob/__init__.py +1 -1
- mlrun/runtimes/mpijob/abstract.py +13 -15
- mlrun/runtimes/mpijob/v1.py +3 -1
- mlrun/runtimes/mpijob/v1alpha1.py +1 -1
- mlrun/runtimes/nuclio.py +1 -1
- mlrun/runtimes/pod.py +51 -26
- mlrun/runtimes/remotesparkjob.py +3 -1
- mlrun/runtimes/serving.py +12 -4
- mlrun/runtimes/sparkjob/__init__.py +1 -2
- mlrun/runtimes/sparkjob/abstract.py +44 -31
- mlrun/runtimes/sparkjob/spark3job.py +11 -9
- mlrun/runtimes/utils.py +61 -42
- mlrun/secrets.py +16 -18
- mlrun/serving/__init__.py +3 -2
- mlrun/serving/merger.py +1 -1
- mlrun/serving/remote.py +1 -1
- mlrun/serving/routers.py +39 -42
- mlrun/serving/server.py +23 -13
- mlrun/serving/serving_wrapper.py +1 -1
- mlrun/serving/states.py +172 -39
- mlrun/serving/utils.py +1 -1
- mlrun/serving/v1_serving.py +1 -1
- mlrun/serving/v2_serving.py +29 -21
- mlrun/utils/__init__.py +1 -2
- mlrun/utils/async_http.py +8 -1
- mlrun/utils/azure_vault.py +1 -1
- mlrun/utils/clones.py +2 -2
- mlrun/utils/condition_evaluator.py +65 -0
- mlrun/utils/db.py +52 -0
- mlrun/utils/helpers.py +188 -13
- mlrun/utils/http.py +89 -54
- mlrun/utils/logger.py +48 -8
- mlrun/utils/model_monitoring.py +132 -100
- mlrun/utils/notifications/__init__.py +1 -1
- mlrun/utils/notifications/notification/__init__.py +8 -6
- mlrun/utils/notifications/notification/base.py +20 -14
- mlrun/utils/notifications/notification/console.py +7 -4
- mlrun/utils/notifications/notification/git.py +36 -19
- mlrun/utils/notifications/notification/ipython.py +10 -8
- mlrun/utils/notifications/notification/slack.py +18 -13
- mlrun/utils/notifications/notification_pusher.py +377 -56
- mlrun/utils/regex.py +6 -1
- mlrun/utils/singleton.py +1 -1
- mlrun/utils/v3io_clients.py +1 -1
- mlrun/utils/vault.py +270 -269
- mlrun/utils/version/__init__.py +1 -1
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +1 -1
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/METADATA +16 -10
- mlrun-1.4.0.dist-info/RECORD +434 -0
- mlrun/api/api/endpoints/marketplace.py +0 -257
- mlrun/api/crud/marketplace.py +0 -221
- mlrun/api/crud/model_monitoring/model_endpoint_store.py +0 -847
- mlrun/api/db/filedb/db.py +0 -518
- mlrun/api/schemas/marketplace.py +0 -128
- mlrun/api/schemas/model_endpoints.py +0 -185
- mlrun/db/filedb.py +0 -891
- mlrun/feature_store/retrieval/online.py +0 -92
- mlrun/model_monitoring/constants.py +0 -67
- mlrun/runtimes/package/context_handler.py +0 -711
- mlrun/runtimes/sparkjob/spark2job.py +0 -59
- mlrun-1.3.3.dist-info/RECORD +0 -381
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
mlrun/model.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 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,13 +16,18 @@ import inspect
|
|
|
16
16
|
import pathlib
|
|
17
17
|
import re
|
|
18
18
|
import time
|
|
19
|
+
import typing
|
|
20
|
+
import warnings
|
|
19
21
|
from collections import OrderedDict
|
|
20
22
|
from copy import deepcopy
|
|
21
23
|
from datetime import datetime
|
|
22
24
|
from os import environ
|
|
23
25
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
24
26
|
|
|
27
|
+
import pydantic.error_wrappers
|
|
28
|
+
|
|
25
29
|
import mlrun
|
|
30
|
+
import mlrun.common.schemas.notification
|
|
26
31
|
|
|
27
32
|
from .utils import (
|
|
28
33
|
dict_to_json,
|
|
@@ -57,7 +62,11 @@ class ModelObj:
|
|
|
57
62
|
return param
|
|
58
63
|
|
|
59
64
|
def to_dict(self, fields=None, exclude=None):
|
|
60
|
-
"""convert the object to a python dictionary
|
|
65
|
+
"""convert the object to a python dictionary
|
|
66
|
+
|
|
67
|
+
:param fields: list of fields to include in the dict
|
|
68
|
+
:param exclude: list of fields to exclude from the dict
|
|
69
|
+
"""
|
|
61
70
|
struct = {}
|
|
62
71
|
fields = fields or self._dict_fields
|
|
63
72
|
if not fields:
|
|
@@ -100,13 +109,19 @@ class ModelObj:
|
|
|
100
109
|
|
|
101
110
|
return new_obj
|
|
102
111
|
|
|
103
|
-
def to_yaml(self) -> str:
|
|
104
|
-
"""convert the object to yaml
|
|
105
|
-
return dict_to_yaml(self.to_dict())
|
|
112
|
+
def to_yaml(self, exclude=None) -> str:
|
|
113
|
+
"""convert the object to yaml
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
"""
|
|
109
|
-
return
|
|
115
|
+
:param exclude: list of fields to exclude from the yaml
|
|
116
|
+
"""
|
|
117
|
+
return dict_to_yaml(self.to_dict(exclude=exclude))
|
|
118
|
+
|
|
119
|
+
def to_json(self, exclude=None):
|
|
120
|
+
"""convert the object to json
|
|
121
|
+
|
|
122
|
+
:param exclude: list of fields to exclude from the json
|
|
123
|
+
"""
|
|
124
|
+
return dict_to_json(self.to_dict(exclude=exclude))
|
|
110
125
|
|
|
111
126
|
def to_str(self):
|
|
112
127
|
"""convert the object to string (with dict layout)"""
|
|
@@ -338,6 +353,7 @@ class ImageBuilder(ModelObj):
|
|
|
338
353
|
origin_filename=None,
|
|
339
354
|
with_mlrun=None,
|
|
340
355
|
auto_build=None,
|
|
356
|
+
requirements: list = None,
|
|
341
357
|
):
|
|
342
358
|
self.functionSourceCode = functionSourceCode #: functionSourceCode
|
|
343
359
|
self.codeEntryType = "" #: codeEntryType
|
|
@@ -355,6 +371,7 @@ class ImageBuilder(ModelObj):
|
|
|
355
371
|
self.with_mlrun = with_mlrun #: with_mlrun
|
|
356
372
|
self.auto_build = auto_build #: auto_build
|
|
357
373
|
self.build_pod = None
|
|
374
|
+
self.requirements = requirements or [] #: pip requirements
|
|
358
375
|
|
|
359
376
|
@property
|
|
360
377
|
def source(self):
|
|
@@ -369,12 +386,200 @@ class ImageBuilder(ModelObj):
|
|
|
369
386
|
or source in [".", "./"]
|
|
370
387
|
):
|
|
371
388
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
372
|
-
"source must be a compressed (tar.gz / zip) file, a git repo, "
|
|
373
|
-
"a file path or in the project's context (.)"
|
|
389
|
+
f"source ({source}) must be a compressed (tar.gz / zip) file, a git repo, "
|
|
390
|
+
f"a file path or in the project's context (.)"
|
|
374
391
|
)
|
|
375
392
|
|
|
376
393
|
self._source = source
|
|
377
394
|
|
|
395
|
+
def build_config(
|
|
396
|
+
self,
|
|
397
|
+
image="",
|
|
398
|
+
base_image=None,
|
|
399
|
+
commands: list = None,
|
|
400
|
+
secret=None,
|
|
401
|
+
source=None,
|
|
402
|
+
extra=None,
|
|
403
|
+
load_source_on_run=None,
|
|
404
|
+
with_mlrun=None,
|
|
405
|
+
auto_build=None,
|
|
406
|
+
requirements=None,
|
|
407
|
+
requirements_file=None,
|
|
408
|
+
overwrite=False,
|
|
409
|
+
):
|
|
410
|
+
if image:
|
|
411
|
+
self.image = image
|
|
412
|
+
if base_image:
|
|
413
|
+
self.base_image = base_image
|
|
414
|
+
if commands:
|
|
415
|
+
self.with_commands(commands, overwrite=overwrite)
|
|
416
|
+
if requirements:
|
|
417
|
+
self.with_requirements(requirements, requirements_file, overwrite=overwrite)
|
|
418
|
+
if extra:
|
|
419
|
+
self.extra = extra
|
|
420
|
+
if secret is not None:
|
|
421
|
+
self.secret = secret
|
|
422
|
+
if source:
|
|
423
|
+
self.source = source
|
|
424
|
+
if load_source_on_run:
|
|
425
|
+
self.load_source_on_run = load_source_on_run
|
|
426
|
+
if with_mlrun is not None:
|
|
427
|
+
self.with_mlrun = with_mlrun
|
|
428
|
+
if auto_build:
|
|
429
|
+
self.auto_build = auto_build
|
|
430
|
+
|
|
431
|
+
def with_commands(
|
|
432
|
+
self,
|
|
433
|
+
commands: List[str],
|
|
434
|
+
overwrite: bool = False,
|
|
435
|
+
):
|
|
436
|
+
"""add commands to build spec.
|
|
437
|
+
|
|
438
|
+
:param commands: list of commands to run during build
|
|
439
|
+
:param overwrite: whether to overwrite the existing commands or add to them (the default)
|
|
440
|
+
|
|
441
|
+
:return: function object
|
|
442
|
+
"""
|
|
443
|
+
if not isinstance(commands, list) or not all(
|
|
444
|
+
isinstance(item, str) for item in commands
|
|
445
|
+
):
|
|
446
|
+
raise ValueError("commands must be a string list")
|
|
447
|
+
if not self.commands or overwrite:
|
|
448
|
+
self.commands = commands
|
|
449
|
+
else:
|
|
450
|
+
# add commands to existing build commands
|
|
451
|
+
for command in commands:
|
|
452
|
+
if command not in self.commands:
|
|
453
|
+
self.commands.append(command)
|
|
454
|
+
# using list(set(x)) won't retain order,
|
|
455
|
+
# solution inspired from https://stackoverflow.com/a/17016257/8116661
|
|
456
|
+
self.commands = list(dict.fromkeys(self.commands))
|
|
457
|
+
|
|
458
|
+
def with_requirements(
|
|
459
|
+
self,
|
|
460
|
+
requirements: Union[str, List[str]],
|
|
461
|
+
requirements_file: str = "",
|
|
462
|
+
overwrite: bool = False,
|
|
463
|
+
):
|
|
464
|
+
"""add package requirements from file or list to build spec.
|
|
465
|
+
|
|
466
|
+
:param requirements: a list of python packages
|
|
467
|
+
:param requirements_file: path to a python requirements file
|
|
468
|
+
:param overwrite: overwrite existing requirements,
|
|
469
|
+
when False (default) will append to existing requirements
|
|
470
|
+
:return: function object
|
|
471
|
+
"""
|
|
472
|
+
if isinstance(requirements, str) and mlrun.utils.is_file_path(requirements):
|
|
473
|
+
# TODO: remove in 1.6.0
|
|
474
|
+
warnings.warn(
|
|
475
|
+
"Passing a requirements file path as a string in the 'requirements' argument is deprecated "
|
|
476
|
+
"and will be removed in 1.6.0, use 'requirements_file' instead",
|
|
477
|
+
FutureWarning,
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
resolved_requirements = self._resolve_requirements(
|
|
481
|
+
requirements, requirements_file
|
|
482
|
+
)
|
|
483
|
+
requirements = self.requirements or [] if not overwrite else []
|
|
484
|
+
|
|
485
|
+
# make sure we don't append the same line twice
|
|
486
|
+
for requirement in resolved_requirements:
|
|
487
|
+
if requirement not in requirements:
|
|
488
|
+
requirements.append(requirement)
|
|
489
|
+
|
|
490
|
+
self.requirements = requirements
|
|
491
|
+
|
|
492
|
+
@staticmethod
|
|
493
|
+
def _resolve_requirements(
|
|
494
|
+
requirements: typing.Union[str, list], requirements_file: str = ""
|
|
495
|
+
) -> list:
|
|
496
|
+
requirements_to_resolve = []
|
|
497
|
+
|
|
498
|
+
# handle the requirements_file argument
|
|
499
|
+
if requirements_file:
|
|
500
|
+
with open(requirements_file, "r") as fp:
|
|
501
|
+
requirements_to_resolve.extend(fp.read().splitlines())
|
|
502
|
+
|
|
503
|
+
# handle the requirements argument
|
|
504
|
+
# TODO: remove in 1.6.0, when requirements can only be a list
|
|
505
|
+
if isinstance(requirements, str):
|
|
506
|
+
# if it's a file path, read the file and add its content to the list
|
|
507
|
+
if mlrun.utils.is_file_path(requirements):
|
|
508
|
+
with open(requirements, "r") as fp:
|
|
509
|
+
requirements_to_resolve.extend(fp.read().splitlines())
|
|
510
|
+
else:
|
|
511
|
+
# it's a string but not a file path, split it by lines and add it to the list
|
|
512
|
+
requirements_to_resolve.append(requirements)
|
|
513
|
+
else:
|
|
514
|
+
# it's a list, add it to the list
|
|
515
|
+
requirements_to_resolve.extend(requirements)
|
|
516
|
+
|
|
517
|
+
requirements = []
|
|
518
|
+
for requirement in requirements_to_resolve:
|
|
519
|
+
# clean redundant leading and trailing whitespaces
|
|
520
|
+
requirement = requirement.strip()
|
|
521
|
+
|
|
522
|
+
# ignore empty lines
|
|
523
|
+
# ignore comments
|
|
524
|
+
if not requirement or requirement.startswith("#"):
|
|
525
|
+
continue
|
|
526
|
+
|
|
527
|
+
# ignore inline comments as well
|
|
528
|
+
inline_comment = requirement.split(" #")
|
|
529
|
+
if len(inline_comment) > 1:
|
|
530
|
+
requirement = inline_comment[0].strip()
|
|
531
|
+
|
|
532
|
+
requirements.append(requirement)
|
|
533
|
+
|
|
534
|
+
return requirements
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
class Notification(ModelObj):
|
|
538
|
+
"""Notification specification"""
|
|
539
|
+
|
|
540
|
+
def __init__(
|
|
541
|
+
self,
|
|
542
|
+
kind=None,
|
|
543
|
+
name=None,
|
|
544
|
+
message=None,
|
|
545
|
+
severity=None,
|
|
546
|
+
when=None,
|
|
547
|
+
condition=None,
|
|
548
|
+
params=None,
|
|
549
|
+
status=None,
|
|
550
|
+
sent_time=None,
|
|
551
|
+
):
|
|
552
|
+
self.kind = kind or mlrun.common.schemas.notification.NotificationKind.slack
|
|
553
|
+
self.name = name or ""
|
|
554
|
+
self.message = message or ""
|
|
555
|
+
self.severity = (
|
|
556
|
+
severity or mlrun.common.schemas.notification.NotificationSeverity.INFO
|
|
557
|
+
)
|
|
558
|
+
self.when = when or ["completed"]
|
|
559
|
+
self.condition = condition or ""
|
|
560
|
+
self.params = params or {}
|
|
561
|
+
self.status = status
|
|
562
|
+
self.sent_time = sent_time
|
|
563
|
+
|
|
564
|
+
self.validate_notification()
|
|
565
|
+
|
|
566
|
+
def validate_notification(self):
|
|
567
|
+
try:
|
|
568
|
+
mlrun.common.schemas.notification.Notification(**self.to_dict())
|
|
569
|
+
except pydantic.error_wrappers.ValidationError as exc:
|
|
570
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
571
|
+
"Invalid notification object"
|
|
572
|
+
) from exc
|
|
573
|
+
|
|
574
|
+
@staticmethod
|
|
575
|
+
def validate_notification_uniqueness(notifications: List["Notification"]):
|
|
576
|
+
"""Validate that all notifications in the list are unique by name"""
|
|
577
|
+
names = [notification.name for notification in notifications]
|
|
578
|
+
if len(names) != len(set(names)):
|
|
579
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
580
|
+
"Notification names must be unique"
|
|
581
|
+
)
|
|
582
|
+
|
|
378
583
|
|
|
379
584
|
class RunMetadata(ModelObj):
|
|
380
585
|
"""Run metadata"""
|
|
@@ -492,6 +697,7 @@ class RunSpec(ModelObj):
|
|
|
492
697
|
allow_empty_resources=None,
|
|
493
698
|
inputs_type_hints=None,
|
|
494
699
|
returns=None,
|
|
700
|
+
notifications=None,
|
|
495
701
|
):
|
|
496
702
|
# A dictionary of parsing configurations that will be read from the inputs the user set. The keys are the inputs
|
|
497
703
|
# keys (parameter names) and the values are the type hint given in the input keys after the colon.
|
|
@@ -526,6 +732,7 @@ class RunSpec(ModelObj):
|
|
|
526
732
|
self.verbose = verbose
|
|
527
733
|
self.scrape_metrics = scrape_metrics
|
|
528
734
|
self.allow_empty_resources = allow_empty_resources
|
|
735
|
+
self._notifications = notifications or []
|
|
529
736
|
|
|
530
737
|
def to_dict(self, fields=None, exclude=None):
|
|
531
738
|
struct = super().to_dict(fields, exclude=["handler"])
|
|
@@ -608,6 +815,9 @@ class RunSpec(ModelObj):
|
|
|
608
815
|
|
|
609
816
|
:raise MLRunInvalidArgumentError: In case one of the values in the list is invalid.
|
|
610
817
|
"""
|
|
818
|
+
# This import is located in the method due to circular imports error.
|
|
819
|
+
from mlrun.package.utils import LogHintUtils
|
|
820
|
+
|
|
611
821
|
if returns is None:
|
|
612
822
|
self._returns = None
|
|
613
823
|
return
|
|
@@ -615,7 +825,7 @@ class RunSpec(ModelObj):
|
|
|
615
825
|
|
|
616
826
|
# Validate:
|
|
617
827
|
for log_hint in returns:
|
|
618
|
-
|
|
828
|
+
LogHintUtils.parse_log_hint(log_hint=log_hint)
|
|
619
829
|
|
|
620
830
|
# Store the results:
|
|
621
831
|
self._returns = returns
|
|
@@ -678,9 +888,22 @@ class RunSpec(ModelObj):
|
|
|
678
888
|
return str(self.handler)
|
|
679
889
|
return ""
|
|
680
890
|
|
|
891
|
+
@property
|
|
892
|
+
def notifications(self):
|
|
893
|
+
return self._notifications
|
|
894
|
+
|
|
895
|
+
@notifications.setter
|
|
896
|
+
def notifications(self, notifications):
|
|
897
|
+
if isinstance(notifications, list):
|
|
898
|
+
self._notifications = ObjectList.from_list(Notification, notifications)
|
|
899
|
+
elif isinstance(notifications, ObjectList):
|
|
900
|
+
self._notifications = notifications
|
|
901
|
+
else:
|
|
902
|
+
raise ValueError("Notifications must be a list")
|
|
903
|
+
|
|
681
904
|
def extract_type_hints_from_inputs(self):
|
|
682
905
|
"""
|
|
683
|
-
This method extracts the type hints from the
|
|
906
|
+
This method extracts the type hints from the input keys in the input dictionary.
|
|
684
907
|
|
|
685
908
|
As a result, after the method ran the inputs dictionary - a dictionary of parameter names as keys and paths as
|
|
686
909
|
values, will be cleared from type hints and the extracted type hints will be saved in the spec's inputs type
|
|
@@ -763,7 +986,7 @@ class RunSpec(ModelObj):
|
|
|
763
986
|
# Validate correct pattern:
|
|
764
987
|
if input_key.count(":") > 1:
|
|
765
988
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
766
|
-
f"Incorrect input pattern.
|
|
989
|
+
f"Incorrect input pattern. Input keys can have only a single ':' in them to specify the desired type "
|
|
767
990
|
f"the input will be parsed as. Given: {input_key}."
|
|
768
991
|
)
|
|
769
992
|
|
|
@@ -790,6 +1013,7 @@ class RunStatus(ModelObj):
|
|
|
790
1013
|
iterations=None,
|
|
791
1014
|
ui_url=None,
|
|
792
1015
|
reason: str = None,
|
|
1016
|
+
notifications: Dict[str, Notification] = None,
|
|
793
1017
|
):
|
|
794
1018
|
self.state = state or "created"
|
|
795
1019
|
self.status_text = status_text
|
|
@@ -803,6 +1027,7 @@ class RunStatus(ModelObj):
|
|
|
803
1027
|
self.iterations = iterations
|
|
804
1028
|
self.ui_url = ui_url
|
|
805
1029
|
self.reason = reason
|
|
1030
|
+
self.notifications = notifications or {}
|
|
806
1031
|
|
|
807
1032
|
|
|
808
1033
|
class RunTemplate(ModelObj):
|
|
@@ -973,6 +1198,20 @@ class RunObject(RunTemplate):
|
|
|
973
1198
|
def status(self, status):
|
|
974
1199
|
self._status = self._verify_dict(status, "status", RunStatus)
|
|
975
1200
|
|
|
1201
|
+
@property
|
|
1202
|
+
def error(self) -> str:
|
|
1203
|
+
"""error string if failed"""
|
|
1204
|
+
if self.status:
|
|
1205
|
+
if self.status.state != "error":
|
|
1206
|
+
return f"Run state ({self.status.state}) is not in error state"
|
|
1207
|
+
return (
|
|
1208
|
+
self.status.error
|
|
1209
|
+
or self.status.reason
|
|
1210
|
+
or self.status.status_text
|
|
1211
|
+
or "Unknown error"
|
|
1212
|
+
)
|
|
1213
|
+
return ""
|
|
1214
|
+
|
|
976
1215
|
def output(self, key):
|
|
977
1216
|
"""return the value of a specific result or artifact by key"""
|
|
978
1217
|
self._outputs_wait_for_completion()
|
|
@@ -1144,7 +1383,6 @@ class RunObject(RunTemplate):
|
|
|
1144
1383
|
)
|
|
1145
1384
|
if logs_enabled and not logs_interval:
|
|
1146
1385
|
self.logs(watch=False)
|
|
1147
|
-
|
|
1148
1386
|
if raise_on_failure and state != mlrun.runtimes.constants.RunStates.completed:
|
|
1149
1387
|
raise mlrun.errors.MLRunRuntimeError(
|
|
1150
1388
|
f"task {self.metadata.name} did not complete (state={state})"
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
|
+
# for backwards compatibility
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"ModelEndpoint",
|
|
20
|
+
"EventFieldType",
|
|
21
|
+
"EventLiveStats",
|
|
22
|
+
"EventKeyMetrics",
|
|
23
|
+
"TimeSeriesTarget",
|
|
24
|
+
"ModelEndpointTarget",
|
|
25
|
+
"FileTargetKind",
|
|
26
|
+
"ProjectSecretKeys",
|
|
27
|
+
"ModelMonitoringStoreKinds",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
from mlrun.common.model_monitoring import (
|
|
31
|
+
EventFieldType,
|
|
32
|
+
EventKeyMetrics,
|
|
33
|
+
EventLiveStats,
|
|
34
|
+
FileTargetKind,
|
|
35
|
+
ModelEndpointTarget,
|
|
36
|
+
ModelMonitoringStoreKinds,
|
|
37
|
+
ProjectSecretKeys,
|
|
38
|
+
TimeSeriesTarget,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
from .model_endpoint import ModelEndpoint
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 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.
|
|
@@ -13,18 +13,25 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
15
|
import pathlib
|
|
16
|
+
import typing
|
|
16
17
|
|
|
17
18
|
import sqlalchemy.orm
|
|
19
|
+
from fastapi import Depends
|
|
18
20
|
|
|
19
21
|
import mlrun
|
|
20
22
|
import mlrun.api.api.utils
|
|
21
23
|
import mlrun.api.crud.secrets
|
|
22
24
|
import mlrun.api.utils.singletons.db
|
|
25
|
+
import mlrun.api.utils.singletons.k8s
|
|
26
|
+
import mlrun.common.model_monitoring as model_monitoring_constants
|
|
27
|
+
import mlrun.common.schemas
|
|
23
28
|
import mlrun.config
|
|
24
29
|
import mlrun.feature_store as fstore
|
|
25
30
|
import mlrun.model_monitoring.stream_processing_fs
|
|
26
31
|
import mlrun.runtimes
|
|
27
32
|
import mlrun.utils.helpers
|
|
33
|
+
import mlrun.utils.model_monitoring
|
|
34
|
+
from mlrun.api.api import deps
|
|
28
35
|
|
|
29
36
|
_CURRENT_FILE_PATH = pathlib.Path(__file__)
|
|
30
37
|
_STREAM_PROCESSING_FUNCTION_PATH = _CURRENT_FILE_PATH.parent / "stream_processing_fs.py"
|
|
@@ -36,16 +43,20 @@ _MONIOTINRG_BATCH_FUNCTION_PATH = (
|
|
|
36
43
|
def initial_model_monitoring_stream_processing_function(
|
|
37
44
|
project: str,
|
|
38
45
|
model_monitoring_access_key: str,
|
|
39
|
-
db_session: sqlalchemy.orm.Session,
|
|
40
46
|
tracking_policy: mlrun.utils.model_monitoring.TrackingPolicy,
|
|
47
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
48
|
+
parquet_target: str,
|
|
41
49
|
):
|
|
42
50
|
"""
|
|
43
51
|
Initialize model monitoring stream processing function.
|
|
44
52
|
|
|
45
|
-
:param project:
|
|
46
|
-
:param model_monitoring_access_key:
|
|
47
|
-
|
|
53
|
+
:param project: Project name.
|
|
54
|
+
:param model_monitoring_access_key: Access key to apply the model monitoring process. Please note that in CE
|
|
55
|
+
deployments this parameter will be None.
|
|
48
56
|
:param tracking_policy: Model monitoring configurations.
|
|
57
|
+
:param auth_info: The auth info of the request.
|
|
58
|
+
:parquet_target: Path to model monitoring parquet file that will be generated by the monitoring
|
|
59
|
+
stream nuclio function.
|
|
49
60
|
|
|
50
61
|
:return: A function object from a mlrun runtime class
|
|
51
62
|
|
|
@@ -54,12 +65,11 @@ def initial_model_monitoring_stream_processing_function(
|
|
|
54
65
|
# Initialize Stream Processor object
|
|
55
66
|
stream_processor = mlrun.model_monitoring.stream_processing_fs.EventStreamProcessor(
|
|
56
67
|
project=project,
|
|
57
|
-
model_monitoring_access_key=model_monitoring_access_key,
|
|
58
68
|
parquet_batching_max_events=mlrun.mlconf.model_endpoint_monitoring.parquet_batching_max_events,
|
|
69
|
+
parquet_target=parquet_target,
|
|
70
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
59
71
|
)
|
|
60
72
|
|
|
61
|
-
http_source = mlrun.datastore.sources.HttpSource()
|
|
62
|
-
|
|
63
73
|
# Create a new serving function for the streaming process
|
|
64
74
|
function = mlrun.code_to_function(
|
|
65
75
|
name="model-monitoring-stream",
|
|
@@ -75,46 +85,34 @@ def initial_model_monitoring_stream_processing_function(
|
|
|
75
85
|
# Set the project to the serving function
|
|
76
86
|
function.metadata.project = project
|
|
77
87
|
|
|
78
|
-
# Add
|
|
79
|
-
|
|
80
|
-
project=project,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
# Set model monitoring access key for managing permissions
|
|
87
|
-
function.set_env_from_secret(
|
|
88
|
-
"MODEL_MONITORING_ACCESS_KEY",
|
|
89
|
-
mlrun.api.utils.singletons.k8s.get_k8s().get_project_secret_name(project),
|
|
90
|
-
mlrun.api.crud.secrets.Secrets().generate_client_project_secret_key(
|
|
91
|
-
mlrun.api.crud.secrets.SecretsClientType.model_monitoring,
|
|
92
|
-
"MODEL_MONITORING_ACCESS_KEY",
|
|
93
|
-
),
|
|
88
|
+
# Add stream triggers
|
|
89
|
+
function = _apply_stream_trigger(
|
|
90
|
+
project=project,
|
|
91
|
+
function=function,
|
|
92
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
93
|
+
auth_info=auth_info,
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
+
# Apply feature store run configurations on the serving function
|
|
96
97
|
run_config = fstore.RunConfig(function=function, local=False)
|
|
97
98
|
function.spec.parameters = run_config.parameters
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
func.metadata.credentials.access_key = model_monitoring_access_key
|
|
101
|
-
func.apply(mlrun.v3io_cred())
|
|
102
|
-
|
|
103
|
-
return func
|
|
100
|
+
return function
|
|
104
101
|
|
|
105
102
|
|
|
106
103
|
def get_model_monitoring_batch_function(
|
|
107
104
|
project: str,
|
|
108
105
|
model_monitoring_access_key: str,
|
|
109
106
|
db_session: sqlalchemy.orm.Session,
|
|
110
|
-
auth_info: mlrun.
|
|
107
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
111
108
|
tracking_policy: mlrun.utils.model_monitoring.TrackingPolicy,
|
|
112
109
|
):
|
|
113
110
|
"""
|
|
114
111
|
Initialize model monitoring batch function.
|
|
115
112
|
|
|
116
113
|
:param project: project name.
|
|
117
|
-
:param model_monitoring_access_key: access key to apply the model monitoring process.
|
|
114
|
+
:param model_monitoring_access_key: access key to apply the model monitoring process. Please note that in CE
|
|
115
|
+
deployments this parameter will be None.
|
|
118
116
|
:param db_session: A session that manages the current dialog with the database.
|
|
119
117
|
:param auth_info: The auth info of the request.
|
|
120
118
|
:param tracking_policy: Model monitoring configurations.
|
|
@@ -137,20 +135,107 @@ def get_model_monitoring_batch_function(
|
|
|
137
135
|
# Set the project to the job function
|
|
138
136
|
function.metadata.project = project
|
|
139
137
|
|
|
138
|
+
if not mlrun.mlconf.is_ce_mode():
|
|
139
|
+
function = _apply_access_key_and_mount_function(
|
|
140
|
+
project=project,
|
|
141
|
+
function=function,
|
|
142
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
143
|
+
auth_info=auth_info,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Enrich runtime with the required configurations
|
|
147
|
+
mlrun.api.api.utils.apply_enrichment_and_validation_on_function(function, auth_info)
|
|
148
|
+
|
|
149
|
+
return function
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _apply_stream_trigger(
|
|
153
|
+
project: str,
|
|
154
|
+
function: mlrun.runtimes.ServingRuntime,
|
|
155
|
+
model_monitoring_access_key: str = None,
|
|
156
|
+
auth_info: mlrun.common.schemas.AuthInfo = Depends(deps.authenticate_request),
|
|
157
|
+
) -> mlrun.runtimes.ServingRuntime:
|
|
158
|
+
"""Adding stream source for the nuclio serving function. By default, the function has HTTP stream trigger along
|
|
159
|
+
with another supported stream source that can be either Kafka or V3IO, depends on the stream path schema that is
|
|
160
|
+
defined under mlrun.mlconf.model_endpoint_monitoring.store_prefixes. Note that if no valid stream path has been
|
|
161
|
+
provided then the function will have a single HTTP stream source.
|
|
162
|
+
|
|
163
|
+
:param project: Project name.
|
|
164
|
+
:param function: The serving function object that will be applied with the stream trigger.
|
|
165
|
+
:param model_monitoring_access_key: Access key to apply the model monitoring stream function when the stream is
|
|
166
|
+
schema is V3IO.
|
|
167
|
+
:param auth_info: The auth info of the request.
|
|
168
|
+
|
|
169
|
+
:return: ServingRuntime object with stream trigger.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
# Get the stream path from the configuration
|
|
173
|
+
# stream_path = mlrun.mlconf.get_file_target_path(project=project, kind="stream", target="stream")
|
|
174
|
+
stream_path = mlrun.utils.model_monitoring.get_stream_path(project=project)
|
|
175
|
+
|
|
176
|
+
if stream_path.startswith("kafka://"):
|
|
177
|
+
|
|
178
|
+
topic, brokers = mlrun.datastore.utils.parse_kafka_url(url=stream_path)
|
|
179
|
+
# Generate Kafka stream source
|
|
180
|
+
stream_source = mlrun.datastore.sources.KafkaSource(
|
|
181
|
+
brokers=brokers,
|
|
182
|
+
topics=[topic],
|
|
183
|
+
)
|
|
184
|
+
function = stream_source.add_nuclio_trigger(function)
|
|
185
|
+
|
|
186
|
+
if not mlrun.mlconf.is_ce_mode():
|
|
187
|
+
function = _apply_access_key_and_mount_function(
|
|
188
|
+
project=project,
|
|
189
|
+
function=function,
|
|
190
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
191
|
+
auth_info=auth_info,
|
|
192
|
+
)
|
|
193
|
+
if stream_path.startswith("v3io://"):
|
|
194
|
+
# Generate V3IO stream trigger
|
|
195
|
+
function.add_v3io_stream_trigger(
|
|
196
|
+
stream_path=stream_path, name="monitoring_stream_trigger"
|
|
197
|
+
)
|
|
198
|
+
# Add the default HTTP source
|
|
199
|
+
http_source = mlrun.datastore.sources.HttpSource()
|
|
200
|
+
function = http_source.add_nuclio_trigger(function)
|
|
201
|
+
|
|
202
|
+
return function
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _apply_access_key_and_mount_function(
|
|
206
|
+
project: str,
|
|
207
|
+
function: typing.Union[
|
|
208
|
+
mlrun.runtimes.KubejobRuntime, mlrun.runtimes.ServingRuntime
|
|
209
|
+
],
|
|
210
|
+
model_monitoring_access_key: str,
|
|
211
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
212
|
+
) -> typing.Union[mlrun.runtimes.KubejobRuntime, mlrun.runtimes.ServingRuntime]:
|
|
213
|
+
"""Applying model monitoring access key on the provided function when using V3IO path. In addition, this method
|
|
214
|
+
mount the V3IO path for the provided function to configure the access to the system files.
|
|
215
|
+
|
|
216
|
+
:param project: Project name.
|
|
217
|
+
:param function: Model monitoring function object that will be filled with the access key and
|
|
218
|
+
the access to the system files.
|
|
219
|
+
:param model_monitoring_access_key: Access key to apply the model monitoring stream function when the stream is
|
|
220
|
+
schema is V3IO.
|
|
221
|
+
:param auth_info: The auth info of the request.
|
|
222
|
+
|
|
223
|
+
:return: function runtime object with access key and access to system files.
|
|
224
|
+
"""
|
|
225
|
+
|
|
140
226
|
# Set model monitoring access key for managing permissions
|
|
141
227
|
function.set_env_from_secret(
|
|
142
|
-
|
|
143
|
-
mlrun.api.utils.singletons.k8s.
|
|
228
|
+
model_monitoring_constants.ProjectSecretKeys.ACCESS_KEY,
|
|
229
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_name(
|
|
230
|
+
project
|
|
231
|
+
),
|
|
144
232
|
mlrun.api.crud.secrets.Secrets().generate_client_project_secret_key(
|
|
145
233
|
mlrun.api.crud.secrets.SecretsClientType.model_monitoring,
|
|
146
|
-
|
|
234
|
+
model_monitoring_constants.ProjectSecretKeys.ACCESS_KEY,
|
|
147
235
|
),
|
|
148
236
|
)
|
|
149
|
-
|
|
150
|
-
function.apply(mlrun.mount_v3io())
|
|
151
|
-
|
|
152
|
-
# Needs to be a member of the project and have access to project data path
|
|
153
237
|
function.metadata.credentials.access_key = model_monitoring_access_key
|
|
238
|
+
function.apply(mlrun.mount_v3io())
|
|
154
239
|
|
|
155
240
|
# Ensure that the auth env vars are set
|
|
156
241
|
mlrun.api.api.utils.ensure_function_has_auth_set(function, auth_info)
|