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,158 @@
|
|
1
|
+
import html
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
from mlflow.models.model import ModelInfo
|
5
|
+
from mlflow.models.signature import ModelSignature
|
6
|
+
from mlflow.types import schema
|
7
|
+
from mlflow.utils import databricks_utils
|
8
|
+
|
9
|
+
|
10
|
+
def _is_input_string(inputs: schema.Schema) -> bool:
|
11
|
+
return (
|
12
|
+
not inputs.has_input_names()
|
13
|
+
and len(inputs.input_types()) == 1
|
14
|
+
and inputs.input_types()[0] == schema.DataType.string
|
15
|
+
)
|
16
|
+
|
17
|
+
|
18
|
+
def _is_input_agent_compatible(inputs: schema.Schema) -> bool:
|
19
|
+
if _is_input_string(inputs):
|
20
|
+
return True
|
21
|
+
if not inputs.has_input_names():
|
22
|
+
return False
|
23
|
+
messages = inputs.input_dict().get("messages")
|
24
|
+
if not messages:
|
25
|
+
return False
|
26
|
+
if not isinstance(messages.type, schema.Array):
|
27
|
+
return False
|
28
|
+
items = messages.type.dtype
|
29
|
+
if not isinstance(items, schema.Object):
|
30
|
+
return False
|
31
|
+
properties = items.properties
|
32
|
+
content = next(filter(lambda prop: prop.name == "content", properties), None)
|
33
|
+
role = next(filter(lambda prop: prop.name == "role", properties), None)
|
34
|
+
return (
|
35
|
+
content
|
36
|
+
and content.dtype == schema.DataType.string
|
37
|
+
and role
|
38
|
+
and role.dtype == schema.DataType.string
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
def _is_output_string_response(outputs: schema.Schema) -> bool:
|
43
|
+
if not outputs.has_input_names():
|
44
|
+
return False
|
45
|
+
content = outputs.input_dict().get("content")
|
46
|
+
if not content:
|
47
|
+
return False
|
48
|
+
return content.type == schema.DataType.string
|
49
|
+
|
50
|
+
|
51
|
+
def _is_output_string(outputs: schema.Schema) -> bool:
|
52
|
+
return (
|
53
|
+
not outputs.has_input_names()
|
54
|
+
and len(outputs.input_types()) == 1
|
55
|
+
and outputs.input_types()[0] == schema.DataType.string
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def _is_output_chat_completion_response(outputs: schema.Schema) -> bool:
|
60
|
+
if not outputs.has_input_names():
|
61
|
+
return False
|
62
|
+
choices = outputs.input_dict().get("choices")
|
63
|
+
if not choices:
|
64
|
+
return False
|
65
|
+
if not isinstance(choices.type, schema.Array):
|
66
|
+
return False
|
67
|
+
items = choices.type.dtype
|
68
|
+
if not isinstance(items, schema.Object):
|
69
|
+
return False
|
70
|
+
properties = items.properties
|
71
|
+
message = next(filter(lambda prop: prop.name == "message", properties), None)
|
72
|
+
if not message:
|
73
|
+
return False
|
74
|
+
if not isinstance(message.dtype, schema.Object):
|
75
|
+
return False
|
76
|
+
message_properties = message.dtype.properties
|
77
|
+
content = next(filter(lambda prop: prop.name == "content", message_properties), None)
|
78
|
+
role = next(filter(lambda prop: prop.name == "role", message_properties), None)
|
79
|
+
return (
|
80
|
+
content
|
81
|
+
and content.dtype == schema.DataType.string
|
82
|
+
and role
|
83
|
+
and role.dtype == schema.DataType.string
|
84
|
+
)
|
85
|
+
|
86
|
+
|
87
|
+
def _is_output_agent_compatible(outputs: schema.Schema) -> bool:
|
88
|
+
return (
|
89
|
+
_is_output_string_response(outputs)
|
90
|
+
or _is_output_string(outputs)
|
91
|
+
or _is_output_chat_completion_response(outputs)
|
92
|
+
)
|
93
|
+
|
94
|
+
|
95
|
+
def _is_signature_agent_compatible(signature: ModelSignature) -> bool:
|
96
|
+
"""Determines whether the given signature is compatible with the agent eval schema.
|
97
|
+
|
98
|
+
See https://docs.databricks.com/en/generative-ai/agent-evaluation/evaluation-schema.html.
|
99
|
+
The schema accepts the OpenAI spec, as well as simpler formats such as vanilla string response
|
100
|
+
and `StringResponse`.
|
101
|
+
"""
|
102
|
+
return _is_input_agent_compatible(signature.inputs) and _is_output_agent_compatible(
|
103
|
+
signature.outputs
|
104
|
+
)
|
105
|
+
|
106
|
+
|
107
|
+
def _should_render_agent_eval_template(signature: ModelSignature) -> bool:
|
108
|
+
if not databricks_utils.is_in_databricks_runtime():
|
109
|
+
return False
|
110
|
+
from IPython import get_ipython
|
111
|
+
|
112
|
+
if get_ipython() is None:
|
113
|
+
return False
|
114
|
+
return _is_signature_agent_compatible(signature)
|
115
|
+
|
116
|
+
|
117
|
+
def _generate_agent_eval_recipe(model_uri: str) -> str:
|
118
|
+
resources_dir = Path(__file__).parent / "notebook_resources"
|
119
|
+
pip_install_command = """%pip install -U databricks-agents
|
120
|
+
dbutils.library.restartPython()
|
121
|
+
## Run the above in a separate cell ##"""
|
122
|
+
eval_with_synthetic_code = (
|
123
|
+
(resources_dir / "eval_with_synthetic_example.py")
|
124
|
+
.read_text()
|
125
|
+
.replace("{{pipInstall}}", pip_install_command)
|
126
|
+
.replace("{{modelUri}}", model_uri)
|
127
|
+
)
|
128
|
+
eval_with_dataset_code = (
|
129
|
+
(resources_dir / "eval_with_dataset_example.py")
|
130
|
+
.read_text()
|
131
|
+
.replace("{{pipInstall}}", pip_install_command)
|
132
|
+
.replace("{{modelUri}}", model_uri)
|
133
|
+
)
|
134
|
+
|
135
|
+
# Remove the ruff noqa comments.
|
136
|
+
ruff_line = "# ruff: noqa: F821, I001\n"
|
137
|
+
eval_with_synthetic_code = eval_with_synthetic_code.replace(ruff_line, "")
|
138
|
+
eval_with_dataset_code = eval_with_dataset_code.replace(ruff_line, "")
|
139
|
+
|
140
|
+
return (
|
141
|
+
(resources_dir / "agent_evaluation_template.html")
|
142
|
+
.read_text()
|
143
|
+
.replace("{{eval_with_synthetic_code}}", html.escape(eval_with_synthetic_code))
|
144
|
+
.replace("{{eval_with_dataset_code}}", html.escape(eval_with_dataset_code))
|
145
|
+
)
|
146
|
+
|
147
|
+
|
148
|
+
def maybe_render_agent_eval_recipe(model_info: ModelInfo) -> None:
|
149
|
+
# For safety, we wrap in try/catch to make sure we don't break `mlflow.*.log_model`.
|
150
|
+
try:
|
151
|
+
if not _should_render_agent_eval_template(model_info.signature):
|
152
|
+
return
|
153
|
+
|
154
|
+
from IPython.display import HTML, display
|
155
|
+
|
156
|
+
display(HTML(_generate_agent_eval_recipe(model_info.model_uri)))
|
157
|
+
except Exception:
|
158
|
+
pass
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
from subprocess import Popen
|
4
|
+
from typing import Optional, Union
|
5
|
+
from urllib.parse import urlparse
|
6
|
+
|
7
|
+
from mlflow.environment_variables import MLFLOW_DOCKER_OPENJDK_VERSION
|
8
|
+
from mlflow.utils import env_manager as em
|
9
|
+
from mlflow.utils.file_utils import _copy_project
|
10
|
+
from mlflow.version import VERSION
|
11
|
+
|
12
|
+
_logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
UBUNTU_BASE_IMAGE = "ubuntu:20.04"
|
15
|
+
PYTHON_SLIM_BASE_IMAGE = "python:{version}-slim"
|
16
|
+
|
17
|
+
|
18
|
+
SETUP_PYENV_AND_VIRTUALENV = r"""# Setup pyenv
|
19
|
+
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata \
|
20
|
+
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
|
21
|
+
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
|
22
|
+
RUN git clone \
|
23
|
+
--depth 1 \
|
24
|
+
--branch $(git ls-remote --tags --sort=v:refname https://github.com/pyenv/pyenv.git | grep -o -E 'v[1-9]+(\.[1-9]+)+$' | tail -1) \
|
25
|
+
https://github.com/pyenv/pyenv.git /root/.pyenv
|
26
|
+
ENV PYENV_ROOT="/root/.pyenv"
|
27
|
+
ENV PATH="$PYENV_ROOT/bin:$PATH"
|
28
|
+
RUN apt install -y software-properties-common \
|
29
|
+
&& apt update \
|
30
|
+
&& add-apt-repository -y ppa:deadsnakes/ppa \
|
31
|
+
&& apt update \
|
32
|
+
&& apt install -y python3.10 python3.10-distutils \
|
33
|
+
&& ln -s -f $(which python3.10) /usr/bin/python \
|
34
|
+
&& wget https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py \
|
35
|
+
&& python /tmp/get-pip.py
|
36
|
+
RUN pip install virtualenv
|
37
|
+
""" # noqa: E501
|
38
|
+
|
39
|
+
_DOCKERFILE_TEMPLATE = """# Build an image that can serve mlflow models.
|
40
|
+
FROM {base_image}
|
41
|
+
|
42
|
+
{setup_python_venv}
|
43
|
+
|
44
|
+
{setup_java}
|
45
|
+
|
46
|
+
WORKDIR /opt/mlflow
|
47
|
+
|
48
|
+
{install_mlflow}
|
49
|
+
|
50
|
+
{install_model_and_deps}
|
51
|
+
|
52
|
+
ENV MLFLOW_DISABLE_ENV_CREATION={disable_env_creation}
|
53
|
+
ENV ENABLE_MLSERVER={enable_mlserver}
|
54
|
+
|
55
|
+
# granting read/write access and conditional execution authority to all child directories
|
56
|
+
# and files to allow for deployment to AWS Sagemaker Serverless Endpoints
|
57
|
+
# (see https://docs.aws.amazon.com/sagemaker/latest/dg/serverless-endpoints.html)
|
58
|
+
RUN chmod o+rwX /opt/mlflow/
|
59
|
+
|
60
|
+
# clean up apt cache to reduce image size
|
61
|
+
RUN rm -rf /var/lib/apt/lists/*
|
62
|
+
|
63
|
+
ENTRYPOINT ["python", "-c", "{entrypoint}"]
|
64
|
+
"""
|
65
|
+
|
66
|
+
|
67
|
+
SETUP_MINICONDA = """# Setup miniconda
|
68
|
+
RUN curl --fail -L https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh > miniconda.sh
|
69
|
+
RUN bash ./miniconda.sh -b -p /miniconda && rm ./miniconda.sh
|
70
|
+
ENV PATH="/miniconda/bin:$PATH"
|
71
|
+
""" # noqa: E501
|
72
|
+
|
73
|
+
|
74
|
+
def generate_dockerfile(
|
75
|
+
output_dir: str,
|
76
|
+
base_image: str,
|
77
|
+
model_install_steps: Optional[str],
|
78
|
+
entrypoint: str,
|
79
|
+
env_manager: Union[em.CONDA, em.LOCAL, em.VIRTUALENV],
|
80
|
+
mlflow_home: Optional[str] = None,
|
81
|
+
enable_mlserver: bool = False,
|
82
|
+
disable_env_creation_at_runtime: bool = True,
|
83
|
+
install_java: Optional[bool] = None,
|
84
|
+
):
|
85
|
+
"""
|
86
|
+
Generates a Dockerfile that can be used to build a docker image, that serves ML model
|
87
|
+
stored and tracked in MLflow.
|
88
|
+
"""
|
89
|
+
|
90
|
+
setup_java_steps = ""
|
91
|
+
setup_python_venv_steps = ""
|
92
|
+
install_mlflow_steps = _pip_mlflow_install_step(output_dir, mlflow_home)
|
93
|
+
|
94
|
+
if base_image.startswith("python:"):
|
95
|
+
if install_java:
|
96
|
+
_logger.warning(
|
97
|
+
"`install_java` option is not supported when using python base image, "
|
98
|
+
"switch to UBUNTU_BASE_IMAGE to enable java installation."
|
99
|
+
)
|
100
|
+
setup_python_venv_steps = (
|
101
|
+
"RUN apt-get -y update && apt-get install -y --no-install-recommends nginx"
|
102
|
+
)
|
103
|
+
|
104
|
+
elif base_image == UBUNTU_BASE_IMAGE:
|
105
|
+
setup_python_venv_steps = (
|
106
|
+
"RUN apt-get -y update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y "
|
107
|
+
"--no-install-recommends wget curl nginx ca-certificates bzip2 build-essential cmake "
|
108
|
+
"git-core\n\n"
|
109
|
+
)
|
110
|
+
setup_python_venv_steps += (
|
111
|
+
SETUP_MINICONDA if env_manager == em.CONDA else SETUP_PYENV_AND_VIRTUALENV
|
112
|
+
)
|
113
|
+
if install_java is not False:
|
114
|
+
jdk_ver = MLFLOW_DOCKER_OPENJDK_VERSION.get()
|
115
|
+
setup_java_steps = (
|
116
|
+
"# Setup Java\n"
|
117
|
+
f"RUN apt-get install -y --no-install-recommends openjdk-{jdk_ver}-jdk maven\n"
|
118
|
+
f"ENV JAVA_HOME=/usr/lib/jvm/java-{jdk_ver}-openjdk-amd64"
|
119
|
+
)
|
120
|
+
|
121
|
+
with open(os.path.join(output_dir, "Dockerfile"), "w") as f:
|
122
|
+
f.write(
|
123
|
+
_DOCKERFILE_TEMPLATE.format(
|
124
|
+
base_image=base_image,
|
125
|
+
setup_python_venv=setup_python_venv_steps,
|
126
|
+
setup_java=setup_java_steps,
|
127
|
+
install_mlflow=install_mlflow_steps,
|
128
|
+
install_model_and_deps=model_install_steps,
|
129
|
+
entrypoint=entrypoint,
|
130
|
+
enable_mlserver=enable_mlserver,
|
131
|
+
disable_env_creation=disable_env_creation_at_runtime,
|
132
|
+
)
|
133
|
+
)
|
134
|
+
|
135
|
+
|
136
|
+
def _get_maven_proxy():
|
137
|
+
http_proxy = os.getenv("http_proxy")
|
138
|
+
https_proxy = os.getenv("https_proxy")
|
139
|
+
if not http_proxy or not https_proxy:
|
140
|
+
return ""
|
141
|
+
|
142
|
+
# Expects proxies as either PROTOCOL://{USER}:{PASSWORD}@HOSTNAME:PORT
|
143
|
+
# or PROTOCOL://HOSTNAME:PORT
|
144
|
+
parsed_http_proxy = urlparse(http_proxy)
|
145
|
+
assert parsed_http_proxy.hostname is not None, "Invalid `http_proxy` hostname."
|
146
|
+
assert parsed_http_proxy.port is not None, f"Invalid proxy port: {parsed_http_proxy.port}"
|
147
|
+
|
148
|
+
parsed_https_proxy = urlparse(https_proxy)
|
149
|
+
assert parsed_https_proxy.hostname is not None, "Invalid `https_proxy` hostname."
|
150
|
+
assert parsed_https_proxy.port is not None, f"Invalid proxy port: {parsed_https_proxy.port}"
|
151
|
+
|
152
|
+
maven_proxy_options = (
|
153
|
+
"-DproxySet=true",
|
154
|
+
f"-Dhttp.proxyHost={parsed_http_proxy.hostname}",
|
155
|
+
f"-Dhttp.proxyPort={parsed_http_proxy.port}",
|
156
|
+
f"-Dhttps.proxyHost={parsed_https_proxy.hostname}",
|
157
|
+
f"-Dhttps.proxyPort={parsed_https_proxy.port}",
|
158
|
+
"-Dhttps.nonProxyHosts=repo.maven.apache.org",
|
159
|
+
)
|
160
|
+
|
161
|
+
if parsed_http_proxy.username is None or parsed_http_proxy.password is None:
|
162
|
+
return " ".join(maven_proxy_options)
|
163
|
+
|
164
|
+
return " ".join(
|
165
|
+
(
|
166
|
+
*maven_proxy_options,
|
167
|
+
f"-Dhttp.proxyUser={parsed_http_proxy.username}",
|
168
|
+
f"-Dhttp.proxyPassword={parsed_http_proxy.password}",
|
169
|
+
)
|
170
|
+
)
|
171
|
+
|
172
|
+
|
173
|
+
def _pip_mlflow_install_step(dockerfile_context_dir, mlflow_home):
|
174
|
+
"""
|
175
|
+
Get docker build commands for installing MLflow given a Docker context dir and optional source
|
176
|
+
directory
|
177
|
+
"""
|
178
|
+
if mlflow_home:
|
179
|
+
mlflow_dir = _copy_project(
|
180
|
+
src_path=os.path.abspath(mlflow_home), dst_path=dockerfile_context_dir
|
181
|
+
)
|
182
|
+
return (
|
183
|
+
"# Install MLflow from local source\n"
|
184
|
+
f"COPY {mlflow_dir} /opt/mlflow\n"
|
185
|
+
"RUN pip install /opt/mlflow"
|
186
|
+
)
|
187
|
+
else:
|
188
|
+
return f"# Install MLflow\nRUN pip install mlflow=={VERSION}"
|
189
|
+
|
190
|
+
|
191
|
+
def build_image_from_context(context_dir: str, image_name: str):
|
192
|
+
import docker
|
193
|
+
|
194
|
+
client = docker.from_env()
|
195
|
+
# In Docker < 19, `docker build` doesn't support the `--platform` option
|
196
|
+
is_platform_supported = int(client.version()["Version"].split(".")[0]) >= 19
|
197
|
+
# Enforcing the AMD64 architecture build for Apple M1 users
|
198
|
+
platform_option = ["--platform", "linux/amd64"] if is_platform_supported else []
|
199
|
+
commands = [
|
200
|
+
"docker",
|
201
|
+
"build",
|
202
|
+
"-t",
|
203
|
+
image_name,
|
204
|
+
"-f",
|
205
|
+
"Dockerfile",
|
206
|
+
*platform_option,
|
207
|
+
".",
|
208
|
+
]
|
209
|
+
proc = Popen(commands, cwd=context_dir)
|
210
|
+
if proc.wait():
|
211
|
+
raise RuntimeError("Docker build failed.")
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from mlflow.data.evaluation_dataset import EvaluationDataset
|
2
|
+
from mlflow.models.evaluation.base import (
|
3
|
+
EvaluationArtifact,
|
4
|
+
EvaluationMetric,
|
5
|
+
EvaluationResult,
|
6
|
+
ModelEvaluator,
|
7
|
+
evaluate,
|
8
|
+
list_evaluators,
|
9
|
+
make_metric,
|
10
|
+
)
|
11
|
+
from mlflow.models.evaluation.validation import MetricThreshold
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"ModelEvaluator",
|
15
|
+
"EvaluationDataset",
|
16
|
+
"EvaluationResult",
|
17
|
+
"EvaluationMetric",
|
18
|
+
"EvaluationArtifact",
|
19
|
+
"make_metric",
|
20
|
+
"evaluate",
|
21
|
+
"list_evaluators",
|
22
|
+
"MetricThreshold",
|
23
|
+
]
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import pickle
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import shap
|
5
|
+
from shap._serializable import Deserializer, Serializable, Serializer
|
6
|
+
|
7
|
+
|
8
|
+
class _PatchedKernelExplainer(shap.KernelExplainer):
|
9
|
+
@staticmethod
|
10
|
+
def not_equal(i, j):
|
11
|
+
# `shap.KernelExplainer.not_equal` method fails on some special types such as
|
12
|
+
# timestamp, this breaks the kernel explainer routine.
|
13
|
+
# `PatchedKernelExplainer` fixes this issue.
|
14
|
+
# See https://github.com/slundberg/shap/pull/2586
|
15
|
+
number_types = (int, float, np.number)
|
16
|
+
if isinstance(i, number_types) and isinstance(j, number_types):
|
17
|
+
return 0 if np.isclose(i, j, equal_nan=True) else 1
|
18
|
+
else:
|
19
|
+
return 0 if i == j else 1
|
20
|
+
|
21
|
+
def save(self, out_file, model_saver=None, masker_saver=None):
|
22
|
+
"""
|
23
|
+
This patched `save` method fix `KernelExplainer.save`.
|
24
|
+
Issues in original `KernelExplainer.save`:
|
25
|
+
- It saves model by calling model.save, but shap.utils._legacy.Model has no save method
|
26
|
+
- It tries to save "masker", but there's no "masker" in KernelExplainer
|
27
|
+
- It does not save "KernelExplainer.data" attribute, the attribute is required when
|
28
|
+
loading back
|
29
|
+
Note: `model_saver` and `masker_saver` are meaningless argument for `KernelExplainer.save`,
|
30
|
+
the model in "KernelExplainer" is an instance of `shap.utils._legacy.Model`
|
31
|
+
(it wraps the predict function), we can only use pickle to dump it.
|
32
|
+
and no `masker` for KernelExplainer so `masker_saver` is meaningless.
|
33
|
+
but I preserve the 2 argument for overridden API compatibility.
|
34
|
+
"""
|
35
|
+
pickle.dump(type(self), out_file)
|
36
|
+
with Serializer(out_file, "shap.Explainer", version=0) as s:
|
37
|
+
s.save("model", self.model)
|
38
|
+
s.save("link", self.link)
|
39
|
+
s.save("data", self.data)
|
40
|
+
|
41
|
+
@classmethod
|
42
|
+
def load(cls, in_file, model_loader=None, masker_loader=None, instantiate=True):
|
43
|
+
"""
|
44
|
+
This patched `load` method fix `KernelExplainer.load`.
|
45
|
+
Issues in original KernelExplainer.load:
|
46
|
+
- Use mismatched model loader to load model
|
47
|
+
- Try to load non-existent "masker" attribute
|
48
|
+
- Does not load "data" attribute and then cause calling " KernelExplainer"
|
49
|
+
constructor lack of "data" argument.
|
50
|
+
Note: `model_loader` and `masker_loader` are meaningless argument for
|
51
|
+
`KernelExplainer.save`, because the `model` object is saved by pickle dump,
|
52
|
+
we must use pickle load to load it.
|
53
|
+
and no `masker` for KernelExplainer so `masker_loader` is meaningless.
|
54
|
+
but I preserve the 2 argument for overridden API compatibility.
|
55
|
+
"""
|
56
|
+
if instantiate:
|
57
|
+
return cls._instantiated_load(in_file, model_loader=None, masker_loader=None)
|
58
|
+
|
59
|
+
kwargs = Serializable.load(in_file, instantiate=False)
|
60
|
+
with Deserializer(in_file, "shap.Explainer", min_version=0, max_version=0) as s:
|
61
|
+
kwargs["model"] = s.load("model")
|
62
|
+
kwargs["link"] = s.load("link")
|
63
|
+
kwargs["data"] = s.load("data")
|
64
|
+
return kwargs
|
@@ -0,0 +1,194 @@
|
|
1
|
+
import json
|
2
|
+
import pathlib
|
3
|
+
import pickle
|
4
|
+
from collections import namedtuple
|
5
|
+
from json import JSONDecodeError
|
6
|
+
|
7
|
+
import matplotlib.pyplot as plt
|
8
|
+
import numpy as np
|
9
|
+
import pandas as pd
|
10
|
+
|
11
|
+
from mlflow.exceptions import MlflowException
|
12
|
+
from mlflow.models.evaluation.base import EvaluationArtifact
|
13
|
+
from mlflow.utils.annotations import developer_stable
|
14
|
+
from mlflow.utils.proto_json_utils import NumpyEncoder
|
15
|
+
|
16
|
+
|
17
|
+
@developer_stable
|
18
|
+
class ImageEvaluationArtifact(EvaluationArtifact):
|
19
|
+
def _save(self, output_artifact_path):
|
20
|
+
self._content.save(output_artifact_path)
|
21
|
+
|
22
|
+
def _load_content_from_file(self, local_artifact_path):
|
23
|
+
from PIL.Image import open as open_image
|
24
|
+
|
25
|
+
self._content = open_image(local_artifact_path)
|
26
|
+
self._content.load() # Load image and close the file descriptor.
|
27
|
+
return self._content
|
28
|
+
|
29
|
+
|
30
|
+
@developer_stable
|
31
|
+
class CsvEvaluationArtifact(EvaluationArtifact):
|
32
|
+
def _save(self, output_artifact_path):
|
33
|
+
self._content.to_csv(output_artifact_path, index=False)
|
34
|
+
|
35
|
+
def _load_content_from_file(self, local_artifact_path):
|
36
|
+
self._content = pd.read_csv(local_artifact_path)
|
37
|
+
return self._content
|
38
|
+
|
39
|
+
|
40
|
+
@developer_stable
|
41
|
+
class ParquetEvaluationArtifact(EvaluationArtifact):
|
42
|
+
def _save(self, output_artifact_path):
|
43
|
+
self._content.to_parquet(output_artifact_path, compression="brotli")
|
44
|
+
|
45
|
+
def _load_content_from_file(self, local_artifact_path):
|
46
|
+
self._content = pd.read_parquet(local_artifact_path)
|
47
|
+
return self._content
|
48
|
+
|
49
|
+
|
50
|
+
@developer_stable
|
51
|
+
class NumpyEvaluationArtifact(EvaluationArtifact):
|
52
|
+
def _save(self, output_artifact_path):
|
53
|
+
np.save(output_artifact_path, self._content, allow_pickle=False)
|
54
|
+
|
55
|
+
def _load_content_from_file(self, local_artifact_path):
|
56
|
+
self._content = np.load(local_artifact_path, allow_pickle=False)
|
57
|
+
return self._content
|
58
|
+
|
59
|
+
|
60
|
+
@developer_stable
|
61
|
+
class JsonEvaluationArtifact(EvaluationArtifact):
|
62
|
+
def _save(self, output_artifact_path):
|
63
|
+
with open(output_artifact_path, "w") as f:
|
64
|
+
json.dump(self._content, f)
|
65
|
+
|
66
|
+
def _load_content_from_file(self, local_artifact_path):
|
67
|
+
with open(local_artifact_path) as f:
|
68
|
+
self._content = json.load(f)
|
69
|
+
return self._content
|
70
|
+
|
71
|
+
|
72
|
+
@developer_stable
|
73
|
+
class TextEvaluationArtifact(EvaluationArtifact):
|
74
|
+
def _save(self, output_artifact_path):
|
75
|
+
with open(output_artifact_path, "w") as f:
|
76
|
+
f.write(self._content)
|
77
|
+
|
78
|
+
def _load_content_from_file(self, local_artifact_path):
|
79
|
+
with open(local_artifact_path) as f:
|
80
|
+
self._content = f.read()
|
81
|
+
return self._content
|
82
|
+
|
83
|
+
|
84
|
+
@developer_stable
|
85
|
+
class PickleEvaluationArtifact(EvaluationArtifact):
|
86
|
+
def _save(self, output_artifact_path):
|
87
|
+
with open(output_artifact_path, "wb") as f:
|
88
|
+
pickle.dump(self._content, f)
|
89
|
+
|
90
|
+
def _load_content_from_file(self, local_artifact_path):
|
91
|
+
with open(local_artifact_path, "rb") as f:
|
92
|
+
self._content = pickle.load(f)
|
93
|
+
return self._content
|
94
|
+
|
95
|
+
|
96
|
+
_EXT_TO_ARTIFACT_MAP = {
|
97
|
+
".png": ImageEvaluationArtifact,
|
98
|
+
".jpg": ImageEvaluationArtifact,
|
99
|
+
".jpeg": ImageEvaluationArtifact,
|
100
|
+
".json": JsonEvaluationArtifact,
|
101
|
+
".npy": NumpyEvaluationArtifact,
|
102
|
+
".csv": CsvEvaluationArtifact,
|
103
|
+
".parquet": ParquetEvaluationArtifact,
|
104
|
+
".txt": TextEvaluationArtifact,
|
105
|
+
}
|
106
|
+
|
107
|
+
_TYPE_TO_EXT_MAP = {
|
108
|
+
pd.DataFrame: ".csv",
|
109
|
+
np.ndarray: ".npy",
|
110
|
+
plt.Figure: ".png",
|
111
|
+
}
|
112
|
+
|
113
|
+
_TYPE_TO_ARTIFACT_MAP = {
|
114
|
+
pd.DataFrame: CsvEvaluationArtifact,
|
115
|
+
np.ndarray: NumpyEvaluationArtifact,
|
116
|
+
plt.Figure: ImageEvaluationArtifact,
|
117
|
+
}
|
118
|
+
|
119
|
+
_InferredArtifactProperties = namedtuple(
|
120
|
+
"_InferredArtifactProperties", ["from_path", "type", "ext"]
|
121
|
+
)
|
122
|
+
|
123
|
+
|
124
|
+
def _infer_artifact_type_and_ext(artifact_name, raw_artifact, custom_metric_tuple):
|
125
|
+
"""
|
126
|
+
This function performs type and file extension inference on the provided artifact
|
127
|
+
|
128
|
+
Args:
|
129
|
+
artifact_name: The name of the provided artifact
|
130
|
+
raw_artifact: The artifact object
|
131
|
+
custom_metric_tuple: Containing a user provided function and its index in the
|
132
|
+
``custom_metrics`` parameter of ``mlflow.evaluate``
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
InferredArtifactProperties namedtuple
|
136
|
+
"""
|
137
|
+
|
138
|
+
exception_header = (
|
139
|
+
f"Custom metric function '{custom_metric_tuple.name}' at index "
|
140
|
+
f"{custom_metric_tuple.index} in the `custom_metrics` parameter produced an "
|
141
|
+
f"artifact '{artifact_name}'"
|
142
|
+
)
|
143
|
+
|
144
|
+
# Given a string, first see if it is a path. Otherwise, check if it is a JsonEvaluationArtifact
|
145
|
+
if isinstance(raw_artifact, str):
|
146
|
+
potential_path = pathlib.Path(raw_artifact)
|
147
|
+
if potential_path.exists():
|
148
|
+
raw_artifact = potential_path
|
149
|
+
else:
|
150
|
+
try:
|
151
|
+
json.loads(raw_artifact)
|
152
|
+
return _InferredArtifactProperties(
|
153
|
+
from_path=False, type=JsonEvaluationArtifact, ext=".json"
|
154
|
+
)
|
155
|
+
except JSONDecodeError:
|
156
|
+
raise MlflowException(
|
157
|
+
f"{exception_header} with string representation '{raw_artifact}' that is "
|
158
|
+
f"neither a valid path to a file nor a JSON string."
|
159
|
+
)
|
160
|
+
|
161
|
+
# Type inference based on the file extension
|
162
|
+
if isinstance(raw_artifact, pathlib.Path):
|
163
|
+
if not raw_artifact.exists():
|
164
|
+
raise MlflowException(f"{exception_header} with path '{raw_artifact}' does not exist.")
|
165
|
+
if not raw_artifact.is_file():
|
166
|
+
raise MlflowException(f"{exception_header} with path '{raw_artifact}' is not a file.")
|
167
|
+
if raw_artifact.suffix not in _EXT_TO_ARTIFACT_MAP:
|
168
|
+
raise MlflowException(
|
169
|
+
f"{exception_header} with path '{raw_artifact}' does not match any of the supported"
|
170
|
+
f" file extensions: {', '.join(_EXT_TO_ARTIFACT_MAP.keys())}."
|
171
|
+
)
|
172
|
+
return _InferredArtifactProperties(
|
173
|
+
from_path=True, type=_EXT_TO_ARTIFACT_MAP[raw_artifact.suffix], ext=raw_artifact.suffix
|
174
|
+
)
|
175
|
+
|
176
|
+
# Type inference based on object type
|
177
|
+
if type(raw_artifact) in _TYPE_TO_ARTIFACT_MAP:
|
178
|
+
return _InferredArtifactProperties(
|
179
|
+
from_path=False,
|
180
|
+
type=_TYPE_TO_ARTIFACT_MAP[type(raw_artifact)],
|
181
|
+
ext=_TYPE_TO_EXT_MAP[type(raw_artifact)],
|
182
|
+
)
|
183
|
+
|
184
|
+
# Given as other python object, we first attempt to infer as JsonEvaluationArtifact. If that
|
185
|
+
# fails, we store it as PickleEvaluationArtifact
|
186
|
+
try:
|
187
|
+
json.dumps(raw_artifact, cls=NumpyEncoder)
|
188
|
+
return _InferredArtifactProperties(
|
189
|
+
from_path=False, type=JsonEvaluationArtifact, ext=".json"
|
190
|
+
)
|
191
|
+
except TypeError:
|
192
|
+
return _InferredArtifactProperties(
|
193
|
+
from_path=False, type=PickleEvaluationArtifact, ext=".pickle"
|
194
|
+
)
|