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,257 @@
|
|
1
|
+
"""Azure authentication handler with advanced token management."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import threading
|
6
|
+
import logging
|
7
|
+
from datetime import datetime, timedelta
|
8
|
+
from typing import Optional
|
9
|
+
|
10
|
+
from azure.core.credentials import AccessToken
|
11
|
+
from azure.core.exceptions import ClientAuthenticationError
|
12
|
+
from azure.identity import (
|
13
|
+
DefaultAzureCredential,
|
14
|
+
ManagedIdentityCredential,
|
15
|
+
ClientSecretCredential,
|
16
|
+
)
|
17
|
+
|
18
|
+
from mlflow.azure.config import AzureAuthConfig, AuthMethod
|
19
|
+
from mlflow.azure.exceptions import TokenAcquisitionError
|
20
|
+
from mlflow.azure.utils import is_token_expired
|
21
|
+
|
22
|
+
logger = logging.getLogger(__name__)
|
23
|
+
|
24
|
+
|
25
|
+
class TokenCache:
|
26
|
+
"""Thread-safe token cache with expiration handling."""
|
27
|
+
|
28
|
+
def __init__(self):
|
29
|
+
self._lock = threading.RLock()
|
30
|
+
self._token: Optional[AccessToken] = None
|
31
|
+
self._expiry: Optional[datetime] = None
|
32
|
+
|
33
|
+
def get_token(self, buffer_seconds: int = 300) -> Optional[AccessToken]:
|
34
|
+
"""Get cached token if it's still valid.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
buffer_seconds: Buffer time before expiry to consider token invalid
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
Cached token if valid, None otherwise
|
41
|
+
"""
|
42
|
+
with self._lock:
|
43
|
+
if self._token and not is_token_expired(self._expiry, buffer_seconds):
|
44
|
+
logger.debug("Using cached token")
|
45
|
+
return self._token
|
46
|
+
|
47
|
+
if self._token:
|
48
|
+
logger.debug("Cached token expired or expiring soon")
|
49
|
+
|
50
|
+
return None
|
51
|
+
|
52
|
+
def set_token(self, token: AccessToken) -> None:
|
53
|
+
"""Cache a new token.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
token: Access token to cache
|
57
|
+
"""
|
58
|
+
with self._lock:
|
59
|
+
self._token = token
|
60
|
+
# Convert timestamp to datetime
|
61
|
+
self._expiry = datetime.fromtimestamp(token.expires_on)
|
62
|
+
|
63
|
+
logger.debug(
|
64
|
+
"Token cached, expires at %s (in %d seconds)",
|
65
|
+
self._expiry.isoformat(),
|
66
|
+
int((self._expiry - datetime.utcnow()).total_seconds()),
|
67
|
+
)
|
68
|
+
|
69
|
+
def clear(self) -> None:
|
70
|
+
"""Clear the cached token."""
|
71
|
+
with self._lock:
|
72
|
+
self._token = None
|
73
|
+
self._expiry = None
|
74
|
+
logger.debug("Token cache cleared")
|
75
|
+
|
76
|
+
|
77
|
+
class AzureAuthHandler:
|
78
|
+
"""Handles Azure authentication and token management for MLflow PostgreSQL connections."""
|
79
|
+
|
80
|
+
def __init__(self, config: AzureAuthConfig):
|
81
|
+
"""Initialize the authentication handler.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
config: Azure authentication configuration
|
85
|
+
"""
|
86
|
+
self.config = config
|
87
|
+
self._token_cache = TokenCache()
|
88
|
+
self._credential = None
|
89
|
+
|
90
|
+
if config.enable_debug_logging:
|
91
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
92
|
+
|
93
|
+
logger.info(
|
94
|
+
"Initialized Azure auth handler: auth_method=%s, client_id=%s",
|
95
|
+
config.auth_method.value,
|
96
|
+
config.client_id[:8] + "..." if config.client_id else None,
|
97
|
+
)
|
98
|
+
|
99
|
+
@property
|
100
|
+
def credential(self):
|
101
|
+
"""Get or create Azure credential based on configuration."""
|
102
|
+
if self._credential is None:
|
103
|
+
self._credential = self._create_credential()
|
104
|
+
return self._credential
|
105
|
+
|
106
|
+
def _create_credential(self):
|
107
|
+
"""Create appropriate Azure credential based on auth method."""
|
108
|
+
auth_method = self.config.auth_method
|
109
|
+
|
110
|
+
logger.info("Creating Azure credential: auth_method=%s", auth_method.value)
|
111
|
+
|
112
|
+
try:
|
113
|
+
if auth_method == AuthMethod.MANAGED_IDENTITY:
|
114
|
+
if self.config.client_id:
|
115
|
+
logger.info(
|
116
|
+
"Using user-assigned managed identity: client_id=%s", self.config.client_id
|
117
|
+
)
|
118
|
+
return ManagedIdentityCredential(client_id=self.config.client_id)
|
119
|
+
else:
|
120
|
+
logger.info("Using system-assigned managed identity")
|
121
|
+
return ManagedIdentityCredential()
|
122
|
+
|
123
|
+
elif auth_method == AuthMethod.SERVICE_PRINCIPAL:
|
124
|
+
if not all(
|
125
|
+
[self.config.client_id, self.config.client_secret, self.config.tenant_id]
|
126
|
+
):
|
127
|
+
raise TokenAcquisitionError(
|
128
|
+
"Service principal authentication requires client_id, client_secret, and tenant_id"
|
129
|
+
)
|
130
|
+
|
131
|
+
logger.info(
|
132
|
+
"Using service principal authentication: client_id=%s, tenant_id=%s",
|
133
|
+
self.config.client_id,
|
134
|
+
self.config.tenant_id,
|
135
|
+
)
|
136
|
+
return ClientSecretCredential(
|
137
|
+
tenant_id=self.config.tenant_id,
|
138
|
+
client_id=self.config.client_id,
|
139
|
+
client_secret=self.config.client_secret,
|
140
|
+
)
|
141
|
+
|
142
|
+
elif auth_method == AuthMethod.DEFAULT_AZURE_CREDENTIAL:
|
143
|
+
logger.info("Using DefaultAzureCredential")
|
144
|
+
return DefaultAzureCredential()
|
145
|
+
|
146
|
+
else:
|
147
|
+
raise TokenAcquisitionError(f"Unsupported authentication method: {auth_method}")
|
148
|
+
|
149
|
+
except Exception as e:
|
150
|
+
logger.error(
|
151
|
+
"Failed to create Azure credential: error=%s, auth_method=%s", str(e), auth_method.value
|
152
|
+
)
|
153
|
+
raise TokenAcquisitionError(f"Failed to create credential: {e}") from e
|
154
|
+
|
155
|
+
def _acquire_token_with_retry(self) -> AccessToken:
|
156
|
+
"""Acquire token with retry logic."""
|
157
|
+
last_exception = None
|
158
|
+
|
159
|
+
for attempt in range(self.config.max_retries):
|
160
|
+
try:
|
161
|
+
logger.debug("Acquiring new token from Azure (attempt %d)", attempt + 1)
|
162
|
+
token = self.credential.get_token(self.config.token_scope)
|
163
|
+
|
164
|
+
logger.info(
|
165
|
+
"Successfully acquired token, expires in %d seconds",
|
166
|
+
int(token.expires_on - datetime.utcnow().timestamp()),
|
167
|
+
)
|
168
|
+
|
169
|
+
return token
|
170
|
+
|
171
|
+
except ClientAuthenticationError as e:
|
172
|
+
logger.error("Authentication failed: %s", str(e))
|
173
|
+
raise TokenAcquisitionError(f"Authentication failed: {e}") from e
|
174
|
+
|
175
|
+
except Exception as e:
|
176
|
+
last_exception = e
|
177
|
+
if attempt < self.config.max_retries - 1:
|
178
|
+
delay = self.config.retry_delay * (self.config.retry_backoff ** attempt)
|
179
|
+
logger.warning(
|
180
|
+
"Token acquisition failed (attempt %d), retrying in %.1f seconds: %s",
|
181
|
+
attempt + 1, delay, str(e)
|
182
|
+
)
|
183
|
+
import time
|
184
|
+
time.sleep(delay)
|
185
|
+
else:
|
186
|
+
logger.error("Token acquisition failed after all retries: %s", str(e))
|
187
|
+
|
188
|
+
raise TokenAcquisitionError(f"Token acquisition failed: {last_exception}") from last_exception
|
189
|
+
|
190
|
+
def get_access_token(self, force_refresh: bool = False) -> str:
|
191
|
+
"""Get a valid access token for PostgreSQL authentication.
|
192
|
+
|
193
|
+
Args:
|
194
|
+
force_refresh: Force token refresh even if cached token is valid
|
195
|
+
|
196
|
+
Returns:
|
197
|
+
Valid access token string
|
198
|
+
|
199
|
+
Raises:
|
200
|
+
TokenAcquisitionError: If token acquisition fails
|
201
|
+
"""
|
202
|
+
if not self.config.should_use_azure_auth:
|
203
|
+
raise TokenAcquisitionError("Azure authentication is not enabled")
|
204
|
+
|
205
|
+
# Try to get cached token first (unless force refresh)
|
206
|
+
if not force_refresh:
|
207
|
+
cached_token = self._token_cache.get_token(self.config.token_refresh_buffer)
|
208
|
+
if cached_token:
|
209
|
+
return cached_token.token
|
210
|
+
|
211
|
+
# Acquire new token
|
212
|
+
try:
|
213
|
+
new_token = self._acquire_token_with_retry()
|
214
|
+
self._token_cache.set_token(new_token)
|
215
|
+
return new_token.token
|
216
|
+
|
217
|
+
except Exception as e:
|
218
|
+
logger.error("Failed to acquire access token: %s", str(e))
|
219
|
+
raise
|
220
|
+
|
221
|
+
def refresh_token_if_needed(self) -> bool:
|
222
|
+
"""Refresh token if it's expiring soon.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
True if token was refreshed, False otherwise
|
226
|
+
"""
|
227
|
+
if not self.config.should_use_azure_auth:
|
228
|
+
return False
|
229
|
+
|
230
|
+
cached_token = self._token_cache.get_token(self.config.token_refresh_buffer)
|
231
|
+
if cached_token:
|
232
|
+
return False # Token is still valid
|
233
|
+
|
234
|
+
try:
|
235
|
+
self.get_access_token(force_refresh=True)
|
236
|
+
logger.info("Token refreshed proactively")
|
237
|
+
return True
|
238
|
+
except Exception as e:
|
239
|
+
logger.warning("Proactive token refresh failed: %s", str(e))
|
240
|
+
return False
|
241
|
+
|
242
|
+
def clear_token_cache(self) -> None:
|
243
|
+
"""Clear the token cache."""
|
244
|
+
self._token_cache.clear()
|
245
|
+
logger.info("Token cache cleared")
|
246
|
+
|
247
|
+
def is_token_valid(self) -> bool:
|
248
|
+
"""Check if current cached token is valid.
|
249
|
+
|
250
|
+
Returns:
|
251
|
+
True if token is valid, False otherwise
|
252
|
+
"""
|
253
|
+
if not self.config.should_use_azure_auth:
|
254
|
+
return True # SQL auth doesn't use tokens
|
255
|
+
|
256
|
+
cached_token = self._token_cache.get_token(self.config.token_refresh_buffer)
|
257
|
+
return cached_token is not None
|
mlflow/azure/client.py
ADDED
@@ -0,0 +1,319 @@
|
|
1
|
+
"""
|
2
|
+
This module provides utilities for performing Azure Blob Storage operations without requiring
|
3
|
+
the heavyweight azure-storage-blob library dependency
|
4
|
+
"""
|
5
|
+
|
6
|
+
import logging
|
7
|
+
import urllib
|
8
|
+
from copy import deepcopy
|
9
|
+
|
10
|
+
from mlflow.utils import rest_utils
|
11
|
+
from mlflow.utils.file_utils import read_chunk
|
12
|
+
|
13
|
+
_logger = logging.getLogger(__name__)
|
14
|
+
_PUT_BLOCK_HEADERS = {
|
15
|
+
"x-ms-blob-type": "BlockBlob",
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
def put_adls_file_creation(sas_url, headers):
|
20
|
+
"""Performs an ADLS Azure file create `Put` operation
|
21
|
+
(https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/create)
|
22
|
+
|
23
|
+
Args:
|
24
|
+
sas_url: A shared access signature URL referring to the Azure ADLS server
|
25
|
+
to which the file creation command should be issued.
|
26
|
+
headers: Additional headers to include in the Put request body.
|
27
|
+
"""
|
28
|
+
request_url = _append_query_parameters(sas_url, {"resource": "file"})
|
29
|
+
|
30
|
+
request_headers = {}
|
31
|
+
for name, value in headers.items():
|
32
|
+
if _is_valid_adls_put_header(name):
|
33
|
+
request_headers[name] = value
|
34
|
+
else:
|
35
|
+
_logger.debug("Removed unsupported '%s' header for ADLS Gen2 Put operation", name)
|
36
|
+
|
37
|
+
with rest_utils.cloud_storage_http_request(
|
38
|
+
"put", request_url, headers=request_headers
|
39
|
+
) as response:
|
40
|
+
rest_utils.augmented_raise_for_status(response)
|
41
|
+
|
42
|
+
|
43
|
+
def patch_adls_file_upload(sas_url, local_file, start_byte, size, position, headers, is_single):
|
44
|
+
"""
|
45
|
+
Performs an ADLS Azure file create `Patch` operation
|
46
|
+
(https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/update)
|
47
|
+
|
48
|
+
Args:
|
49
|
+
sas_url: A shared access signature URL referring to the Azure ADLS server
|
50
|
+
to which the file update command should be issued.
|
51
|
+
local_file: The local file to upload
|
52
|
+
start_byte: The starting byte of the local file to upload
|
53
|
+
size: The number of bytes to upload
|
54
|
+
position: Positional offset of the data in the Patch request
|
55
|
+
headers: Additional headers to include in the Patch request body
|
56
|
+
is_single: Whether this is the only patch operation for this file
|
57
|
+
"""
|
58
|
+
new_params = {"action": "append", "position": str(position)}
|
59
|
+
if is_single:
|
60
|
+
new_params["flush"] = "true"
|
61
|
+
request_url = _append_query_parameters(sas_url, new_params)
|
62
|
+
|
63
|
+
request_headers = {}
|
64
|
+
for name, value in headers.items():
|
65
|
+
if _is_valid_adls_patch_header(name):
|
66
|
+
request_headers[name] = value
|
67
|
+
else:
|
68
|
+
_logger.debug("Removed unsupported '%s' header for ADLS Gen2 Patch operation", name)
|
69
|
+
|
70
|
+
data = read_chunk(local_file, size, start_byte)
|
71
|
+
with rest_utils.cloud_storage_http_request(
|
72
|
+
"patch", request_url, data=data, headers=request_headers
|
73
|
+
) as response:
|
74
|
+
rest_utils.augmented_raise_for_status(response)
|
75
|
+
|
76
|
+
|
77
|
+
def patch_adls_flush(sas_url, position, headers):
|
78
|
+
"""Performs an ADLS Azure file flush `Patch` operation
|
79
|
+
(https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/update)
|
80
|
+
|
81
|
+
Args:
|
82
|
+
sas_url: A shared access signature URL referring to the Azure ADLS server
|
83
|
+
to which the file update command should be issued.
|
84
|
+
position: The final size of the file to flush.
|
85
|
+
headers: Additional headers to include in the Patch request body.
|
86
|
+
|
87
|
+
"""
|
88
|
+
request_url = _append_query_parameters(sas_url, {"action": "flush", "position": str(position)})
|
89
|
+
|
90
|
+
request_headers = {}
|
91
|
+
for name, value in headers.items():
|
92
|
+
if _is_valid_adls_put_header(name):
|
93
|
+
request_headers[name] = value
|
94
|
+
else:
|
95
|
+
_logger.debug("Removed unsupported '%s' header for ADLS Gen2 Patch operation", name)
|
96
|
+
|
97
|
+
with rest_utils.cloud_storage_http_request(
|
98
|
+
"patch", request_url, headers=request_headers
|
99
|
+
) as response:
|
100
|
+
rest_utils.augmented_raise_for_status(response)
|
101
|
+
|
102
|
+
|
103
|
+
def put_block(sas_url, block_id, data, headers):
|
104
|
+
"""
|
105
|
+
Performs an Azure `Put Block` operation
|
106
|
+
(https://docs.microsoft.com/en-us/rest/api/storageservices/put-block)
|
107
|
+
|
108
|
+
Args:
|
109
|
+
sas_url: A shared access signature URL referring to the Azure Block Blob
|
110
|
+
to which the specified data should be staged.
|
111
|
+
block_id: A base64-encoded string identifying the block.
|
112
|
+
data: Data to include in the Put Block request body.
|
113
|
+
headers: Additional headers to include in the Put Block request body
|
114
|
+
(the `x-ms-blob-type` header is always included automatically).
|
115
|
+
"""
|
116
|
+
request_url = _append_query_parameters(sas_url, {"comp": "block", "blockid": block_id})
|
117
|
+
|
118
|
+
request_headers = deepcopy(_PUT_BLOCK_HEADERS)
|
119
|
+
for name, value in headers.items():
|
120
|
+
if _is_valid_put_block_header(name):
|
121
|
+
request_headers[name] = value
|
122
|
+
else:
|
123
|
+
_logger.debug("Removed unsupported '%s' header for Put Block operation", name)
|
124
|
+
|
125
|
+
with rest_utils.cloud_storage_http_request(
|
126
|
+
"put", request_url, data=data, headers=request_headers
|
127
|
+
) as response:
|
128
|
+
rest_utils.augmented_raise_for_status(response)
|
129
|
+
|
130
|
+
|
131
|
+
def put_block_list(sas_url, block_list, headers):
|
132
|
+
"""Performs an Azure `Put Block List` operation
|
133
|
+
(https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list)
|
134
|
+
|
135
|
+
Args:
|
136
|
+
sas_url: A shared access signature URL referring to the Azure Block Blob
|
137
|
+
to which the specified data should be staged.
|
138
|
+
block_list: A list of uncommitted base64-encoded string block IDs to commit. For
|
139
|
+
more information, see
|
140
|
+
https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list.
|
141
|
+
headers: Headers to include in the Put Block request body.
|
142
|
+
|
143
|
+
"""
|
144
|
+
request_url = _append_query_parameters(sas_url, {"comp": "blocklist"})
|
145
|
+
data = _build_block_list_xml(block_list)
|
146
|
+
|
147
|
+
request_headers = {}
|
148
|
+
for name, value in headers.items():
|
149
|
+
if _is_valid_put_block_list_header(name):
|
150
|
+
request_headers[name] = value
|
151
|
+
else:
|
152
|
+
_logger.debug("Removed unsupported '%s' header for Put Block List operation", name)
|
153
|
+
|
154
|
+
with rest_utils.cloud_storage_http_request(
|
155
|
+
"put", request_url, data=data, headers=request_headers
|
156
|
+
) as response:
|
157
|
+
rest_utils.augmented_raise_for_status(response)
|
158
|
+
|
159
|
+
|
160
|
+
def _append_query_parameters(url, parameters):
|
161
|
+
parsed_url = urllib.parse.urlparse(url)
|
162
|
+
query_dict = dict(urllib.parse.parse_qsl(parsed_url.query))
|
163
|
+
query_dict.update(parameters)
|
164
|
+
new_query = urllib.parse.urlencode(query_dict)
|
165
|
+
new_url_components = parsed_url._replace(query=new_query)
|
166
|
+
return urllib.parse.urlunparse(new_url_components)
|
167
|
+
|
168
|
+
|
169
|
+
def _build_block_list_xml(block_list):
|
170
|
+
xml = '<?xml version="1.0" encoding="utf-8"?>\n<BlockList>\n'
|
171
|
+
for block_id in block_list:
|
172
|
+
# Because block IDs are base64-encoded and base64 strings do not contain
|
173
|
+
# XML special characters, we can safely insert the block ID directly into
|
174
|
+
# the XML document
|
175
|
+
xml += f"<Uncommitted>{block_id}</Uncommitted>\n"
|
176
|
+
xml += "</BlockList>"
|
177
|
+
return xml
|
178
|
+
|
179
|
+
|
180
|
+
def _is_valid_put_block_list_header(header_name):
|
181
|
+
"""
|
182
|
+
Returns:
|
183
|
+
True if the specified header name is a valid header for the Put Block List operation,
|
184
|
+
False otherwise. For a list of valid headers, see https://docs.microsoft.com/en-us/
|
185
|
+
rest/api/storageservices/put-block-list#request-headers and https://docs.microsoft.com/
|
186
|
+
en-us/rest/api/storageservices/
|
187
|
+
specifying-conditional-headers-for-blob-service-operations#Subheading1.
|
188
|
+
"""
|
189
|
+
return header_name.startswith("x-ms-meta-") or header_name in {
|
190
|
+
"Authorization",
|
191
|
+
"Date",
|
192
|
+
"x-ms-date",
|
193
|
+
"x-ms-version",
|
194
|
+
"Content-Length",
|
195
|
+
"Content-MD5",
|
196
|
+
"x-ms-content-crc64",
|
197
|
+
"x-ms-blob-cache-control",
|
198
|
+
"x-ms-blob-content-type",
|
199
|
+
"x-ms-blob-content-encoding",
|
200
|
+
"x-ms-blob-content-language",
|
201
|
+
"x-ms-blob-content-md5",
|
202
|
+
"x-ms-encryption-scope",
|
203
|
+
"x-ms-tags",
|
204
|
+
"x-ms-lease-id",
|
205
|
+
"x-ms-client-request-id",
|
206
|
+
"x-ms-blob-content-disposition",
|
207
|
+
"x-ms-access-tier",
|
208
|
+
"If-Modified-Since",
|
209
|
+
"If-Unmodified-Since",
|
210
|
+
"If-Match",
|
211
|
+
"If-None-Match",
|
212
|
+
}
|
213
|
+
|
214
|
+
|
215
|
+
def _is_valid_put_block_header(header_name):
|
216
|
+
"""
|
217
|
+
Returns:
|
218
|
+
True if the specified header name is a valid header for the Put Block operation, False
|
219
|
+
otherwise. For a list of valid headers, see
|
220
|
+
https://docs.microsoft.com/en-us/rest/api/storageservices/put-block#request-headers and
|
221
|
+
https://docs.microsoft.com/en-us/rest/api/storageservices/put-block#
|
222
|
+
request-headers-customer-provided-encryption-keys.
|
223
|
+
"""
|
224
|
+
return header_name in {
|
225
|
+
"Authorization",
|
226
|
+
"x-ms-date",
|
227
|
+
"x-ms-version",
|
228
|
+
"Content-Length",
|
229
|
+
"Content-MD5",
|
230
|
+
"x-ms-content-crc64",
|
231
|
+
"x-ms-encryption-scope",
|
232
|
+
"x-ms-lease-id",
|
233
|
+
"x-ms-client-request-id",
|
234
|
+
"x-ms-encryption-key",
|
235
|
+
"x-ms-encryption-key-sha256",
|
236
|
+
"x-ms-encryption-algorithm",
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
def _is_valid_adls_put_header(header_name):
|
241
|
+
"""
|
242
|
+
Returns:
|
243
|
+
True if the specified header name is a valid header for the ADLS Put operation, False
|
244
|
+
otherwise. For a list of valid headers, see
|
245
|
+
https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/create
|
246
|
+
"""
|
247
|
+
return header_name in {
|
248
|
+
"Cache-Control",
|
249
|
+
"Content-Encoding",
|
250
|
+
"Content-Language",
|
251
|
+
"Content-Disposition",
|
252
|
+
"x-ms-cache-control",
|
253
|
+
"x-ms-content-type",
|
254
|
+
"x-ms-content-encoding",
|
255
|
+
"x-ms-content-language",
|
256
|
+
"x-ms-content-disposition",
|
257
|
+
"x-ms-rename-source",
|
258
|
+
"x-ms-lease-id",
|
259
|
+
"x-ms-properties",
|
260
|
+
"x-ms-permissions",
|
261
|
+
"x-ms-umask",
|
262
|
+
"x-ms-owner",
|
263
|
+
"x-ms-group",
|
264
|
+
"x-ms-acl",
|
265
|
+
"x-ms-proposed-lease-id",
|
266
|
+
"x-ms-expiry-option",
|
267
|
+
"x-ms-expiry-time",
|
268
|
+
"If-Match",
|
269
|
+
"If-None-Match",
|
270
|
+
"If-Modified-Since",
|
271
|
+
"If-Unmodified-Since",
|
272
|
+
"x-ms-source-if-match",
|
273
|
+
"x-ms-source-if-none-match",
|
274
|
+
"x-ms-source-if-modified-since",
|
275
|
+
"x-ms-source-if-unmodified-since",
|
276
|
+
"x-ms-encryption-key",
|
277
|
+
"x-ms-encryption-key-sha256",
|
278
|
+
"x-ms-encryption-algorithm",
|
279
|
+
"x-ms-encryption-context",
|
280
|
+
"x-ms-client-request-id",
|
281
|
+
"x-ms-date",
|
282
|
+
"x-ms-version",
|
283
|
+
}
|
284
|
+
|
285
|
+
|
286
|
+
def _is_valid_adls_patch_header(header_name):
|
287
|
+
"""
|
288
|
+
Returns:
|
289
|
+
True if the specified header name is a valid header for the ADLS Patch operation, False
|
290
|
+
otherwise. For a list of valid headers, see
|
291
|
+
https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/update
|
292
|
+
"""
|
293
|
+
return header_name in {
|
294
|
+
"Content-Length",
|
295
|
+
"Content-MD5",
|
296
|
+
"x-ms-lease-id",
|
297
|
+
"x-ms-cache-control",
|
298
|
+
"x-ms-content-type",
|
299
|
+
"x-ms-content-disposition",
|
300
|
+
"x-ms-content-encoding",
|
301
|
+
"x-ms-content-language",
|
302
|
+
"x-ms-content-md5",
|
303
|
+
"x-ms-properties",
|
304
|
+
"x-ms-owner",
|
305
|
+
"x-ms-group",
|
306
|
+
"x-ms-permissions",
|
307
|
+
"x-ms-acl",
|
308
|
+
"If-Match",
|
309
|
+
"If-None-Match",
|
310
|
+
"If-Modified-Since",
|
311
|
+
"If-Unmodified-Since",
|
312
|
+
"x-ms-encryption-key",
|
313
|
+
"x-ms-encryption-key-sha256",
|
314
|
+
"x-ms-encryption-algorithm",
|
315
|
+
"x-ms-encryption-context",
|
316
|
+
"x-ms-client-request-id",
|
317
|
+
"x-ms-date",
|
318
|
+
"x-ms-version",
|
319
|
+
}
|
mlflow/azure/config.py
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
"""Configuration management for Azure authentication."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from enum import Enum
|
6
|
+
import os
|
7
|
+
from typing import Optional
|
8
|
+
|
9
|
+
|
10
|
+
class AuthMethod(str, Enum):
|
11
|
+
"""Supported authentication methods."""
|
12
|
+
|
13
|
+
MANAGED_IDENTITY = "managed_identity"
|
14
|
+
SERVICE_PRINCIPAL = "service_principal"
|
15
|
+
SQL_AUTH = "sql_auth"
|
16
|
+
DEFAULT_AZURE_CREDENTIAL = "default_azure_credential"
|
17
|
+
|
18
|
+
|
19
|
+
class AzureAuthConfig:
|
20
|
+
"""Configuration for Azure authentication.
|
21
|
+
|
22
|
+
This configuration can be loaded from environment variables or
|
23
|
+
provided programmatically.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(
|
27
|
+
self,
|
28
|
+
auth_enabled: Optional[bool] = None,
|
29
|
+
auth_method: Optional[str] = None,
|
30
|
+
client_id: Optional[str] = None,
|
31
|
+
client_secret: Optional[str] = None,
|
32
|
+
tenant_id: Optional[str] = None,
|
33
|
+
token_scope: str = "https://ossrdbms-aad.database.windows.net/.default",
|
34
|
+
connection_timeout: int = 30,
|
35
|
+
token_refresh_buffer: int = 300,
|
36
|
+
pool_size: int = 20,
|
37
|
+
max_overflow: int = 10,
|
38
|
+
pool_recycle: int = 3600,
|
39
|
+
pool_pre_ping: bool = True,
|
40
|
+
max_retries: int = 3,
|
41
|
+
retry_delay: float = 1.0,
|
42
|
+
retry_backoff: float = 2.0,
|
43
|
+
enable_debug_logging: bool = False,
|
44
|
+
):
|
45
|
+
"""Initialize Azure authentication configuration."""
|
46
|
+
|
47
|
+
# Core settings - use provided values or environment variables
|
48
|
+
self.auth_enabled = (
|
49
|
+
auth_enabled
|
50
|
+
if auth_enabled is not None
|
51
|
+
else os.getenv("MLFLOW_AZURE_AUTH_ENABLED", "false").lower() == "true"
|
52
|
+
)
|
53
|
+
|
54
|
+
self.auth_method = AuthMethod(
|
55
|
+
auth_method.lower()
|
56
|
+
if auth_method
|
57
|
+
else os.getenv("MLFLOW_AZURE_AUTH_METHOD", "sql_auth").lower()
|
58
|
+
)
|
59
|
+
|
60
|
+
# Azure specific settings - check both provided values and environment
|
61
|
+
self.client_id = client_id or os.getenv("AZURE_CLIENT_ID")
|
62
|
+
self.client_secret = client_secret or os.getenv("AZURE_CLIENT_SECRET")
|
63
|
+
self.tenant_id = tenant_id or os.getenv("AZURE_TENANT_ID")
|
64
|
+
|
65
|
+
# Connection settings
|
66
|
+
self.token_scope = token_scope
|
67
|
+
self.connection_timeout = connection_timeout
|
68
|
+
self.token_refresh_buffer = token_refresh_buffer
|
69
|
+
|
70
|
+
# Pool settings
|
71
|
+
self.pool_size = pool_size
|
72
|
+
self.max_overflow = max_overflow
|
73
|
+
self.pool_recycle = pool_recycle
|
74
|
+
self.pool_pre_ping = pool_pre_ping
|
75
|
+
|
76
|
+
# Retry settings
|
77
|
+
self.max_retries = max_retries
|
78
|
+
self.retry_delay = retry_delay
|
79
|
+
self.retry_backoff = retry_backoff
|
80
|
+
|
81
|
+
# Logging
|
82
|
+
self.enable_debug_logging = (
|
83
|
+
enable_debug_logging
|
84
|
+
or os.getenv("MLFLOW_AZURE_DEBUG", "false").lower() == "true"
|
85
|
+
)
|
86
|
+
|
87
|
+
# Additional environment variable checks
|
88
|
+
# Only override auth method if not explicitly set
|
89
|
+
if (os.getenv("MLFLOW_POSTGRES_USE_MANAGED_IDENTITY", "false").lower() == "true" and
|
90
|
+
auth_method is None and
|
91
|
+
os.getenv("MLFLOW_AZURE_AUTH_METHOD") is None):
|
92
|
+
self.auth_enabled = True
|
93
|
+
self.auth_method = AuthMethod.MANAGED_IDENTITY
|
94
|
+
|
95
|
+
# Validate configuration
|
96
|
+
self._validate()
|
97
|
+
|
98
|
+
def _validate(self):
|
99
|
+
"""Validate configuration settings."""
|
100
|
+
if self.auth_method == AuthMethod.SERVICE_PRINCIPAL:
|
101
|
+
if not self.client_secret:
|
102
|
+
raise ValueError("client_secret is required for service principal authentication")
|
103
|
+
if not self.client_id:
|
104
|
+
raise ValueError("client_id is required for service principal authentication")
|
105
|
+
if not self.tenant_id:
|
106
|
+
raise ValueError("tenant_id is required for service principal authentication")
|
107
|
+
|
108
|
+
@property
|
109
|
+
def should_use_azure_auth(self) -> bool:
|
110
|
+
"""Check if Azure authentication should be used."""
|
111
|
+
return self.auth_enabled and self.auth_method != AuthMethod.SQL_AUTH
|
112
|
+
|
113
|
+
@property
|
114
|
+
def requires_token_refresh(self) -> bool:
|
115
|
+
"""Check if the auth method requires token refresh."""
|
116
|
+
return self.auth_method in [
|
117
|
+
AuthMethod.MANAGED_IDENTITY,
|
118
|
+
AuthMethod.SERVICE_PRINCIPAL,
|
119
|
+
AuthMethod.DEFAULT_AZURE_CREDENTIAL,
|
120
|
+
]
|