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,233 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import time
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
import numpy as np
|
7
|
+
import pandas as pd
|
8
|
+
|
9
|
+
import mlflow
|
10
|
+
from mlflow.entities.metric import Metric
|
11
|
+
from mlflow.exceptions import MlflowException
|
12
|
+
from mlflow.metrics import (
|
13
|
+
MetricValue,
|
14
|
+
ari_grade_level,
|
15
|
+
exact_match,
|
16
|
+
flesch_kincaid_grade_level,
|
17
|
+
ndcg_at_k,
|
18
|
+
precision_at_k,
|
19
|
+
recall_at_k,
|
20
|
+
rouge1,
|
21
|
+
rouge2,
|
22
|
+
rougeL,
|
23
|
+
rougeLsum,
|
24
|
+
token_count,
|
25
|
+
toxicity,
|
26
|
+
)
|
27
|
+
from mlflow.metrics.genai.genai_metric import _GENAI_CUSTOM_METRICS_FILE_NAME
|
28
|
+
from mlflow.models.evaluation.artifacts import JsonEvaluationArtifact
|
29
|
+
from mlflow.models.evaluation.base import EvaluationMetric, EvaluationResult, _ModelType
|
30
|
+
from mlflow.models.evaluation.default_evaluator import (
|
31
|
+
_LATENCY_METRIC_NAME,
|
32
|
+
BuiltInEvaluator,
|
33
|
+
_extract_output_and_other_columns,
|
34
|
+
_extract_predict_fn,
|
35
|
+
)
|
36
|
+
from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
|
37
|
+
|
38
|
+
_logger = logging.getLogger(__name__)
|
39
|
+
|
40
|
+
|
41
|
+
class DefaultEvaluator(BuiltInEvaluator):
|
42
|
+
"""
|
43
|
+
The default built-in evaluator for any models that cannot be evaluated
|
44
|
+
by other built-in evaluators, such as question-answering.
|
45
|
+
"""
|
46
|
+
|
47
|
+
name = "default"
|
48
|
+
|
49
|
+
@classmethod
|
50
|
+
def can_evaluate(cls, *, model_type, evaluator_config, **kwargs):
|
51
|
+
return model_type in _ModelType.values() or model_type is None
|
52
|
+
|
53
|
+
def _evaluate(
|
54
|
+
self,
|
55
|
+
model: Optional["mlflow.pyfunc.PyFuncModel"],
|
56
|
+
extra_metrics: list[EvaluationMetric],
|
57
|
+
custom_artifacts=None,
|
58
|
+
**kwargs,
|
59
|
+
) -> Optional[EvaluationResult]:
|
60
|
+
compute_latency = False
|
61
|
+
for extra_metric in extra_metrics:
|
62
|
+
# If latency metric is specified, we will compute latency for the model
|
63
|
+
# during prediction, and we will remove the metric from the list of extra
|
64
|
+
# metrics to be computed after prediction.
|
65
|
+
if extra_metric.name == _LATENCY_METRIC_NAME:
|
66
|
+
compute_latency = True
|
67
|
+
extra_metrics.remove(extra_metric)
|
68
|
+
self._log_genai_custom_metrics(extra_metrics)
|
69
|
+
|
70
|
+
# Generate model predictions and evaluate metrics
|
71
|
+
y_pred, other_model_outputs, self.predictions = self._generate_model_predictions(
|
72
|
+
model, input_df=self.X.copy_to_avoid_mutation(), compute_latency=compute_latency
|
73
|
+
)
|
74
|
+
y_true = self.dataset.labels_data
|
75
|
+
|
76
|
+
metrics = self._builtin_metrics() + extra_metrics
|
77
|
+
self.evaluate_metrics(
|
78
|
+
metrics,
|
79
|
+
prediction=y_pred,
|
80
|
+
target=self.dataset.labels_data,
|
81
|
+
other_output_df=other_model_outputs,
|
82
|
+
)
|
83
|
+
self.evaluate_and_log_custom_artifacts(custom_artifacts, prediction=y_pred, target=y_true)
|
84
|
+
|
85
|
+
# Log metrics and artifacts
|
86
|
+
self.log_metrics()
|
87
|
+
self.log_eval_table(y_pred, other_model_outputs)
|
88
|
+
return EvaluationResult(
|
89
|
+
metrics=self.aggregate_metrics, artifacts=self.artifacts, run_id=self.run_id
|
90
|
+
)
|
91
|
+
|
92
|
+
def _builtin_metrics(self) -> list[Metric]:
|
93
|
+
"""
|
94
|
+
Get a list of builtin metrics for the model type.
|
95
|
+
"""
|
96
|
+
text_metrics = [
|
97
|
+
token_count(),
|
98
|
+
toxicity(),
|
99
|
+
flesch_kincaid_grade_level(),
|
100
|
+
ari_grade_level(),
|
101
|
+
]
|
102
|
+
builtin_metrics = []
|
103
|
+
|
104
|
+
# NB: Classifier and Regressor are handled by dedicated built-in evaluators,
|
105
|
+
if self.model_type == _ModelType.QUESTION_ANSWERING:
|
106
|
+
builtin_metrics = [*text_metrics, exact_match()]
|
107
|
+
elif self.model_type == _ModelType.TEXT_SUMMARIZATION:
|
108
|
+
builtin_metrics = [
|
109
|
+
*text_metrics,
|
110
|
+
rouge1(),
|
111
|
+
rouge2(),
|
112
|
+
rougeL(),
|
113
|
+
rougeLsum(),
|
114
|
+
]
|
115
|
+
elif self.model_type == _ModelType.TEXT:
|
116
|
+
builtin_metrics = text_metrics
|
117
|
+
elif self.model_type == _ModelType.RETRIEVER:
|
118
|
+
# default k to 3 if not specified
|
119
|
+
retriever_k = self.evaluator_config.pop("retriever_k", 3)
|
120
|
+
builtin_metrics = [
|
121
|
+
precision_at_k(retriever_k),
|
122
|
+
recall_at_k(retriever_k),
|
123
|
+
ndcg_at_k(retriever_k),
|
124
|
+
]
|
125
|
+
|
126
|
+
return builtin_metrics
|
127
|
+
|
128
|
+
def _generate_model_predictions(
|
129
|
+
self,
|
130
|
+
model: Optional["mlflow.pyfunc.PyFuncModel"],
|
131
|
+
input_df: pd.DataFrame,
|
132
|
+
compute_latency=False,
|
133
|
+
):
|
134
|
+
"""
|
135
|
+
Helper method for generating model predictions
|
136
|
+
"""
|
137
|
+
predict_fn = _extract_predict_fn(model)
|
138
|
+
|
139
|
+
def predict_with_latency(X_copy):
|
140
|
+
y_pred_list = []
|
141
|
+
pred_latencies = []
|
142
|
+
if len(X_copy) == 0:
|
143
|
+
raise ValueError("Empty input data")
|
144
|
+
|
145
|
+
is_dataframe = isinstance(X_copy, pd.DataFrame)
|
146
|
+
|
147
|
+
for row in X_copy.iterrows() if is_dataframe else enumerate(X_copy):
|
148
|
+
i, row_data = row
|
149
|
+
single_input = row_data.to_frame().T if is_dataframe else row_data
|
150
|
+
start_time = time.time()
|
151
|
+
y_pred = predict_fn(single_input)
|
152
|
+
end_time = time.time()
|
153
|
+
pred_latencies.append(end_time - start_time)
|
154
|
+
y_pred_list.append(y_pred)
|
155
|
+
|
156
|
+
# Update latency metric
|
157
|
+
self.metrics_values.update({_LATENCY_METRIC_NAME: MetricValue(scores=pred_latencies)})
|
158
|
+
|
159
|
+
# Aggregate all predictions into model_predictions
|
160
|
+
sample_pred = y_pred_list[0]
|
161
|
+
if isinstance(sample_pred, pd.DataFrame):
|
162
|
+
return pd.concat(y_pred_list)
|
163
|
+
elif isinstance(sample_pred, np.ndarray):
|
164
|
+
return np.concatenate(y_pred_list, axis=0)
|
165
|
+
elif isinstance(sample_pred, list):
|
166
|
+
return sum(y_pred_list, [])
|
167
|
+
elif isinstance(sample_pred, pd.Series):
|
168
|
+
return pd.concat(y_pred_list, ignore_index=True)
|
169
|
+
elif isinstance(sample_pred, str):
|
170
|
+
return y_pred_list
|
171
|
+
else:
|
172
|
+
raise MlflowException(
|
173
|
+
message=f"Unsupported prediction type {type(sample_pred)} for model type "
|
174
|
+
f"{self.model_type}.",
|
175
|
+
error_code=INVALID_PARAMETER_VALUE,
|
176
|
+
)
|
177
|
+
|
178
|
+
if model is not None:
|
179
|
+
_logger.info("Computing model predictions.")
|
180
|
+
|
181
|
+
if compute_latency:
|
182
|
+
model_predictions = predict_with_latency(input_df)
|
183
|
+
else:
|
184
|
+
model_predictions = predict_fn(input_df)
|
185
|
+
else:
|
186
|
+
if compute_latency:
|
187
|
+
_logger.warning(
|
188
|
+
"Setting the latency to 0 for all entries because the model is not provided."
|
189
|
+
)
|
190
|
+
self.metrics_values.update(
|
191
|
+
{_LATENCY_METRIC_NAME: MetricValue(scores=[0.0] * len(input_df))}
|
192
|
+
)
|
193
|
+
model_predictions = self.dataset.predictions_data
|
194
|
+
|
195
|
+
output_column_name = self.predictions
|
196
|
+
(
|
197
|
+
y_pred,
|
198
|
+
other_output_df,
|
199
|
+
predictions_column_name,
|
200
|
+
) = _extract_output_and_other_columns(model_predictions, output_column_name)
|
201
|
+
|
202
|
+
return y_pred, other_output_df, predictions_column_name
|
203
|
+
|
204
|
+
def _log_genai_custom_metrics(self, extra_metrics: list[EvaluationMetric]):
|
205
|
+
genai_custom_metrics = [
|
206
|
+
extra_metric.genai_metric_args
|
207
|
+
for extra_metric in extra_metrics
|
208
|
+
# When the field is present, the metric is created from either make_genai_metric
|
209
|
+
# or make_genai_metric_from_prompt. We will log the metric definition.
|
210
|
+
if extra_metric.genai_metric_args is not None
|
211
|
+
]
|
212
|
+
|
213
|
+
if len(genai_custom_metrics) == 0:
|
214
|
+
return
|
215
|
+
|
216
|
+
names = []
|
217
|
+
versions = []
|
218
|
+
metric_args_list = []
|
219
|
+
|
220
|
+
for metric_args in genai_custom_metrics:
|
221
|
+
names.append(metric_args["name"])
|
222
|
+
# Custom metrics created from make_genai_metric_from_prompt don't have version
|
223
|
+
versions.append(metric_args.get("version", ""))
|
224
|
+
metric_args_list.append(metric_args)
|
225
|
+
|
226
|
+
data = {"name": names, "version": versions, "metric_args": metric_args_list}
|
227
|
+
|
228
|
+
mlflow.log_table(data, artifact_file=_GENAI_CUSTOM_METRICS_FILE_NAME)
|
229
|
+
|
230
|
+
artifact_name = os.path.splitext(_GENAI_CUSTOM_METRICS_FILE_NAME)[0]
|
231
|
+
self.artifacts[artifact_name] = JsonEvaluationArtifact(
|
232
|
+
uri=mlflow.get_artifact_uri(_GENAI_CUSTOM_METRICS_FILE_NAME)
|
233
|
+
)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
from sklearn import metrics as sk_metrics
|
5
|
+
|
6
|
+
import mlflow
|
7
|
+
from mlflow.models.evaluation.base import EvaluationMetric, EvaluationResult, _ModelType
|
8
|
+
from mlflow.models.evaluation.default_evaluator import (
|
9
|
+
BuiltInEvaluator,
|
10
|
+
_extract_output_and_other_columns,
|
11
|
+
_extract_predict_fn,
|
12
|
+
_get_aggregate_metrics_values,
|
13
|
+
)
|
14
|
+
|
15
|
+
|
16
|
+
class RegressorEvaluator(BuiltInEvaluator):
|
17
|
+
"""
|
18
|
+
A built-in evaluator for regressor models.
|
19
|
+
"""
|
20
|
+
|
21
|
+
name = "regressor"
|
22
|
+
|
23
|
+
@classmethod
|
24
|
+
def can_evaluate(cls, *, model_type, evaluator_config, **kwargs):
|
25
|
+
return model_type == _ModelType.REGRESSOR
|
26
|
+
|
27
|
+
def _evaluate(
|
28
|
+
self,
|
29
|
+
model: Optional["mlflow.pyfunc.PyFuncModel"],
|
30
|
+
extra_metrics: list[EvaluationMetric],
|
31
|
+
custom_artifacts=None,
|
32
|
+
**kwargs,
|
33
|
+
) -> Optional[EvaluationResult]:
|
34
|
+
self.y_true = self.dataset.labels_data
|
35
|
+
self.sample_weights = self.evaluator_config.get("sample_weights", None)
|
36
|
+
|
37
|
+
input_df = self.X.copy_to_avoid_mutation()
|
38
|
+
self.y_pred = self._generate_model_predictions(model, input_df)
|
39
|
+
self._compute_buildin_metrics(model)
|
40
|
+
|
41
|
+
self.evaluate_metrics(extra_metrics, prediction=self.y_pred, target=self.y_true)
|
42
|
+
self.evaluate_and_log_custom_artifacts(
|
43
|
+
custom_artifacts, prediction=self.y_pred, target=self.y_true
|
44
|
+
)
|
45
|
+
|
46
|
+
self.log_metrics()
|
47
|
+
self.log_eval_table(self.y_pred)
|
48
|
+
|
49
|
+
return EvaluationResult(
|
50
|
+
metrics=self.aggregate_metrics, artifacts=self.artifacts, run_id=self.run_id
|
51
|
+
)
|
52
|
+
|
53
|
+
def _generate_model_predictions(self, model, input_df):
|
54
|
+
if predict_fn := _extract_predict_fn(model):
|
55
|
+
preds = predict_fn(input_df)
|
56
|
+
y_pred, _, _ = _extract_output_and_other_columns(preds, self.predictions)
|
57
|
+
return y_pred
|
58
|
+
else:
|
59
|
+
return self.dataset.predictions_data
|
60
|
+
|
61
|
+
def _compute_buildin_metrics(self, model):
|
62
|
+
self._evaluate_sklearn_model_score_if_scorable(model, self.y_true, self.sample_weights)
|
63
|
+
self.metrics_values.update(
|
64
|
+
_get_aggregate_metrics_values(
|
65
|
+
_get_regressor_metrics(self.y_true, self.y_pred, self.sample_weights)
|
66
|
+
)
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
def _get_regressor_metrics(y, y_pred, sample_weights):
|
71
|
+
from mlflow.metrics.metric_definitions import _root_mean_squared_error
|
72
|
+
|
73
|
+
sum_on_target = (
|
74
|
+
(np.array(y) * np.array(sample_weights)).sum() if sample_weights is not None else sum(y)
|
75
|
+
)
|
76
|
+
return {
|
77
|
+
"example_count": len(y),
|
78
|
+
"mean_absolute_error": sk_metrics.mean_absolute_error(
|
79
|
+
y, y_pred, sample_weight=sample_weights
|
80
|
+
),
|
81
|
+
"mean_squared_error": sk_metrics.mean_squared_error(
|
82
|
+
y, y_pred, sample_weight=sample_weights
|
83
|
+
),
|
84
|
+
"root_mean_squared_error": _root_mean_squared_error(
|
85
|
+
y_true=y,
|
86
|
+
y_pred=y_pred,
|
87
|
+
sample_weight=sample_weights,
|
88
|
+
),
|
89
|
+
"sum_on_target": sum_on_target,
|
90
|
+
"mean_on_target": sum_on_target / len(y),
|
91
|
+
"r2_score": sk_metrics.r2_score(y, y_pred, sample_weight=sample_weights),
|
92
|
+
"max_error": sk_metrics.max_error(y, y_pred),
|
93
|
+
"mean_absolute_percentage_error": sk_metrics.mean_absolute_percentage_error(
|
94
|
+
y, y_pred, sample_weight=sample_weights
|
95
|
+
),
|
96
|
+
}
|
@@ -0,0 +1,296 @@
|
|
1
|
+
import functools
|
2
|
+
import logging
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
from packaging.version import Version
|
7
|
+
from sklearn.pipeline import Pipeline as sk_Pipeline
|
8
|
+
|
9
|
+
import mlflow
|
10
|
+
from mlflow import MlflowException
|
11
|
+
from mlflow.models.evaluation.base import EvaluationMetric, EvaluationResult, _ModelType
|
12
|
+
from mlflow.models.evaluation.default_evaluator import (
|
13
|
+
BuiltInEvaluator,
|
14
|
+
_extract_predict_fn,
|
15
|
+
_extract_raw_model,
|
16
|
+
_get_dataframe_with_renamed_columns,
|
17
|
+
)
|
18
|
+
from mlflow.models.evaluation.evaluators.classifier import (
|
19
|
+
_is_continuous,
|
20
|
+
_suppress_class_imbalance_errors,
|
21
|
+
)
|
22
|
+
from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
|
23
|
+
from mlflow.pyfunc import _ServedPyFuncModel
|
24
|
+
|
25
|
+
_logger = logging.getLogger(__name__)
|
26
|
+
|
27
|
+
|
28
|
+
_SUPPORTED_SHAP_ALGORITHMS = ("exact", "permutation", "partition", "kernel")
|
29
|
+
_DEFAULT_SAMPLE_ROWS_FOR_SHAP = 2000
|
30
|
+
|
31
|
+
|
32
|
+
def _shap_predict_fn(x, predict_fn, feature_names):
|
33
|
+
return predict_fn(_get_dataframe_with_renamed_columns(x, feature_names))
|
34
|
+
|
35
|
+
|
36
|
+
class ShapEvaluator(BuiltInEvaluator):
|
37
|
+
"""
|
38
|
+
A built-in evaluator to get SHAP explainability insights for classifier and regressor models.
|
39
|
+
|
40
|
+
This evaluator often run with the main evaluator for the model like ClassifierEvaluator.
|
41
|
+
"""
|
42
|
+
|
43
|
+
name = "shap"
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def can_evaluate(cls, *, model_type, evaluator_config, **kwargs):
|
47
|
+
return model_type in (_ModelType.CLASSIFIER, _ModelType.REGRESSOR) and evaluator_config.get(
|
48
|
+
"log_model_explainability", True
|
49
|
+
)
|
50
|
+
|
51
|
+
def _evaluate(
|
52
|
+
self,
|
53
|
+
model: Optional["mlflow.pyfunc.PyFuncModel"],
|
54
|
+
extra_metrics: list[EvaluationMetric],
|
55
|
+
custom_artifacts=None,
|
56
|
+
**kwargs,
|
57
|
+
) -> Optional[EvaluationResult]:
|
58
|
+
if isinstance(model, _ServedPyFuncModel):
|
59
|
+
_logger.warning(
|
60
|
+
"Skipping model explainability because a model server is used for environment "
|
61
|
+
"restoration."
|
62
|
+
)
|
63
|
+
return
|
64
|
+
|
65
|
+
model_loader_module, raw_model = _extract_raw_model(model)
|
66
|
+
if model_loader_module == "mlflow.spark":
|
67
|
+
# TODO: Shap explainer need to manipulate on each feature values,
|
68
|
+
# but spark model input dataframe contains Vector type feature column
|
69
|
+
# which shap explainer does not support.
|
70
|
+
# To support this, we need expand the Vector type feature column into
|
71
|
+
# multiple scalar feature columns and pass it to shap explainer.
|
72
|
+
_logger.warning(
|
73
|
+
"Logging model explainability insights is not currently supported for PySpark "
|
74
|
+
"models."
|
75
|
+
)
|
76
|
+
return
|
77
|
+
|
78
|
+
self.y_true = self.dataset.labels_data
|
79
|
+
self.label_list = self.evaluator_config.get("label_list")
|
80
|
+
self.pos_label = self.evaluator_config.get("pos_label")
|
81
|
+
|
82
|
+
if not (np.issubdtype(self.y_true.dtype, np.number) or self.y_true.dtype == np.bool_):
|
83
|
+
# Note: python bool type inherits number type but np.bool_ does not inherit np.number.
|
84
|
+
_logger.warning(
|
85
|
+
"Skip logging model explainability insights because it requires all label "
|
86
|
+
"values to be numeric or boolean."
|
87
|
+
)
|
88
|
+
return
|
89
|
+
|
90
|
+
algorithm = self.evaluator_config.get("explainability_algorithm", None)
|
91
|
+
if algorithm is not None and algorithm not in _SUPPORTED_SHAP_ALGORITHMS:
|
92
|
+
raise MlflowException(
|
93
|
+
message=f"Specified explainer algorithm {algorithm} is unsupported. Currently only "
|
94
|
+
f"support {','.join(_SUPPORTED_SHAP_ALGORITHMS)} algorithms.",
|
95
|
+
error_code=INVALID_PARAMETER_VALUE,
|
96
|
+
)
|
97
|
+
|
98
|
+
if algorithm != "kernel":
|
99
|
+
feature_dtypes = list(self.X.get_original().dtypes)
|
100
|
+
for feature_dtype in feature_dtypes:
|
101
|
+
if not np.issubdtype(feature_dtype, np.number):
|
102
|
+
_logger.warning(
|
103
|
+
"Skip logging model explainability insights because the shap explainer "
|
104
|
+
f"{algorithm} requires all feature values to be numeric, and each feature "
|
105
|
+
"column must only contain scalar values."
|
106
|
+
)
|
107
|
+
return
|
108
|
+
|
109
|
+
try:
|
110
|
+
import shap
|
111
|
+
from matplotlib import pyplot
|
112
|
+
except ImportError:
|
113
|
+
_logger.warning(
|
114
|
+
"SHAP or matplotlib package is not installed, so model explainability insights "
|
115
|
+
"will not be logged."
|
116
|
+
)
|
117
|
+
return
|
118
|
+
|
119
|
+
if Version(shap.__version__) < Version("0.40"):
|
120
|
+
_logger.warning(
|
121
|
+
"Shap package version is lower than 0.40, Skip log model explainability."
|
122
|
+
)
|
123
|
+
return
|
124
|
+
|
125
|
+
sample_rows = self.evaluator_config.get(
|
126
|
+
"explainability_nsamples", _DEFAULT_SAMPLE_ROWS_FOR_SHAP
|
127
|
+
)
|
128
|
+
|
129
|
+
X_df = self.X.copy_to_avoid_mutation()
|
130
|
+
|
131
|
+
sampled_X = shap.sample(X_df, sample_rows, random_state=0)
|
132
|
+
|
133
|
+
mode_or_mean_dict = _compute_df_mode_or_mean(X_df)
|
134
|
+
sampled_X = sampled_X.fillna(mode_or_mean_dict)
|
135
|
+
|
136
|
+
# shap explainer might call provided `predict_fn` with a `numpy.ndarray` type
|
137
|
+
# argument, this might break some model inference, so convert the argument into
|
138
|
+
# a pandas dataframe.
|
139
|
+
# The `shap_predict_fn` calls model's predict function, we need to restore the input
|
140
|
+
# dataframe with original column names, because some model prediction routine uses
|
141
|
+
# the column name.
|
142
|
+
|
143
|
+
predict_fn = _extract_predict_fn(model)
|
144
|
+
shap_predict_fn = functools.partial(
|
145
|
+
_shap_predict_fn, predict_fn=predict_fn, feature_names=self.dataset.feature_names
|
146
|
+
)
|
147
|
+
|
148
|
+
if self.label_list is None:
|
149
|
+
# If label list is not specified, infer label list from model output.
|
150
|
+
# We need to copy the input data as the model might mutate the input data.
|
151
|
+
y_pred = predict_fn(X_df.copy()) if predict_fn else self.dataset.predictions_data
|
152
|
+
self.label_list = np.unique(np.concatenate([self.y_true, y_pred]))
|
153
|
+
|
154
|
+
try:
|
155
|
+
if algorithm:
|
156
|
+
if algorithm == "kernel":
|
157
|
+
# We need to lazily import shap, so lazily import `_PatchedKernelExplainer`
|
158
|
+
from mlflow.models.evaluation._shap_patch import _PatchedKernelExplainer
|
159
|
+
|
160
|
+
kernel_link = self.evaluator_config.get(
|
161
|
+
"explainability_kernel_link", "identity"
|
162
|
+
)
|
163
|
+
if kernel_link not in ["identity", "logit"]:
|
164
|
+
raise ValueError(
|
165
|
+
"explainability_kernel_link config can only be set to 'identity' or "
|
166
|
+
f"'logit', but got '{kernel_link}'."
|
167
|
+
)
|
168
|
+
background_X = shap.sample(X_df, sample_rows, random_state=3)
|
169
|
+
background_X = background_X.fillna(mode_or_mean_dict)
|
170
|
+
|
171
|
+
explainer = _PatchedKernelExplainer(
|
172
|
+
shap_predict_fn, background_X, link=kernel_link
|
173
|
+
)
|
174
|
+
else:
|
175
|
+
explainer = shap.Explainer(
|
176
|
+
shap_predict_fn,
|
177
|
+
sampled_X,
|
178
|
+
feature_names=self.dataset.feature_names,
|
179
|
+
algorithm=algorithm,
|
180
|
+
)
|
181
|
+
else:
|
182
|
+
if (
|
183
|
+
raw_model
|
184
|
+
and not len(self.label_list) > 2
|
185
|
+
and not isinstance(raw_model, sk_Pipeline)
|
186
|
+
):
|
187
|
+
# For mulitnomial classifier, shap.Explainer may choose Tree/Linear explainer
|
188
|
+
# for raw model, this case shap plot doesn't support it well, so exclude the
|
189
|
+
# multinomial_classifier case here.
|
190
|
+
explainer = shap.Explainer(
|
191
|
+
raw_model, sampled_X, feature_names=self.dataset.feature_names
|
192
|
+
)
|
193
|
+
else:
|
194
|
+
# fallback to default explainer
|
195
|
+
explainer = shap.Explainer(
|
196
|
+
shap_predict_fn, sampled_X, feature_names=self.dataset.feature_names
|
197
|
+
)
|
198
|
+
|
199
|
+
_logger.info(f"Shap explainer {explainer.__class__.__name__} is used.")
|
200
|
+
|
201
|
+
if algorithm == "kernel":
|
202
|
+
shap_values = shap.Explanation(
|
203
|
+
explainer.shap_values(sampled_X), feature_names=self.dataset.feature_names
|
204
|
+
)
|
205
|
+
else:
|
206
|
+
shap_values = explainer(sampled_X)
|
207
|
+
except Exception as e:
|
208
|
+
# Shap evaluation might fail on some edge cases, e.g., unsupported input data values
|
209
|
+
# or unsupported model on specific shap explainer. Catch exception to prevent it
|
210
|
+
# breaking the whole `evaluate` function.
|
211
|
+
|
212
|
+
if not self.evaluator_config.get("ignore_exceptions", True):
|
213
|
+
raise e
|
214
|
+
|
215
|
+
_logger.warning(
|
216
|
+
f"Shap evaluation failed. Reason: {e!r}. "
|
217
|
+
"Set logging level to DEBUG to see the full traceback."
|
218
|
+
)
|
219
|
+
_logger.debug("", exc_info=True)
|
220
|
+
return
|
221
|
+
|
222
|
+
if self.evaluator_config.get("log_explainer", False):
|
223
|
+
try:
|
224
|
+
mlflow.shap.log_explainer(explainer, name="explainer")
|
225
|
+
except Exception as e:
|
226
|
+
# TODO: The explainer saver is buggy, if `get_underlying_model_flavor` return
|
227
|
+
# "unknown", then fallback to shap explainer saver, and shap explainer will call
|
228
|
+
# `model.save` for sklearn model, there is no `.save` method, so error will
|
229
|
+
# happen.
|
230
|
+
_logger.warning(
|
231
|
+
f"Logging explainer failed. Reason: {e!r}. "
|
232
|
+
"Set logging level to DEBUG to see the full traceback."
|
233
|
+
)
|
234
|
+
_logger.debug("", exc_info=True)
|
235
|
+
|
236
|
+
def _adjust_color_bar():
|
237
|
+
pyplot.gcf().axes[-1].set_aspect("auto")
|
238
|
+
pyplot.gcf().axes[-1].set_box_aspect(50)
|
239
|
+
|
240
|
+
def _adjust_axis_tick():
|
241
|
+
pyplot.xticks(fontsize=10)
|
242
|
+
pyplot.yticks(fontsize=10)
|
243
|
+
|
244
|
+
def plot_beeswarm():
|
245
|
+
shap.plots.beeswarm(shap_values, show=False, color_bar=True)
|
246
|
+
_adjust_color_bar()
|
247
|
+
_adjust_axis_tick()
|
248
|
+
|
249
|
+
with _suppress_class_imbalance_errors(ValueError, log_warning=False):
|
250
|
+
self._log_image_artifact(
|
251
|
+
plot_beeswarm,
|
252
|
+
"shap_beeswarm_plot",
|
253
|
+
)
|
254
|
+
|
255
|
+
def plot_summary():
|
256
|
+
shap.summary_plot(shap_values, show=False, color_bar=True)
|
257
|
+
_adjust_color_bar()
|
258
|
+
_adjust_axis_tick()
|
259
|
+
|
260
|
+
with _suppress_class_imbalance_errors(TypeError, log_warning=False):
|
261
|
+
self._log_image_artifact(
|
262
|
+
plot_summary,
|
263
|
+
"shap_summary_plot",
|
264
|
+
)
|
265
|
+
|
266
|
+
def plot_feature_importance():
|
267
|
+
shap.plots.bar(shap_values, show=False)
|
268
|
+
_adjust_axis_tick()
|
269
|
+
|
270
|
+
with _suppress_class_imbalance_errors(IndexError, log_warning=False):
|
271
|
+
self._log_image_artifact(
|
272
|
+
plot_feature_importance,
|
273
|
+
"shap_feature_importance_plot",
|
274
|
+
)
|
275
|
+
|
276
|
+
return EvaluationResult(
|
277
|
+
metrics=self.aggregate_metrics,
|
278
|
+
artifacts=self.artifacts,
|
279
|
+
run_id=self.run_id,
|
280
|
+
)
|
281
|
+
|
282
|
+
|
283
|
+
def _compute_df_mode_or_mean(df):
|
284
|
+
"""
|
285
|
+
Compute mean (for continuous columns) and compute mode (for other columns) for the
|
286
|
+
input dataframe, return a dict, key is column name, value is the corresponding mode or
|
287
|
+
mean value, this function calls `_is_continuous` to determine whether the
|
288
|
+
column is continuous column.
|
289
|
+
"""
|
290
|
+
continuous_cols = [c for c in df.columns if _is_continuous(df[c])]
|
291
|
+
df_cont = df[continuous_cols]
|
292
|
+
df_non_cont = df.drop(continuous_cols, axis=1)
|
293
|
+
|
294
|
+
means = {} if df_cont.empty else df_cont.mean().to_dict()
|
295
|
+
modes = {} if df_non_cont.empty else df_non_cont.mode().loc[0].to_dict()
|
296
|
+
return {**means, **modes}
|