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/serving/states.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.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
__all__ = ["TaskStep", "RouterStep", "RootFlowStep"]
|
|
15
|
+
__all__ = ["TaskStep", "RouterStep", "RootFlowStep", "ErrorStep"]
|
|
16
16
|
|
|
17
17
|
import os
|
|
18
18
|
import pathlib
|
|
@@ -28,7 +28,7 @@ from ..errors import MLRunInvalidArgumentError, err_to_str
|
|
|
28
28
|
from ..model import ModelObj, ObjectDict
|
|
29
29
|
from ..platforms.iguazio import parse_path
|
|
30
30
|
from ..utils import get_class, get_function
|
|
31
|
-
from .utils import _extract_input_data, _update_result_body
|
|
31
|
+
from .utils import StepToDict, _extract_input_data, _update_result_body
|
|
32
32
|
|
|
33
33
|
callable_prefix = "_"
|
|
34
34
|
path_splitter = "/"
|
|
@@ -49,6 +49,7 @@ class StepKinds:
|
|
|
49
49
|
queue = "queue"
|
|
50
50
|
choice = "choice"
|
|
51
51
|
root = "root"
|
|
52
|
+
error_step = "error_step"
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
_task_step_fields = [
|
|
@@ -134,11 +135,82 @@ class BaseStep(ModelObj):
|
|
|
134
135
|
self.after.append(name)
|
|
135
136
|
return self
|
|
136
137
|
|
|
137
|
-
def error_handler(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
def error_handler(
|
|
139
|
+
self,
|
|
140
|
+
name: str = None,
|
|
141
|
+
class_name=None,
|
|
142
|
+
handler=None,
|
|
143
|
+
before=None,
|
|
144
|
+
function=None,
|
|
145
|
+
full_event: bool = None,
|
|
146
|
+
input_path: str = None,
|
|
147
|
+
result_path: str = None,
|
|
148
|
+
**class_args,
|
|
149
|
+
):
|
|
150
|
+
"""set error handler on a step or the entire graph (to be executed on failure/raise)
|
|
151
|
+
|
|
152
|
+
When setting the error_handler on the graph object, the graph completes after the error handler execution.
|
|
153
|
+
|
|
154
|
+
example:
|
|
155
|
+
in the below example, an 'error_catcher' step is set as the error_handler of the 'raise' step:
|
|
156
|
+
in case of error/raise in 'raise' step, the handle_error will be run. after that,
|
|
157
|
+
the 'echo' step will be run.
|
|
158
|
+
graph = function.set_topology('flow', engine='async')
|
|
159
|
+
graph.to(name='raise', handler='raising_step')\
|
|
160
|
+
.error_handler(name='error_catcher', handler='handle_error', full_event=True, before='echo')
|
|
161
|
+
graph.add_step(name="echo", handler='echo', after="raise").respond()
|
|
162
|
+
|
|
163
|
+
:param name: unique name (and path) for the error handler step, default is class name
|
|
164
|
+
:param class_name: class name or step object to build the step from
|
|
165
|
+
the error handler step is derived from task step (ie no router/queue functionally)
|
|
166
|
+
:param handler: class/function handler to invoke on run/event
|
|
167
|
+
:param before: string or list of next step(s) names that will run after this step.
|
|
168
|
+
the `before` param must not specify upstream steps as it will cause a loop.
|
|
169
|
+
if `before` is not specified, the graph will complete after the error handler execution.
|
|
170
|
+
:param function: function this step should run in
|
|
171
|
+
:param full_event: this step accepts the full event (not just the body)
|
|
172
|
+
:param input_path: selects the key/path in the event to use as input to the step
|
|
173
|
+
this requires that the event body will behave like a dict, for example:
|
|
174
|
+
event: {"data": {"a": 5, "b": 7}}, input_path="data.b" means the step will
|
|
175
|
+
receive 7 as input
|
|
176
|
+
:param result_path: selects the key/path in the event to write the results to
|
|
177
|
+
this requires that the event body will behave like a dict, for example:
|
|
178
|
+
event: {"x": 5} , result_path="y" means the output of the step will be written
|
|
179
|
+
to event["y"] resulting in {"x": 5, "y": <result>}
|
|
180
|
+
:param class_args: class init arguments
|
|
181
|
+
|
|
182
|
+
"""
|
|
183
|
+
if not (class_name or handler):
|
|
184
|
+
raise MLRunInvalidArgumentError("class_name or handler must be provided")
|
|
185
|
+
if isinstance(self, RootFlowStep) and before:
|
|
186
|
+
raise MLRunInvalidArgumentError(
|
|
187
|
+
"`before` arg can't be specified for graph error handler"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
name = get_name(name, class_name)
|
|
191
|
+
step = ErrorStep(
|
|
192
|
+
class_name,
|
|
193
|
+
class_args,
|
|
194
|
+
handler,
|
|
195
|
+
name=name,
|
|
196
|
+
function=function,
|
|
197
|
+
full_event=full_event,
|
|
198
|
+
input_path=input_path,
|
|
199
|
+
result_path=result_path,
|
|
200
|
+
)
|
|
201
|
+
self.on_error = name
|
|
202
|
+
before = [before] if isinstance(before, str) else before
|
|
203
|
+
step.before = before or []
|
|
204
|
+
step.base_step = self.name
|
|
205
|
+
if hasattr(self, "_parent") and self._parent:
|
|
206
|
+
# when self is a step
|
|
207
|
+
step = self._parent._steps.update(name, step)
|
|
208
|
+
step.set_parent(self._parent)
|
|
209
|
+
else:
|
|
210
|
+
# when self is the graph
|
|
211
|
+
step = self._steps.update(name, step)
|
|
212
|
+
step.set_parent(self)
|
|
213
|
+
|
|
142
214
|
return self
|
|
143
215
|
|
|
144
216
|
def init_object(self, context, namespace, mode="sync", reset=False, **extra_kwargs):
|
|
@@ -186,10 +258,11 @@ class BaseStep(ModelObj):
|
|
|
186
258
|
|
|
187
259
|
def _call_error_handler(self, event, err, **kwargs):
|
|
188
260
|
"""call the error handler if exist"""
|
|
189
|
-
if
|
|
190
|
-
event.error =
|
|
191
|
-
|
|
192
|
-
|
|
261
|
+
if not event.error:
|
|
262
|
+
event.error = {}
|
|
263
|
+
event.error[self.name] = err_to_str(err)
|
|
264
|
+
event.origin_state = self.fullname
|
|
265
|
+
return self._on_error_handler(event)
|
|
193
266
|
|
|
194
267
|
def path_to_step(self, path: str):
|
|
195
268
|
"""return step object from step relative/fullname"""
|
|
@@ -206,7 +279,7 @@ class BaseStep(ModelObj):
|
|
|
206
279
|
|
|
207
280
|
def to(
|
|
208
281
|
self,
|
|
209
|
-
class_name: Union[str,
|
|
282
|
+
class_name: Union[str, StepToDict] = None,
|
|
210
283
|
name: str = None,
|
|
211
284
|
handler: str = None,
|
|
212
285
|
graph_shape: str = None,
|
|
@@ -218,11 +291,12 @@ class BaseStep(ModelObj):
|
|
|
218
291
|
):
|
|
219
292
|
"""add a step right after this step and return the new step
|
|
220
293
|
|
|
221
|
-
example
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
294
|
+
example:
|
|
295
|
+
a 4-step pipeline ending with a stream:
|
|
296
|
+
graph.to('URLDownloader')\
|
|
297
|
+
.to('ToParagraphs')\
|
|
298
|
+
.to(name='to_json', handler='json.dumps')\
|
|
299
|
+
.to('>>', 'to_v3io', path=stream_path)\
|
|
226
300
|
|
|
227
301
|
:param class_name: class name or step object to build the step from
|
|
228
302
|
for router steps the class name should start with '*'
|
|
@@ -233,7 +307,7 @@ class BaseStep(ModelObj):
|
|
|
233
307
|
:param function: function this step should run in
|
|
234
308
|
:param full_event: this step accepts the full event (not just body)
|
|
235
309
|
:param input_path: selects the key/path in the event to use as input to the step
|
|
236
|
-
this
|
|
310
|
+
this requires that the event body will behave like a dict, example:
|
|
237
311
|
event: {"data": {"a": 5, "b": 7}}, input_path="data.b" means the step will
|
|
238
312
|
receive 7 as input
|
|
239
313
|
:param result_path: selects the key/path in the event to write the results to
|
|
@@ -327,6 +401,7 @@ class TaskStep(BaseStep):
|
|
|
327
401
|
args = signature(self._handler).parameters
|
|
328
402
|
if args and "context" in list(args.keys()):
|
|
329
403
|
self._inject_context = True
|
|
404
|
+
self._set_error_handler()
|
|
330
405
|
return
|
|
331
406
|
|
|
332
407
|
self._class_object, self.class_name = self.get_step_class_object(
|
|
@@ -464,14 +539,23 @@ class TaskStep(BaseStep):
|
|
|
464
539
|
)
|
|
465
540
|
event.body = _update_result_body(self.result_path, event.body, result)
|
|
466
541
|
except Exception as exc:
|
|
467
|
-
self.
|
|
468
|
-
|
|
469
|
-
|
|
542
|
+
if self._on_error_handler:
|
|
543
|
+
self._log_error(event, exc)
|
|
544
|
+
result = self._call_error_handler(event, exc)
|
|
545
|
+
event.body = _update_result_body(self.result_path, event.body, result)
|
|
546
|
+
else:
|
|
470
547
|
raise exc
|
|
471
|
-
event.terminated = True
|
|
472
548
|
return event
|
|
473
549
|
|
|
474
550
|
|
|
551
|
+
class ErrorStep(TaskStep):
|
|
552
|
+
"""error execution step, runs a class or handler"""
|
|
553
|
+
|
|
554
|
+
kind = "error_step"
|
|
555
|
+
_dict_fields = _task_step_fields + ["before", "base_step"]
|
|
556
|
+
_default_class = ""
|
|
557
|
+
|
|
558
|
+
|
|
475
559
|
class RouterStep(TaskStep):
|
|
476
560
|
"""router step, implement routing logic for running child routes"""
|
|
477
561
|
|
|
@@ -824,6 +908,7 @@ class FlowStep(BaseStep):
|
|
|
824
908
|
def init_object(self, context, namespace, mode="sync", reset=False, **extra_kwargs):
|
|
825
909
|
"""initialize graph objects and classes"""
|
|
826
910
|
self.context = context
|
|
911
|
+
self._insert_all_error_handlers()
|
|
827
912
|
self.check_and_process_graph()
|
|
828
913
|
|
|
829
914
|
for step in self._steps.values():
|
|
@@ -866,7 +951,11 @@ class FlowStep(BaseStep):
|
|
|
866
951
|
|
|
867
952
|
responders = []
|
|
868
953
|
for step in self._steps.values():
|
|
869
|
-
if
|
|
954
|
+
if (
|
|
955
|
+
hasattr(step, "responder")
|
|
956
|
+
and step.responder
|
|
957
|
+
and step.kind != "error_step"
|
|
958
|
+
):
|
|
870
959
|
responders.append(step.name)
|
|
871
960
|
if step.on_error and step.on_error in start_steps:
|
|
872
961
|
start_steps.remove(step.on_error)
|
|
@@ -979,6 +1068,10 @@ class FlowStep(BaseStep):
|
|
|
979
1068
|
# never set a step as its own error handler
|
|
980
1069
|
if step != error_step:
|
|
981
1070
|
step.async_object.set_recovery_step(error_step.async_object)
|
|
1071
|
+
for next_step in error_step.next or []:
|
|
1072
|
+
next_state = self[next_step]
|
|
1073
|
+
if next_state.async_object and error_step.async_object:
|
|
1074
|
+
error_step.async_object.to(next_state.async_object)
|
|
982
1075
|
|
|
983
1076
|
self._controller = source.run()
|
|
984
1077
|
|
|
@@ -1059,15 +1152,22 @@ class FlowStep(BaseStep):
|
|
|
1059
1152
|
try:
|
|
1060
1153
|
event = next_obj.run(event, *args, **kwargs)
|
|
1061
1154
|
except Exception as exc:
|
|
1062
|
-
self.
|
|
1063
|
-
|
|
1064
|
-
|
|
1155
|
+
if self._on_error_handler:
|
|
1156
|
+
self._log_error(event, exc, failed_step=next_obj.name)
|
|
1157
|
+
event.body = self._call_error_handler(event, exc)
|
|
1158
|
+
event.terminated = True
|
|
1159
|
+
return event
|
|
1160
|
+
else:
|
|
1065
1161
|
raise exc
|
|
1066
|
-
event.terminated = True
|
|
1067
|
-
return event
|
|
1068
1162
|
|
|
1069
1163
|
if hasattr(event, "terminated") and event.terminated:
|
|
1070
1164
|
return event
|
|
1165
|
+
if (
|
|
1166
|
+
hasattr(event, "error")
|
|
1167
|
+
and isinstance(event.error, dict)
|
|
1168
|
+
and next_obj.name in event.error
|
|
1169
|
+
):
|
|
1170
|
+
next_obj = self._steps[next_obj.on_error]
|
|
1071
1171
|
next = next_obj.next
|
|
1072
1172
|
if next and len(next) > 1:
|
|
1073
1173
|
raise GraphError(
|
|
@@ -1103,6 +1203,33 @@ class FlowStep(BaseStep):
|
|
|
1103
1203
|
**kw,
|
|
1104
1204
|
)
|
|
1105
1205
|
|
|
1206
|
+
def _insert_all_error_handlers(self):
|
|
1207
|
+
"""
|
|
1208
|
+
insert all error steps to the graph
|
|
1209
|
+
run after deployment
|
|
1210
|
+
"""
|
|
1211
|
+
for name, step in self._steps.items():
|
|
1212
|
+
if step.kind == "error_step":
|
|
1213
|
+
self._insert_error_step(name, step)
|
|
1214
|
+
|
|
1215
|
+
def _insert_error_step(self, name, step):
|
|
1216
|
+
"""
|
|
1217
|
+
insert error step to the graph
|
|
1218
|
+
run after deployment
|
|
1219
|
+
"""
|
|
1220
|
+
if not step.before and not any(
|
|
1221
|
+
[step.name in other_step.after for other_step in self._steps.values()]
|
|
1222
|
+
):
|
|
1223
|
+
step.responder = True
|
|
1224
|
+
return
|
|
1225
|
+
|
|
1226
|
+
for step_name in step.before:
|
|
1227
|
+
if step_name not in self._steps.keys():
|
|
1228
|
+
raise MLRunInvalidArgumentError(
|
|
1229
|
+
f"cant set before, there is no step named {step_name}"
|
|
1230
|
+
)
|
|
1231
|
+
self[step_name].after_step(name)
|
|
1232
|
+
|
|
1106
1233
|
|
|
1107
1234
|
class RootFlowStep(FlowStep):
|
|
1108
1235
|
"""root flow step"""
|
|
@@ -1116,6 +1243,7 @@ classes_map = {
|
|
|
1116
1243
|
"router": RouterStep,
|
|
1117
1244
|
"flow": FlowStep,
|
|
1118
1245
|
"queue": QueueStep,
|
|
1246
|
+
"error_step": ErrorStep,
|
|
1119
1247
|
}
|
|
1120
1248
|
|
|
1121
1249
|
|
|
@@ -1155,15 +1283,8 @@ def _add_graphviz_flow(
|
|
|
1155
1283
|
_add_graphviz_router(sg, child)
|
|
1156
1284
|
else:
|
|
1157
1285
|
graph.node(child.fullname, label=child.name, shape=child.get_shape())
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
previous_object = step[item]
|
|
1161
|
-
kw = (
|
|
1162
|
-
{"ltail": "cluster_" + previous_object.fullname}
|
|
1163
|
-
if previous_object.kind == StepKinds.router
|
|
1164
|
-
else {}
|
|
1165
|
-
)
|
|
1166
|
-
graph.edge(previous_object.fullname, child.fullname, **kw)
|
|
1286
|
+
_add_edges(child.after or [], step, graph, child)
|
|
1287
|
+
_add_edges(getattr(child, "before", []), step, graph, child, after=False)
|
|
1167
1288
|
if child.on_error:
|
|
1168
1289
|
graph.edge(child.fullname, child.on_error, style="dashed")
|
|
1169
1290
|
|
|
@@ -1183,6 +1304,18 @@ def _add_graphviz_flow(
|
|
|
1183
1304
|
graph.edge(last_step, target.fullname)
|
|
1184
1305
|
|
|
1185
1306
|
|
|
1307
|
+
def _add_edges(items, step, graph, child, after=True):
|
|
1308
|
+
for item in items:
|
|
1309
|
+
next_or_prev_object = step[item]
|
|
1310
|
+
kw = {}
|
|
1311
|
+
if next_or_prev_object.kind == StepKinds.router:
|
|
1312
|
+
kw["ltail"] = f"cluster_{next_or_prev_object.fullname}"
|
|
1313
|
+
if after:
|
|
1314
|
+
graph.edge(next_or_prev_object.fullname, child.fullname, **kw)
|
|
1315
|
+
else:
|
|
1316
|
+
graph.edge(child.fullname, next_or_prev_object.fullname, **kw)
|
|
1317
|
+
|
|
1318
|
+
|
|
1186
1319
|
def _generate_graphviz(
|
|
1187
1320
|
step,
|
|
1188
1321
|
renderer,
|
|
@@ -1355,7 +1488,7 @@ def _init_async_objects(context, steps):
|
|
|
1355
1488
|
endpoint, stream_path = parse_path(step.path)
|
|
1356
1489
|
stream_path = stream_path.strip("/")
|
|
1357
1490
|
step._async_object = storey.StreamTarget(
|
|
1358
|
-
storey.V3ioDriver(endpoint),
|
|
1491
|
+
storey.V3ioDriver(endpoint or config.v3io_api),
|
|
1359
1492
|
stream_path,
|
|
1360
1493
|
context=context,
|
|
1361
1494
|
**options,
|
mlrun/serving/utils.py
CHANGED
mlrun/serving/v1_serving.py
CHANGED
mlrun/serving/v2_serving.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.
|
|
@@ -11,23 +11,18 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
14
15
|
import threading
|
|
15
16
|
import time
|
|
16
17
|
import traceback
|
|
17
18
|
from typing import Dict, Union
|
|
18
19
|
|
|
19
20
|
import mlrun
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ModelEndpointMetadata,
|
|
23
|
-
ModelEndpointSpec,
|
|
24
|
-
ModelEndpointStatus,
|
|
25
|
-
ModelMonitoringMode,
|
|
26
|
-
)
|
|
21
|
+
import mlrun.common.model_monitoring
|
|
22
|
+
import mlrun.common.schemas
|
|
27
23
|
from mlrun.artifacts import ModelArtifact # noqa: F401
|
|
28
24
|
from mlrun.config import config
|
|
29
25
|
from mlrun.utils import logger, now_date, parse_versioned_object_uri
|
|
30
|
-
from mlrun.utils.model_monitoring import EndpointType
|
|
31
26
|
|
|
32
27
|
from .server import GraphServer
|
|
33
28
|
from .utils import StepToDict, _extract_input_data, _update_result_body
|
|
@@ -265,11 +260,20 @@ class V2ModelServer(StepToDict):
|
|
|
265
260
|
# get model health operation
|
|
266
261
|
setattr(event, "terminated", True)
|
|
267
262
|
if self.ready:
|
|
268
|
-
|
|
263
|
+
# Generate a response, confirming that the model is ready
|
|
264
|
+
event.body = self.context.Response(
|
|
265
|
+
status_code=200,
|
|
266
|
+
body=bytes(
|
|
267
|
+
f"Model {self.name} is ready (event_id = {event_id})",
|
|
268
|
+
encoding="utf-8",
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
|
|
269
272
|
else:
|
|
270
273
|
event.body = self.context.Response(
|
|
271
274
|
status_code=408, body=b"model not ready"
|
|
272
275
|
)
|
|
276
|
+
|
|
273
277
|
return event
|
|
274
278
|
|
|
275
279
|
elif op == "" and event.method == "GET":
|
|
@@ -404,11 +408,12 @@ class _ModelLogPusher:
|
|
|
404
408
|
return base_data
|
|
405
409
|
|
|
406
410
|
def push(self, start, request, resp=None, op=None, error=None):
|
|
411
|
+
start_str = start.isoformat(sep=" ", timespec="microseconds")
|
|
407
412
|
if error:
|
|
408
413
|
data = self.base_data()
|
|
409
414
|
data["request"] = request
|
|
410
415
|
data["op"] = op
|
|
411
|
-
data["when"] =
|
|
416
|
+
data["when"] = start_str
|
|
412
417
|
message = str(error)
|
|
413
418
|
if self.verbose:
|
|
414
419
|
message = f"{message}\n{traceback.format_exc()}"
|
|
@@ -445,7 +450,7 @@ class _ModelLogPusher:
|
|
|
445
450
|
data["request"] = request
|
|
446
451
|
data["op"] = op
|
|
447
452
|
data["resp"] = resp
|
|
448
|
-
data["when"] =
|
|
453
|
+
data["when"] = start_str
|
|
449
454
|
data["microsec"] = microsec
|
|
450
455
|
if getattr(self.model, "metrics", None):
|
|
451
456
|
data["metrics"] = self.model.metrics
|
|
@@ -486,7 +491,7 @@ def _init_endpoint_record(
|
|
|
486
491
|
versioned_model_name = f"{model.name}:latest"
|
|
487
492
|
|
|
488
493
|
# Generating model endpoint ID based on function uri and model version
|
|
489
|
-
uid = mlrun.
|
|
494
|
+
uid = mlrun.common.model_monitoring.create_model_endpoint_uid(
|
|
490
495
|
function_uri=graph_server.function_uri, versioned_model=versioned_model_name
|
|
491
496
|
).uid
|
|
492
497
|
|
|
@@ -498,11 +503,11 @@ def _init_endpoint_record(
|
|
|
498
503
|
logger.info("Creating a new model endpoint record", endpoint_id=uid)
|
|
499
504
|
|
|
500
505
|
try:
|
|
501
|
-
model_endpoint = ModelEndpoint(
|
|
502
|
-
metadata=ModelEndpointMetadata(
|
|
506
|
+
model_endpoint = mlrun.common.schemas.ModelEndpoint(
|
|
507
|
+
metadata=mlrun.common.schemas.ModelEndpointMetadata(
|
|
503
508
|
project=project, labels=model.labels, uid=uid
|
|
504
509
|
),
|
|
505
|
-
spec=ModelEndpointSpec(
|
|
510
|
+
spec=mlrun.common.schemas.ModelEndpointSpec(
|
|
506
511
|
function_uri=graph_server.function_uri,
|
|
507
512
|
model=versioned_model_name,
|
|
508
513
|
model_class=model.__class__.__name__,
|
|
@@ -511,18 +516,21 @@ def _init_endpoint_record(
|
|
|
511
516
|
project=project, kind="stream"
|
|
512
517
|
),
|
|
513
518
|
active=True,
|
|
514
|
-
monitoring_mode=ModelMonitoringMode.enabled
|
|
519
|
+
monitoring_mode=mlrun.common.model_monitoring.ModelMonitoringMode.enabled
|
|
515
520
|
if model.context.server.track_models
|
|
516
|
-
else ModelMonitoringMode.disabled,
|
|
521
|
+
else mlrun.common.model_monitoring.ModelMonitoringMode.disabled,
|
|
522
|
+
),
|
|
523
|
+
status=mlrun.common.schemas.ModelEndpointStatus(
|
|
524
|
+
endpoint_type=mlrun.common.model_monitoring.EndpointType.NODE_EP
|
|
517
525
|
),
|
|
518
|
-
status=ModelEndpointStatus(endpoint_type=EndpointType.NODE_EP),
|
|
519
526
|
)
|
|
520
527
|
|
|
521
528
|
db = mlrun.get_run_db()
|
|
529
|
+
|
|
522
530
|
db.create_model_endpoint(
|
|
523
531
|
project=project,
|
|
524
|
-
endpoint_id=
|
|
525
|
-
model_endpoint=model_endpoint,
|
|
532
|
+
endpoint_id=uid,
|
|
533
|
+
model_endpoint=model_endpoint.dict(),
|
|
526
534
|
)
|
|
527
535
|
|
|
528
536
|
except Exception as e:
|
mlrun/utils/__init__.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.
|
|
@@ -18,4 +18,3 @@ from .clones import get_git_username_password_from_token # noqa
|
|
|
18
18
|
from .helpers import * # noqa
|
|
19
19
|
from .http import * # noqa
|
|
20
20
|
from .logger import * # noqa
|
|
21
|
-
from .vault import * # noqa
|
mlrun/utils/async_http.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.
|
|
@@ -134,6 +134,13 @@ class _CustomRequestContext(_RequestContext):
|
|
|
134
134
|
params = self._params_list[-1]
|
|
135
135
|
|
|
136
136
|
headers = {k: v for k, v in params.headers.items() if v is not None}
|
|
137
|
+
|
|
138
|
+
# enrich user agent
|
|
139
|
+
# will help traceability and debugging
|
|
140
|
+
headers[
|
|
141
|
+
aiohttp.hdrs.USER_AGENT
|
|
142
|
+
] = f"{aiohttp.http.SERVER_SOFTWARE} mlrun/{config.version}"
|
|
143
|
+
|
|
137
144
|
response: typing.Optional[
|
|
138
145
|
aiohttp.ClientResponse
|
|
139
146
|
] = await self._request_func(
|
mlrun/utils/azure_vault.py
CHANGED
mlrun/utils/clones.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.
|
|
@@ -51,7 +51,7 @@ def get_git_username_password_from_token(token):
|
|
|
51
51
|
# Github's access tokens have a known prefix according to their type. See
|
|
52
52
|
# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#githubs-token-formats
|
|
53
53
|
# We distinguish new fine-grained access tokens (begin with "github_pat_" from classic tokens.
|
|
54
|
-
if token.startswith("github_pat_"):
|
|
54
|
+
if token.startswith("github_pat_") or token.startswith("glpat"):
|
|
55
55
|
username = "oauth2"
|
|
56
56
|
password = token
|
|
57
57
|
else:
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import multiprocessing
|
|
16
|
+
import typing
|
|
17
|
+
|
|
18
|
+
from mlrun.utils import logger
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def evaluate_condition_in_separate_process(
|
|
22
|
+
condition: str, context: typing.Dict[str, typing.Any], timeout: int = 5
|
|
23
|
+
):
|
|
24
|
+
|
|
25
|
+
if not condition:
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
receiver, sender = multiprocessing.Pipe()
|
|
29
|
+
p = multiprocessing.Process(
|
|
30
|
+
target=_evaluate_condition_wrapper,
|
|
31
|
+
args=(sender, condition, context),
|
|
32
|
+
)
|
|
33
|
+
p.start()
|
|
34
|
+
if receiver.poll(timeout):
|
|
35
|
+
result = receiver.recv()
|
|
36
|
+
p.join()
|
|
37
|
+
return result
|
|
38
|
+
else:
|
|
39
|
+
p.kill()
|
|
40
|
+
logger.warning(
|
|
41
|
+
f"Condition evaluation timed out after {timeout} seconds. Ignoring condition",
|
|
42
|
+
condition=condition,
|
|
43
|
+
)
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _evaluate_condition_wrapper(
|
|
48
|
+
connection, condition: str, context: typing.Dict[str, typing.Any]
|
|
49
|
+
):
|
|
50
|
+
connection.send(_evaluate_condition(condition, context))
|
|
51
|
+
return connection.close()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _evaluate_condition(condition: str, context: typing.Dict[str, typing.Any]):
|
|
55
|
+
|
|
56
|
+
import jinja2.sandbox
|
|
57
|
+
|
|
58
|
+
jinja_env = jinja2.sandbox.SandboxedEnvironment()
|
|
59
|
+
template = jinja_env.from_string(condition)
|
|
60
|
+
result = template.render(**context)
|
|
61
|
+
if result.lower() in ["0", "no", "n", "f", "false", "off"]:
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
# if the condition is not a boolean, we ignore the condition
|
|
65
|
+
return True
|
mlrun/utils/db.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
import pickle
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
|
|
18
|
+
from sqlalchemy.orm import class_mapper
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BaseModel:
|
|
22
|
+
def to_dict(self, exclude=None):
|
|
23
|
+
"""
|
|
24
|
+
NOTE - this function (currently) does not handle serializing relationships
|
|
25
|
+
"""
|
|
26
|
+
exclude = exclude or []
|
|
27
|
+
mapper = class_mapper(self.__class__)
|
|
28
|
+
columns = [column.key for column in mapper.columns if column.key not in exclude]
|
|
29
|
+
get_key_value = (
|
|
30
|
+
lambda c: (c, getattr(self, c).isoformat())
|
|
31
|
+
if isinstance(getattr(self, c), datetime)
|
|
32
|
+
else (c, getattr(self, c))
|
|
33
|
+
)
|
|
34
|
+
return dict(map(get_key_value, columns))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class HasStruct(BaseModel):
|
|
38
|
+
@property
|
|
39
|
+
def struct(self):
|
|
40
|
+
return pickle.loads(self.body)
|
|
41
|
+
|
|
42
|
+
@struct.setter
|
|
43
|
+
def struct(self, value):
|
|
44
|
+
self.body = pickle.dumps(value)
|
|
45
|
+
|
|
46
|
+
def to_dict(self, exclude=None):
|
|
47
|
+
"""
|
|
48
|
+
NOTE - this function (currently) does not handle serializing relationships
|
|
49
|
+
"""
|
|
50
|
+
exclude = exclude or []
|
|
51
|
+
exclude.append("body")
|
|
52
|
+
return super().to_dict(exclude)
|