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,259 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import urllib.parse
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Optional, Union
|
6
|
+
|
7
|
+
import mlflow
|
8
|
+
from mlflow.exceptions import MlflowException
|
9
|
+
from mlflow.store.artifact.artifact_repo import ArtifactRepository
|
10
|
+
from mlflow.store.artifact.databricks_models_artifact_repo import DatabricksModelsArtifactRepository
|
11
|
+
from mlflow.store.artifact.unity_catalog_models_artifact_repo import (
|
12
|
+
UnityCatalogModelsArtifactRepository,
|
13
|
+
)
|
14
|
+
from mlflow.store.artifact.unity_catalog_oss_models_artifact_repo import (
|
15
|
+
UnityCatalogOSSModelsArtifactRepository,
|
16
|
+
)
|
17
|
+
from mlflow.store.artifact.utils.models import (
|
18
|
+
_parse_model_uri,
|
19
|
+
get_model_name_and_version,
|
20
|
+
is_using_databricks_registry,
|
21
|
+
)
|
22
|
+
from mlflow.utils.uri import (
|
23
|
+
add_databricks_profile_info_to_artifact_uri,
|
24
|
+
get_databricks_profile_uri_from_artifact_uri,
|
25
|
+
is_databricks_unity_catalog_uri,
|
26
|
+
is_models_uri,
|
27
|
+
is_oss_unity_catalog_uri,
|
28
|
+
)
|
29
|
+
|
30
|
+
REGISTERED_MODEL_META_FILE_NAME = "registered_model_meta"
|
31
|
+
|
32
|
+
_logger = logging.getLogger(__name__)
|
33
|
+
|
34
|
+
|
35
|
+
class ModelsArtifactRepository(ArtifactRepository):
|
36
|
+
"""
|
37
|
+
Handles artifacts associated with a model version in the model registry via URIs of the form:
|
38
|
+
- `models:/<model_name>/<model_version>`
|
39
|
+
- `models:/<model_name>/<stage>` (refers to the latest model version in the given stage)
|
40
|
+
- `models:/<model_name>/latest` (refers to the latest of all model versions)
|
41
|
+
It is a light wrapper that resolves the artifact path to an absolute URI then instantiates
|
42
|
+
and uses the artifact repository for that URI.
|
43
|
+
"""
|
44
|
+
|
45
|
+
def __init__(self, artifact_uri: str, tracking_uri: Optional[str] = None) -> None:
|
46
|
+
from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
|
47
|
+
|
48
|
+
super().__init__(artifact_uri, tracking_uri)
|
49
|
+
registry_uri = mlflow.get_registry_uri()
|
50
|
+
self.is_logged_model_uri = self._is_logged_model_uri(artifact_uri)
|
51
|
+
if is_databricks_unity_catalog_uri(uri=registry_uri) and not self.is_logged_model_uri:
|
52
|
+
self.repo = UnityCatalogModelsArtifactRepository(
|
53
|
+
artifact_uri=artifact_uri, registry_uri=registry_uri
|
54
|
+
)
|
55
|
+
self.model_name = self.repo.model_name
|
56
|
+
self.model_version = self.repo.model_version
|
57
|
+
elif is_oss_unity_catalog_uri(uri=registry_uri) and not self.is_logged_model_uri:
|
58
|
+
self.repo = UnityCatalogOSSModelsArtifactRepository(
|
59
|
+
artifact_uri=artifact_uri, registry_uri=registry_uri
|
60
|
+
)
|
61
|
+
self.model_name = self.repo.model_name
|
62
|
+
self.model_version = self.repo.model_version
|
63
|
+
elif is_using_databricks_registry(artifact_uri) and not self.is_logged_model_uri:
|
64
|
+
# Use the DatabricksModelsArtifactRepository if a databricks profile is being used.
|
65
|
+
self.repo = DatabricksModelsArtifactRepository(artifact_uri)
|
66
|
+
self.model_name = self.repo.model_name
|
67
|
+
self.model_version = self.repo.model_version
|
68
|
+
else:
|
69
|
+
(
|
70
|
+
self.model_name,
|
71
|
+
self.model_version,
|
72
|
+
underlying_uri,
|
73
|
+
) = ModelsArtifactRepository._get_model_uri_infos(artifact_uri)
|
74
|
+
self.repo = get_artifact_repository(underlying_uri)
|
75
|
+
# TODO: it may be nice to fall back to the source URI explicitly here if for some reason
|
76
|
+
# we don't get a download URI here, or fail during the download itself.
|
77
|
+
|
78
|
+
@staticmethod
|
79
|
+
def is_models_uri(uri):
|
80
|
+
return urllib.parse.urlparse(uri).scheme == "models"
|
81
|
+
|
82
|
+
@staticmethod
|
83
|
+
def split_models_uri(uri):
|
84
|
+
"""
|
85
|
+
Split 'models:/<name>/<version>/path/to/model' into
|
86
|
+
('models:/<name>/<version>', 'path/to/model').
|
87
|
+
Split 'models://<scope>:<prefix>@databricks/<name>/<version>/path/to/model' into
|
88
|
+
('models://<scope>:<prefix>@databricks/<name>/<version>', 'path/to/model').
|
89
|
+
Split 'models:/<name>@alias/path/to/model' into
|
90
|
+
('models:/<name>@alias', 'path/to/model').
|
91
|
+
"""
|
92
|
+
uri = uri.rstrip("/")
|
93
|
+
parsed_url = urllib.parse.urlparse(uri)
|
94
|
+
path = parsed_url.path
|
95
|
+
netloc = parsed_url.netloc
|
96
|
+
if path.count("/") >= 2 and not path.endswith("/"):
|
97
|
+
splits = path.split("/", 3)
|
98
|
+
cut_index = 2 if "@" in splits[1] else 3
|
99
|
+
model_name_and_version = splits[:cut_index]
|
100
|
+
artifact_path = "/".join(splits[cut_index:])
|
101
|
+
base_part = f"models://{netloc}" if netloc else "models:"
|
102
|
+
return base_part + "/".join(model_name_and_version), artifact_path
|
103
|
+
return uri, ""
|
104
|
+
|
105
|
+
@staticmethod
|
106
|
+
def _is_logged_model_uri(uri: Union[str, Path]) -> bool:
|
107
|
+
"""
|
108
|
+
Returns True if the URI is a logged model URI (e.g. 'models:/<model_id>'), False otherwise.
|
109
|
+
"""
|
110
|
+
uri = str(uri)
|
111
|
+
return is_models_uri(uri) and _parse_model_uri(uri).model_id is not None
|
112
|
+
|
113
|
+
@staticmethod
|
114
|
+
def _get_model_uri_infos(uri):
|
115
|
+
# Note: to support a registry URI that is different from the tracking URI here,
|
116
|
+
# we'll need to add setting of registry URIs via environment variables.
|
117
|
+
|
118
|
+
from mlflow import MlflowClient
|
119
|
+
|
120
|
+
databricks_profile_uri = (
|
121
|
+
get_databricks_profile_uri_from_artifact_uri(uri) or mlflow.get_registry_uri()
|
122
|
+
)
|
123
|
+
client = MlflowClient(registry_uri=databricks_profile_uri)
|
124
|
+
name_and_version_or_id = get_model_name_and_version(client, uri)
|
125
|
+
if len(name_and_version_or_id) == 1:
|
126
|
+
name = None
|
127
|
+
version = None
|
128
|
+
model_id = name_and_version_or_id[0]
|
129
|
+
download_uri = client.get_logged_model(model_id).artifact_location
|
130
|
+
else:
|
131
|
+
name, version = name_and_version_or_id
|
132
|
+
download_uri = client.get_model_version_download_uri(name, version)
|
133
|
+
|
134
|
+
return (
|
135
|
+
name,
|
136
|
+
version,
|
137
|
+
add_databricks_profile_info_to_artifact_uri(download_uri, databricks_profile_uri),
|
138
|
+
)
|
139
|
+
|
140
|
+
@staticmethod
|
141
|
+
def get_underlying_uri(uri):
|
142
|
+
_, _, underlying_uri = ModelsArtifactRepository._get_model_uri_infos(uri)
|
143
|
+
|
144
|
+
return underlying_uri
|
145
|
+
|
146
|
+
def log_artifact(self, local_file, artifact_path=None):
|
147
|
+
"""
|
148
|
+
Log a local file as an artifact, optionally taking an ``artifact_path`` to place it in
|
149
|
+
within the run's artifacts. Run artifacts can be organized into directories, so you can
|
150
|
+
place the artifact in a directory this way.
|
151
|
+
|
152
|
+
Args:
|
153
|
+
local_file: Path to artifact to log.
|
154
|
+
artifact_path: Directory within the run's artifact directory in which to log the
|
155
|
+
artifact.
|
156
|
+
"""
|
157
|
+
if self.is_logged_model_uri:
|
158
|
+
return self.repo.log_artifact(local_file, artifact_path)
|
159
|
+
raise ValueError(
|
160
|
+
"log_artifact is not supported for models:/<name>/<version> URIs. "
|
161
|
+
"Use register_model instead."
|
162
|
+
)
|
163
|
+
|
164
|
+
def log_artifacts(self, local_dir, artifact_path=None):
|
165
|
+
"""
|
166
|
+
Log the files in the specified local directory as artifacts, optionally taking
|
167
|
+
an ``artifact_path`` to place them in within the run's artifacts.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
local_dir: Directory of local artifacts to log.
|
171
|
+
artifact_path: Directory within the run's artifact directory in which to log the
|
172
|
+
artifacts.
|
173
|
+
"""
|
174
|
+
if self.is_logged_model_uri:
|
175
|
+
return self.repo.log_artifacts(local_dir, artifact_path)
|
176
|
+
raise ValueError(
|
177
|
+
"log_artifacts is not supported for models:/<name>/<version> URIs. "
|
178
|
+
"Use register_model instead."
|
179
|
+
)
|
180
|
+
|
181
|
+
def list_artifacts(self, path):
|
182
|
+
"""
|
183
|
+
Return all the artifacts for this run_id directly under path. If path is a file, returns
|
184
|
+
an empty list. Will error if path is neither a file nor directory.
|
185
|
+
|
186
|
+
Args:
|
187
|
+
path: Relative source path that contain desired artifacts.
|
188
|
+
|
189
|
+
Returns:
|
190
|
+
List of artifacts as FileInfo listed directly under path.
|
191
|
+
"""
|
192
|
+
return self.repo.list_artifacts(path)
|
193
|
+
|
194
|
+
def _add_registered_model_meta_file(self, model_path):
|
195
|
+
from mlflow.utils.yaml_utils import write_yaml
|
196
|
+
|
197
|
+
write_yaml(
|
198
|
+
model_path,
|
199
|
+
REGISTERED_MODEL_META_FILE_NAME,
|
200
|
+
{
|
201
|
+
"model_name": self.model_name,
|
202
|
+
"model_version": self.model_version,
|
203
|
+
},
|
204
|
+
overwrite=True,
|
205
|
+
ensure_yaml_extension=False,
|
206
|
+
)
|
207
|
+
|
208
|
+
def download_artifacts(self, artifact_path, dst_path=None, lineage_header_info=None):
|
209
|
+
"""
|
210
|
+
Download an artifact file or directory to a local directory if applicable, and return a
|
211
|
+
local path for it.
|
212
|
+
For registered models, when the artifact is downloaded, the model name and version
|
213
|
+
are saved in the "registered_model_meta" file on the caller's side.
|
214
|
+
The caller is responsible for managing the lifecycle of the downloaded artifacts.
|
215
|
+
|
216
|
+
Args:
|
217
|
+
artifact_path: Relative source path to the desired artifacts.
|
218
|
+
dst_path: Absolute path of the local filesystem destination directory to which to
|
219
|
+
download the specified artifacts. This directory must already exist.
|
220
|
+
If unspecified, the artifacts will either be downloaded to a new
|
221
|
+
uniquely-named directory on the local filesystem or will be returned
|
222
|
+
directly in the case of the LocalArtifactRepository.
|
223
|
+
lineage_header_info: Linear header information.
|
224
|
+
|
225
|
+
Returns:
|
226
|
+
Absolute path of the local filesystem location containing the desired artifacts.
|
227
|
+
"""
|
228
|
+
|
229
|
+
from mlflow.models.model import MLMODEL_FILE_NAME
|
230
|
+
|
231
|
+
# Pass lineage header info if model is registered in UC
|
232
|
+
if isinstance(self.repo, UnityCatalogModelsArtifactRepository):
|
233
|
+
model_path = self.repo.download_artifacts(
|
234
|
+
artifact_path, dst_path, lineage_header_info=lineage_header_info
|
235
|
+
)
|
236
|
+
else:
|
237
|
+
model_path = self.repo.download_artifacts(artifact_path, dst_path)
|
238
|
+
# NB: only add the registered model metadata iff the artifact path is at the root model
|
239
|
+
# directory. For individual files or subdirectories within the model directory, do not
|
240
|
+
# create the metadata file.
|
241
|
+
if os.path.isdir(model_path) and MLMODEL_FILE_NAME in os.listdir(model_path):
|
242
|
+
self._add_registered_model_meta_file(model_path)
|
243
|
+
|
244
|
+
return model_path
|
245
|
+
|
246
|
+
def _download_file(self, remote_file_path, local_path):
|
247
|
+
"""
|
248
|
+
Download the file at the specified relative remote path and saves
|
249
|
+
it at the specified local path.
|
250
|
+
|
251
|
+
Args:
|
252
|
+
remote_file_path: Source path to the remote file, relative to the root
|
253
|
+
directory of the artifact repository.
|
254
|
+
local_path: The path to which to save the downloaded file.
|
255
|
+
"""
|
256
|
+
self.repo._download_file(remote_file_path, local_path)
|
257
|
+
|
258
|
+
def delete_artifacts(self, artifact_path=None):
|
259
|
+
raise MlflowException("Not implemented yet")
|
@@ -0,0 +1,356 @@
|
|
1
|
+
import json
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import posixpath
|
5
|
+
import urllib.parse
|
6
|
+
from mimetypes import guess_type
|
7
|
+
|
8
|
+
from mlflow.entities import FileInfo
|
9
|
+
from mlflow.environment_variables import (
|
10
|
+
MLFLOW_ENABLE_MULTIPART_UPLOAD,
|
11
|
+
MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE,
|
12
|
+
MLFLOW_S3_UPLOAD_EXTRA_ARGS,
|
13
|
+
)
|
14
|
+
from mlflow.exceptions import MlflowException
|
15
|
+
from mlflow.protos.databricks_artifacts_pb2 import ArtifactCredentialInfo
|
16
|
+
from mlflow.store.artifact.artifact_repo import _retry_with_new_creds
|
17
|
+
from mlflow.store.artifact.cloud_artifact_repo import (
|
18
|
+
CloudArtifactRepository,
|
19
|
+
_complete_futures,
|
20
|
+
_compute_num_chunks,
|
21
|
+
_validate_chunk_size_aws,
|
22
|
+
)
|
23
|
+
from mlflow.store.artifact.s3_artifact_repo import _get_s3_client
|
24
|
+
from mlflow.utils.file_utils import read_chunk
|
25
|
+
from mlflow.utils.request_utils import cloud_storage_http_request
|
26
|
+
from mlflow.utils.rest_utils import augmented_raise_for_status
|
27
|
+
|
28
|
+
_logger = logging.getLogger(__name__)
|
29
|
+
_BUCKET_REGION = "BucketRegion"
|
30
|
+
_RESPONSE_METADATA = "ResponseMetadata"
|
31
|
+
_HTTP_HEADERS = "HTTPHeaders"
|
32
|
+
_HTTP_HEADER_BUCKET_REGION = "x-amz-bucket-region"
|
33
|
+
_BUCKET_LOCATION_NAME = "BucketLocationName"
|
34
|
+
|
35
|
+
|
36
|
+
class OptimizedS3ArtifactRepository(CloudArtifactRepository):
|
37
|
+
"""
|
38
|
+
An optimized version of the S3 Artifact Repository.
|
39
|
+
|
40
|
+
This class is used for uploading and downloading S3 artifacts for UC models. While it largely
|
41
|
+
copies the behavior of the S3ArtifactRepository, the `log_artifact`, `log_artifacts`, and
|
42
|
+
`_download_file` methods are optimized by replacing boto3 client operations with the use of
|
43
|
+
presigned URLs for both uploads and downloads.
|
44
|
+
"""
|
45
|
+
|
46
|
+
def __init__(
|
47
|
+
self,
|
48
|
+
artifact_uri,
|
49
|
+
access_key_id=None,
|
50
|
+
secret_access_key=None,
|
51
|
+
session_token=None,
|
52
|
+
credential_refresh_def=None,
|
53
|
+
addressing_style=None,
|
54
|
+
s3_endpoint_url=None,
|
55
|
+
s3_upload_extra_args=None,
|
56
|
+
):
|
57
|
+
super().__init__(artifact_uri)
|
58
|
+
self._access_key_id = access_key_id
|
59
|
+
self._secret_access_key = secret_access_key
|
60
|
+
self._session_token = session_token
|
61
|
+
self._credential_refresh_def = credential_refresh_def
|
62
|
+
self._addressing_style = addressing_style
|
63
|
+
self._s3_endpoint_url = s3_endpoint_url
|
64
|
+
self.bucket, self.bucket_path = self.parse_s3_compliant_uri(self.artifact_uri)
|
65
|
+
self._region_name = self._get_region_name()
|
66
|
+
self._s3_upload_extra_args = s3_upload_extra_args if s3_upload_extra_args else {}
|
67
|
+
|
68
|
+
def _refresh_credentials(self):
|
69
|
+
if not self._credential_refresh_def:
|
70
|
+
return self._get_s3_client()
|
71
|
+
new_creds = self._credential_refresh_def()
|
72
|
+
self._access_key_id = new_creds["access_key_id"]
|
73
|
+
self._secret_access_key = new_creds["secret_access_key"]
|
74
|
+
self._session_token = new_creds["session_token"]
|
75
|
+
self._s3_upload_extra_args = new_creds["s3_upload_extra_args"]
|
76
|
+
return self._get_s3_client()
|
77
|
+
|
78
|
+
def _get_region_name(self):
|
79
|
+
from botocore.exceptions import ClientError
|
80
|
+
|
81
|
+
temp_client = _get_s3_client(
|
82
|
+
addressing_style=self._addressing_style,
|
83
|
+
access_key_id=self._access_key_id,
|
84
|
+
secret_access_key=self._secret_access_key,
|
85
|
+
session_token=self._session_token,
|
86
|
+
s3_endpoint_url=self._s3_endpoint_url,
|
87
|
+
)
|
88
|
+
try:
|
89
|
+
head_bucket_resp = temp_client.head_bucket(Bucket=self.bucket)
|
90
|
+
# A normal response will have the region in the Bucket_Region field of the response
|
91
|
+
if _BUCKET_REGION in head_bucket_resp:
|
92
|
+
return head_bucket_resp[_BUCKET_REGION]
|
93
|
+
# If the bucket exists but the caller does not have permissions, the http headers
|
94
|
+
# are passed back as part of the metadata of a normal, non-throwing response. In
|
95
|
+
# this case we use the x-amz-bucket-region field of the HTTP headers which should
|
96
|
+
# always be populated with the region.
|
97
|
+
if (
|
98
|
+
_RESPONSE_METADATA in head_bucket_resp
|
99
|
+
and _HTTP_HEADERS in head_bucket_resp[_RESPONSE_METADATA]
|
100
|
+
and _HTTP_HEADER_BUCKET_REGION
|
101
|
+
in head_bucket_resp[_RESPONSE_METADATA][_HTTP_HEADERS]
|
102
|
+
):
|
103
|
+
return head_bucket_resp[_RESPONSE_METADATA][_HTTP_HEADERS][
|
104
|
+
_HTTP_HEADER_BUCKET_REGION
|
105
|
+
]
|
106
|
+
# Directory buckets do not have a Bucket_Region and instead have a
|
107
|
+
# Bucket_Location_Name. This name cannot be used as the region name
|
108
|
+
# however, so we warn that this has happened and allow the exception
|
109
|
+
# at the end to be raised.
|
110
|
+
if _BUCKET_LOCATION_NAME in head_bucket_resp:
|
111
|
+
_logger.warning(
|
112
|
+
f"Directory bucket {self.bucket} found with BucketLocationName "
|
113
|
+
f"{head_bucket_resp[_BUCKET_LOCATION_NAME]}."
|
114
|
+
)
|
115
|
+
raise Exception(f"Unable to get the region name for bucket {self.bucket}.")
|
116
|
+
except ClientError as error:
|
117
|
+
# If a client error occurs, we check to see if the x-amz-bucket-region field is set
|
118
|
+
# in the response and return that. If it is not present, this will raise due to the
|
119
|
+
# key not being present.
|
120
|
+
return error.response[_RESPONSE_METADATA][_HTTP_HEADERS][_HTTP_HEADER_BUCKET_REGION]
|
121
|
+
|
122
|
+
def _get_s3_client(self):
|
123
|
+
return _get_s3_client(
|
124
|
+
addressing_style=self._addressing_style,
|
125
|
+
access_key_id=self._access_key_id,
|
126
|
+
secret_access_key=self._secret_access_key,
|
127
|
+
session_token=self._session_token,
|
128
|
+
region_name=self._region_name,
|
129
|
+
s3_endpoint_url=self._s3_endpoint_url,
|
130
|
+
)
|
131
|
+
|
132
|
+
def parse_s3_compliant_uri(self, uri):
|
133
|
+
"""Parse an S3 URI, returning (bucket, path)"""
|
134
|
+
parsed = urllib.parse.urlparse(uri)
|
135
|
+
if parsed.scheme != "s3":
|
136
|
+
raise Exception(f"Not an S3 URI: {uri}")
|
137
|
+
path = parsed.path
|
138
|
+
if path.startswith("/"):
|
139
|
+
path = path[1:]
|
140
|
+
return parsed.netloc, path
|
141
|
+
|
142
|
+
@staticmethod
|
143
|
+
def get_s3_file_upload_extra_args():
|
144
|
+
s3_file_upload_extra_args = MLFLOW_S3_UPLOAD_EXTRA_ARGS.get()
|
145
|
+
if s3_file_upload_extra_args:
|
146
|
+
return json.loads(s3_file_upload_extra_args)
|
147
|
+
else:
|
148
|
+
return None
|
149
|
+
|
150
|
+
def _upload_file(self, s3_client, local_file, bucket, key):
|
151
|
+
extra_args = {}
|
152
|
+
extra_args.update(self._s3_upload_extra_args)
|
153
|
+
guessed_type, guessed_encoding = guess_type(local_file)
|
154
|
+
if guessed_type is not None:
|
155
|
+
extra_args["ContentType"] = guessed_type
|
156
|
+
if guessed_encoding is not None:
|
157
|
+
extra_args["ContentEncoding"] = guessed_encoding
|
158
|
+
environ_extra_args = self.get_s3_file_upload_extra_args()
|
159
|
+
if environ_extra_args is not None:
|
160
|
+
extra_args.update(environ_extra_args)
|
161
|
+
|
162
|
+
def try_func(creds):
|
163
|
+
creds.upload_file(Filename=local_file, Bucket=bucket, Key=key, ExtraArgs=extra_args)
|
164
|
+
|
165
|
+
_retry_with_new_creds(
|
166
|
+
try_func=try_func, creds_func=self._refresh_credentials, orig_creds=s3_client
|
167
|
+
)
|
168
|
+
|
169
|
+
def log_artifact(self, local_file, artifact_path=None):
|
170
|
+
artifact_file_path = os.path.basename(local_file)
|
171
|
+
if artifact_path:
|
172
|
+
artifact_file_path = posixpath.join(artifact_path, artifact_file_path)
|
173
|
+
self._upload_to_cloud(
|
174
|
+
cloud_credential_info=self._get_s3_client(),
|
175
|
+
src_file_path=local_file,
|
176
|
+
artifact_file_path=artifact_file_path,
|
177
|
+
)
|
178
|
+
|
179
|
+
def _get_write_credential_infos(self, remote_file_paths):
|
180
|
+
"""
|
181
|
+
Instead of returning ArtifactCredentialInfo objects, we instead return a list of initialized
|
182
|
+
S3 client. We do so because S3 clients cannot be instantiated within each thread.
|
183
|
+
"""
|
184
|
+
return [self._get_s3_client() for _ in remote_file_paths]
|
185
|
+
|
186
|
+
def _upload_to_cloud(self, cloud_credential_info, src_file_path, artifact_file_path):
|
187
|
+
dest_path = posixpath.join(self.bucket_path, artifact_file_path)
|
188
|
+
key = posixpath.normpath(dest_path)
|
189
|
+
if (
|
190
|
+
MLFLOW_ENABLE_MULTIPART_UPLOAD.get()
|
191
|
+
and os.path.getsize(src_file_path) > MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE.get()
|
192
|
+
):
|
193
|
+
self._multipart_upload(cloud_credential_info, src_file_path, self.bucket, key)
|
194
|
+
else:
|
195
|
+
self._upload_file(cloud_credential_info, src_file_path, self.bucket, key)
|
196
|
+
|
197
|
+
def _multipart_upload(self, cloud_credential_info, local_file, bucket, key):
|
198
|
+
# Create multipart upload
|
199
|
+
s3_client = cloud_credential_info
|
200
|
+
response = s3_client.create_multipart_upload(Bucket=bucket, Key=key)
|
201
|
+
upload_id = response["UploadId"]
|
202
|
+
|
203
|
+
num_parts = _compute_num_chunks(local_file, MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE.get())
|
204
|
+
_validate_chunk_size_aws(MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE.get())
|
205
|
+
|
206
|
+
# define helper functions for uploading data
|
207
|
+
def _upload_part(part_number, local_file, start_byte, size):
|
208
|
+
data = read_chunk(local_file, size, start_byte)
|
209
|
+
|
210
|
+
def try_func(creds):
|
211
|
+
# Create presigned URL for each part
|
212
|
+
presigned_url = creds.generate_presigned_url(
|
213
|
+
"upload_part",
|
214
|
+
Params={
|
215
|
+
"Bucket": bucket,
|
216
|
+
"Key": key,
|
217
|
+
"UploadId": upload_id,
|
218
|
+
"PartNumber": part_number,
|
219
|
+
},
|
220
|
+
)
|
221
|
+
with cloud_storage_http_request("put", presigned_url, data=data) as response:
|
222
|
+
augmented_raise_for_status(response)
|
223
|
+
return response.headers["ETag"]
|
224
|
+
|
225
|
+
return _retry_with_new_creds(
|
226
|
+
try_func=try_func, creds_func=self._refresh_credentials, orig_creds=s3_client
|
227
|
+
)
|
228
|
+
|
229
|
+
try:
|
230
|
+
# Upload each part with retries
|
231
|
+
futures = {}
|
232
|
+
for index in range(num_parts):
|
233
|
+
part_number = index + 1
|
234
|
+
start_byte = index * MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE.get()
|
235
|
+
future = self.chunk_thread_pool.submit(
|
236
|
+
_upload_part,
|
237
|
+
part_number=part_number,
|
238
|
+
local_file=local_file,
|
239
|
+
start_byte=start_byte,
|
240
|
+
size=MLFLOW_MULTIPART_UPLOAD_CHUNK_SIZE.get(),
|
241
|
+
)
|
242
|
+
futures[future] = part_number
|
243
|
+
|
244
|
+
results, errors = _complete_futures(futures, local_file)
|
245
|
+
if errors:
|
246
|
+
raise MlflowException(
|
247
|
+
f"Failed to upload at least one part of {local_file}. Errors: {errors}"
|
248
|
+
)
|
249
|
+
parts = [
|
250
|
+
{"PartNumber": part_number, "ETag": results[part_number]}
|
251
|
+
for part_number in sorted(results)
|
252
|
+
]
|
253
|
+
|
254
|
+
# Complete multipart upload
|
255
|
+
s3_client.complete_multipart_upload(
|
256
|
+
Bucket=bucket,
|
257
|
+
Key=key,
|
258
|
+
UploadId=upload_id,
|
259
|
+
MultipartUpload={"Parts": parts},
|
260
|
+
)
|
261
|
+
except Exception as e:
|
262
|
+
_logger.warning(
|
263
|
+
"Encountered an unexpected error during multipart upload: %s, aborting", e
|
264
|
+
)
|
265
|
+
s3_client.abort_multipart_upload(
|
266
|
+
Bucket=bucket,
|
267
|
+
Key=key,
|
268
|
+
UploadId=upload_id,
|
269
|
+
)
|
270
|
+
raise e
|
271
|
+
|
272
|
+
def list_artifacts(self, path=None):
|
273
|
+
artifact_path = self.bucket_path
|
274
|
+
dest_path = self.bucket_path
|
275
|
+
if path:
|
276
|
+
dest_path = posixpath.join(dest_path, path)
|
277
|
+
infos = []
|
278
|
+
dest_path = dest_path.rstrip("/") if dest_path else ""
|
279
|
+
prefix = dest_path + "/" if dest_path else ""
|
280
|
+
s3_client = self._get_s3_client()
|
281
|
+
paginator = s3_client.get_paginator("list_objects_v2")
|
282
|
+
results = paginator.paginate(Bucket=self.bucket, Prefix=prefix, Delimiter="/")
|
283
|
+
for result in results:
|
284
|
+
# Subdirectories will be listed as "common prefixes" due to the way we made the request
|
285
|
+
for obj in result.get("CommonPrefixes", []):
|
286
|
+
subdir_path = obj.get("Prefix")
|
287
|
+
self._verify_listed_object_contains_artifact_path_prefix(
|
288
|
+
listed_object_path=subdir_path, artifact_path=artifact_path
|
289
|
+
)
|
290
|
+
subdir_rel_path = posixpath.relpath(path=subdir_path, start=artifact_path)
|
291
|
+
if subdir_rel_path.endswith("/"):
|
292
|
+
subdir_rel_path = subdir_rel_path[:-1]
|
293
|
+
infos.append(FileInfo(subdir_rel_path, True, None))
|
294
|
+
# Objects listed directly will be files
|
295
|
+
for obj in result.get("Contents", []):
|
296
|
+
file_path = obj.get("Key")
|
297
|
+
self._verify_listed_object_contains_artifact_path_prefix(
|
298
|
+
listed_object_path=file_path, artifact_path=artifact_path
|
299
|
+
)
|
300
|
+
file_rel_path = posixpath.relpath(path=file_path, start=artifact_path)
|
301
|
+
file_size = int(obj.get("Size"))
|
302
|
+
infos.append(FileInfo(file_rel_path, False, file_size))
|
303
|
+
return sorted(infos, key=lambda f: f.path)
|
304
|
+
|
305
|
+
@staticmethod
|
306
|
+
def _verify_listed_object_contains_artifact_path_prefix(listed_object_path, artifact_path):
|
307
|
+
if not listed_object_path.startswith(artifact_path):
|
308
|
+
raise MlflowException(
|
309
|
+
"The path of the listed S3 object does not begin with the specified"
|
310
|
+
f" artifact path. Artifact path: {artifact_path}. Object path:"
|
311
|
+
f" {listed_object_path}."
|
312
|
+
)
|
313
|
+
|
314
|
+
def _get_presigned_uri(self, remote_file_path):
|
315
|
+
s3_client = self._get_s3_client()
|
316
|
+
s3_full_path = posixpath.join(self.bucket_path, remote_file_path)
|
317
|
+
return s3_client.generate_presigned_url(
|
318
|
+
"get_object", Params={"Bucket": self.bucket, "Key": s3_full_path}
|
319
|
+
)
|
320
|
+
|
321
|
+
def _get_read_credential_infos(self, remote_file_paths):
|
322
|
+
return [
|
323
|
+
ArtifactCredentialInfo(signed_uri=self._get_presigned_uri(path))
|
324
|
+
for path in remote_file_paths
|
325
|
+
]
|
326
|
+
|
327
|
+
def _download_from_cloud(self, remote_file_path, local_path):
|
328
|
+
s3_client = self._get_s3_client()
|
329
|
+
s3_full_path = posixpath.join(self.bucket_path, remote_file_path)
|
330
|
+
|
331
|
+
def try_func(creds):
|
332
|
+
creds.download_file(self.bucket, s3_full_path, local_path)
|
333
|
+
|
334
|
+
_retry_with_new_creds(
|
335
|
+
try_func=try_func, creds_func=self._refresh_credentials, orig_creds=s3_client
|
336
|
+
)
|
337
|
+
|
338
|
+
def delete_artifacts(self, artifact_path=None):
|
339
|
+
dest_path = self.bucket_path
|
340
|
+
if artifact_path:
|
341
|
+
dest_path = posixpath.join(dest_path, artifact_path)
|
342
|
+
|
343
|
+
dest_path = dest_path.rstrip("/") if dest_path else ""
|
344
|
+
s3_client = self._get_s3_client()
|
345
|
+
paginator = s3_client.get_paginator("list_objects_v2")
|
346
|
+
results = paginator.paginate(Bucket=self.bucket, Prefix=dest_path)
|
347
|
+
for result in results:
|
348
|
+
keys = []
|
349
|
+
for to_delete_obj in result.get("Contents", []):
|
350
|
+
file_path = to_delete_obj.get("Key")
|
351
|
+
self._verify_listed_object_contains_artifact_path_prefix(
|
352
|
+
listed_object_path=file_path, artifact_path=dest_path
|
353
|
+
)
|
354
|
+
keys.append({"Key": file_path})
|
355
|
+
if keys:
|
356
|
+
s3_client.delete_objects(Bucket=self.bucket, Delete={"Objects": keys})
|