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,173 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
import posixpath
|
4
|
+
|
5
|
+
from mlflow.entities import FileInfo
|
6
|
+
from mlflow.environment_variables import MLFLOW_MULTIPART_DOWNLOAD_CHUNK_SIZE
|
7
|
+
from mlflow.exceptions import RestException
|
8
|
+
from mlflow.protos.databricks_artifacts_pb2 import ArtifactCredentialInfo
|
9
|
+
from mlflow.protos.databricks_filesystem_service_pb2 import (
|
10
|
+
CreateDownloadUrlRequest,
|
11
|
+
CreateDownloadUrlResponse,
|
12
|
+
CreateUploadUrlRequest,
|
13
|
+
CreateUploadUrlResponse,
|
14
|
+
FilesystemService,
|
15
|
+
ListDirectoryResponse,
|
16
|
+
)
|
17
|
+
from mlflow.protos.databricks_pb2 import NOT_FOUND, ErrorCode
|
18
|
+
from mlflow.store.artifact.artifact_repo import _retry_with_new_creds
|
19
|
+
from mlflow.store.artifact.cloud_artifact_repo import CloudArtifactRepository
|
20
|
+
from mlflow.utils.file_utils import download_file_using_http_uri
|
21
|
+
from mlflow.utils.proto_json_utils import message_to_json
|
22
|
+
from mlflow.utils.request_utils import augmented_raise_for_status, cloud_storage_http_request
|
23
|
+
from mlflow.utils.rest_utils import (
|
24
|
+
_REST_API_PATH_PREFIX,
|
25
|
+
call_endpoint,
|
26
|
+
extract_api_info_for_service,
|
27
|
+
)
|
28
|
+
|
29
|
+
FILESYSTEM_METHOD_TO_INFO = extract_api_info_for_service(FilesystemService, _REST_API_PATH_PREFIX)
|
30
|
+
DIRECTORIES_ENDPOINT = "/api/2.0/fs/directories"
|
31
|
+
|
32
|
+
|
33
|
+
class PresignedUrlArtifactRepository(CloudArtifactRepository):
|
34
|
+
"""
|
35
|
+
Stores and retrieves model artifacts using presigned URLs.
|
36
|
+
"""
|
37
|
+
|
38
|
+
def __init__(self, db_creds, model_full_name, model_version):
|
39
|
+
artifact_uri = posixpath.join(
|
40
|
+
"/Models", model_full_name.replace(".", "/"), str(model_version)
|
41
|
+
)
|
42
|
+
super().__init__(artifact_uri)
|
43
|
+
self.db_creds = db_creds
|
44
|
+
|
45
|
+
def log_artifact(self, local_file, artifact_path=None):
|
46
|
+
artifact_file_path = os.path.basename(local_file)
|
47
|
+
if artifact_path:
|
48
|
+
artifact_file_path = posixpath.join(artifact_path, artifact_file_path)
|
49
|
+
cloud_credentials = self._get_write_credential_infos(
|
50
|
+
remote_file_paths=[artifact_file_path]
|
51
|
+
)[0]
|
52
|
+
self._upload_to_cloud(
|
53
|
+
cloud_credential_info=cloud_credentials,
|
54
|
+
src_file_path=local_file,
|
55
|
+
artifact_file_path=artifact_file_path,
|
56
|
+
)
|
57
|
+
|
58
|
+
def _get_write_credential_infos(self, remote_file_paths):
|
59
|
+
endpoint, method = FILESYSTEM_METHOD_TO_INFO[CreateUploadUrlRequest]
|
60
|
+
credential_infos = []
|
61
|
+
for relative_path in remote_file_paths:
|
62
|
+
fs_full_path = posixpath.join(self.artifact_uri, relative_path)
|
63
|
+
req_body = message_to_json(CreateUploadUrlRequest(path=fs_full_path))
|
64
|
+
response_proto = CreateUploadUrlResponse()
|
65
|
+
resp = call_endpoint(
|
66
|
+
host_creds=self.db_creds,
|
67
|
+
endpoint=endpoint,
|
68
|
+
method=method,
|
69
|
+
json_body=req_body,
|
70
|
+
response_proto=response_proto,
|
71
|
+
)
|
72
|
+
headers = [
|
73
|
+
ArtifactCredentialInfo.HttpHeader(name=header.name, value=header.value)
|
74
|
+
for header in resp.headers
|
75
|
+
]
|
76
|
+
credential_infos.append(ArtifactCredentialInfo(signed_uri=resp.url, headers=headers))
|
77
|
+
return credential_infos
|
78
|
+
|
79
|
+
def _upload_to_cloud(self, cloud_credential_info, src_file_path, artifact_file_path=None):
|
80
|
+
# artifact_file_path is unused in this implementation because the presigned URL
|
81
|
+
# and local file path are sufficient for upload to cloud storage
|
82
|
+
def try_func(creds):
|
83
|
+
presigned_url = creds.signed_uri
|
84
|
+
headers = {header.name: header.value for header in creds.headers}
|
85
|
+
with open(src_file_path, "rb") as source_file:
|
86
|
+
data = source_file.read()
|
87
|
+
with cloud_storage_http_request(
|
88
|
+
"put", presigned_url, data=data, headers=headers
|
89
|
+
) as response:
|
90
|
+
augmented_raise_for_status(response)
|
91
|
+
|
92
|
+
def creds_func():
|
93
|
+
return self._get_write_credential_infos(remote_file_paths=[artifact_file_path])[0]
|
94
|
+
|
95
|
+
_retry_with_new_creds(
|
96
|
+
try_func=try_func, creds_func=creds_func, orig_creds=cloud_credential_info
|
97
|
+
)
|
98
|
+
|
99
|
+
def list_artifacts(self, path=""):
|
100
|
+
infos = []
|
101
|
+
page_token = ""
|
102
|
+
while True:
|
103
|
+
endpoint = posixpath.join(DIRECTORIES_ENDPOINT, self.artifact_uri.lstrip("/"), path)
|
104
|
+
req_body = json.dumps({"page_token": page_token}) if page_token else None
|
105
|
+
|
106
|
+
response_proto = ListDirectoryResponse()
|
107
|
+
|
108
|
+
# If the path specified is not a directory, we return an empty list instead of raising
|
109
|
+
# an exception. This is due to this method being used in artifact_repo._is_directory
|
110
|
+
# to determine when a filepath is a directory.
|
111
|
+
try:
|
112
|
+
resp = call_endpoint(
|
113
|
+
host_creds=self.db_creds,
|
114
|
+
endpoint=endpoint,
|
115
|
+
method="GET",
|
116
|
+
json_body=req_body,
|
117
|
+
response_proto=response_proto,
|
118
|
+
)
|
119
|
+
except RestException as e:
|
120
|
+
if e.error_code == ErrorCode.Name(NOT_FOUND):
|
121
|
+
return []
|
122
|
+
else:
|
123
|
+
raise e
|
124
|
+
for dir_entry in resp.contents:
|
125
|
+
rel_path = posixpath.relpath(dir_entry.path, self.artifact_uri)
|
126
|
+
if dir_entry.is_directory:
|
127
|
+
infos.append(FileInfo(rel_path, True, None))
|
128
|
+
else:
|
129
|
+
infos.append(FileInfo(rel_path, False, dir_entry.file_size))
|
130
|
+
page_token = resp.next_page_token
|
131
|
+
if not page_token:
|
132
|
+
break
|
133
|
+
return sorted(infos, key=lambda f: f.path)
|
134
|
+
|
135
|
+
def _get_read_credential_infos(self, remote_file_paths):
|
136
|
+
credential_infos = []
|
137
|
+
for remote_file_path in remote_file_paths:
|
138
|
+
resp = self._get_download_presigned_url_and_headers(remote_file_path)
|
139
|
+
headers = [
|
140
|
+
ArtifactCredentialInfo.HttpHeader(name=header.name, value=header.value)
|
141
|
+
for header in resp.headers
|
142
|
+
]
|
143
|
+
credential_infos.append(ArtifactCredentialInfo(signed_uri=resp.url, headers=headers))
|
144
|
+
return credential_infos
|
145
|
+
|
146
|
+
def _download_from_cloud(self, remote_file_path, local_path):
|
147
|
+
def creds_func():
|
148
|
+
return self._get_download_presigned_url_and_headers(remote_file_path)
|
149
|
+
|
150
|
+
def try_func(creds):
|
151
|
+
presigned_url = creds.url
|
152
|
+
headers = {header.name: header.value for header in creds.headers}
|
153
|
+
download_file_using_http_uri(
|
154
|
+
http_uri=presigned_url,
|
155
|
+
download_path=local_path,
|
156
|
+
chunk_size=MLFLOW_MULTIPART_DOWNLOAD_CHUNK_SIZE.get(),
|
157
|
+
headers=headers,
|
158
|
+
)
|
159
|
+
|
160
|
+
_retry_with_new_creds(try_func=try_func, creds_func=creds_func)
|
161
|
+
|
162
|
+
def _get_download_presigned_url_and_headers(self, remote_file_path):
|
163
|
+
remote_file_full_path = posixpath.join(self.artifact_uri, remote_file_path)
|
164
|
+
endpoint, method = FILESYSTEM_METHOD_TO_INFO[CreateDownloadUrlRequest]
|
165
|
+
req_body = message_to_json(CreateDownloadUrlRequest(path=remote_file_full_path))
|
166
|
+
response_proto = CreateDownloadUrlResponse()
|
167
|
+
return call_endpoint(
|
168
|
+
host_creds=self.db_creds,
|
169
|
+
endpoint=endpoint,
|
170
|
+
method=method,
|
171
|
+
json_body=req_body,
|
172
|
+
response_proto=response_proto,
|
173
|
+
)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
from urllib.parse import urlparse
|
2
|
+
|
3
|
+
from mlflow.store.artifact.optimized_s3_artifact_repo import OptimizedS3ArtifactRepository
|
4
|
+
from mlflow.store.artifact.s3_artifact_repo import _get_s3_client
|
5
|
+
|
6
|
+
|
7
|
+
class R2ArtifactRepository(OptimizedS3ArtifactRepository):
|
8
|
+
"""Stores artifacts on Cloudflare R2."""
|
9
|
+
|
10
|
+
def __init__(
|
11
|
+
self,
|
12
|
+
artifact_uri,
|
13
|
+
access_key_id=None,
|
14
|
+
secret_access_key=None,
|
15
|
+
session_token=None,
|
16
|
+
credential_refresh_def=None,
|
17
|
+
s3_upload_extra_args=None,
|
18
|
+
):
|
19
|
+
# setup Cloudflare R2 backend to be endpoint_url, otherwise all s3 requests
|
20
|
+
# will go to AWS S3 by default
|
21
|
+
s3_endpoint_url = self.convert_r2_uri_to_s3_endpoint_url(artifact_uri)
|
22
|
+
self._access_key_id = access_key_id
|
23
|
+
self._secret_access_key = secret_access_key
|
24
|
+
self._session_token = session_token
|
25
|
+
self._s3_endpoint_url = s3_endpoint_url
|
26
|
+
self.bucket, self.bucket_path = self.parse_s3_compliant_uri(artifact_uri)
|
27
|
+
super().__init__(
|
28
|
+
artifact_uri,
|
29
|
+
access_key_id=access_key_id,
|
30
|
+
secret_access_key=secret_access_key,
|
31
|
+
session_token=session_token,
|
32
|
+
credential_refresh_def=credential_refresh_def,
|
33
|
+
addressing_style="virtual",
|
34
|
+
s3_endpoint_url=s3_endpoint_url,
|
35
|
+
s3_upload_extra_args=s3_upload_extra_args,
|
36
|
+
)
|
37
|
+
|
38
|
+
# Cloudflare implementation of head_bucket is not the same as AWS's, so we
|
39
|
+
# temporarily use the old method of get_bucket_location until cloudflare
|
40
|
+
# updates their implementation
|
41
|
+
def _get_region_name(self):
|
42
|
+
# note: s3 client enforces path addressing style for get_bucket_location
|
43
|
+
temp_client = _get_s3_client(
|
44
|
+
addressing_style="path",
|
45
|
+
access_key_id=self._access_key_id,
|
46
|
+
secret_access_key=self._secret_access_key,
|
47
|
+
session_token=self._session_token,
|
48
|
+
s3_endpoint_url=self._s3_endpoint_url,
|
49
|
+
)
|
50
|
+
return temp_client.get_bucket_location(Bucket=self.bucket)["LocationConstraint"]
|
51
|
+
|
52
|
+
def parse_s3_compliant_uri(self, uri):
|
53
|
+
# r2 uri format(virtual): r2://<bucket-name>@<account-id>.r2.cloudflarestorage.com/<path>
|
54
|
+
parsed = urlparse(uri)
|
55
|
+
if parsed.scheme != "r2":
|
56
|
+
raise Exception(f"Not an R2 URI: {uri}")
|
57
|
+
|
58
|
+
host = parsed.netloc
|
59
|
+
path = parsed.path
|
60
|
+
|
61
|
+
bucket = host.split("@")[0]
|
62
|
+
if path.startswith("/"):
|
63
|
+
path = path[1:]
|
64
|
+
return bucket, path
|
65
|
+
|
66
|
+
@staticmethod
|
67
|
+
def convert_r2_uri_to_s3_endpoint_url(r2_uri):
|
68
|
+
host = urlparse(r2_uri).netloc
|
69
|
+
host_without_bucket = host.split("@")[-1]
|
70
|
+
return f"https://{host_without_bucket}"
|
@@ -0,0 +1,265 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import urllib.parse
|
4
|
+
from typing import Iterator, Optional
|
5
|
+
|
6
|
+
import mlflow
|
7
|
+
from mlflow.entities.file_info import FileInfo
|
8
|
+
from mlflow.entities.logged_model import LoggedModel
|
9
|
+
from mlflow.exceptions import MlflowException
|
10
|
+
from mlflow.protos.databricks_pb2 import RESOURCE_DOES_NOT_EXIST
|
11
|
+
from mlflow.store.artifact.artifact_repo import ArtifactRepository
|
12
|
+
from mlflow.utils.file_utils import create_tmp_dir
|
13
|
+
from mlflow.utils.uri import (
|
14
|
+
add_databricks_profile_info_to_artifact_uri,
|
15
|
+
get_databricks_profile_uri_from_artifact_uri,
|
16
|
+
)
|
17
|
+
|
18
|
+
_logger = logging.getLogger(__name__)
|
19
|
+
|
20
|
+
|
21
|
+
class RunsArtifactRepository(ArtifactRepository):
|
22
|
+
"""
|
23
|
+
Handles artifacts associated with a Run via URIs of the form
|
24
|
+
`runs:/<run_id>/run-relative/path/to/artifact`.
|
25
|
+
It is a light wrapper that resolves the artifact path to an absolute URI then instantiates
|
26
|
+
and uses the artifact repository for that URI.
|
27
|
+
|
28
|
+
The relative path part of ``artifact_uri`` is expected to be in posixpath format, so Windows
|
29
|
+
users should take special care when constructing the URI.
|
30
|
+
"""
|
31
|
+
|
32
|
+
def __init__(self, artifact_uri: str, tracking_uri: Optional[str] = None) -> None:
|
33
|
+
from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
|
34
|
+
|
35
|
+
super().__init__(artifact_uri, tracking_uri)
|
36
|
+
uri = RunsArtifactRepository.get_underlying_uri(artifact_uri, tracking_uri)
|
37
|
+
self.repo = get_artifact_repository(uri, self.tracking_uri)
|
38
|
+
|
39
|
+
@staticmethod
|
40
|
+
def is_runs_uri(uri):
|
41
|
+
return urllib.parse.urlparse(uri).scheme == "runs"
|
42
|
+
|
43
|
+
@staticmethod
|
44
|
+
def get_underlying_uri(runs_uri: str, tracking_uri: Optional[str] = None) -> str:
|
45
|
+
from mlflow.tracking.artifact_utils import get_artifact_uri
|
46
|
+
|
47
|
+
(run_id, artifact_path) = RunsArtifactRepository.parse_runs_uri(runs_uri)
|
48
|
+
databricks_profile_uri = get_databricks_profile_uri_from_artifact_uri(runs_uri)
|
49
|
+
uri = get_artifact_uri(
|
50
|
+
run_id=run_id,
|
51
|
+
artifact_path=artifact_path,
|
52
|
+
tracking_uri=databricks_profile_uri or tracking_uri,
|
53
|
+
)
|
54
|
+
assert not RunsArtifactRepository.is_runs_uri(uri) # avoid an infinite loop
|
55
|
+
return add_databricks_profile_info_to_artifact_uri(
|
56
|
+
artifact_uri=uri, databricks_profile_uri=databricks_profile_uri or tracking_uri
|
57
|
+
)
|
58
|
+
|
59
|
+
@staticmethod
|
60
|
+
def parse_runs_uri(run_uri):
|
61
|
+
parsed = urllib.parse.urlparse(run_uri)
|
62
|
+
if parsed.scheme != "runs":
|
63
|
+
raise MlflowException(
|
64
|
+
f"Not a proper runs:/ URI: {run_uri}. "
|
65
|
+
+ "Runs URIs must be of the form 'runs:/<run_id>/run-relative/path/to/artifact'"
|
66
|
+
)
|
67
|
+
|
68
|
+
path = parsed.path
|
69
|
+
if not path.startswith("/") or len(path) <= 1:
|
70
|
+
raise MlflowException(
|
71
|
+
f"Not a proper runs:/ URI: {run_uri}. "
|
72
|
+
+ "Runs URIs must be of the form 'runs:/<run_id>/run-relative/path/to/artifact'"
|
73
|
+
)
|
74
|
+
path = path[1:]
|
75
|
+
|
76
|
+
path_parts = path.split("/")
|
77
|
+
run_id = path_parts[0]
|
78
|
+
if run_id == "":
|
79
|
+
raise MlflowException(
|
80
|
+
f"Not a proper runs:/ URI: {run_uri}. "
|
81
|
+
+ "Runs URIs must be of the form 'runs:/<run_id>/run-relative/path/to/artifact'"
|
82
|
+
)
|
83
|
+
|
84
|
+
artifact_path = "/".join(path_parts[1:]) if len(path_parts) > 1 else None
|
85
|
+
artifact_path = artifact_path if artifact_path != "" else None
|
86
|
+
|
87
|
+
return run_id, artifact_path
|
88
|
+
|
89
|
+
def log_artifact(self, local_file, artifact_path=None):
|
90
|
+
"""
|
91
|
+
Log a local file as an artifact, optionally taking an ``artifact_path`` to place it in
|
92
|
+
within the run's artifacts. Run artifacts can be organized into directories, so you can
|
93
|
+
place the artifact in a directory this way.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
local_file: Path to artifact to log.
|
97
|
+
artifact_path: Directory within the run's artifact directory in which to log the
|
98
|
+
artifact.
|
99
|
+
"""
|
100
|
+
self.repo.log_artifact(local_file, artifact_path)
|
101
|
+
|
102
|
+
def log_artifacts(self, local_dir, artifact_path=None):
|
103
|
+
"""
|
104
|
+
Log the files in the specified local directory as artifacts, optionally taking
|
105
|
+
an ``artifact_path`` to place them in within the run's artifacts.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
local_dir: Directory of local artifacts to log.
|
109
|
+
artifact_path: Directory within the run's artifact directory in which to log the
|
110
|
+
artifacts.
|
111
|
+
"""
|
112
|
+
self.repo.log_artifacts(local_dir, artifact_path)
|
113
|
+
|
114
|
+
def _is_directory(self, artifact_path):
|
115
|
+
return self.repo._is_directory(artifact_path)
|
116
|
+
|
117
|
+
def list_artifacts(self, path: Optional[str] = None) -> list[FileInfo]:
|
118
|
+
"""
|
119
|
+
Return all the artifacts for this run_id directly under path. If path is a file, returns
|
120
|
+
an empty list. Will error if path is neither a file nor directory. When the run has an
|
121
|
+
associated model, the artifacts of the model are also listed.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
path: Relative source path that contain desired artifacts
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
List of artifacts as FileInfo listed directly under path.
|
128
|
+
"""
|
129
|
+
return self._list_run_artifacts(path) + self._list_model_artifacts(path)
|
130
|
+
|
131
|
+
def _list_run_artifacts(self, path: Optional[str] = None) -> list[FileInfo]:
|
132
|
+
return self.repo.list_artifacts(path)
|
133
|
+
|
134
|
+
def _get_logged_model_artifact_repo(
|
135
|
+
self, run_id: str, name: str
|
136
|
+
) -> Optional[ArtifactRepository]:
|
137
|
+
"""
|
138
|
+
Get the artifact repository for a logged model with the given name and run ID.
|
139
|
+
Returns None if no such model exists.
|
140
|
+
"""
|
141
|
+
from mlflow.store.artifact.artifact_repository_registry import get_artifact_repository
|
142
|
+
|
143
|
+
client = mlflow.tracking.MlflowClient(self.tracking_uri)
|
144
|
+
experiment_id = client.get_run(run_id).info.experiment_id
|
145
|
+
|
146
|
+
def iter_models() -> Iterator[LoggedModel]:
|
147
|
+
page_token: Optional[str] = None
|
148
|
+
while True:
|
149
|
+
page = client.search_logged_models(
|
150
|
+
experiment_ids=[experiment_id],
|
151
|
+
# TODO: Filter by 'source_run_id' once Databricks backend supports it
|
152
|
+
filter_string=f"name = '{name}'",
|
153
|
+
page_token=page_token,
|
154
|
+
)
|
155
|
+
yield from page
|
156
|
+
if not page.token:
|
157
|
+
break
|
158
|
+
page_token = page.token
|
159
|
+
|
160
|
+
if matched := next((m for m in iter_models() if m.source_run_id == run_id), None):
|
161
|
+
return get_artifact_repository(matched.artifact_location, self.tracking_uri)
|
162
|
+
|
163
|
+
return None
|
164
|
+
|
165
|
+
def _list_model_artifacts(self, path: Optional[str] = None) -> list[FileInfo]:
|
166
|
+
"""
|
167
|
+
A run can have an associated model. If so, this method lists the artifacts of the model.
|
168
|
+
"""
|
169
|
+
full_path = f"{self.artifact_uri}/{path}" if path else self.artifact_uri
|
170
|
+
run_id, rel_path = RunsArtifactRepository.parse_runs_uri(full_path)
|
171
|
+
if not rel_path:
|
172
|
+
# At least one part of the path must be present (e.g. "runs:/<run_id>/<name>")
|
173
|
+
return []
|
174
|
+
[model_name, *rest] = rel_path.split("/", 1)
|
175
|
+
rel_path = rest[0] if rest else ""
|
176
|
+
if repo := self._get_logged_model_artifact_repo(run_id=run_id, name=model_name):
|
177
|
+
artifacts = repo.list_artifacts(path=rel_path)
|
178
|
+
return [
|
179
|
+
FileInfo(path=f"{model_name}/{a.path}", is_dir=a.is_dir, file_size=a.file_size)
|
180
|
+
for a in artifacts
|
181
|
+
]
|
182
|
+
|
183
|
+
return []
|
184
|
+
|
185
|
+
def download_artifacts(self, artifact_path: str, dst_path: Optional[str] = None) -> str:
|
186
|
+
"""
|
187
|
+
Download an artifact file or directory to a local directory if applicable, and return a
|
188
|
+
local path for it. When the run has an associated model, the artifacts of the model are also
|
189
|
+
downloaded to the specified destination directory. The caller is responsible for managing
|
190
|
+
the lifecycle of the downloaded artifacts.
|
191
|
+
|
192
|
+
Args:
|
193
|
+
artifact_path: Relative source path to the desired artifacts.
|
194
|
+
dst_path: Absolute path of the local filesystem destination directory to which to
|
195
|
+
download the specified artifacts. This directory must already exist.
|
196
|
+
If unspecified, the artifacts will either be downloaded to a new
|
197
|
+
uniquely-named directory on the local filesystem or will be returned
|
198
|
+
directly in the case of the LocalArtifactRepository.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
Absolute path of the local filesystem location containing the desired artifacts.
|
202
|
+
"""
|
203
|
+
dst_path = dst_path or create_tmp_dir()
|
204
|
+
run_out_path: Optional[str] = None
|
205
|
+
try:
|
206
|
+
# This fails when the run has no artifacts, so we catch the exception
|
207
|
+
run_out_path = self.repo.download_artifacts(artifact_path, dst_path)
|
208
|
+
except Exception:
|
209
|
+
_logger.debug(
|
210
|
+
f"Failed to download artifacts from {self.artifact_uri}/{artifact_path}.",
|
211
|
+
exc_info=True,
|
212
|
+
)
|
213
|
+
|
214
|
+
# If there are artifacts with the same name in the run and model, the model artifacts
|
215
|
+
# will overwrite the run artifacts.
|
216
|
+
model_out_path: Optional[str] = None
|
217
|
+
try:
|
218
|
+
model_out_path = self._download_model_artifacts(artifact_path, dst_path=dst_path)
|
219
|
+
except Exception:
|
220
|
+
_logger.debug(
|
221
|
+
f"Failed to download model artifacts from {self.artifact_uri}/{artifact_path}.",
|
222
|
+
exc_info=True,
|
223
|
+
)
|
224
|
+
path = run_out_path or model_out_path
|
225
|
+
if path is None:
|
226
|
+
raise MlflowException(
|
227
|
+
f"Failed to download artifacts from path {artifact_path!r}, "
|
228
|
+
"please ensure that the path is correct.",
|
229
|
+
error_code=RESOURCE_DOES_NOT_EXIST,
|
230
|
+
)
|
231
|
+
return path
|
232
|
+
|
233
|
+
def _download_model_artifacts(self, artifact_path: str, dst_path: str) -> Optional[str]:
|
234
|
+
"""
|
235
|
+
A run can have an associated model. If so, this method downloads the artifacts of the model.
|
236
|
+
"""
|
237
|
+
full_path = f"{self.artifact_uri}/{artifact_path}" if artifact_path else self.artifact_uri
|
238
|
+
run_id, rel_path = RunsArtifactRepository.parse_runs_uri(full_path)
|
239
|
+
if not rel_path:
|
240
|
+
# At least one part of the path must be present (e.g. "runs:/<run_id>/<name>")
|
241
|
+
return None
|
242
|
+
[model_name, *rest] = rel_path.split("/", 1)
|
243
|
+
rel_path = rest[0] if rest else ""
|
244
|
+
if repo := self._get_logged_model_artifact_repo(run_id=run_id, name=model_name):
|
245
|
+
dst = os.path.join(dst_path, model_name)
|
246
|
+
os.makedirs(dst, exist_ok=True)
|
247
|
+
return repo.download_artifacts(artifact_path=rel_path, dst_path=dst)
|
248
|
+
|
249
|
+
return None
|
250
|
+
|
251
|
+
def _download_file(self, remote_file_path, local_path):
|
252
|
+
"""
|
253
|
+
Download the file at the specified relative remote path and saves
|
254
|
+
it at the specified local path.
|
255
|
+
|
256
|
+
Args:
|
257
|
+
remote_file_path: Source path to the remote file, relative to the root
|
258
|
+
directory of the artifact repository.
|
259
|
+
local_path: The path to which to save the downloaded file.
|
260
|
+
|
261
|
+
"""
|
262
|
+
self.repo._download_file(remote_file_path, local_path)
|
263
|
+
|
264
|
+
def delete_artifacts(self, artifact_path=None):
|
265
|
+
self.repo.delete_artifacts(artifact_path)
|