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
|
@@ -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.
|
|
@@ -12,33 +12,32 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
import json
|
|
17
16
|
import os
|
|
18
17
|
import typing
|
|
18
|
+
import warnings
|
|
19
19
|
|
|
20
20
|
import sqlalchemy.orm
|
|
21
21
|
|
|
22
22
|
import mlrun.api.api.endpoints.functions
|
|
23
23
|
import mlrun.api.api.utils
|
|
24
|
-
import mlrun.api.
|
|
25
|
-
import mlrun.api.schemas.model_endpoints
|
|
24
|
+
import mlrun.api.crud.runtimes.nuclio.function
|
|
26
25
|
import mlrun.api.utils.singletons.k8s
|
|
27
26
|
import mlrun.artifacts
|
|
27
|
+
import mlrun.common.model_monitoring as model_monitoring_constants
|
|
28
|
+
import mlrun.common.schemas
|
|
29
|
+
import mlrun.common.schemas.model_endpoints
|
|
28
30
|
import mlrun.config
|
|
29
31
|
import mlrun.datastore.store_resources
|
|
30
32
|
import mlrun.errors
|
|
31
33
|
import mlrun.feature_store
|
|
32
|
-
import mlrun.model_monitoring.constants as model_monitoring_constants
|
|
33
34
|
import mlrun.model_monitoring.helpers
|
|
34
|
-
import mlrun.runtimes.function
|
|
35
35
|
import mlrun.utils.helpers
|
|
36
36
|
import mlrun.utils.model_monitoring
|
|
37
37
|
import mlrun.utils.v3io_clients
|
|
38
|
+
from mlrun.model_monitoring.stores import get_model_endpoint_store
|
|
38
39
|
from mlrun.utils import logger
|
|
39
40
|
|
|
40
|
-
from .model_endpoint_store import get_model_endpoint_target
|
|
41
|
-
|
|
42
41
|
|
|
43
42
|
class ModelEndpoints:
|
|
44
43
|
"""Provide different methods for handling model endpoints such as listing, writing and deleting"""
|
|
@@ -47,12 +46,17 @@ class ModelEndpoints:
|
|
|
47
46
|
self,
|
|
48
47
|
db_session: sqlalchemy.orm.Session,
|
|
49
48
|
access_key: str,
|
|
50
|
-
model_endpoint: mlrun.
|
|
51
|
-
auth_info: mlrun.
|
|
52
|
-
) -> mlrun.
|
|
53
|
-
# TODO: deprecated, remove in 1.5.0.
|
|
49
|
+
model_endpoint: mlrun.common.schemas.ModelEndpoint,
|
|
50
|
+
auth_info: mlrun.common.schemas.AuthInfo = mlrun.common.schemas.AuthInfo(),
|
|
51
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
52
|
+
# TODO: deprecated in 1.3.0, remove in 1.5.0.
|
|
53
|
+
warnings.warn(
|
|
54
|
+
"This is deprecated in 1.3.0, and will be removed in 1.5.0."
|
|
55
|
+
"Please use create_model_endpoint() for create or patch_model_endpoint() for update",
|
|
56
|
+
FutureWarning,
|
|
57
|
+
)
|
|
54
58
|
"""
|
|
55
|
-
Either create or updates the record of a given ModelEndpoint object.
|
|
59
|
+
Either create or updates the record of a given `ModelEndpoint` object.
|
|
56
60
|
Leaving here for backwards compatibility, remove in 1.5.0.
|
|
57
61
|
|
|
58
62
|
:param db_session: A session that manages the current dialog with the database
|
|
@@ -60,7 +64,7 @@ class ModelEndpoints:
|
|
|
60
64
|
:param model_endpoint: Model endpoint object to update
|
|
61
65
|
:param auth_info: The auth info of the request
|
|
62
66
|
|
|
63
|
-
:return:
|
|
67
|
+
:return: `ModelEndpoint` object.
|
|
64
68
|
"""
|
|
65
69
|
|
|
66
70
|
return self.create_model_endpoint(
|
|
@@ -70,16 +74,16 @@ class ModelEndpoints:
|
|
|
70
74
|
def create_model_endpoint(
|
|
71
75
|
self,
|
|
72
76
|
db_session: sqlalchemy.orm.Session,
|
|
73
|
-
model_endpoint: mlrun.
|
|
74
|
-
) -> mlrun.
|
|
77
|
+
model_endpoint: mlrun.common.schemas.ModelEndpoint,
|
|
78
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
75
79
|
"""
|
|
76
80
|
Creates model endpoint record in DB. The DB target type is defined under
|
|
77
|
-
mlrun.config.model_endpoint_monitoring.store_type (
|
|
81
|
+
`mlrun.config.model_endpoint_monitoring.store_type` (V3IO-NOSQL by default).
|
|
78
82
|
|
|
79
83
|
:param db_session: A session that manages the current dialog with the database.
|
|
80
84
|
:param model_endpoint: Model endpoint object to update.
|
|
81
85
|
|
|
82
|
-
:return:
|
|
86
|
+
:return: `ModelEndpoint` object.
|
|
83
87
|
"""
|
|
84
88
|
|
|
85
89
|
if model_endpoint.spec.model_uri or model_endpoint.status.feature_stats:
|
|
@@ -107,23 +111,22 @@ class ModelEndpoints:
|
|
|
107
111
|
if not model_endpoint.status.feature_stats and hasattr(
|
|
108
112
|
model_obj, "feature_stats"
|
|
109
113
|
):
|
|
110
|
-
model_endpoint.status.feature_stats = model_obj.feature_stats
|
|
111
|
-
|
|
114
|
+
model_endpoint.status.feature_stats = model_obj.spec.feature_stats
|
|
112
115
|
# Get labels from model object if not found in model endpoint object
|
|
113
|
-
if not model_endpoint.spec.label_names and
|
|
116
|
+
if not model_endpoint.spec.label_names and model_obj.spec.outputs:
|
|
114
117
|
model_label_names = [
|
|
115
|
-
self._clean_feature_name(f.name) for f in model_obj.outputs
|
|
118
|
+
self._clean_feature_name(f.name) for f in model_obj.spec.outputs
|
|
116
119
|
]
|
|
117
120
|
model_endpoint.spec.label_names = model_label_names
|
|
118
121
|
|
|
119
122
|
# Get algorithm from model object if not found in model endpoint object
|
|
120
|
-
if not model_endpoint.spec.algorithm and
|
|
121
|
-
model_endpoint.spec.algorithm = model_obj.algorithm
|
|
123
|
+
if not model_endpoint.spec.algorithm and model_obj.spec.algorithm:
|
|
124
|
+
model_endpoint.spec.algorithm = model_obj.spec.algorithm
|
|
122
125
|
|
|
123
126
|
# Create monitoring feature set if monitoring found in model endpoint object
|
|
124
127
|
if (
|
|
125
128
|
model_endpoint.spec.monitoring_mode
|
|
126
|
-
== mlrun.
|
|
129
|
+
== mlrun.common.model_monitoring.ModelMonitoringMode.enabled.value
|
|
127
130
|
):
|
|
128
131
|
monitoring_feature_set = self.create_monitoring_feature_set(
|
|
129
132
|
model_endpoint, model_obj, db_session, run_db
|
|
@@ -158,18 +161,18 @@ class ModelEndpoints:
|
|
|
158
161
|
logger.info("Creating model endpoint", endpoint_id=model_endpoint.metadata.uid)
|
|
159
162
|
|
|
160
163
|
# Write the new model endpoint
|
|
161
|
-
|
|
164
|
+
model_endpoint_store = get_model_endpoint_store(
|
|
162
165
|
project=model_endpoint.metadata.project,
|
|
163
166
|
)
|
|
164
|
-
|
|
167
|
+
model_endpoint_store.write_model_endpoint(endpoint=model_endpoint.flat_dict())
|
|
165
168
|
|
|
166
169
|
logger.info("Model endpoint created", endpoint_id=model_endpoint.metadata.uid)
|
|
167
170
|
|
|
168
171
|
return model_endpoint
|
|
169
172
|
|
|
170
|
-
@staticmethod
|
|
171
173
|
def create_monitoring_feature_set(
|
|
172
|
-
|
|
174
|
+
self,
|
|
175
|
+
model_endpoint: mlrun.common.schemas.ModelEndpoint,
|
|
173
176
|
model_obj: mlrun.artifacts.ModelArtifact,
|
|
174
177
|
db_session: sqlalchemy.orm.Session,
|
|
175
178
|
run_db: mlrun.db.sqldb.SQLDB,
|
|
@@ -195,29 +198,29 @@ class ModelEndpoints:
|
|
|
195
198
|
|
|
196
199
|
feature_set = mlrun.feature_store.FeatureSet(
|
|
197
200
|
f"monitoring-{serving_function_name}-{model_name}",
|
|
198
|
-
entities=[
|
|
199
|
-
timestamp_key=
|
|
201
|
+
entities=[model_monitoring_constants.EventFieldType.ENDPOINT_ID],
|
|
202
|
+
timestamp_key=model_monitoring_constants.EventFieldType.TIMESTAMP,
|
|
200
203
|
description=f"Monitoring feature set for endpoint: {model_endpoint.spec.model}",
|
|
201
204
|
)
|
|
202
205
|
feature_set.metadata.project = model_endpoint.metadata.project
|
|
203
206
|
|
|
204
207
|
feature_set.metadata.labels = {
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
model_monitoring_constants.EventFieldType.ENDPOINT_ID: model_endpoint.metadata.uid,
|
|
209
|
+
model_monitoring_constants.EventFieldType.MODEL_CLASS: model_endpoint.spec.model_class,
|
|
207
210
|
}
|
|
208
211
|
|
|
209
212
|
# Add features to the feature set according to the model object
|
|
210
|
-
if model_obj.inputs
|
|
211
|
-
for feature in model_obj.inputs
|
|
213
|
+
if model_obj.spec.inputs:
|
|
214
|
+
for feature in model_obj.spec.inputs:
|
|
212
215
|
feature_set.add_feature(
|
|
213
216
|
mlrun.feature_store.Feature(
|
|
214
217
|
name=feature.name, value_type=feature.value_type
|
|
215
218
|
)
|
|
216
219
|
)
|
|
217
220
|
# Check if features can be found within the feature vector
|
|
218
|
-
elif model_obj.feature_vector:
|
|
221
|
+
elif model_obj.spec.feature_vector:
|
|
219
222
|
_, name, _, tag, _ = mlrun.utils.helpers.parse_artifact_uri(
|
|
220
|
-
model_obj.feature_vector
|
|
223
|
+
model_obj.spec.feature_vector
|
|
221
224
|
)
|
|
222
225
|
fv = run_db.get_feature_vector(
|
|
223
226
|
name=name, project=model_endpoint.metadata.project, tag=tag
|
|
@@ -236,16 +239,22 @@ class ModelEndpoints:
|
|
|
236
239
|
|
|
237
240
|
# Define parquet target for this feature set
|
|
238
241
|
parquet_path = (
|
|
239
|
-
|
|
240
|
-
|
|
242
|
+
self._get_monitoring_parquet_path(
|
|
243
|
+
db_session=db_session, project=model_endpoint.metadata.project
|
|
244
|
+
)
|
|
245
|
+
+ f"/key={model_endpoint.metadata.uid}"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
parquet_target = mlrun.datastore.targets.ParquetTarget(
|
|
249
|
+
model_monitoring_constants.FileTargetKind.PARQUET, parquet_path
|
|
241
250
|
)
|
|
242
|
-
parquet_target = mlrun.datastore.targets.ParquetTarget("parquet", parquet_path)
|
|
243
251
|
driver = mlrun.datastore.targets.get_target_driver(parquet_target, feature_set)
|
|
244
|
-
|
|
252
|
+
|
|
245
253
|
feature_set.set_targets(
|
|
246
254
|
[mlrun.datastore.targets.ParquetTarget(path=parquet_path)],
|
|
247
255
|
with_defaults=False,
|
|
248
256
|
)
|
|
257
|
+
driver.update_resource_status("created")
|
|
249
258
|
|
|
250
259
|
# Save the new feature set
|
|
251
260
|
feature_set._override_run_db(db_session)
|
|
@@ -258,10 +267,39 @@ class ModelEndpoints:
|
|
|
258
267
|
|
|
259
268
|
return feature_set
|
|
260
269
|
|
|
270
|
+
@staticmethod
|
|
271
|
+
def _get_monitoring_parquet_path(
|
|
272
|
+
db_session: sqlalchemy.orm.Session, project: str
|
|
273
|
+
) -> str:
|
|
274
|
+
"""Getting model monitoring parquet target for the current project. The parquet target path is based on the
|
|
275
|
+
project artifact path. If project artifact path is not defined, the parquet target path will be based on MLRun
|
|
276
|
+
artifact path.
|
|
277
|
+
|
|
278
|
+
:param db_session: A session that manages the current dialog with the database. Will be used in this function
|
|
279
|
+
to get the project record from DB.
|
|
280
|
+
:param project: Project name.
|
|
281
|
+
|
|
282
|
+
:return: Monitoring parquet target path.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
# Get the artifact path from the project record that was stored in the DB
|
|
286
|
+
project_obj = mlrun.api.crud.projects.Projects().get_project(
|
|
287
|
+
session=db_session, name=project
|
|
288
|
+
)
|
|
289
|
+
artifact_path = project_obj.spec.artifact_path
|
|
290
|
+
# Generate monitoring parquet path value
|
|
291
|
+
parquet_path = mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
292
|
+
project=project,
|
|
293
|
+
kind=model_monitoring_constants.FileTargetKind.PARQUET,
|
|
294
|
+
target="offline",
|
|
295
|
+
artifact_path=artifact_path,
|
|
296
|
+
)
|
|
297
|
+
return parquet_path
|
|
298
|
+
|
|
261
299
|
@staticmethod
|
|
262
300
|
def _validate_length_features_and_labels(model_endpoint):
|
|
263
301
|
"""
|
|
264
|
-
Validate that the length of feature_stats is equal to the length of feature_names and label_names
|
|
302
|
+
Validate that the length of feature_stats is equal to the length of `feature_names` and `label_names`
|
|
265
303
|
|
|
266
304
|
:param model_endpoint: An object representing the model endpoint.
|
|
267
305
|
"""
|
|
@@ -288,8 +326,8 @@ class ModelEndpoints:
|
|
|
288
326
|
self, model_endpoint
|
|
289
327
|
) -> typing.Tuple[typing.Dict, typing.List]:
|
|
290
328
|
"""
|
|
291
|
-
Create a clean matching version of feature names for both feature_stats and feature_names
|
|
292
|
-
label names exist only in feature_stats and label_names
|
|
329
|
+
Create a clean matching version of feature names for both `feature_stats` and `feature_names`. Please note that
|
|
330
|
+
label names exist only in `feature_stats` and `label_names`.
|
|
293
331
|
|
|
294
332
|
:param model_endpoint: An object representing the model endpoint.
|
|
295
333
|
:return: A tuple of:
|
|
@@ -312,36 +350,42 @@ class ModelEndpoints:
|
|
|
312
350
|
clean_feature_names.append(clean_name)
|
|
313
351
|
return clean_feature_stats, clean_feature_names
|
|
314
352
|
|
|
315
|
-
@staticmethod
|
|
316
353
|
def patch_model_endpoint(
|
|
354
|
+
self,
|
|
317
355
|
project: str,
|
|
318
356
|
endpoint_id: str,
|
|
319
357
|
attributes: dict,
|
|
320
|
-
) -> mlrun.
|
|
358
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
321
359
|
"""
|
|
322
360
|
Update a model endpoint record with a given attributes.
|
|
323
361
|
|
|
324
362
|
:param project: The name of the project.
|
|
325
363
|
:param endpoint_id: The unique id of the model endpoint.
|
|
326
364
|
:param attributes: Dictionary of attributes that will be used for update the model endpoint. Note that the keys
|
|
327
|
-
of the attributes dictionary should exist in the
|
|
365
|
+
of the attributes dictionary should exist in the DB table. More details about the model
|
|
328
366
|
endpoint available attributes can be found under
|
|
329
|
-
:py:class:`~mlrun.
|
|
367
|
+
:py:class:`~mlrun.common.schemas.ModelEndpoint`.
|
|
330
368
|
|
|
331
|
-
:return: A patched ModelEndpoint object.
|
|
369
|
+
:return: A patched `ModelEndpoint` object.
|
|
332
370
|
"""
|
|
333
371
|
|
|
334
|
-
|
|
372
|
+
# Generate a model endpoint store object and apply the update process
|
|
373
|
+
model_endpoint_store = get_model_endpoint_store(
|
|
335
374
|
project=project,
|
|
336
375
|
)
|
|
337
|
-
|
|
376
|
+
model_endpoint_store.update_model_endpoint(
|
|
338
377
|
endpoint_id=endpoint_id, attributes=attributes
|
|
339
378
|
)
|
|
340
379
|
|
|
341
|
-
|
|
342
|
-
|
|
380
|
+
logger.info("Model endpoint table updated", endpoint_id=endpoint_id)
|
|
381
|
+
|
|
382
|
+
# Get the patched model endpoint record
|
|
383
|
+
model_endpoint_record = model_endpoint_store.get_model_endpoint(
|
|
384
|
+
endpoint_id=endpoint_id,
|
|
343
385
|
)
|
|
344
386
|
|
|
387
|
+
return self._convert_into_model_endpoint_object(endpoint=model_endpoint_record)
|
|
388
|
+
|
|
345
389
|
@staticmethod
|
|
346
390
|
def delete_model_endpoint(
|
|
347
391
|
project: str,
|
|
@@ -353,59 +397,83 @@ class ModelEndpoints:
|
|
|
353
397
|
:param project: The name of the project.
|
|
354
398
|
:param endpoint_id: The id of the endpoint.
|
|
355
399
|
"""
|
|
356
|
-
|
|
400
|
+
model_endpoint_store = get_model_endpoint_store(
|
|
357
401
|
project=project,
|
|
358
402
|
)
|
|
359
|
-
model_endpoint_target.delete_model_endpoint(endpoint_id=endpoint_id)
|
|
360
403
|
|
|
361
|
-
|
|
404
|
+
model_endpoint_store.delete_model_endpoint(endpoint_id=endpoint_id)
|
|
405
|
+
|
|
406
|
+
logger.info("Model endpoint table cleared", endpoint_id=endpoint_id)
|
|
407
|
+
|
|
362
408
|
def get_model_endpoint(
|
|
363
|
-
|
|
409
|
+
self,
|
|
410
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
364
411
|
project: str,
|
|
365
412
|
endpoint_id: str,
|
|
366
413
|
metrics: typing.List[str] = None,
|
|
367
414
|
start: str = "now-1h",
|
|
368
415
|
end: str = "now",
|
|
369
416
|
feature_analysis: bool = False,
|
|
370
|
-
) -> mlrun.
|
|
417
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
371
418
|
"""Get a single model endpoint object. You can apply different time series metrics that will be added to the
|
|
372
419
|
result.
|
|
373
420
|
|
|
374
|
-
:param auth_info:
|
|
375
|
-
:param project:
|
|
376
|
-
:param endpoint_id:
|
|
377
|
-
:param metrics:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
421
|
+
:param auth_info: The auth info of the request
|
|
422
|
+
:param project: The name of the project
|
|
423
|
+
:param endpoint_id: The unique id of the model endpoint.
|
|
424
|
+
:param metrics: A list of metrics to return for the model endpoint. There are pre-defined
|
|
425
|
+
metrics for model endpoints such as predictions_per_second and
|
|
426
|
+
latency_avg_5m but also custom metrics defined by the user. Please note that
|
|
427
|
+
these metrics are stored in the time series DB and the results will be
|
|
428
|
+
appeared under `model_endpoint.spec.metrics`.
|
|
429
|
+
:param start: The start time of the metrics. Can be represented by a string containing an
|
|
430
|
+
RFC 3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
|
|
431
|
+
`'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or
|
|
432
|
+
0 for the earliest time.
|
|
433
|
+
:param end: The end time of the metrics. Can be represented by a string containing an
|
|
434
|
+
RFC 3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
|
|
435
|
+
`'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or
|
|
436
|
+
0 for the earliest time.
|
|
437
|
+
:param feature_analysis: When True, the base feature statistics and current feature statistics will
|
|
438
|
+
be added to the output of the resulting object.
|
|
439
|
+
|
|
440
|
+
:return: A `ModelEndpoint` object.
|
|
393
441
|
"""
|
|
394
442
|
|
|
395
|
-
|
|
443
|
+
logger.info(
|
|
444
|
+
"Getting model endpoint record from DB",
|
|
445
|
+
endpoint_id=endpoint_id,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Generate a model endpoint store object and get the model endpoint record as a dictionary
|
|
449
|
+
model_endpoint_store = get_model_endpoint_store(
|
|
396
450
|
project=project, access_key=auth_info.data_session
|
|
397
451
|
)
|
|
398
|
-
|
|
452
|
+
|
|
453
|
+
model_endpoint_record = model_endpoint_store.get_model_endpoint(
|
|
399
454
|
endpoint_id=endpoint_id,
|
|
400
|
-
metrics=metrics,
|
|
401
|
-
start=start,
|
|
402
|
-
end=end,
|
|
403
|
-
feature_analysis=feature_analysis,
|
|
404
455
|
)
|
|
405
456
|
|
|
406
|
-
|
|
457
|
+
# Convert to `ModelEndpoint` object
|
|
458
|
+
model_endpoint_object = self._convert_into_model_endpoint_object(
|
|
459
|
+
endpoint=model_endpoint_record, feature_analysis=feature_analysis
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
# If time metrics were provided, retrieve the results from the time series DB
|
|
463
|
+
if metrics:
|
|
464
|
+
self._add_real_time_metrics(
|
|
465
|
+
model_endpoint_store=model_endpoint_store,
|
|
466
|
+
model_endpoint_object=model_endpoint_object,
|
|
467
|
+
metrics=metrics,
|
|
468
|
+
start=start,
|
|
469
|
+
end=end,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
return model_endpoint_object
|
|
473
|
+
|
|
407
474
|
def list_model_endpoints(
|
|
408
|
-
|
|
475
|
+
self,
|
|
476
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
409
477
|
project: str,
|
|
410
478
|
model: str = None,
|
|
411
479
|
function: str = None,
|
|
@@ -415,10 +483,11 @@ class ModelEndpoints:
|
|
|
415
483
|
end: str = "now",
|
|
416
484
|
top_level: bool = False,
|
|
417
485
|
uids: typing.List[str] = None,
|
|
418
|
-
) -> mlrun.
|
|
486
|
+
) -> mlrun.common.schemas.ModelEndpointList:
|
|
419
487
|
"""
|
|
420
|
-
Returns a list of
|
|
421
|
-
This functions supports filtering by the following
|
|
488
|
+
Returns a list of `ModelEndpoint` objects, wrapped in `ModelEndpointList` object. Each `ModelEndpoint`
|
|
489
|
+
object represents the current state of a model endpoint. This functions supports filtering by the following
|
|
490
|
+
parameters:
|
|
422
491
|
1) model
|
|
423
492
|
2) function
|
|
424
493
|
3) labels
|
|
@@ -435,22 +504,22 @@ class ModelEndpoints:
|
|
|
435
504
|
:param model: The name of the model to filter by.
|
|
436
505
|
:param function: The name of the function to filter by.
|
|
437
506
|
:param labels: A list of labels to filter by. Label filters work by either filtering a specific value of a
|
|
438
|
-
label (i.e. list("key
|
|
507
|
+
label (i.e. list("key=value")) or by looking for the existence of a given key (i.e. "key").
|
|
439
508
|
:param metrics: A list of metrics to return for each endpoint. There are pre-defined metrics for model
|
|
440
|
-
endpoints such as predictions_per_second and latency_avg_5m but also custom metrics
|
|
441
|
-
by the user. Please note that these metrics are stored in the time series DB and the
|
|
442
|
-
will be appeared under model_endpoint.spec.metrics of each endpoint.
|
|
509
|
+
endpoints such as `predictions_per_second` and `latency_avg_5m` but also custom metrics
|
|
510
|
+
defined by the user. Please note that these metrics are stored in the time series DB and the
|
|
511
|
+
results will be appeared under model_endpoint.spec.metrics of each endpoint.
|
|
443
512
|
:param start: The start time of the metrics. Can be represented by a string containing an RFC 3339 time,
|
|
444
513
|
a Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where `m`
|
|
445
514
|
= minutes, `h` = hours, and `'d'` = days), or 0 for the earliest time.
|
|
446
515
|
:param end: The end time of the metrics. Can be represented by a string containing an RFC 3339 time,
|
|
447
516
|
a Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where `m`
|
|
448
517
|
= minutes, `h` = hours, and `'d'` = days), or 0 for the earliest time.
|
|
449
|
-
:param top_level: If True
|
|
450
|
-
:param uids:
|
|
518
|
+
:param top_level: If True, return only routers and endpoints that are NOT children of any router.
|
|
519
|
+
:param uids: List of model endpoint unique ids to include in the result.
|
|
451
520
|
|
|
452
|
-
:return: An object of ModelEndpointList which is literally a list of model endpoints along with some metadata.
|
|
453
|
-
To get a standard list of model endpoints use ModelEndpointList.endpoints
|
|
521
|
+
:return: An object of `ModelEndpointList` which is literally a list of model endpoints along with some metadata.
|
|
522
|
+
To get a standard list of model endpoints use `ModelEndpointList.endpoints`.
|
|
454
523
|
"""
|
|
455
524
|
|
|
456
525
|
logger.info(
|
|
@@ -466,39 +535,181 @@ class ModelEndpoints:
|
|
|
466
535
|
uids=uids,
|
|
467
536
|
)
|
|
468
537
|
|
|
469
|
-
|
|
538
|
+
# Initialize an empty model endpoints list
|
|
539
|
+
endpoint_list = mlrun.common.schemas.model_endpoints.ModelEndpointList(
|
|
540
|
+
endpoints=[]
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
# Generate a model endpoint store object and get a list of model endpoint dictionaries
|
|
544
|
+
endpoint_store = get_model_endpoint_store(
|
|
470
545
|
access_key=auth_info.data_session, project=project
|
|
471
546
|
)
|
|
472
547
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
548
|
+
endpoint_dictionary_list = endpoint_store.list_model_endpoints(
|
|
549
|
+
function=function,
|
|
550
|
+
model=model,
|
|
551
|
+
labels=labels,
|
|
552
|
+
top_level=top_level,
|
|
553
|
+
uids=uids,
|
|
476
554
|
)
|
|
477
555
|
|
|
478
|
-
|
|
479
|
-
if uids is None:
|
|
480
|
-
uids = endpoint_target.list_model_endpoints(
|
|
481
|
-
function=function, model=model, labels=labels, top_level=top_level
|
|
482
|
-
)
|
|
556
|
+
for endpoint_dict in endpoint_dictionary_list:
|
|
483
557
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
metrics=metrics,
|
|
488
|
-
endpoint_id=endpoint_id,
|
|
489
|
-
start=start,
|
|
490
|
-
end=end,
|
|
558
|
+
# Convert to `ModelEndpoint` object
|
|
559
|
+
endpoint_obj = self._convert_into_model_endpoint_object(
|
|
560
|
+
endpoint=endpoint_dict
|
|
491
561
|
)
|
|
492
|
-
|
|
562
|
+
|
|
563
|
+
# If time metrics were provided, retrieve the results from the time series DB
|
|
564
|
+
if metrics:
|
|
565
|
+
self._add_real_time_metrics(
|
|
566
|
+
model_endpoint_store=endpoint_store,
|
|
567
|
+
model_endpoint_object=endpoint_obj,
|
|
568
|
+
metrics=metrics,
|
|
569
|
+
start=start,
|
|
570
|
+
end=end,
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
# Add the `ModelEndpoint` object into the model endpoints list
|
|
574
|
+
endpoint_list.endpoints.append(endpoint_obj)
|
|
493
575
|
|
|
494
576
|
return endpoint_list
|
|
495
577
|
|
|
578
|
+
@staticmethod
|
|
579
|
+
def _add_real_time_metrics(
|
|
580
|
+
model_endpoint_store: mlrun.model_monitoring.stores.ModelEndpointStore,
|
|
581
|
+
model_endpoint_object: mlrun.common.schemas.ModelEndpoint,
|
|
582
|
+
metrics: typing.List[str] = None,
|
|
583
|
+
start: str = "now-1h",
|
|
584
|
+
end: str = "now",
|
|
585
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
586
|
+
"""Add real time metrics from the time series DB to a provided `ModelEndpoint` object. The real time metrics
|
|
587
|
+
will be stored under `ModelEndpoint.status.metrics.real_time`
|
|
588
|
+
|
|
589
|
+
:param model_endpoint_store: `ModelEndpointStore` object that will be used for communicating with the database
|
|
590
|
+
and querying the required metrics.
|
|
591
|
+
:param model_endpoint_object: `ModelEndpoint` object that will be filled with the relevant
|
|
592
|
+
real time metrics.
|
|
593
|
+
:param metrics: A list of metrics to return for each endpoint. There are pre-defined metrics for
|
|
594
|
+
model endpoints such as `predictions_per_second` and `latency_avg_5m` but also
|
|
595
|
+
custom metrics defined by the user. Please note that these metrics are stored in
|
|
596
|
+
the time series DB and the results will be appeared under
|
|
597
|
+
model_endpoint.spec.metrics of each endpoint.
|
|
598
|
+
:param start: The start time of the metrics. Can be represented by a string containing an RFC
|
|
599
|
+
3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
|
|
600
|
+
`'now-[0-9]+[mhd]'`, where `m`= minutes, `h` = hours, and `'d'` = days), or 0
|
|
601
|
+
for the earliest time.
|
|
602
|
+
:param end: The end time of the metrics. Can be represented by a string containing an RFC
|
|
603
|
+
3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
|
|
604
|
+
`'now-[0-9]+[mhd]'`, where `m`= minutes, `h` = hours, and `'d'` = days), or 0
|
|
605
|
+
for the earliest time.
|
|
606
|
+
|
|
607
|
+
"""
|
|
608
|
+
if model_endpoint_object.status.metrics is None:
|
|
609
|
+
model_endpoint_object.status.metrics = {}
|
|
610
|
+
|
|
611
|
+
endpoint_metrics = model_endpoint_store.get_endpoint_real_time_metrics(
|
|
612
|
+
endpoint_id=model_endpoint_object.metadata.uid,
|
|
613
|
+
start=start,
|
|
614
|
+
end=end,
|
|
615
|
+
metrics=metrics,
|
|
616
|
+
)
|
|
617
|
+
if endpoint_metrics:
|
|
618
|
+
model_endpoint_object.status.metrics[
|
|
619
|
+
model_monitoring_constants.EventKeyMetrics.REAL_TIME
|
|
620
|
+
] = endpoint_metrics
|
|
621
|
+
return model_endpoint_object
|
|
622
|
+
|
|
623
|
+
def _convert_into_model_endpoint_object(
|
|
624
|
+
self, endpoint: typing.Dict[str, typing.Any], feature_analysis: bool = False
|
|
625
|
+
) -> mlrun.common.schemas.ModelEndpoint:
|
|
626
|
+
"""
|
|
627
|
+
Create a `ModelEndpoint` object according to a provided model endpoint dictionary.
|
|
628
|
+
|
|
629
|
+
:param endpoint: Dictinoary that represents a DB record of a model endpoint which need to be converted
|
|
630
|
+
into a valid `ModelEndpoint` object.
|
|
631
|
+
:param feature_analysis: When True, the base feature statistics and current feature statistics will be added to
|
|
632
|
+
the output of the resulting object.
|
|
633
|
+
|
|
634
|
+
:return: A `ModelEndpoint` object.
|
|
635
|
+
"""
|
|
636
|
+
|
|
637
|
+
# Convert into `ModelEndpoint` object
|
|
638
|
+
endpoint_obj = mlrun.common.schemas.ModelEndpoint().from_flat_dict(endpoint)
|
|
639
|
+
|
|
640
|
+
# If feature analysis was applied, add feature stats and current stats to the model endpoint result
|
|
641
|
+
if feature_analysis and endpoint_obj.spec.feature_names:
|
|
642
|
+
|
|
643
|
+
endpoint_features = self.get_endpoint_features(
|
|
644
|
+
feature_names=endpoint_obj.spec.feature_names,
|
|
645
|
+
feature_stats=endpoint_obj.status.feature_stats,
|
|
646
|
+
current_stats=endpoint_obj.status.current_stats,
|
|
647
|
+
)
|
|
648
|
+
if endpoint_features:
|
|
649
|
+
endpoint_obj.status.features = endpoint_features
|
|
650
|
+
# Add the latest drift measures results (calculated by the model monitoring batch)
|
|
651
|
+
drift_measures = self._json_loads_if_not_none(
|
|
652
|
+
endpoint.get(
|
|
653
|
+
model_monitoring_constants.EventFieldType.DRIFT_MEASURES
|
|
654
|
+
)
|
|
655
|
+
)
|
|
656
|
+
endpoint_obj.status.drift_measures = drift_measures
|
|
657
|
+
|
|
658
|
+
return endpoint_obj
|
|
659
|
+
|
|
660
|
+
@staticmethod
|
|
661
|
+
def get_endpoint_features(
|
|
662
|
+
feature_names: typing.List[str],
|
|
663
|
+
feature_stats: dict = None,
|
|
664
|
+
current_stats: dict = None,
|
|
665
|
+
) -> typing.List[mlrun.common.schemas.Features]:
|
|
666
|
+
"""
|
|
667
|
+
Getting a new list of features that exist in feature_names along with their expected (feature_stats) and
|
|
668
|
+
actual (current_stats) stats. The expected stats were calculated during the creation of the model endpoint,
|
|
669
|
+
usually based on the data from the Model Artifact. The actual stats are based on the results from the latest
|
|
670
|
+
model monitoring batch job.
|
|
671
|
+
|
|
672
|
+
param feature_names: List of feature names.
|
|
673
|
+
param feature_stats: Dictionary of feature stats that were stored during the creation of the model endpoint
|
|
674
|
+
object.
|
|
675
|
+
param current_stats: Dictionary of the latest stats that were stored during the last run of the model monitoring
|
|
676
|
+
batch job.
|
|
677
|
+
|
|
678
|
+
return: List of feature objects. Each feature has a name, weight, expected values, and actual values. More info
|
|
679
|
+
can be found under `mlrun.common.schemas.Features`.
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
# Initialize feature and current stats dictionaries
|
|
683
|
+
safe_feature_stats = feature_stats or {}
|
|
684
|
+
safe_current_stats = current_stats or {}
|
|
685
|
+
|
|
686
|
+
# Create feature object and add it to a general features list
|
|
687
|
+
features = []
|
|
688
|
+
for name in feature_names:
|
|
689
|
+
if feature_stats is not None and name not in feature_stats:
|
|
690
|
+
logger.warn("Feature missing from 'feature_stats'", name=name)
|
|
691
|
+
if current_stats is not None and name not in current_stats:
|
|
692
|
+
logger.warn("Feature missing from 'current_stats'", name=name)
|
|
693
|
+
f = mlrun.common.schemas.Features.new(
|
|
694
|
+
name, safe_feature_stats.get(name), safe_current_stats.get(name)
|
|
695
|
+
)
|
|
696
|
+
features.append(f)
|
|
697
|
+
return features
|
|
698
|
+
|
|
699
|
+
@staticmethod
|
|
700
|
+
def _json_loads_if_not_none(field: typing.Any) -> typing.Any:
|
|
701
|
+
return (
|
|
702
|
+
json.loads(field)
|
|
703
|
+
if field and field != "null" and field is not None
|
|
704
|
+
else None
|
|
705
|
+
)
|
|
706
|
+
|
|
496
707
|
def deploy_monitoring_functions(
|
|
497
708
|
self,
|
|
498
709
|
project: str,
|
|
499
710
|
model_monitoring_access_key: str,
|
|
500
711
|
db_session: sqlalchemy.orm.Session,
|
|
501
|
-
auth_info: mlrun.
|
|
712
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
502
713
|
tracking_policy: mlrun.utils.model_monitoring.TrackingPolicy,
|
|
503
714
|
):
|
|
504
715
|
"""
|
|
@@ -526,7 +737,7 @@ class ModelEndpoints:
|
|
|
526
737
|
)
|
|
527
738
|
|
|
528
739
|
def verify_project_has_no_model_endpoints(self, project_name: str):
|
|
529
|
-
auth_info = mlrun.
|
|
740
|
+
auth_info = mlrun.common.schemas.AuthInfo(
|
|
530
741
|
data_session=os.getenv("V3IO_ACCESS_KEY")
|
|
531
742
|
)
|
|
532
743
|
|
|
@@ -539,13 +750,14 @@ class ModelEndpoints:
|
|
|
539
750
|
f"Project {project_name} can not be deleted since related resources found: model endpoints"
|
|
540
751
|
)
|
|
541
752
|
|
|
542
|
-
|
|
753
|
+
@staticmethod
|
|
754
|
+
def delete_model_endpoints_resources(project_name: str):
|
|
543
755
|
"""
|
|
544
756
|
Delete all model endpoints resources.
|
|
545
757
|
|
|
546
758
|
:param project_name: The name of the project.
|
|
547
759
|
"""
|
|
548
|
-
auth_info = mlrun.
|
|
760
|
+
auth_info = mlrun.common.schemas.AuthInfo(
|
|
549
761
|
data_session=os.getenv("V3IO_ACCESS_KEY")
|
|
550
762
|
)
|
|
551
763
|
|
|
@@ -554,19 +766,21 @@ class ModelEndpoints:
|
|
|
554
766
|
if not mlrun.mlconf.igz_version or not mlrun.mlconf.v3io_api:
|
|
555
767
|
return
|
|
556
768
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
endpoint_target = get_model_endpoint_target(
|
|
769
|
+
# Generate a model endpoint store object and get a list of model endpoint dictionaries
|
|
770
|
+
endpoint_store = get_model_endpoint_store(
|
|
560
771
|
access_key=auth_info.data_session, project=project_name
|
|
561
772
|
)
|
|
562
|
-
|
|
773
|
+
endpoints = endpoint_store.list_model_endpoints()
|
|
774
|
+
|
|
775
|
+
# Delete model endpoints resources from databases using the model endpoint store object
|
|
776
|
+
endpoint_store.delete_model_endpoints_resources(endpoints)
|
|
563
777
|
|
|
564
|
-
@staticmethod
|
|
565
778
|
def deploy_model_monitoring_stream_processing(
|
|
779
|
+
self,
|
|
566
780
|
project: str,
|
|
567
781
|
model_monitoring_access_key: str,
|
|
568
782
|
db_session: sqlalchemy.orm.Session,
|
|
569
|
-
auth_info: mlrun.
|
|
783
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
570
784
|
tracking_policy: mlrun.utils.model_monitoring.TrackingPolicy,
|
|
571
785
|
):
|
|
572
786
|
"""
|
|
@@ -587,7 +801,7 @@ class ModelEndpoints:
|
|
|
587
801
|
)
|
|
588
802
|
try:
|
|
589
803
|
# validate that the model monitoring stream has not yet been deployed
|
|
590
|
-
mlrun.runtimes.function.get_nuclio_deploy_status(
|
|
804
|
+
mlrun.api.crud.runtimes.nuclio.function.get_nuclio_deploy_status(
|
|
591
805
|
name="model-monitoring-stream",
|
|
592
806
|
project=project,
|
|
593
807
|
tag="",
|
|
@@ -603,8 +817,17 @@ class ModelEndpoints:
|
|
|
603
817
|
"Deploying model monitoring stream processing function", project=project
|
|
604
818
|
)
|
|
605
819
|
|
|
820
|
+
# Get parquet target value for model monitoring stream function
|
|
821
|
+
parquet_target = self._get_monitoring_parquet_path(
|
|
822
|
+
db_session=db_session, project=project
|
|
823
|
+
)
|
|
824
|
+
|
|
606
825
|
fn = mlrun.model_monitoring.helpers.initial_model_monitoring_stream_processing_function(
|
|
607
|
-
project,
|
|
826
|
+
project=project,
|
|
827
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
828
|
+
tracking_policy=tracking_policy,
|
|
829
|
+
auth_info=auth_info,
|
|
830
|
+
parquet_target=parquet_target,
|
|
608
831
|
)
|
|
609
832
|
|
|
610
833
|
mlrun.api.api.endpoints.functions._build_function(
|
|
@@ -616,7 +839,7 @@ class ModelEndpoints:
|
|
|
616
839
|
project: str,
|
|
617
840
|
model_monitoring_access_key: str,
|
|
618
841
|
db_session: sqlalchemy.orm.Session,
|
|
619
|
-
auth_info: mlrun.
|
|
842
|
+
auth_info: mlrun.common.schemas.AuthInfo,
|
|
620
843
|
tracking_policy: mlrun.utils.model_monitoring.TrackingPolicy,
|
|
621
844
|
):
|
|
622
845
|
"""
|
|
@@ -700,7 +923,7 @@ class ModelEndpoints:
|
|
|
700
923
|
return feature_name.replace(" ", "_").replace("(", "").replace(")", "")
|
|
701
924
|
|
|
702
925
|
@staticmethod
|
|
703
|
-
def get_access_key(auth_info: mlrun.
|
|
926
|
+
def get_access_key(auth_info: mlrun.common.schemas.AuthInfo):
|
|
704
927
|
"""
|
|
705
928
|
Getting access key from the current data session. This method is usually used to verify that the session
|
|
706
929
|
is valid and contains an access key.
|
|
@@ -739,7 +962,7 @@ class ModelEndpoints:
|
|
|
739
962
|
|
|
740
963
|
@staticmethod
|
|
741
964
|
def _convert_to_cron_string(
|
|
742
|
-
cron_trigger: mlrun.
|
|
965
|
+
cron_trigger: mlrun.common.schemas.schedule.ScheduleCronTrigger,
|
|
743
966
|
):
|
|
744
967
|
"""Converting the batch interval `ScheduleCronTrigger` into a cron trigger expression"""
|
|
745
968
|
return "{} {} {} * *".format(
|