genesis-flow 1.0.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.
- genesis_flow-1.0.0.dist-info/METADATA +822 -0
- genesis_flow-1.0.0.dist-info/RECORD +645 -0
- genesis_flow-1.0.0.dist-info/WHEEL +5 -0
- genesis_flow-1.0.0.dist-info/entry_points.txt +19 -0
- genesis_flow-1.0.0.dist-info/licenses/LICENSE.txt +202 -0
- genesis_flow-1.0.0.dist-info/top_level.txt +1 -0
- mlflow/__init__.py +367 -0
- mlflow/__main__.py +3 -0
- mlflow/ag2/__init__.py +56 -0
- mlflow/ag2/ag2_logger.py +294 -0
- mlflow/anthropic/__init__.py +40 -0
- mlflow/anthropic/autolog.py +129 -0
- mlflow/anthropic/chat.py +144 -0
- mlflow/artifacts/__init__.py +268 -0
- mlflow/autogen/__init__.py +144 -0
- mlflow/autogen/chat.py +142 -0
- mlflow/azure/__init__.py +26 -0
- mlflow/azure/auth_handler.py +257 -0
- mlflow/azure/client.py +319 -0
- mlflow/azure/config.py +120 -0
- mlflow/azure/connection_factory.py +340 -0
- mlflow/azure/exceptions.py +27 -0
- mlflow/azure/stores.py +327 -0
- mlflow/azure/utils.py +183 -0
- mlflow/bedrock/__init__.py +45 -0
- mlflow/bedrock/_autolog.py +202 -0
- mlflow/bedrock/chat.py +122 -0
- mlflow/bedrock/stream.py +160 -0
- mlflow/bedrock/utils.py +43 -0
- mlflow/cli.py +707 -0
- mlflow/client.py +12 -0
- mlflow/config/__init__.py +56 -0
- mlflow/crewai/__init__.py +79 -0
- mlflow/crewai/autolog.py +253 -0
- mlflow/crewai/chat.py +29 -0
- mlflow/data/__init__.py +75 -0
- mlflow/data/artifact_dataset_sources.py +170 -0
- mlflow/data/code_dataset_source.py +40 -0
- mlflow/data/dataset.py +123 -0
- mlflow/data/dataset_registry.py +168 -0
- mlflow/data/dataset_source.py +110 -0
- mlflow/data/dataset_source_registry.py +219 -0
- mlflow/data/delta_dataset_source.py +167 -0
- mlflow/data/digest_utils.py +108 -0
- mlflow/data/evaluation_dataset.py +562 -0
- mlflow/data/filesystem_dataset_source.py +81 -0
- mlflow/data/http_dataset_source.py +145 -0
- mlflow/data/huggingface_dataset.py +258 -0
- mlflow/data/huggingface_dataset_source.py +118 -0
- mlflow/data/meta_dataset.py +104 -0
- mlflow/data/numpy_dataset.py +223 -0
- mlflow/data/pandas_dataset.py +231 -0
- mlflow/data/polars_dataset.py +352 -0
- mlflow/data/pyfunc_dataset_mixin.py +31 -0
- mlflow/data/schema.py +76 -0
- mlflow/data/sources.py +1 -0
- mlflow/data/spark_dataset.py +406 -0
- mlflow/data/spark_dataset_source.py +74 -0
- mlflow/data/spark_delta_utils.py +118 -0
- mlflow/data/tensorflow_dataset.py +350 -0
- mlflow/data/uc_volume_dataset_source.py +81 -0
- mlflow/db.py +27 -0
- mlflow/dspy/__init__.py +17 -0
- mlflow/dspy/autolog.py +197 -0
- mlflow/dspy/callback.py +398 -0
- mlflow/dspy/constant.py +1 -0
- mlflow/dspy/load.py +93 -0
- mlflow/dspy/save.py +393 -0
- mlflow/dspy/util.py +109 -0
- mlflow/dspy/wrapper.py +226 -0
- mlflow/entities/__init__.py +104 -0
- mlflow/entities/_mlflow_object.py +52 -0
- mlflow/entities/assessment.py +545 -0
- mlflow/entities/assessment_error.py +80 -0
- mlflow/entities/assessment_source.py +141 -0
- mlflow/entities/dataset.py +92 -0
- mlflow/entities/dataset_input.py +51 -0
- mlflow/entities/dataset_summary.py +62 -0
- mlflow/entities/document.py +48 -0
- mlflow/entities/experiment.py +109 -0
- mlflow/entities/experiment_tag.py +35 -0
- mlflow/entities/file_info.py +45 -0
- mlflow/entities/input_tag.py +35 -0
- mlflow/entities/lifecycle_stage.py +35 -0
- mlflow/entities/logged_model.py +228 -0
- mlflow/entities/logged_model_input.py +26 -0
- mlflow/entities/logged_model_output.py +32 -0
- mlflow/entities/logged_model_parameter.py +46 -0
- mlflow/entities/logged_model_status.py +74 -0
- mlflow/entities/logged_model_tag.py +33 -0
- mlflow/entities/metric.py +200 -0
- mlflow/entities/model_registry/__init__.py +29 -0
- mlflow/entities/model_registry/_model_registry_entity.py +13 -0
- mlflow/entities/model_registry/model_version.py +243 -0
- mlflow/entities/model_registry/model_version_deployment_job_run_state.py +44 -0
- mlflow/entities/model_registry/model_version_deployment_job_state.py +70 -0
- mlflow/entities/model_registry/model_version_search.py +25 -0
- mlflow/entities/model_registry/model_version_stages.py +25 -0
- mlflow/entities/model_registry/model_version_status.py +35 -0
- mlflow/entities/model_registry/model_version_tag.py +35 -0
- mlflow/entities/model_registry/prompt.py +73 -0
- mlflow/entities/model_registry/prompt_version.py +244 -0
- mlflow/entities/model_registry/registered_model.py +175 -0
- mlflow/entities/model_registry/registered_model_alias.py +35 -0
- mlflow/entities/model_registry/registered_model_deployment_job_state.py +39 -0
- mlflow/entities/model_registry/registered_model_search.py +25 -0
- mlflow/entities/model_registry/registered_model_tag.py +35 -0
- mlflow/entities/multipart_upload.py +74 -0
- mlflow/entities/param.py +49 -0
- mlflow/entities/run.py +97 -0
- mlflow/entities/run_data.py +84 -0
- mlflow/entities/run_info.py +188 -0
- mlflow/entities/run_inputs.py +59 -0
- mlflow/entities/run_outputs.py +43 -0
- mlflow/entities/run_status.py +41 -0
- mlflow/entities/run_tag.py +36 -0
- mlflow/entities/source_type.py +31 -0
- mlflow/entities/span.py +774 -0
- mlflow/entities/span_event.py +96 -0
- mlflow/entities/span_status.py +102 -0
- mlflow/entities/trace.py +317 -0
- mlflow/entities/trace_data.py +71 -0
- mlflow/entities/trace_info.py +220 -0
- mlflow/entities/trace_info_v2.py +162 -0
- mlflow/entities/trace_location.py +173 -0
- mlflow/entities/trace_state.py +39 -0
- mlflow/entities/trace_status.py +68 -0
- mlflow/entities/view_type.py +51 -0
- mlflow/environment_variables.py +866 -0
- mlflow/evaluation/__init__.py +16 -0
- mlflow/evaluation/assessment.py +369 -0
- mlflow/evaluation/evaluation.py +411 -0
- mlflow/evaluation/evaluation_tag.py +61 -0
- mlflow/evaluation/fluent.py +48 -0
- mlflow/evaluation/utils.py +201 -0
- mlflow/exceptions.py +213 -0
- mlflow/experiments.py +140 -0
- mlflow/gemini/__init__.py +81 -0
- mlflow/gemini/autolog.py +186 -0
- mlflow/gemini/chat.py +261 -0
- mlflow/genai/__init__.py +71 -0
- mlflow/genai/datasets/__init__.py +67 -0
- mlflow/genai/datasets/evaluation_dataset.py +131 -0
- mlflow/genai/evaluation/__init__.py +3 -0
- mlflow/genai/evaluation/base.py +411 -0
- mlflow/genai/evaluation/constant.py +23 -0
- mlflow/genai/evaluation/utils.py +244 -0
- mlflow/genai/judges/__init__.py +21 -0
- mlflow/genai/judges/databricks.py +404 -0
- mlflow/genai/label_schemas/__init__.py +153 -0
- mlflow/genai/label_schemas/label_schemas.py +209 -0
- mlflow/genai/labeling/__init__.py +159 -0
- mlflow/genai/labeling/labeling.py +250 -0
- mlflow/genai/optimize/__init__.py +13 -0
- mlflow/genai/optimize/base.py +198 -0
- mlflow/genai/optimize/optimizers/__init__.py +4 -0
- mlflow/genai/optimize/optimizers/base_optimizer.py +38 -0
- mlflow/genai/optimize/optimizers/dspy_mipro_optimizer.py +221 -0
- mlflow/genai/optimize/optimizers/dspy_optimizer.py +91 -0
- mlflow/genai/optimize/optimizers/utils/dspy_mipro_callback.py +76 -0
- mlflow/genai/optimize/optimizers/utils/dspy_mipro_utils.py +18 -0
- mlflow/genai/optimize/types.py +75 -0
- mlflow/genai/optimize/util.py +30 -0
- mlflow/genai/prompts/__init__.py +206 -0
- mlflow/genai/scheduled_scorers.py +431 -0
- mlflow/genai/scorers/__init__.py +26 -0
- mlflow/genai/scorers/base.py +492 -0
- mlflow/genai/scorers/builtin_scorers.py +765 -0
- mlflow/genai/scorers/scorer_utils.py +138 -0
- mlflow/genai/scorers/validation.py +165 -0
- mlflow/genai/utils/data_validation.py +146 -0
- mlflow/genai/utils/enum_utils.py +23 -0
- mlflow/genai/utils/trace_utils.py +211 -0
- mlflow/groq/__init__.py +42 -0
- mlflow/groq/_groq_autolog.py +74 -0
- mlflow/johnsnowlabs/__init__.py +888 -0
- mlflow/langchain/__init__.py +24 -0
- mlflow/langchain/api_request_parallel_processor.py +330 -0
- mlflow/langchain/autolog.py +147 -0
- mlflow/langchain/chat_agent_langgraph.py +340 -0
- mlflow/langchain/constant.py +1 -0
- mlflow/langchain/constants.py +1 -0
- mlflow/langchain/databricks_dependencies.py +444 -0
- mlflow/langchain/langchain_tracer.py +597 -0
- mlflow/langchain/model.py +919 -0
- mlflow/langchain/output_parsers.py +142 -0
- mlflow/langchain/retriever_chain.py +153 -0
- mlflow/langchain/runnables.py +527 -0
- mlflow/langchain/utils/chat.py +402 -0
- mlflow/langchain/utils/logging.py +671 -0
- mlflow/langchain/utils/serialization.py +36 -0
- mlflow/legacy_databricks_cli/__init__.py +0 -0
- mlflow/legacy_databricks_cli/configure/__init__.py +0 -0
- mlflow/legacy_databricks_cli/configure/provider.py +482 -0
- mlflow/litellm/__init__.py +175 -0
- mlflow/llama_index/__init__.py +22 -0
- mlflow/llama_index/autolog.py +55 -0
- mlflow/llama_index/chat.py +43 -0
- mlflow/llama_index/constant.py +1 -0
- mlflow/llama_index/model.py +577 -0
- mlflow/llama_index/pyfunc_wrapper.py +332 -0
- mlflow/llama_index/serialize_objects.py +188 -0
- mlflow/llama_index/tracer.py +561 -0
- mlflow/metrics/__init__.py +479 -0
- mlflow/metrics/base.py +39 -0
- mlflow/metrics/genai/__init__.py +25 -0
- mlflow/metrics/genai/base.py +101 -0
- mlflow/metrics/genai/genai_metric.py +771 -0
- mlflow/metrics/genai/metric_definitions.py +450 -0
- mlflow/metrics/genai/model_utils.py +371 -0
- mlflow/metrics/genai/prompt_template.py +68 -0
- mlflow/metrics/genai/prompts/__init__.py +0 -0
- mlflow/metrics/genai/prompts/v1.py +422 -0
- mlflow/metrics/genai/utils.py +6 -0
- mlflow/metrics/metric_definitions.py +619 -0
- mlflow/mismatch.py +34 -0
- mlflow/mistral/__init__.py +34 -0
- mlflow/mistral/autolog.py +71 -0
- mlflow/mistral/chat.py +135 -0
- mlflow/ml_package_versions.py +452 -0
- mlflow/models/__init__.py +97 -0
- mlflow/models/auth_policy.py +83 -0
- mlflow/models/cli.py +354 -0
- mlflow/models/container/__init__.py +294 -0
- mlflow/models/container/scoring_server/__init__.py +0 -0
- mlflow/models/container/scoring_server/nginx.conf +39 -0
- mlflow/models/dependencies_schemas.py +287 -0
- mlflow/models/display_utils.py +158 -0
- mlflow/models/docker_utils.py +211 -0
- mlflow/models/evaluation/__init__.py +23 -0
- mlflow/models/evaluation/_shap_patch.py +64 -0
- mlflow/models/evaluation/artifacts.py +194 -0
- mlflow/models/evaluation/base.py +1811 -0
- mlflow/models/evaluation/calibration_curve.py +109 -0
- mlflow/models/evaluation/default_evaluator.py +996 -0
- mlflow/models/evaluation/deprecated.py +23 -0
- mlflow/models/evaluation/evaluator_registry.py +80 -0
- mlflow/models/evaluation/evaluators/classifier.py +704 -0
- mlflow/models/evaluation/evaluators/default.py +233 -0
- mlflow/models/evaluation/evaluators/regressor.py +96 -0
- mlflow/models/evaluation/evaluators/shap.py +296 -0
- mlflow/models/evaluation/lift_curve.py +178 -0
- mlflow/models/evaluation/utils/metric.py +123 -0
- mlflow/models/evaluation/utils/trace.py +179 -0
- mlflow/models/evaluation/validation.py +434 -0
- mlflow/models/flavor_backend.py +93 -0
- mlflow/models/flavor_backend_registry.py +53 -0
- mlflow/models/model.py +1639 -0
- mlflow/models/model_config.py +150 -0
- mlflow/models/notebook_resources/agent_evaluation_template.html +235 -0
- mlflow/models/notebook_resources/eval_with_dataset_example.py +22 -0
- mlflow/models/notebook_resources/eval_with_synthetic_example.py +22 -0
- mlflow/models/python_api.py +369 -0
- mlflow/models/rag_signatures.py +128 -0
- mlflow/models/resources.py +321 -0
- mlflow/models/signature.py +662 -0
- mlflow/models/utils.py +2054 -0
- mlflow/models/wheeled_model.py +280 -0
- mlflow/openai/__init__.py +57 -0
- mlflow/openai/_agent_tracer.py +364 -0
- mlflow/openai/api_request_parallel_processor.py +131 -0
- mlflow/openai/autolog.py +509 -0
- mlflow/openai/constant.py +1 -0
- mlflow/openai/model.py +824 -0
- mlflow/openai/utils/chat_schema.py +367 -0
- mlflow/optuna/__init__.py +3 -0
- mlflow/optuna/storage.py +646 -0
- mlflow/plugins/__init__.py +72 -0
- mlflow/plugins/base.py +358 -0
- mlflow/plugins/builtin/__init__.py +24 -0
- mlflow/plugins/builtin/pytorch_plugin.py +150 -0
- mlflow/plugins/builtin/sklearn_plugin.py +158 -0
- mlflow/plugins/builtin/transformers_plugin.py +187 -0
- mlflow/plugins/cli.py +321 -0
- mlflow/plugins/discovery.py +340 -0
- mlflow/plugins/manager.py +465 -0
- mlflow/plugins/registry.py +316 -0
- mlflow/plugins/templates/framework_plugin_template.py +329 -0
- mlflow/prompt/constants.py +20 -0
- mlflow/prompt/promptlab_model.py +197 -0
- mlflow/prompt/registry_utils.py +248 -0
- mlflow/promptflow/__init__.py +495 -0
- mlflow/protos/__init__.py +0 -0
- mlflow/protos/assessments_pb2.py +174 -0
- mlflow/protos/databricks_artifacts_pb2.py +489 -0
- mlflow/protos/databricks_filesystem_service_pb2.py +196 -0
- mlflow/protos/databricks_managed_catalog_messages_pb2.py +95 -0
- mlflow/protos/databricks_managed_catalog_service_pb2.py +86 -0
- mlflow/protos/databricks_pb2.py +267 -0
- mlflow/protos/databricks_trace_server_pb2.py +374 -0
- mlflow/protos/databricks_uc_registry_messages_pb2.py +1249 -0
- mlflow/protos/databricks_uc_registry_service_pb2.py +170 -0
- mlflow/protos/facet_feature_statistics_pb2.py +296 -0
- mlflow/protos/internal_pb2.py +77 -0
- mlflow/protos/mlflow_artifacts_pb2.py +336 -0
- mlflow/protos/model_registry_pb2.py +1073 -0
- mlflow/protos/scalapb/__init__.py +0 -0
- mlflow/protos/scalapb/scalapb_pb2.py +104 -0
- mlflow/protos/service_pb2.py +2600 -0
- mlflow/protos/unity_catalog_oss_messages_pb2.py +457 -0
- mlflow/protos/unity_catalog_oss_service_pb2.py +130 -0
- mlflow/protos/unity_catalog_prompt_messages_pb2.py +447 -0
- mlflow/protos/unity_catalog_prompt_messages_pb2_grpc.py +24 -0
- mlflow/protos/unity_catalog_prompt_service_pb2.py +164 -0
- mlflow/protos/unity_catalog_prompt_service_pb2_grpc.py +785 -0
- mlflow/py.typed +0 -0
- mlflow/pydantic_ai/__init__.py +57 -0
- mlflow/pydantic_ai/autolog.py +173 -0
- mlflow/pyfunc/__init__.py +3844 -0
- mlflow/pyfunc/_mlflow_pyfunc_backend_predict.py +61 -0
- mlflow/pyfunc/backend.py +523 -0
- mlflow/pyfunc/context.py +78 -0
- mlflow/pyfunc/dbconnect_artifact_cache.py +144 -0
- mlflow/pyfunc/loaders/__init__.py +7 -0
- mlflow/pyfunc/loaders/chat_agent.py +117 -0
- mlflow/pyfunc/loaders/chat_model.py +125 -0
- mlflow/pyfunc/loaders/code_model.py +31 -0
- mlflow/pyfunc/loaders/responses_agent.py +112 -0
- mlflow/pyfunc/mlserver.py +46 -0
- mlflow/pyfunc/model.py +1473 -0
- mlflow/pyfunc/scoring_server/__init__.py +604 -0
- mlflow/pyfunc/scoring_server/app.py +7 -0
- mlflow/pyfunc/scoring_server/client.py +146 -0
- mlflow/pyfunc/spark_model_cache.py +48 -0
- mlflow/pyfunc/stdin_server.py +44 -0
- mlflow/pyfunc/utils/__init__.py +3 -0
- mlflow/pyfunc/utils/data_validation.py +224 -0
- mlflow/pyfunc/utils/environment.py +22 -0
- mlflow/pyfunc/utils/input_converter.py +47 -0
- mlflow/pyfunc/utils/serving_data_parser.py +11 -0
- mlflow/pytorch/__init__.py +1171 -0
- mlflow/pytorch/_lightning_autolog.py +580 -0
- mlflow/pytorch/_pytorch_autolog.py +50 -0
- mlflow/pytorch/pickle_module.py +35 -0
- mlflow/rfunc/__init__.py +42 -0
- mlflow/rfunc/backend.py +134 -0
- mlflow/runs.py +89 -0
- mlflow/server/__init__.py +302 -0
- mlflow/server/auth/__init__.py +1224 -0
- mlflow/server/auth/__main__.py +4 -0
- mlflow/server/auth/basic_auth.ini +6 -0
- mlflow/server/auth/cli.py +11 -0
- mlflow/server/auth/client.py +537 -0
- mlflow/server/auth/config.py +34 -0
- mlflow/server/auth/db/__init__.py +0 -0
- mlflow/server/auth/db/cli.py +18 -0
- mlflow/server/auth/db/migrations/__init__.py +0 -0
- mlflow/server/auth/db/migrations/alembic.ini +110 -0
- mlflow/server/auth/db/migrations/env.py +76 -0
- mlflow/server/auth/db/migrations/versions/8606fa83a998_initial_migration.py +51 -0
- mlflow/server/auth/db/migrations/versions/__init__.py +0 -0
- mlflow/server/auth/db/models.py +67 -0
- mlflow/server/auth/db/utils.py +37 -0
- mlflow/server/auth/entities.py +165 -0
- mlflow/server/auth/logo.py +14 -0
- mlflow/server/auth/permissions.py +65 -0
- mlflow/server/auth/routes.py +18 -0
- mlflow/server/auth/sqlalchemy_store.py +263 -0
- mlflow/server/graphql/__init__.py +0 -0
- mlflow/server/graphql/autogenerated_graphql_schema.py +353 -0
- mlflow/server/graphql/graphql_custom_scalars.py +24 -0
- mlflow/server/graphql/graphql_errors.py +15 -0
- mlflow/server/graphql/graphql_no_batching.py +89 -0
- mlflow/server/graphql/graphql_schema_extensions.py +74 -0
- mlflow/server/handlers.py +3217 -0
- mlflow/server/prometheus_exporter.py +17 -0
- mlflow/server/validation.py +30 -0
- mlflow/shap/__init__.py +691 -0
- mlflow/sklearn/__init__.py +1994 -0
- mlflow/sklearn/utils.py +1041 -0
- mlflow/smolagents/__init__.py +66 -0
- mlflow/smolagents/autolog.py +139 -0
- mlflow/smolagents/chat.py +29 -0
- mlflow/store/__init__.py +10 -0
- mlflow/store/_unity_catalog/__init__.py +1 -0
- mlflow/store/_unity_catalog/lineage/__init__.py +1 -0
- mlflow/store/_unity_catalog/lineage/constants.py +2 -0
- mlflow/store/_unity_catalog/registry/__init__.py +6 -0
- mlflow/store/_unity_catalog/registry/prompt_info.py +75 -0
- mlflow/store/_unity_catalog/registry/rest_store.py +1740 -0
- mlflow/store/_unity_catalog/registry/uc_oss_rest_store.py +507 -0
- mlflow/store/_unity_catalog/registry/utils.py +121 -0
- mlflow/store/artifact/__init__.py +0 -0
- mlflow/store/artifact/artifact_repo.py +472 -0
- mlflow/store/artifact/artifact_repository_registry.py +154 -0
- mlflow/store/artifact/azure_blob_artifact_repo.py +275 -0
- mlflow/store/artifact/azure_data_lake_artifact_repo.py +295 -0
- mlflow/store/artifact/cli.py +141 -0
- mlflow/store/artifact/cloud_artifact_repo.py +332 -0
- mlflow/store/artifact/databricks_artifact_repo.py +729 -0
- mlflow/store/artifact/databricks_artifact_repo_resources.py +301 -0
- mlflow/store/artifact/databricks_logged_model_artifact_repo.py +93 -0
- mlflow/store/artifact/databricks_models_artifact_repo.py +216 -0
- mlflow/store/artifact/databricks_sdk_artifact_repo.py +134 -0
- mlflow/store/artifact/databricks_sdk_models_artifact_repo.py +97 -0
- mlflow/store/artifact/dbfs_artifact_repo.py +240 -0
- mlflow/store/artifact/ftp_artifact_repo.py +132 -0
- mlflow/store/artifact/gcs_artifact_repo.py +296 -0
- mlflow/store/artifact/hdfs_artifact_repo.py +209 -0
- mlflow/store/artifact/http_artifact_repo.py +218 -0
- mlflow/store/artifact/local_artifact_repo.py +142 -0
- mlflow/store/artifact/mlflow_artifacts_repo.py +94 -0
- mlflow/store/artifact/models_artifact_repo.py +259 -0
- mlflow/store/artifact/optimized_s3_artifact_repo.py +356 -0
- mlflow/store/artifact/presigned_url_artifact_repo.py +173 -0
- mlflow/store/artifact/r2_artifact_repo.py +70 -0
- mlflow/store/artifact/runs_artifact_repo.py +265 -0
- mlflow/store/artifact/s3_artifact_repo.py +330 -0
- mlflow/store/artifact/sftp_artifact_repo.py +141 -0
- mlflow/store/artifact/uc_volume_artifact_repo.py +76 -0
- mlflow/store/artifact/unity_catalog_models_artifact_repo.py +168 -0
- mlflow/store/artifact/unity_catalog_oss_models_artifact_repo.py +168 -0
- mlflow/store/artifact/utils/__init__.py +0 -0
- mlflow/store/artifact/utils/models.py +148 -0
- mlflow/store/db/__init__.py +0 -0
- mlflow/store/db/base_sql_model.py +3 -0
- mlflow/store/db/db_types.py +10 -0
- mlflow/store/db/utils.py +314 -0
- mlflow/store/db_migrations/__init__.py +0 -0
- mlflow/store/db_migrations/alembic.ini +74 -0
- mlflow/store/db_migrations/env.py +84 -0
- mlflow/store/db_migrations/versions/0584bdc529eb_add_cascading_deletion_to_datasets_from_experiments.py +88 -0
- mlflow/store/db_migrations/versions/0a8213491aaa_drop_duplicate_killed_constraint.py +49 -0
- mlflow/store/db_migrations/versions/0c779009ac13_add_deleted_time_field_to_runs_table.py +24 -0
- mlflow/store/db_migrations/versions/181f10493468_allow_nulls_for_metric_values.py +35 -0
- mlflow/store/db_migrations/versions/27a6a02d2cf1_add_model_version_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/2b4d017a5e9b_add_model_registry_tables_to_db.py +77 -0
- mlflow/store/db_migrations/versions/2d6e25af4d3e_increase_max_param_val_length.py +33 -0
- mlflow/store/db_migrations/versions/3500859a5d39_add_model_aliases_table.py +50 -0
- mlflow/store/db_migrations/versions/39d1c3be5f05_add_is_nan_constraint_for_metrics_tables_if_necessary.py +41 -0
- mlflow/store/db_migrations/versions/400f98739977_add_logged_model_tables.py +123 -0
- mlflow/store/db_migrations/versions/4465047574b1_increase_max_dataset_schema_size.py +38 -0
- mlflow/store/db_migrations/versions/451aebb31d03_add_metric_step.py +35 -0
- mlflow/store/db_migrations/versions/5b0e9adcef9c_add_cascade_deletion_to_trace_tables_fk.py +40 -0
- mlflow/store/db_migrations/versions/6953534de441_add_step_to_inputs_table.py +25 -0
- mlflow/store/db_migrations/versions/728d730b5ebd_add_registered_model_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/7ac759974ad8_update_run_tags_with_larger_limit.py +36 -0
- mlflow/store/db_migrations/versions/7f2a7d5fae7d_add_datasets_inputs_input_tags_tables.py +82 -0
- mlflow/store/db_migrations/versions/84291f40a231_add_run_link_to_model_version.py +26 -0
- mlflow/store/db_migrations/versions/867495a8f9d4_add_trace_tables.py +90 -0
- mlflow/store/db_migrations/versions/89d4b8295536_create_latest_metrics_table.py +169 -0
- mlflow/store/db_migrations/versions/90e64c465722_migrate_user_column_to_tags.py +64 -0
- mlflow/store/db_migrations/versions/97727af70f4d_creation_time_last_update_time_experiments.py +25 -0
- mlflow/store/db_migrations/versions/__init__.py +0 -0
- mlflow/store/db_migrations/versions/a8c4a736bde6_allow_nulls_for_run_id.py +27 -0
- mlflow/store/db_migrations/versions/acf3f17fdcc7_add_storage_location_field_to_model_.py +29 -0
- mlflow/store/db_migrations/versions/bd07f7e963c5_create_index_on_run_uuid.py +26 -0
- mlflow/store/db_migrations/versions/bda7b8c39065_increase_model_version_tag_value_limit.py +38 -0
- mlflow/store/db_migrations/versions/c48cb773bb87_reset_default_value_for_is_nan_in_metrics_table_for_mysql.py +41 -0
- mlflow/store/db_migrations/versions/cbc13b556ace_add_v3_trace_schema_columns.py +31 -0
- mlflow/store/db_migrations/versions/cc1f77228345_change_param_value_length_to_500.py +34 -0
- mlflow/store/db_migrations/versions/cfd24bdc0731_update_run_status_constraint_with_killed.py +78 -0
- mlflow/store/db_migrations/versions/df50e92ffc5e_add_experiment_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/f5a4f2784254_increase_run_tag_value_limit.py +36 -0
- mlflow/store/entities/__init__.py +3 -0
- mlflow/store/entities/paged_list.py +18 -0
- mlflow/store/model_registry/__init__.py +10 -0
- mlflow/store/model_registry/abstract_store.py +1081 -0
- mlflow/store/model_registry/base_rest_store.py +44 -0
- mlflow/store/model_registry/databricks_workspace_model_registry_rest_store.py +37 -0
- mlflow/store/model_registry/dbmodels/__init__.py +0 -0
- mlflow/store/model_registry/dbmodels/models.py +206 -0
- mlflow/store/model_registry/file_store.py +1091 -0
- mlflow/store/model_registry/rest_store.py +481 -0
- mlflow/store/model_registry/sqlalchemy_store.py +1286 -0
- mlflow/store/tracking/__init__.py +23 -0
- mlflow/store/tracking/abstract_store.py +816 -0
- mlflow/store/tracking/dbmodels/__init__.py +0 -0
- mlflow/store/tracking/dbmodels/initial_models.py +243 -0
- mlflow/store/tracking/dbmodels/models.py +1073 -0
- mlflow/store/tracking/file_store.py +2438 -0
- mlflow/store/tracking/postgres_managed_identity.py +146 -0
- mlflow/store/tracking/rest_store.py +1131 -0
- mlflow/store/tracking/sqlalchemy_store.py +2785 -0
- mlflow/system_metrics/__init__.py +61 -0
- mlflow/system_metrics/metrics/__init__.py +0 -0
- mlflow/system_metrics/metrics/base_metrics_monitor.py +32 -0
- mlflow/system_metrics/metrics/cpu_monitor.py +23 -0
- mlflow/system_metrics/metrics/disk_monitor.py +21 -0
- mlflow/system_metrics/metrics/gpu_monitor.py +71 -0
- mlflow/system_metrics/metrics/network_monitor.py +34 -0
- mlflow/system_metrics/metrics/rocm_monitor.py +123 -0
- mlflow/system_metrics/system_metrics_monitor.py +198 -0
- mlflow/tracing/__init__.py +16 -0
- mlflow/tracing/assessment.py +356 -0
- mlflow/tracing/client.py +531 -0
- mlflow/tracing/config.py +125 -0
- mlflow/tracing/constant.py +105 -0
- mlflow/tracing/destination.py +81 -0
- mlflow/tracing/display/__init__.py +40 -0
- mlflow/tracing/display/display_handler.py +196 -0
- mlflow/tracing/export/async_export_queue.py +186 -0
- mlflow/tracing/export/inference_table.py +138 -0
- mlflow/tracing/export/mlflow_v3.py +137 -0
- mlflow/tracing/export/utils.py +70 -0
- mlflow/tracing/fluent.py +1417 -0
- mlflow/tracing/processor/base_mlflow.py +199 -0
- mlflow/tracing/processor/inference_table.py +175 -0
- mlflow/tracing/processor/mlflow_v3.py +47 -0
- mlflow/tracing/processor/otel.py +73 -0
- mlflow/tracing/provider.py +487 -0
- mlflow/tracing/trace_manager.py +200 -0
- mlflow/tracing/utils/__init__.py +616 -0
- mlflow/tracing/utils/artifact_utils.py +28 -0
- mlflow/tracing/utils/copy.py +55 -0
- mlflow/tracing/utils/environment.py +55 -0
- mlflow/tracing/utils/exception.py +21 -0
- mlflow/tracing/utils/once.py +35 -0
- mlflow/tracing/utils/otlp.py +63 -0
- mlflow/tracing/utils/processor.py +54 -0
- mlflow/tracing/utils/search.py +292 -0
- mlflow/tracing/utils/timeout.py +250 -0
- mlflow/tracing/utils/token.py +19 -0
- mlflow/tracing/utils/truncation.py +124 -0
- mlflow/tracing/utils/warning.py +76 -0
- mlflow/tracking/__init__.py +39 -0
- mlflow/tracking/_model_registry/__init__.py +1 -0
- mlflow/tracking/_model_registry/client.py +764 -0
- mlflow/tracking/_model_registry/fluent.py +853 -0
- mlflow/tracking/_model_registry/registry.py +67 -0
- mlflow/tracking/_model_registry/utils.py +251 -0
- mlflow/tracking/_tracking_service/__init__.py +0 -0
- mlflow/tracking/_tracking_service/client.py +883 -0
- mlflow/tracking/_tracking_service/registry.py +56 -0
- mlflow/tracking/_tracking_service/utils.py +275 -0
- mlflow/tracking/artifact_utils.py +179 -0
- mlflow/tracking/client.py +5900 -0
- mlflow/tracking/context/__init__.py +0 -0
- mlflow/tracking/context/abstract_context.py +35 -0
- mlflow/tracking/context/databricks_cluster_context.py +15 -0
- mlflow/tracking/context/databricks_command_context.py +15 -0
- mlflow/tracking/context/databricks_job_context.py +49 -0
- mlflow/tracking/context/databricks_notebook_context.py +41 -0
- mlflow/tracking/context/databricks_repo_context.py +43 -0
- mlflow/tracking/context/default_context.py +51 -0
- mlflow/tracking/context/git_context.py +32 -0
- mlflow/tracking/context/registry.py +98 -0
- mlflow/tracking/context/system_environment_context.py +15 -0
- mlflow/tracking/default_experiment/__init__.py +1 -0
- mlflow/tracking/default_experiment/abstract_context.py +43 -0
- mlflow/tracking/default_experiment/databricks_notebook_experiment_provider.py +44 -0
- mlflow/tracking/default_experiment/registry.py +75 -0
- mlflow/tracking/fluent.py +3595 -0
- mlflow/tracking/metric_value_conversion_utils.py +93 -0
- mlflow/tracking/multimedia.py +206 -0
- mlflow/tracking/registry.py +86 -0
- mlflow/tracking/request_auth/__init__.py +0 -0
- mlflow/tracking/request_auth/abstract_request_auth_provider.py +34 -0
- mlflow/tracking/request_auth/registry.py +60 -0
- mlflow/tracking/request_header/__init__.py +0 -0
- mlflow/tracking/request_header/abstract_request_header_provider.py +36 -0
- mlflow/tracking/request_header/databricks_request_header_provider.py +38 -0
- mlflow/tracking/request_header/default_request_header_provider.py +17 -0
- mlflow/tracking/request_header/registry.py +79 -0
- mlflow/transformers/__init__.py +2982 -0
- mlflow/transformers/flavor_config.py +258 -0
- mlflow/transformers/hub_utils.py +83 -0
- mlflow/transformers/llm_inference_utils.py +468 -0
- mlflow/transformers/model_io.py +301 -0
- mlflow/transformers/peft.py +51 -0
- mlflow/transformers/signature.py +183 -0
- mlflow/transformers/torch_utils.py +55 -0
- mlflow/types/__init__.py +21 -0
- mlflow/types/agent.py +270 -0
- mlflow/types/chat.py +240 -0
- mlflow/types/llm.py +935 -0
- mlflow/types/responses.py +139 -0
- mlflow/types/responses_helpers.py +416 -0
- mlflow/types/schema.py +1505 -0
- mlflow/types/type_hints.py +647 -0
- mlflow/types/utils.py +753 -0
- mlflow/utils/__init__.py +283 -0
- mlflow/utils/_capture_modules.py +256 -0
- mlflow/utils/_capture_transformers_modules.py +75 -0
- mlflow/utils/_spark_utils.py +201 -0
- mlflow/utils/_unity_catalog_oss_utils.py +97 -0
- mlflow/utils/_unity_catalog_utils.py +479 -0
- mlflow/utils/annotations.py +218 -0
- mlflow/utils/arguments_utils.py +16 -0
- mlflow/utils/async_logging/__init__.py +1 -0
- mlflow/utils/async_logging/async_artifacts_logging_queue.py +258 -0
- mlflow/utils/async_logging/async_logging_queue.py +366 -0
- mlflow/utils/async_logging/run_artifact.py +38 -0
- mlflow/utils/async_logging/run_batch.py +58 -0
- mlflow/utils/async_logging/run_operations.py +49 -0
- mlflow/utils/autologging_utils/__init__.py +737 -0
- mlflow/utils/autologging_utils/client.py +432 -0
- mlflow/utils/autologging_utils/config.py +33 -0
- mlflow/utils/autologging_utils/events.py +294 -0
- mlflow/utils/autologging_utils/logging_and_warnings.py +328 -0
- mlflow/utils/autologging_utils/metrics_queue.py +71 -0
- mlflow/utils/autologging_utils/safety.py +1104 -0
- mlflow/utils/autologging_utils/versioning.py +95 -0
- mlflow/utils/checkpoint_utils.py +206 -0
- mlflow/utils/class_utils.py +6 -0
- mlflow/utils/cli_args.py +257 -0
- mlflow/utils/conda.py +354 -0
- mlflow/utils/credentials.py +231 -0
- mlflow/utils/data_utils.py +17 -0
- mlflow/utils/databricks_utils.py +1436 -0
- mlflow/utils/docstring_utils.py +477 -0
- mlflow/utils/doctor.py +133 -0
- mlflow/utils/download_cloud_file_chunk.py +43 -0
- mlflow/utils/env_manager.py +16 -0
- mlflow/utils/env_pack.py +131 -0
- mlflow/utils/environment.py +1009 -0
- mlflow/utils/exception_utils.py +14 -0
- mlflow/utils/file_utils.py +978 -0
- mlflow/utils/git_utils.py +77 -0
- mlflow/utils/gorilla.py +797 -0
- mlflow/utils/import_hooks/__init__.py +363 -0
- mlflow/utils/lazy_load.py +51 -0
- mlflow/utils/logging_utils.py +168 -0
- mlflow/utils/mime_type_utils.py +58 -0
- mlflow/utils/mlflow_tags.py +103 -0
- mlflow/utils/model_utils.py +486 -0
- mlflow/utils/name_utils.py +346 -0
- mlflow/utils/nfs_on_spark.py +62 -0
- mlflow/utils/openai_utils.py +164 -0
- mlflow/utils/os.py +12 -0
- mlflow/utils/oss_registry_utils.py +29 -0
- mlflow/utils/plugins.py +17 -0
- mlflow/utils/process.py +182 -0
- mlflow/utils/promptlab_utils.py +146 -0
- mlflow/utils/proto_json_utils.py +743 -0
- mlflow/utils/pydantic_utils.py +54 -0
- mlflow/utils/request_utils.py +279 -0
- mlflow/utils/requirements_utils.py +704 -0
- mlflow/utils/rest_utils.py +673 -0
- mlflow/utils/search_logged_model_utils.py +127 -0
- mlflow/utils/search_utils.py +2111 -0
- mlflow/utils/secure_loading.py +221 -0
- mlflow/utils/security_validation.py +384 -0
- mlflow/utils/server_cli_utils.py +61 -0
- mlflow/utils/spark_utils.py +15 -0
- mlflow/utils/string_utils.py +138 -0
- mlflow/utils/thread_utils.py +63 -0
- mlflow/utils/time.py +54 -0
- mlflow/utils/timeout.py +42 -0
- mlflow/utils/uri.py +572 -0
- mlflow/utils/validation.py +662 -0
- mlflow/utils/virtualenv.py +458 -0
- mlflow/utils/warnings_utils.py +25 -0
- mlflow/utils/yaml_utils.py +179 -0
- mlflow/version.py +24 -0
@@ -0,0 +1,434 @@
|
|
1
|
+
import logging
|
2
|
+
import operator
|
3
|
+
import os
|
4
|
+
from decimal import Decimal
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
from mlflow.exceptions import MlflowException
|
8
|
+
from mlflow.models.evaluation import EvaluationResult
|
9
|
+
from mlflow.protos.databricks_pb2 import BAD_REQUEST, INVALID_PARAMETER_VALUE
|
10
|
+
|
11
|
+
_logger = logging.getLogger(__name__)
|
12
|
+
|
13
|
+
|
14
|
+
class MetricThreshold:
|
15
|
+
"""
|
16
|
+
This class allows you to define metric thresholds for model validation.
|
17
|
+
Allowed thresholds are: threshold, min_absolute_change, min_relative_change.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
threshold: (Optional) A number representing the value threshold for the metric.
|
21
|
+
|
22
|
+
- If greater is better for the metric, the metric value has to be
|
23
|
+
>= threshold to pass validation.
|
24
|
+
- Otherwise, the metric value has to be <= threshold to pass the validation.
|
25
|
+
|
26
|
+
min_absolute_change: (Optional) A positive number representing the minimum absolute
|
27
|
+
change required for candidate model to pass validation with
|
28
|
+
the baseline model.
|
29
|
+
|
30
|
+
- If greater is better for the metric, metric value has to be
|
31
|
+
>= baseline model metric value + min_absolute_change to pass the validation.
|
32
|
+
- Otherwise, metric value has to be <= baseline model metric value - min_absolute_change
|
33
|
+
to pass the validation.
|
34
|
+
|
35
|
+
min_relative_change: (Optional) A floating point number between 0 and 1 representing
|
36
|
+
the minimum relative change (in percentage of
|
37
|
+
baseline model metric value) for candidate model
|
38
|
+
to pass the comparison with the baseline model.
|
39
|
+
|
40
|
+
- If greater is better for the metric, metric value has to be
|
41
|
+
>= baseline model metric value * (1 + min_relative_change)
|
42
|
+
- Otherwise, metric value has to be
|
43
|
+
<= baseline model metric value * (1 - min_relative_change)
|
44
|
+
- Note that if the baseline model metric value is equal to 0, the
|
45
|
+
threshold falls back performing a simple verification that the
|
46
|
+
candidate metric value is better than the baseline metric value,
|
47
|
+
i.e. metric value >= baseline model metric value + 1e-10 if greater
|
48
|
+
is better; metric value <= baseline model metric value - 1e-10 if
|
49
|
+
lower is better.
|
50
|
+
|
51
|
+
greater_is_better: A required boolean representing whether greater value is
|
52
|
+
better for the metric.
|
53
|
+
"""
|
54
|
+
|
55
|
+
def __init__(
|
56
|
+
self,
|
57
|
+
threshold=None,
|
58
|
+
min_absolute_change=None,
|
59
|
+
min_relative_change=None,
|
60
|
+
greater_is_better=None,
|
61
|
+
):
|
62
|
+
if threshold is not None and type(threshold) not in {int, float}:
|
63
|
+
raise MetricThresholdClassException("`threshold` parameter must be a number.")
|
64
|
+
if min_absolute_change is not None and (
|
65
|
+
type(min_absolute_change) not in {int, float} or min_absolute_change <= 0
|
66
|
+
):
|
67
|
+
raise MetricThresholdClassException(
|
68
|
+
"`min_absolute_change` parameter must be a positive number."
|
69
|
+
)
|
70
|
+
if min_relative_change is not None:
|
71
|
+
if not isinstance(min_relative_change, float):
|
72
|
+
raise MetricThresholdClassException(
|
73
|
+
"`min_relative_change` parameter must be a floating point number."
|
74
|
+
)
|
75
|
+
if min_relative_change < 0 or min_relative_change > 1:
|
76
|
+
raise MetricThresholdClassException(
|
77
|
+
"`min_relative_change` parameter must be between 0 and 1."
|
78
|
+
)
|
79
|
+
if greater_is_better is None:
|
80
|
+
raise MetricThresholdClassException("`greater_is_better` parameter must be defined.")
|
81
|
+
if not isinstance(greater_is_better, bool):
|
82
|
+
raise MetricThresholdClassException("`greater_is_better` parameter must be a boolean.")
|
83
|
+
if threshold is None and min_absolute_change is None and min_relative_change is None:
|
84
|
+
raise MetricThresholdClassException("no threshold was specified.")
|
85
|
+
self._threshold = threshold
|
86
|
+
self._min_absolute_change = min_absolute_change
|
87
|
+
self._min_relative_change = min_relative_change
|
88
|
+
self._greater_is_better = greater_is_better
|
89
|
+
|
90
|
+
@property
|
91
|
+
def threshold(self):
|
92
|
+
"""
|
93
|
+
Value of the threshold.
|
94
|
+
"""
|
95
|
+
return self._threshold
|
96
|
+
|
97
|
+
@property
|
98
|
+
def min_absolute_change(self):
|
99
|
+
"""
|
100
|
+
Value of the minimum absolute change required to pass model comparison with baseline model.
|
101
|
+
"""
|
102
|
+
return self._min_absolute_change
|
103
|
+
|
104
|
+
@property
|
105
|
+
def min_relative_change(self):
|
106
|
+
"""
|
107
|
+
Float value of the minimum relative change required to pass model comparison with
|
108
|
+
baseline model.
|
109
|
+
"""
|
110
|
+
return self._min_relative_change
|
111
|
+
|
112
|
+
@property
|
113
|
+
def greater_is_better(self):
|
114
|
+
"""
|
115
|
+
Boolean value representing whether greater value is better for the metric.
|
116
|
+
"""
|
117
|
+
return self._greater_is_better
|
118
|
+
|
119
|
+
def __str__(self):
|
120
|
+
"""
|
121
|
+
Returns a human-readable string consisting of all specified thresholds.
|
122
|
+
"""
|
123
|
+
threshold_strs = []
|
124
|
+
if self._threshold is not None:
|
125
|
+
threshold_strs.append(f"Threshold: {self._threshold}.")
|
126
|
+
if self._min_absolute_change is not None:
|
127
|
+
threshold_strs.append(f"Minimum Absolute Change: {self._min_absolute_change}.")
|
128
|
+
if self._min_relative_change is not None:
|
129
|
+
threshold_strs.append(f"Minimum Relative Change: {self._min_relative_change}.")
|
130
|
+
if self._greater_is_better is not None:
|
131
|
+
if self._greater_is_better:
|
132
|
+
threshold_strs.append("Greater value is better.")
|
133
|
+
else:
|
134
|
+
threshold_strs.append("Lower value is better.")
|
135
|
+
return " ".join(threshold_strs)
|
136
|
+
|
137
|
+
|
138
|
+
class MetricThresholdClassException(MlflowException):
|
139
|
+
def __init__(self, _message, **kwargs):
|
140
|
+
message = "Could not instantiate MetricThreshold class: " + _message
|
141
|
+
super().__init__(message, error_code=INVALID_PARAMETER_VALUE, **kwargs)
|
142
|
+
|
143
|
+
|
144
|
+
class _MetricValidationResult:
|
145
|
+
"""
|
146
|
+
Internal class for representing validation result per metric.
|
147
|
+
Not user facing, used for organizing metric failures and generating failure message
|
148
|
+
more conveniently.
|
149
|
+
|
150
|
+
Args:
|
151
|
+
metric_name: String representing the metric name
|
152
|
+
candidate_metric_value: value of metric for candidate model
|
153
|
+
metric_threshold: :py:class: `MetricThreshold<mlflow.models.validation.MetricThreshold>`
|
154
|
+
The MetricThreshold for the metric.
|
155
|
+
baseline_metric_value: value of metric for baseline model
|
156
|
+
"""
|
157
|
+
|
158
|
+
missing_candidate = False
|
159
|
+
missing_baseline = False
|
160
|
+
threshold_failed = False
|
161
|
+
min_absolute_change_failed = False
|
162
|
+
min_relative_change_failed = False
|
163
|
+
|
164
|
+
def __init__(
|
165
|
+
self,
|
166
|
+
metric_name,
|
167
|
+
candidate_metric_value,
|
168
|
+
metric_threshold,
|
169
|
+
baseline_metric_value=None,
|
170
|
+
):
|
171
|
+
self.metric_name = metric_name
|
172
|
+
self.candidate_metric_value = candidate_metric_value
|
173
|
+
self.baseline_metric_value = baseline_metric_value
|
174
|
+
self.metric_threshold = metric_threshold
|
175
|
+
|
176
|
+
def __str__(self):
|
177
|
+
"""
|
178
|
+
Returns a human-readable string representing the validation result for the metric.
|
179
|
+
"""
|
180
|
+
if self.is_success():
|
181
|
+
return f"Metric {self.metric_name} passed the validation."
|
182
|
+
|
183
|
+
if self.missing_candidate:
|
184
|
+
return (
|
185
|
+
f"Metric validation failed: metric {self.metric_name} was missing from the "
|
186
|
+
f"evaluation result of the candidate model."
|
187
|
+
)
|
188
|
+
|
189
|
+
result_strs = []
|
190
|
+
if self.threshold_failed:
|
191
|
+
result_strs.append(
|
192
|
+
f"Metric {self.metric_name} value threshold check failed: "
|
193
|
+
f"candidate model {self.metric_name} = {self.candidate_metric_value}, "
|
194
|
+
f"{self.metric_name} threshold = {self.metric_threshold.threshold}."
|
195
|
+
)
|
196
|
+
if self.missing_baseline:
|
197
|
+
result_strs.append(
|
198
|
+
f"Model comparison failed: metric {self.metric_name} was missing from "
|
199
|
+
f"the evaluation result of the baseline model."
|
200
|
+
)
|
201
|
+
else:
|
202
|
+
if self.min_absolute_change_failed:
|
203
|
+
result_strs.append(
|
204
|
+
f"Metric {self.metric_name} minimum absolute change check failed: "
|
205
|
+
f"candidate model {self.metric_name} = {self.candidate_metric_value}, "
|
206
|
+
f"baseline model {self.metric_name} = {self.baseline_metric_value}, "
|
207
|
+
f"{self.metric_name} minimum absolute change threshold = "
|
208
|
+
f"{self.metric_threshold.min_absolute_change}."
|
209
|
+
)
|
210
|
+
if self.min_relative_change_failed:
|
211
|
+
result_strs.append(
|
212
|
+
f"Metric {self.metric_name} minimum relative change check failed: "
|
213
|
+
f"candidate model {self.metric_name} = {self.candidate_metric_value}, "
|
214
|
+
f"baseline model {self.metric_name} = {self.baseline_metric_value}, "
|
215
|
+
f"{self.metric_name} minimum relative change threshold = "
|
216
|
+
f"{self.metric_threshold.min_relative_change}."
|
217
|
+
)
|
218
|
+
return " ".join(result_strs)
|
219
|
+
|
220
|
+
def is_success(self):
|
221
|
+
return (
|
222
|
+
not self.missing_candidate
|
223
|
+
and not self.missing_baseline
|
224
|
+
and not self.threshold_failed
|
225
|
+
and not self.min_absolute_change_failed
|
226
|
+
and not self.min_relative_change_failed
|
227
|
+
)
|
228
|
+
|
229
|
+
|
230
|
+
class ModelValidationFailedException(MlflowException):
|
231
|
+
def __init__(self, message, **kwargs):
|
232
|
+
super().__init__(message, error_code=BAD_REQUEST, **kwargs)
|
233
|
+
|
234
|
+
|
235
|
+
def validate_evaluation_results(
|
236
|
+
validation_thresholds: dict[str, MetricThreshold],
|
237
|
+
candidate_result: EvaluationResult,
|
238
|
+
baseline_result: Optional[EvaluationResult] = None,
|
239
|
+
):
|
240
|
+
"""
|
241
|
+
Validate the evaluation result from one model (candidate) against another
|
242
|
+
model (baseline). If the candidate results do not meet the validation
|
243
|
+
thresholds, an ModelValidationFailedException will be raised.
|
244
|
+
|
245
|
+
.. note::
|
246
|
+
|
247
|
+
This API is a replacement for the deprecated model validation
|
248
|
+
functionality in the :py:func:`mlflow.evaluate` API.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
validation_thresholds: A dictionary of metric name to
|
252
|
+
:py:class:`mlflow.models.MetricThreshold` used for model validation.
|
253
|
+
Each metric name must either be the name of a builtin metric or the
|
254
|
+
name of a metric defined in the ``extra_metrics`` parameter.
|
255
|
+
candidate_result: The evaluation result of the candidate model.
|
256
|
+
Returned by the :py:func:`mlflow.evaluate` API.
|
257
|
+
baseline_result: The evaluation result of the baseline model.
|
258
|
+
Returned by the :py:func:`mlflow.evaluate` API.
|
259
|
+
If set to None, the candidate model result will be
|
260
|
+
compared against the threshold values directly.
|
261
|
+
|
262
|
+
Code Example:
|
263
|
+
|
264
|
+
.. code-block:: python
|
265
|
+
:caption: Example of Model Validation
|
266
|
+
|
267
|
+
import mlflow
|
268
|
+
from mlflow.models import MetricThreshold
|
269
|
+
|
270
|
+
thresholds = {
|
271
|
+
"accuracy_score": MetricThreshold(
|
272
|
+
# accuracy should be >=0.8
|
273
|
+
threshold=0.8,
|
274
|
+
# accuracy should be at least 5 percent greater than baseline model accuracy
|
275
|
+
min_absolute_change=0.05,
|
276
|
+
# accuracy should be at least 0.05 greater than baseline model accuracy
|
277
|
+
min_relative_change=0.05,
|
278
|
+
greater_is_better=True,
|
279
|
+
),
|
280
|
+
}
|
281
|
+
|
282
|
+
# Get evaluation results for the candidate model
|
283
|
+
candidate_result = mlflow.evaluate(
|
284
|
+
model="<YOUR_CANDIDATE_MODEL_URI>",
|
285
|
+
data=eval_dataset,
|
286
|
+
targets="ground_truth",
|
287
|
+
model_type="classifier",
|
288
|
+
)
|
289
|
+
|
290
|
+
# Get evaluation results for the baseline model
|
291
|
+
baseline_result = mlflow.evaluate(
|
292
|
+
model="<YOUR_BASELINE_MODEL_URI>",
|
293
|
+
data=eval_dataset,
|
294
|
+
targets="ground_truth",
|
295
|
+
model_type="classifier",
|
296
|
+
)
|
297
|
+
|
298
|
+
# Validate the results
|
299
|
+
mlflow.validate_evaluation_results(
|
300
|
+
thresholds,
|
301
|
+
candidate_result,
|
302
|
+
baseline_result,
|
303
|
+
)
|
304
|
+
|
305
|
+
See `the Model Validation documentation
|
306
|
+
<../../models/index.html#performing-model-validation>`_ for more details.
|
307
|
+
"""
|
308
|
+
try:
|
309
|
+
assert type(validation_thresholds) is dict
|
310
|
+
for key in validation_thresholds.keys():
|
311
|
+
assert type(key) is str
|
312
|
+
for threshold in validation_thresholds.values():
|
313
|
+
assert isinstance(threshold, MetricThreshold)
|
314
|
+
except AssertionError:
|
315
|
+
raise MlflowException(
|
316
|
+
message="The validation thresholds argument must be a dictionary that maps strings "
|
317
|
+
"to MetricThreshold objects.",
|
318
|
+
error_code=INVALID_PARAMETER_VALUE,
|
319
|
+
)
|
320
|
+
|
321
|
+
_logger.info("Validating candidate model metrics against baseline")
|
322
|
+
_validate(
|
323
|
+
validation_thresholds,
|
324
|
+
candidate_result.metrics,
|
325
|
+
baseline_result.metrics if baseline_result else {},
|
326
|
+
)
|
327
|
+
_logger.info("Model validation passed!")
|
328
|
+
|
329
|
+
|
330
|
+
def _validate(
|
331
|
+
validation_thresholds: dict[str, MetricThreshold],
|
332
|
+
candidate_metrics: dict[str, float],
|
333
|
+
baseline_metrics: dict[str, float],
|
334
|
+
):
|
335
|
+
"""
|
336
|
+
Validate the model based on validation_thresholds by metrics value and
|
337
|
+
metrics comparison between candidate model's metrics (candidate_metrics) and
|
338
|
+
baseline model's metrics (baseline_metrics).
|
339
|
+
|
340
|
+
Args:
|
341
|
+
validation_thresholds: A dictionary from metric_name to MetricThreshold.
|
342
|
+
candidate_metrics: The metric evaluation result of the candidate model.
|
343
|
+
baseline_metrics: The metric evaluation result of the baseline model.
|
344
|
+
|
345
|
+
Raises:
|
346
|
+
If the validation does not pass, raise an MlflowException with detail failure message.
|
347
|
+
"""
|
348
|
+
validation_results = {
|
349
|
+
metric_name: _MetricValidationResult(
|
350
|
+
metric_name,
|
351
|
+
candidate_metrics.get(metric_name),
|
352
|
+
threshold,
|
353
|
+
baseline_metrics.get(metric_name),
|
354
|
+
)
|
355
|
+
for (metric_name, threshold) in validation_thresholds.items()
|
356
|
+
}
|
357
|
+
|
358
|
+
for metric_name, metric_threshold in validation_thresholds.items():
|
359
|
+
validation_result = validation_results[metric_name]
|
360
|
+
|
361
|
+
if metric_name not in candidate_metrics:
|
362
|
+
validation_result.missing_candidate = True
|
363
|
+
continue
|
364
|
+
|
365
|
+
candidate_metric_value = candidate_metrics[metric_name]
|
366
|
+
baseline_metric_value = baseline_metrics[metric_name] if baseline_metrics else None
|
367
|
+
|
368
|
+
# If metric is greater is better, >= is used, otherwise <= is used
|
369
|
+
# for thresholding metric value and model comparison
|
370
|
+
comparator_fn = operator.__ge__ if metric_threshold.greater_is_better else operator.__le__
|
371
|
+
operator_fn = operator.add if metric_threshold.greater_is_better else operator.sub
|
372
|
+
|
373
|
+
if metric_threshold.threshold is not None:
|
374
|
+
# metric threshold fails
|
375
|
+
# - if not (metric_value >= threshold) for greater is better
|
376
|
+
# - if not (metric_value <= threshold) for lower is better
|
377
|
+
validation_result.threshold_failed = not comparator_fn(
|
378
|
+
candidate_metric_value, metric_threshold.threshold
|
379
|
+
)
|
380
|
+
|
381
|
+
if (
|
382
|
+
metric_threshold.min_relative_change or metric_threshold.min_absolute_change
|
383
|
+
) and metric_name not in baseline_metrics:
|
384
|
+
validation_result.missing_baseline = True
|
385
|
+
continue
|
386
|
+
|
387
|
+
if metric_threshold.min_absolute_change is not None:
|
388
|
+
# metric comparison absolute change fails
|
389
|
+
# - if not (metric_value >= baseline + min_absolute_change) for greater is better
|
390
|
+
# - if not (metric_value <= baseline - min_absolute_change) for lower is better
|
391
|
+
validation_result.min_absolute_change_failed = not comparator_fn(
|
392
|
+
Decimal(candidate_metric_value),
|
393
|
+
Decimal(operator_fn(baseline_metric_value, metric_threshold.min_absolute_change)),
|
394
|
+
)
|
395
|
+
|
396
|
+
if metric_threshold.min_relative_change is not None:
|
397
|
+
# If baseline metric value equals 0, fallback to simple comparison check
|
398
|
+
if baseline_metric_value == 0:
|
399
|
+
_logger.warning(
|
400
|
+
f"Cannot perform relative model comparison for metric {metric_name} as "
|
401
|
+
"baseline metric value is 0. Falling back to simple comparison: verifying "
|
402
|
+
"that candidate metric value is better than the baseline metric value."
|
403
|
+
)
|
404
|
+
validation_result.min_relative_change_failed = not comparator_fn(
|
405
|
+
Decimal(candidate_metric_value),
|
406
|
+
Decimal(operator_fn(baseline_metric_value, 1e-10)),
|
407
|
+
)
|
408
|
+
continue
|
409
|
+
# metric comparison relative change fails
|
410
|
+
# - if (metric_value - baseline) / baseline < min_relative_change for greater is better
|
411
|
+
# - if (baseline - metric_value) / baseline < min_relative_change for lower is better
|
412
|
+
if metric_threshold.greater_is_better:
|
413
|
+
relative_change = (
|
414
|
+
candidate_metric_value - baseline_metric_value
|
415
|
+
) / baseline_metric_value
|
416
|
+
else:
|
417
|
+
relative_change = (
|
418
|
+
baseline_metric_value - candidate_metric_value
|
419
|
+
) / baseline_metric_value
|
420
|
+
validation_result.min_relative_change_failed = (
|
421
|
+
relative_change < metric_threshold.min_relative_change
|
422
|
+
)
|
423
|
+
|
424
|
+
failure_messages = []
|
425
|
+
|
426
|
+
for metric_validation_result in validation_results.values():
|
427
|
+
if metric_validation_result.is_success():
|
428
|
+
continue
|
429
|
+
failure_messages.append(str(metric_validation_result))
|
430
|
+
|
431
|
+
if not failure_messages:
|
432
|
+
return
|
433
|
+
|
434
|
+
raise ModelValidationFailedException(message=os.linesep.join(failure_messages))
|
@@ -0,0 +1,93 @@
|
|
1
|
+
from abc import ABCMeta, abstractmethod
|
2
|
+
|
3
|
+
from mlflow.utils.annotations import developer_stable
|
4
|
+
|
5
|
+
|
6
|
+
@developer_stable
|
7
|
+
class FlavorBackend:
|
8
|
+
"""
|
9
|
+
Abstract class for Flavor Backend.
|
10
|
+
This class defines the API interface for local model deployment of MLflow model flavors.
|
11
|
+
"""
|
12
|
+
|
13
|
+
__metaclass__ = ABCMeta
|
14
|
+
|
15
|
+
def __init__(self, config, **kwargs):
|
16
|
+
self._config = config
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
def predict(self, model_uri, input_path, output_path, content_type):
|
20
|
+
"""
|
21
|
+
Generate predictions using a saved MLflow model referenced by the given URI.
|
22
|
+
Input and output are read from and written to a file or stdin / stdout.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
model_uri: URI pointing to the MLflow model to be used for scoring.
|
26
|
+
input_path: Path to the file with input data. If not specified, data is read from
|
27
|
+
stdin.
|
28
|
+
output_path: Path to the file with output predictions. If not specified, data is
|
29
|
+
written to stdout.
|
30
|
+
content_type: Specifies the input format. Can be one of {``json``, ``csv``}
|
31
|
+
"""
|
32
|
+
|
33
|
+
@abstractmethod
|
34
|
+
def serve(
|
35
|
+
self,
|
36
|
+
model_uri,
|
37
|
+
port,
|
38
|
+
host,
|
39
|
+
timeout,
|
40
|
+
enable_mlserver,
|
41
|
+
synchronous=True,
|
42
|
+
stdout=None,
|
43
|
+
stderr=None,
|
44
|
+
):
|
45
|
+
"""
|
46
|
+
Serve the specified MLflow model locally.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
model_uri: URI pointing to the MLflow model to be used for scoring.
|
50
|
+
port: Port to use for the model deployment.
|
51
|
+
host: Host to use for the model deployment. Defaults to ``localhost``.
|
52
|
+
timeout: Timeout in seconds to serve a request. Defaults to 60.
|
53
|
+
enable_mlserver: Whether to use MLServer or the local scoring server.
|
54
|
+
synchronous: If True, wait until server process exit and return 0, if process exit
|
55
|
+
with non-zero return code, raise exception.
|
56
|
+
If False, return the server process `Popen` instance immediately.
|
57
|
+
stdout: Redirect server stdout
|
58
|
+
stderr: Redirect server stderr
|
59
|
+
"""
|
60
|
+
|
61
|
+
def prepare_env(self, model_uri, capture_output=False):
|
62
|
+
"""
|
63
|
+
Performs any preparation necessary to predict or serve the model, for example
|
64
|
+
downloading dependencies or initializing a conda environment. After preparation,
|
65
|
+
calling predict or serve should be fast.
|
66
|
+
"""
|
67
|
+
|
68
|
+
@abstractmethod
|
69
|
+
def build_image(
|
70
|
+
self, model_uri, image_name, install_mlflow, mlflow_home, enable_mlserver, base_image=None
|
71
|
+
): ...
|
72
|
+
|
73
|
+
@abstractmethod
|
74
|
+
def generate_dockerfile(
|
75
|
+
self, model_uri, output_path, install_mlflow, mlflow_home, enable_mlserver, base_image=None
|
76
|
+
): ...
|
77
|
+
|
78
|
+
@abstractmethod
|
79
|
+
def can_score_model(self):
|
80
|
+
"""
|
81
|
+
Check whether this flavor backend can be deployed in the current environment.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
True if this flavor backend can be applied in the current environment.
|
85
|
+
"""
|
86
|
+
|
87
|
+
def can_build_image(self):
|
88
|
+
"""
|
89
|
+
Returns:
|
90
|
+
True if this flavor has a `build_image` method defined for building a docker
|
91
|
+
container capable of serving the model, False otherwise.
|
92
|
+
"""
|
93
|
+
return callable(getattr(self.__class__, "build_image", None))
|
@@ -0,0 +1,53 @@
|
|
1
|
+
"""
|
2
|
+
Registry of supported flavor backends. Contains a mapping of flavors to flavor backends. This
|
3
|
+
mapping is used to select suitable flavor when deploying generic MLflow models.
|
4
|
+
|
5
|
+
Flavor backend can deploy particular flavor locally to generate predictions, deploy as a local
|
6
|
+
REST api endpoint, or build a docker image for serving the model locally or remotely.
|
7
|
+
Not all flavors have a flavor backend.
|
8
|
+
"""
|
9
|
+
|
10
|
+
import logging
|
11
|
+
|
12
|
+
from mlflow.models.model import Model
|
13
|
+
from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
|
14
|
+
from mlflow.tracking.artifact_utils import (
|
15
|
+
_get_root_uri_and_artifact_path,
|
16
|
+
)
|
17
|
+
from mlflow.utils.file_utils import TempDir
|
18
|
+
|
19
|
+
_logger = logging.getLogger(__name__)
|
20
|
+
|
21
|
+
|
22
|
+
def _get_flavor_backend_for_local_model(model=None, build_docker=True, **kwargs):
|
23
|
+
from mlflow import pyfunc, rfunc
|
24
|
+
from mlflow.pyfunc.backend import PyFuncBackend
|
25
|
+
from mlflow.rfunc.backend import RFuncBackend
|
26
|
+
|
27
|
+
if not model:
|
28
|
+
return pyfunc.FLAVOR_NAME, PyFuncBackend({}, **kwargs)
|
29
|
+
|
30
|
+
backends = {pyfunc.FLAVOR_NAME: PyFuncBackend, rfunc.FLAVOR_NAME: RFuncBackend}
|
31
|
+
for flavor, Backend in backends.items():
|
32
|
+
if flavor in model.flavors:
|
33
|
+
backend = Backend(model.flavors[flavor], **kwargs)
|
34
|
+
if (build_docker and backend.can_build_image()) or backend.can_score_model():
|
35
|
+
return flavor, backend
|
36
|
+
|
37
|
+
return None, None
|
38
|
+
|
39
|
+
|
40
|
+
def get_flavor_backend(model_uri, **kwargs):
|
41
|
+
if model_uri:
|
42
|
+
with TempDir() as tmp:
|
43
|
+
root_uri, artifact_path = _get_root_uri_and_artifact_path(model_uri)
|
44
|
+
artifact_repo = get_artifact_repository(root_uri)
|
45
|
+
local_path = artifact_repo.download_artifacts(artifact_path, dst_path=tmp.path())
|
46
|
+
model = Model.load(local_path)
|
47
|
+
else:
|
48
|
+
model = None
|
49
|
+
flavor_name, flavor_backend = _get_flavor_backend_for_local_model(model, **kwargs)
|
50
|
+
if flavor_backend is None:
|
51
|
+
raise Exception("No suitable flavor backend was found for the model.")
|
52
|
+
_logger.info("Selected backend for flavor '%s'", flavor_name)
|
53
|
+
return flavor_backend
|