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,647 @@
|
|
1
|
+
import base64
|
2
|
+
import logging
|
3
|
+
from datetime import datetime
|
4
|
+
from functools import lru_cache
|
5
|
+
from typing import Any, NamedTuple, Optional, TypeVar, Union, get_args, get_origin
|
6
|
+
|
7
|
+
import pydantic
|
8
|
+
import pydantic.fields
|
9
|
+
|
10
|
+
from mlflow.environment_variables import _MLFLOW_IS_IN_SERVING_ENVIRONMENT
|
11
|
+
from mlflow.exceptions import MlflowException
|
12
|
+
from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
|
13
|
+
from mlflow.types.schema import (
|
14
|
+
COLSPEC_TYPES,
|
15
|
+
AnyType,
|
16
|
+
Array,
|
17
|
+
ColSpec,
|
18
|
+
DataType,
|
19
|
+
Map,
|
20
|
+
Object,
|
21
|
+
Property,
|
22
|
+
Schema,
|
23
|
+
)
|
24
|
+
from mlflow.utils.pydantic_utils import IS_PYDANTIC_V2_OR_NEWER, model_dump_compat
|
25
|
+
from mlflow.utils.warnings_utils import color_warning
|
26
|
+
|
27
|
+
FIELD_TYPE = pydantic.fields.FieldInfo if IS_PYDANTIC_V2_OR_NEWER else pydantic.fields.ModelField
|
28
|
+
_logger = logging.getLogger(__name__)
|
29
|
+
NONE_TYPE = type(None)
|
30
|
+
UNION_TYPES = (Union,)
|
31
|
+
try:
|
32
|
+
# this import is only available in Python 3.10+
|
33
|
+
from types import UnionType
|
34
|
+
|
35
|
+
UNION_TYPES += (UnionType,)
|
36
|
+
except ImportError:
|
37
|
+
pass
|
38
|
+
|
39
|
+
# special type hint that can be used to convert data to
|
40
|
+
# the input example type after data validation
|
41
|
+
TypeFromExample = TypeVar("TypeFromExample")
|
42
|
+
OPTIONAL_INPUT_MSG = (
|
43
|
+
"Input cannot be Optional type. Fix this by removing the "
|
44
|
+
"Optional wrapper from the type hint. To use optional fields, "
|
45
|
+
"use a Pydantic-based type hint definition. See "
|
46
|
+
"https://docs.pydantic.dev/latest/api/base_model/ for pydantic "
|
47
|
+
"BaseModel examples. Check https://mlflow.org/docs/latest/model/python_model.html#supported-type-hints"
|
48
|
+
" for more details."
|
49
|
+
)
|
50
|
+
|
51
|
+
|
52
|
+
# numpy types are not supported
|
53
|
+
TYPE_HINTS_TO_DATATYPE_MAPPING = {
|
54
|
+
int: DataType.long,
|
55
|
+
str: DataType.string,
|
56
|
+
bool: DataType.boolean,
|
57
|
+
float: DataType.double,
|
58
|
+
bytes: DataType.binary,
|
59
|
+
datetime: DataType.datetime,
|
60
|
+
}
|
61
|
+
|
62
|
+
SUPPORTED_TYPE_HINT_MSG = (
|
63
|
+
"Type hints must be a list[...] where collection element type is one of these types: "
|
64
|
+
f"{list(TYPE_HINTS_TO_DATATYPE_MAPPING.keys())}, pydantic BaseModel subclasses, "
|
65
|
+
"lists and dictionaries of primitive types, or typing.Any. Check "
|
66
|
+
"https://mlflow.org/docs/latest/model/python_model.html#supported-type-hints for more details."
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
def _try_import_numpy():
|
71
|
+
try:
|
72
|
+
import numpy
|
73
|
+
|
74
|
+
return numpy
|
75
|
+
except ImportError:
|
76
|
+
return
|
77
|
+
|
78
|
+
|
79
|
+
@lru_cache(maxsize=1)
|
80
|
+
def type_hints_no_signature_inference():
|
81
|
+
"""
|
82
|
+
This function returns a tuple of types that can be used
|
83
|
+
as type hints, but no schema can be inferred from them.
|
84
|
+
|
85
|
+
..note::
|
86
|
+
These types can not be used as nested types in other type hints.
|
87
|
+
"""
|
88
|
+
type_hints = ()
|
89
|
+
try:
|
90
|
+
import pandas as pd
|
91
|
+
|
92
|
+
type_hints += (
|
93
|
+
pd.DataFrame,
|
94
|
+
pd.Series,
|
95
|
+
)
|
96
|
+
except ImportError:
|
97
|
+
pass
|
98
|
+
|
99
|
+
try:
|
100
|
+
import numpy as np
|
101
|
+
|
102
|
+
type_hints += (np.ndarray,)
|
103
|
+
except ImportError:
|
104
|
+
pass
|
105
|
+
|
106
|
+
try:
|
107
|
+
from scipy.sparse import csc_matrix, csr_matrix
|
108
|
+
|
109
|
+
type_hints += (csc_matrix, csr_matrix)
|
110
|
+
except ImportError:
|
111
|
+
pass
|
112
|
+
|
113
|
+
return type_hints
|
114
|
+
|
115
|
+
|
116
|
+
class ColSpecType(NamedTuple):
|
117
|
+
dtype: COLSPEC_TYPES
|
118
|
+
required: bool
|
119
|
+
|
120
|
+
|
121
|
+
class UnsupportedTypeHintException(MlflowException):
|
122
|
+
def __init__(self, type_hint):
|
123
|
+
super().__init__(
|
124
|
+
f"Unsupported type hint `{_type_hint_repr(type_hint)}`. {SUPPORTED_TYPE_HINT_MSG}",
|
125
|
+
error_code=INVALID_PARAMETER_VALUE,
|
126
|
+
)
|
127
|
+
|
128
|
+
|
129
|
+
class InvalidTypeHintException(MlflowException):
|
130
|
+
def __init__(self, *, message):
|
131
|
+
super().__init__(message, error_code=INVALID_PARAMETER_VALUE)
|
132
|
+
|
133
|
+
|
134
|
+
def _signature_cannot_be_inferred_from_type_hint(type_hint: type[Any]) -> bool:
|
135
|
+
return type_hint in type_hints_no_signature_inference()
|
136
|
+
|
137
|
+
|
138
|
+
def _is_type_hint_from_example(type_hint: type[Any]) -> bool:
|
139
|
+
return type_hint == TypeFromExample
|
140
|
+
|
141
|
+
|
142
|
+
def _is_example_valid_for_type_from_example(example: Any) -> bool:
|
143
|
+
allowed_types = (list,)
|
144
|
+
try:
|
145
|
+
import pandas as pd
|
146
|
+
|
147
|
+
allowed_types += (pd.DataFrame, pd.Series)
|
148
|
+
except ImportError:
|
149
|
+
pass
|
150
|
+
return isinstance(example, allowed_types)
|
151
|
+
|
152
|
+
|
153
|
+
def _convert_dataframe_to_example_format(data: Any, input_example: Any) -> Any:
|
154
|
+
import numpy as np
|
155
|
+
import pandas as pd
|
156
|
+
|
157
|
+
if isinstance(data, pd.DataFrame):
|
158
|
+
if isinstance(input_example, pd.DataFrame):
|
159
|
+
return data
|
160
|
+
if isinstance(input_example, pd.Series):
|
161
|
+
data = data.iloc[:, 0]
|
162
|
+
data.name = input_example.name
|
163
|
+
return data
|
164
|
+
if np.isscalar(input_example):
|
165
|
+
return data.iloc[0, 0]
|
166
|
+
if isinstance(input_example, dict):
|
167
|
+
if len(data) == 1:
|
168
|
+
return data.to_dict(orient="records")[0]
|
169
|
+
else:
|
170
|
+
# This case shouldn't happen
|
171
|
+
_logger.warning("Cannot convert DataFrame to a single dictionary.")
|
172
|
+
return data
|
173
|
+
if isinstance(input_example, list):
|
174
|
+
# list[scalar]
|
175
|
+
if len(data.columns) == 1 and all(np.isscalar(x) for x in input_example):
|
176
|
+
return data.iloc[:, 0].tolist()
|
177
|
+
else:
|
178
|
+
# NB: there are some cases that this doesn't work well, but it's the best we can do
|
179
|
+
# e.g. list of dictionaries with different keys
|
180
|
+
# [{"a": 1}, {"b": 2}] -> pd.DataFrame(...) during schema enforcement
|
181
|
+
# here -> [{'a': 1.0, 'b': nan}, {'a': nan, 'b': 2.0}]
|
182
|
+
return data.to_dict(orient="records")
|
183
|
+
|
184
|
+
return data
|
185
|
+
|
186
|
+
|
187
|
+
def _infer_colspec_type_from_type_hint(type_hint: type[Any]) -> ColSpecType:
|
188
|
+
"""
|
189
|
+
Infer the ColSpec type from a type hint.
|
190
|
+
The inferred dtype should be one of the supported data types in COLSPEC_TYPES.
|
191
|
+
"""
|
192
|
+
if type_hint == Any:
|
193
|
+
color_warning(
|
194
|
+
message="Any type hint is inferred as AnyType, and MLflow doesn't validate the data "
|
195
|
+
"for this type. Please use a more specific type hint to enable data validation.",
|
196
|
+
stacklevel=2,
|
197
|
+
color="yellow_bold",
|
198
|
+
)
|
199
|
+
return ColSpecType(dtype=AnyType(), required=True)
|
200
|
+
if datatype := TYPE_HINTS_TO_DATATYPE_MAPPING.get(type_hint):
|
201
|
+
return ColSpecType(dtype=datatype, required=True)
|
202
|
+
elif _is_pydantic_type_hint(type_hint):
|
203
|
+
dtype = _infer_type_from_pydantic_model(type_hint)
|
204
|
+
return ColSpecType(dtype=dtype, required=True)
|
205
|
+
elif origin_type := get_origin(type_hint):
|
206
|
+
args = get_args(type_hint)
|
207
|
+
if origin_type is list:
|
208
|
+
internal_type = _get_element_type_of_list_type_hint(type_hint)
|
209
|
+
return ColSpecType(
|
210
|
+
dtype=Array(_infer_colspec_type_from_type_hint(type_hint=internal_type).dtype),
|
211
|
+
required=True,
|
212
|
+
)
|
213
|
+
if origin_type is dict:
|
214
|
+
if len(args) == 2:
|
215
|
+
if args[0] != str:
|
216
|
+
raise InvalidTypeHintException(
|
217
|
+
message=f"Dictionary key type must be str, got {args[0]} in type hint "
|
218
|
+
f"{_type_hint_repr(type_hint)}"
|
219
|
+
)
|
220
|
+
return ColSpecType(
|
221
|
+
dtype=Map(_infer_colspec_type_from_type_hint(type_hint=args[1]).dtype),
|
222
|
+
required=True,
|
223
|
+
)
|
224
|
+
raise InvalidTypeHintException(
|
225
|
+
message="Dictionary type hint must contain two element types, got "
|
226
|
+
f"{_type_hint_repr(type_hint)}"
|
227
|
+
)
|
228
|
+
if origin_type in UNION_TYPES:
|
229
|
+
if NONE_TYPE in args:
|
230
|
+
# This case shouldn't happen, but added for completeness
|
231
|
+
if len(args) < 2:
|
232
|
+
raise InvalidTypeHintException(
|
233
|
+
message=f"Union type hint must contain at least one non-None type, "
|
234
|
+
f"got {_type_hint_repr(type_hint)}"
|
235
|
+
)
|
236
|
+
# Optional type
|
237
|
+
elif len(args) == 2:
|
238
|
+
effective_type = next((arg for arg in args if arg is not NONE_TYPE), None)
|
239
|
+
return ColSpecType(
|
240
|
+
dtype=_infer_colspec_type_from_type_hint(effective_type).dtype,
|
241
|
+
required=False,
|
242
|
+
)
|
243
|
+
# Optional Union type
|
244
|
+
else:
|
245
|
+
_logger.warning(
|
246
|
+
"Union type hint with multiple non-None types is inferred as AnyType, "
|
247
|
+
"and MLflow doesn't validate the data against its element types."
|
248
|
+
)
|
249
|
+
return ColSpecType(dtype=AnyType(), required=False)
|
250
|
+
# Union type with all valid types is matched as AnyType
|
251
|
+
else:
|
252
|
+
_logger.warning(
|
253
|
+
"Union type hint is inferred as AnyType, and MLflow doesn't validate the data "
|
254
|
+
"against its element types."
|
255
|
+
)
|
256
|
+
return ColSpecType(dtype=AnyType(), required=True)
|
257
|
+
_raise_type_hint_error(type_hint)
|
258
|
+
|
259
|
+
|
260
|
+
def _raise_type_hint_error(type_hint: type[Any]) -> None:
|
261
|
+
if (
|
262
|
+
type_hint
|
263
|
+
in (
|
264
|
+
list,
|
265
|
+
dict,
|
266
|
+
Optional,
|
267
|
+
)
|
268
|
+
+ UNION_TYPES
|
269
|
+
):
|
270
|
+
raise InvalidTypeHintException(
|
271
|
+
message=f"Invalid type hint `{_type_hint_repr(type_hint)}`, it must include "
|
272
|
+
f"a valid element type. {SUPPORTED_TYPE_HINT_MSG}"
|
273
|
+
)
|
274
|
+
raise UnsupportedTypeHintException(type_hint=type_hint)
|
275
|
+
|
276
|
+
|
277
|
+
def _infer_type_from_pydantic_model(model: pydantic.BaseModel) -> Object:
|
278
|
+
"""
|
279
|
+
Infer the object schema from a pydantic model.
|
280
|
+
"""
|
281
|
+
if _is_pydantic_type_hint(model):
|
282
|
+
fields = model_fields(model)
|
283
|
+
else:
|
284
|
+
raise TypeError(f"model must be a Pydantic model class, but got {type(model)}")
|
285
|
+
|
286
|
+
properties = []
|
287
|
+
invalid_fields = []
|
288
|
+
for field_name, field_info in fields.items():
|
289
|
+
annotation = field_info.annotation
|
290
|
+
# this shouldn't happen since pydantic has checks for missing annotations
|
291
|
+
# but added here to avoid potential edge cases
|
292
|
+
if annotation is None:
|
293
|
+
invalid_fields.append(field_name)
|
294
|
+
continue
|
295
|
+
colspec_type = _infer_colspec_type_from_type_hint(annotation)
|
296
|
+
if colspec_type.required is False and field_required(field_info):
|
297
|
+
raise InvalidTypeHintException(
|
298
|
+
message=f"Optional field `{field_name}` in Pydantic model `{model.__name__}` "
|
299
|
+
"doesn't have a default value. Please set default value to None for this field."
|
300
|
+
)
|
301
|
+
properties.append(
|
302
|
+
Property(
|
303
|
+
name=field_name,
|
304
|
+
dtype=colspec_type.dtype,
|
305
|
+
required=colspec_type.required,
|
306
|
+
)
|
307
|
+
)
|
308
|
+
if invalid_fields:
|
309
|
+
raise InvalidTypeHintException(
|
310
|
+
message="The following fields in the Pydantic model do not have type annotations: "
|
311
|
+
f"{invalid_fields}. Please add type annotations to these fields."
|
312
|
+
)
|
313
|
+
|
314
|
+
return Object(properties=properties)
|
315
|
+
|
316
|
+
|
317
|
+
def _is_pydantic_type_hint(type_hint: type[Any]) -> bool:
|
318
|
+
try:
|
319
|
+
return issubclass(type_hint, pydantic.BaseModel)
|
320
|
+
# inspect.isclass(dict[str, int]) is True, but issubclass raises a TypeError
|
321
|
+
except TypeError:
|
322
|
+
return False
|
323
|
+
|
324
|
+
|
325
|
+
def model_fields(
|
326
|
+
model: pydantic.BaseModel,
|
327
|
+
) -> dict[str, type[FIELD_TYPE]]:
|
328
|
+
if IS_PYDANTIC_V2_OR_NEWER:
|
329
|
+
return model.model_fields
|
330
|
+
return model.__fields__
|
331
|
+
|
332
|
+
|
333
|
+
def model_validate(model: pydantic.BaseModel, values: Any) -> None:
|
334
|
+
if IS_PYDANTIC_V2_OR_NEWER:
|
335
|
+
# use strict mode to avoid any data conversion here
|
336
|
+
# e.g. "123" will not be converted to 123 if the type is int
|
337
|
+
model.model_validate(values, strict=True)
|
338
|
+
else:
|
339
|
+
model.validate(values)
|
340
|
+
|
341
|
+
|
342
|
+
def field_required(field: type[FIELD_TYPE]) -> bool:
|
343
|
+
if IS_PYDANTIC_V2_OR_NEWER:
|
344
|
+
return field.is_required()
|
345
|
+
return field.required
|
346
|
+
|
347
|
+
|
348
|
+
def _get_element_type_of_list_type_hint(type_hint: type[list[Any]]) -> Any:
|
349
|
+
"""
|
350
|
+
Get the element type of list[...] type hint
|
351
|
+
"""
|
352
|
+
args = get_args(type_hint)
|
353
|
+
# Optional[list[...]]
|
354
|
+
if type(None) in args:
|
355
|
+
raise MlflowException.invalid_parameter_value(OPTIONAL_INPUT_MSG)
|
356
|
+
# a valid list[...] type hint must only contain one argument
|
357
|
+
if len(args) == 0:
|
358
|
+
raise InvalidTypeHintException(
|
359
|
+
message=f"Type hint `{_type_hint_repr(type_hint)}` doesn't contain a collection "
|
360
|
+
"element type. Fix by adding an element type to the collection type definition, "
|
361
|
+
"e.g. `list[str]` instead of `list`."
|
362
|
+
)
|
363
|
+
if len(args) > 1:
|
364
|
+
raise InvalidTypeHintException(
|
365
|
+
message=f"Type hint `{_type_hint_repr(type_hint)}` contains {len(args)} element types. "
|
366
|
+
"Collections must have only a single type definition e.g. `list[int]` is valid; "
|
367
|
+
"`list[str, int]` is invalid."
|
368
|
+
)
|
369
|
+
return args[0]
|
370
|
+
|
371
|
+
|
372
|
+
def _is_list_type_hint(type_hint: type[Any]) -> bool:
|
373
|
+
origin_type = _get_origin_type(type_hint)
|
374
|
+
return type_hint == list or origin_type is list
|
375
|
+
|
376
|
+
|
377
|
+
def _infer_schema_from_list_type_hint(type_hint: type[list[Any]]) -> Schema:
|
378
|
+
"""
|
379
|
+
Infer schema from a list type hint.
|
380
|
+
The type hint must be list[...], and the inferred schema contains a
|
381
|
+
single ColSpec, where the type is based on the element type of the list type hint,
|
382
|
+
since ColSpec represents a column's data type of the dataset.
|
383
|
+
e.g. list[int] -> Schema([ColSpec(type=DataType.long, required=True)])
|
384
|
+
A valid `predict` function of a pyfunc model must use list type hint for the input.
|
385
|
+
"""
|
386
|
+
if not _is_list_type_hint(type_hint):
|
387
|
+
# This should be invalid, but to keep backwards compatibility of ChatCompletionRequest
|
388
|
+
# type hint used in some rag models, we raise UnsupportedTypeHintException here
|
389
|
+
# so that the model with such type hint can still be logged
|
390
|
+
raise MlflowException.invalid_parameter_value(
|
391
|
+
message="Type hints must be wrapped in list[...] because MLflow assumes the "
|
392
|
+
"predict method to take multiple input instances. Specify your type hint as "
|
393
|
+
f"`list[{_type_hint_repr(type_hint)}]` for a valid signature."
|
394
|
+
)
|
395
|
+
internal_type = _get_element_type_of_list_type_hint(type_hint)
|
396
|
+
return _infer_schema_from_type_hint(internal_type)
|
397
|
+
|
398
|
+
|
399
|
+
def _infer_schema_from_type_hint(type_hint: type[Any]) -> Schema:
|
400
|
+
col_spec_type = _infer_colspec_type_from_type_hint(type_hint)
|
401
|
+
# Creating Schema with unnamed optional inputs is not supported
|
402
|
+
if col_spec_type.required is False:
|
403
|
+
raise InvalidTypeHintException(message=OPTIONAL_INPUT_MSG)
|
404
|
+
return Schema([ColSpec(type=col_spec_type.dtype, required=col_spec_type.required)])
|
405
|
+
|
406
|
+
|
407
|
+
def _validate_data_against_type_hint(data: Any, type_hint: type[Any]) -> Any:
|
408
|
+
"""
|
409
|
+
Validate the data against provided type hint.
|
410
|
+
The allowed conversions are:
|
411
|
+
dictionary data with Pydantic model type hint -> Pydantic model instance
|
412
|
+
|
413
|
+
Args:
|
414
|
+
data: The data to validate
|
415
|
+
type_hint: The type hint to validate against
|
416
|
+
"""
|
417
|
+
if _is_pydantic_type_hint(type_hint):
|
418
|
+
# if data is a pydantic model instance, convert it to a dictionary for validation
|
419
|
+
if isinstance(data, pydantic.BaseModel):
|
420
|
+
data_dict = model_dump_compat(data)
|
421
|
+
elif isinstance(data, dict):
|
422
|
+
data_dict = data
|
423
|
+
else:
|
424
|
+
raise MlflowException.invalid_parameter_value(
|
425
|
+
"Expecting example to be a dictionary or pydantic model instance for "
|
426
|
+
f"Pydantic type hint, got {type(data)}"
|
427
|
+
)
|
428
|
+
try:
|
429
|
+
model_validate(type_hint, data_dict)
|
430
|
+
except pydantic.ValidationError as e:
|
431
|
+
raise MlflowException.invalid_parameter_value(
|
432
|
+
message=f"Data doesn't match type hint, error: {e}. Expected fields in the "
|
433
|
+
f"type hint: {model_fields(type_hint)}; passed data: {data_dict}. Check "
|
434
|
+
"https://mlflow.org/docs/latest/model/python_model.html#pydantic-model-type-hints-data-conversion"
|
435
|
+
" for more details.",
|
436
|
+
) from e
|
437
|
+
else:
|
438
|
+
return type_hint(**data_dict) if isinstance(data, dict) else data
|
439
|
+
elif type_hint == Any:
|
440
|
+
return data
|
441
|
+
elif type_hint in TYPE_HINTS_TO_DATATYPE_MAPPING:
|
442
|
+
if _MLFLOW_IS_IN_SERVING_ENVIRONMENT.get():
|
443
|
+
data = _parse_data_for_datatype_hint(data=data, type_hint=type_hint)
|
444
|
+
if isinstance(data, type_hint):
|
445
|
+
return data
|
446
|
+
raise MlflowException.invalid_parameter_value(
|
447
|
+
f"Expected type {_type_hint_repr(type_hint)}, but got {type(data).__name__}"
|
448
|
+
)
|
449
|
+
elif origin_type := get_origin(type_hint):
|
450
|
+
args = get_args(type_hint)
|
451
|
+
if origin_type is list:
|
452
|
+
return _validate_list_elements(element_type=args[0], data=data)
|
453
|
+
elif origin_type is dict:
|
454
|
+
return _validate_dict_elements(element_type=args[1], data=data)
|
455
|
+
elif origin_type in UNION_TYPES:
|
456
|
+
# Optional type
|
457
|
+
if NONE_TYPE in args:
|
458
|
+
if data is None:
|
459
|
+
return data
|
460
|
+
if len(args) == 2:
|
461
|
+
effective_type = next((arg for arg in args if arg is not NONE_TYPE), None)
|
462
|
+
return _validate_data_against_type_hint(data=data, type_hint=effective_type)
|
463
|
+
# Union type with all valid types is matched as AnyType
|
464
|
+
# no validation needed for AnyType
|
465
|
+
return data
|
466
|
+
_raise_type_hint_error(type_hint)
|
467
|
+
|
468
|
+
|
469
|
+
def _parse_data_for_datatype_hint(data: Any, type_hint: type[Any]) -> Any:
|
470
|
+
"""
|
471
|
+
Parse the data based on the type hint.
|
472
|
+
This should only be used in MLflow serving environment to convert
|
473
|
+
json data to the expected format.
|
474
|
+
Allowed conversions:
|
475
|
+
- string data with datetime type hint -> datetime object
|
476
|
+
- string data with bytes type hint -> bytes object
|
477
|
+
"""
|
478
|
+
if type_hint == bytes and isinstance(data, str):
|
479
|
+
# The assumption is that the data is base64 encoded, and
|
480
|
+
# scoring server accepts base64 encoded string for bytes fields.
|
481
|
+
# MLflow uses the same method for saving input example
|
482
|
+
# via base64.encodebytes(x).decode("ascii")
|
483
|
+
return base64.decodebytes(bytes(data, "utf8"))
|
484
|
+
if type_hint == datetime and isinstance(data, str):
|
485
|
+
# The assumption is that the data is in ISO format
|
486
|
+
return datetime.fromisoformat(data)
|
487
|
+
return data
|
488
|
+
|
489
|
+
|
490
|
+
class ValidationResult(NamedTuple):
|
491
|
+
value: Optional[Any] = None
|
492
|
+
error_message: Optional[str] = None
|
493
|
+
|
494
|
+
|
495
|
+
def _get_data_validation_result(data: Any, type_hint: type[Any]) -> ValidationResult:
|
496
|
+
try:
|
497
|
+
value = _validate_data_against_type_hint(data=data, type_hint=type_hint)
|
498
|
+
return ValidationResult(value=value)
|
499
|
+
except MlflowException as e:
|
500
|
+
return ValidationResult(error_message=e.message)
|
501
|
+
|
502
|
+
|
503
|
+
def _type_hint_repr(type_hint: type[Any]) -> str:
|
504
|
+
return (
|
505
|
+
type_hint.__name__
|
506
|
+
if _is_pydantic_type_hint(type_hint) or type(type_hint) == type
|
507
|
+
else str(type_hint)
|
508
|
+
)
|
509
|
+
|
510
|
+
|
511
|
+
def _validate_list_elements(element_type: type[Any], data: Any) -> list[Any]:
|
512
|
+
if not isinstance(data, list):
|
513
|
+
raise MlflowException.invalid_parameter_value(
|
514
|
+
f"Expected list, but got {type(data).__name__}"
|
515
|
+
)
|
516
|
+
invalid_elems = []
|
517
|
+
result = []
|
518
|
+
for elem in data:
|
519
|
+
validation_result = _get_data_validation_result(data=elem, type_hint=element_type)
|
520
|
+
if validation_result.error_message:
|
521
|
+
invalid_elems.append((str(elem), validation_result.error_message))
|
522
|
+
else:
|
523
|
+
result.append(validation_result.value)
|
524
|
+
if invalid_elems:
|
525
|
+
invalid_elems_msg = (
|
526
|
+
f"{invalid_elems[:5]} ... (truncated)" if len(invalid_elems) > 5 else invalid_elems
|
527
|
+
)
|
528
|
+
raise MlflowException.invalid_parameter_value(
|
529
|
+
f"Failed to validate data against type hint `list[{_type_hint_repr(element_type)}]`, "
|
530
|
+
f"invalid elements: {invalid_elems_msg}"
|
531
|
+
)
|
532
|
+
return result
|
533
|
+
|
534
|
+
|
535
|
+
def _validate_dict_elements(element_type: type[Any], data: Any) -> dict[str, Any]:
|
536
|
+
if not isinstance(data, dict):
|
537
|
+
raise MlflowException.invalid_parameter_value(
|
538
|
+
f"Expected dict, but got {type(data).__name__}"
|
539
|
+
)
|
540
|
+
invalid_elems = {}
|
541
|
+
result = {}
|
542
|
+
for key, value in data.items():
|
543
|
+
if not isinstance(key, str):
|
544
|
+
invalid_elems[str(key)] = f"Key must be a string, got {type(key).__name__}"
|
545
|
+
continue
|
546
|
+
validation_result = _get_data_validation_result(data=value, type_hint=element_type)
|
547
|
+
if validation_result.error_message:
|
548
|
+
invalid_elems[key] = validation_result.error_message
|
549
|
+
else:
|
550
|
+
result[key] = validation_result.value
|
551
|
+
if invalid_elems:
|
552
|
+
raise MlflowException.invalid_parameter_value(
|
553
|
+
f"Failed to validate data against type hint "
|
554
|
+
f"`dict[str, {_type_hint_repr(element_type)}]`, "
|
555
|
+
f"invalid elements: {invalid_elems}"
|
556
|
+
)
|
557
|
+
return result
|
558
|
+
|
559
|
+
|
560
|
+
def _get_origin_type(type_hint: type[Any]) -> Any:
|
561
|
+
"""
|
562
|
+
Get the origin type of a type hint.
|
563
|
+
If the type hint is Union type, return the origin type of the effective type.
|
564
|
+
If the type hint is Union type with multiple effective types, return Any.
|
565
|
+
"""
|
566
|
+
origin_type = get_origin(type_hint)
|
567
|
+
if origin_type in UNION_TYPES:
|
568
|
+
args = get_args(type_hint)
|
569
|
+
if NONE_TYPE in args and len(args) == 2:
|
570
|
+
effective_type = next((arg for arg in args if arg is not NONE_TYPE), None)
|
571
|
+
return _get_origin_type(effective_type)
|
572
|
+
else:
|
573
|
+
# Union types match Any
|
574
|
+
return Any
|
575
|
+
return origin_type
|
576
|
+
|
577
|
+
|
578
|
+
def _convert_data_to_type_hint(data: Any, type_hint: type[Any]) -> Any:
|
579
|
+
"""
|
580
|
+
Convert data to the expected format based on the type hint.
|
581
|
+
This function is used in data validation of @pyfunc to support compatibility with
|
582
|
+
functions such as mlflow.evaluate and spark_udf since they accept pandas DF as input.
|
583
|
+
NB: the input pandas DataFrame must contain a single column with the same type as the type hint.
|
584
|
+
Supported conversions:
|
585
|
+
- pandas DataFrame with a single column + list[...] type hint -> list
|
586
|
+
- pandas DataFrame with multiple columns + list[dict[...]] type hint -> list[dict[...]]
|
587
|
+
"""
|
588
|
+
import pandas as pd
|
589
|
+
|
590
|
+
result = data
|
591
|
+
if isinstance(data, pd.DataFrame) and type_hint != pd.DataFrame:
|
592
|
+
origin_type = _get_origin_type(type_hint)
|
593
|
+
if origin_type is not list:
|
594
|
+
raise MlflowException(
|
595
|
+
"Only `list[...]` type hint supports pandas DataFrame input "
|
596
|
+
f"with a single column. But got {_type_hint_repr(type_hint)}."
|
597
|
+
)
|
598
|
+
element_type = _get_element_type_of_list_type_hint(type_hint)
|
599
|
+
# This is needed for list[dict] or list[pydantic.BaseModel] type hints
|
600
|
+
# since the data can be converted to pandas DataFrame with multiple columns
|
601
|
+
# inside spark_udf
|
602
|
+
if element_type is dict or _is_pydantic_type_hint(element_type):
|
603
|
+
# if the column is 0, then each row is a dictionary
|
604
|
+
if list(data.columns) == [0]:
|
605
|
+
result = data.iloc[:, 0].tolist()
|
606
|
+
else:
|
607
|
+
result = data.to_dict(orient="records")
|
608
|
+
else:
|
609
|
+
if len(data.columns) != 1:
|
610
|
+
# TODO: remove the warning and raise Exception once the bug about evaluate
|
611
|
+
# DF containing multiple columns is fixed
|
612
|
+
_logger.warning(
|
613
|
+
"`predict` function with list[...] type hints of non-dictionary collection "
|
614
|
+
"type only supports pandas DataFrame with a single column. But got "
|
615
|
+
f"{len(data.columns)} columns. The data will be converted to a list "
|
616
|
+
"of the first column."
|
617
|
+
)
|
618
|
+
result = data.iloc[:, 0].tolist()
|
619
|
+
# only sanitize the data when it's converted from pandas DataFrame
|
620
|
+
# since spark_udf implicitly converts lists into numpy arrays
|
621
|
+
return _sanitize_data(result)
|
622
|
+
|
623
|
+
return data
|
624
|
+
|
625
|
+
|
626
|
+
def _sanitize_data(data: Any) -> Any:
|
627
|
+
"""
|
628
|
+
Sanitize the data by converting any numpy lists to Python lists.
|
629
|
+
This is needed because spark_udf (pandas_udf) implicitly converts lists into numpy arrays.
|
630
|
+
|
631
|
+
For example, below udf demonstrates the behavior:
|
632
|
+
df = spark.createDataFrame(pd.DataFrame({"input": [["a", "b"], ["c", "d"]]}))
|
633
|
+
@pandas_udf(ArrayType(StringType()))
|
634
|
+
def my_udf(input_series: pd.Series) -> pd.Series:
|
635
|
+
print(type(input_series.iloc[0]))
|
636
|
+
df.withColumn("output", my_udf("input")).show()
|
637
|
+
"""
|
638
|
+
if np := _try_import_numpy():
|
639
|
+
if isinstance(data, np.ndarray):
|
640
|
+
data = data.tolist()
|
641
|
+
if isinstance(data, list):
|
642
|
+
data = [_sanitize_data(elem) for elem in data]
|
643
|
+
if isinstance(data, dict):
|
644
|
+
data = {key: _sanitize_data(value) for key, value in data.items()}
|
645
|
+
if isinstance(data, float) and np.isnan(data):
|
646
|
+
data = None
|
647
|
+
return data
|