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,616 @@
|
|
1
|
+
# TODO: Split this file into multiple files and move under utils directory.
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import inspect
|
5
|
+
import json
|
6
|
+
import logging
|
7
|
+
import uuid
|
8
|
+
from collections import Counter
|
9
|
+
from contextlib import contextmanager
|
10
|
+
from dataclasses import asdict, is_dataclass
|
11
|
+
from functools import lru_cache
|
12
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
13
|
+
|
14
|
+
from opentelemetry import trace as trace_api
|
15
|
+
from opentelemetry.sdk.trace import Span as OTelSpan
|
16
|
+
from packaging.version import Version
|
17
|
+
|
18
|
+
from mlflow.exceptions import BAD_REQUEST, MlflowTracingException
|
19
|
+
from mlflow.tracing.constant import (
|
20
|
+
TRACE_REQUEST_ID_PREFIX,
|
21
|
+
SpanAttributeKey,
|
22
|
+
TokenUsageKey,
|
23
|
+
TraceMetadataKey,
|
24
|
+
TraceSizeStatsKey,
|
25
|
+
)
|
26
|
+
from mlflow.utils.mlflow_tags import IMMUTABLE_TAGS
|
27
|
+
from mlflow.version import IS_TRACING_SDK_ONLY
|
28
|
+
|
29
|
+
_logger = logging.getLogger(__name__)
|
30
|
+
|
31
|
+
SPANS_COLUMN_NAME = "spans"
|
32
|
+
|
33
|
+
if TYPE_CHECKING:
|
34
|
+
from mlflow.entities import LiveSpan, Trace
|
35
|
+
from mlflow.pyfunc.context import Context
|
36
|
+
from mlflow.types.chat import ChatMessage, ChatTool
|
37
|
+
|
38
|
+
|
39
|
+
def capture_function_input_args(func, args, kwargs) -> Optional[dict[str, Any]]:
|
40
|
+
try:
|
41
|
+
func_signature = inspect.signature(func)
|
42
|
+
bound_arguments = func_signature.bind(*args, **kwargs)
|
43
|
+
bound_arguments.apply_defaults()
|
44
|
+
|
45
|
+
# Remove `self` from bound arguments if it exists
|
46
|
+
if bound_arguments.arguments.get("self"):
|
47
|
+
del bound_arguments.arguments["self"]
|
48
|
+
|
49
|
+
# Remove `cls` from bound arguments if it's the first parameter and it's a type
|
50
|
+
# This detects classmethods more reliably
|
51
|
+
params = list(bound_arguments.arguments.keys())
|
52
|
+
if params and params[0] == "cls" and isinstance(bound_arguments.arguments["cls"], type):
|
53
|
+
del bound_arguments.arguments["cls"]
|
54
|
+
|
55
|
+
return bound_arguments.arguments
|
56
|
+
except Exception:
|
57
|
+
_logger.warning(f"Failed to capture inputs for function {func.__name__}.")
|
58
|
+
return None
|
59
|
+
|
60
|
+
|
61
|
+
class TraceJSONEncoder(json.JSONEncoder):
|
62
|
+
"""
|
63
|
+
Custom JSON encoder for serializing non-OpenTelemetry compatible objects in a trace or span.
|
64
|
+
|
65
|
+
Trace may contain types that require custom serialization logic, such as Pydantic models,
|
66
|
+
non-JSON-serializable types, etc.
|
67
|
+
"""
|
68
|
+
|
69
|
+
def default(self, obj):
|
70
|
+
try:
|
71
|
+
import langchain
|
72
|
+
|
73
|
+
# LangChain < 0.3.0 does some trick to support Pydantic 1.x and 2.x, so checking
|
74
|
+
# type with installed Pydantic version might not work for some models.
|
75
|
+
# https://github.com/langchain-ai/langchain/blob/b66a4f48fa5656871c3e849f7e1790dfb5a4c56b/libs/core/langchain_core/pydantic_v1/__init__.py#L7
|
76
|
+
if Version(langchain.__version__) < Version("0.3.0"):
|
77
|
+
from langchain_core.pydantic_v1 import BaseModel as LangChainBaseModel
|
78
|
+
|
79
|
+
if isinstance(obj, LangChainBaseModel):
|
80
|
+
return obj.dict()
|
81
|
+
except ImportError:
|
82
|
+
pass
|
83
|
+
|
84
|
+
try:
|
85
|
+
import pydantic
|
86
|
+
|
87
|
+
if isinstance(obj, pydantic.BaseModel):
|
88
|
+
# NB: Pydantic 2.0+ has a different API for model serialization
|
89
|
+
if Version(pydantic.VERSION) >= Version("2.0"):
|
90
|
+
return obj.model_dump()
|
91
|
+
else:
|
92
|
+
return obj.dict()
|
93
|
+
except ImportError:
|
94
|
+
pass
|
95
|
+
|
96
|
+
# Some dataclass object defines __str__ method that doesn't return the full object
|
97
|
+
# representation, so we use dict representation instead.
|
98
|
+
# E.g. https://github.com/run-llama/llama_index/blob/29ece9b058f6b9a1cf29bc723ed4aa3a39879ad5/llama-index-core/llama_index/core/chat_engine/types.py#L63-L64
|
99
|
+
if is_dataclass(obj):
|
100
|
+
try:
|
101
|
+
return asdict(obj)
|
102
|
+
except TypeError:
|
103
|
+
pass
|
104
|
+
|
105
|
+
# Some object has dangerous side effect in __str__ method, so we use class name instead.
|
106
|
+
if not self._is_safe_to_encode_str(obj):
|
107
|
+
return type(obj)
|
108
|
+
|
109
|
+
try:
|
110
|
+
return super().default(obj)
|
111
|
+
except TypeError:
|
112
|
+
return str(obj)
|
113
|
+
|
114
|
+
def _is_safe_to_encode_str(self, obj) -> bool:
|
115
|
+
"""Check if it's safe to encode the object as a string."""
|
116
|
+
try:
|
117
|
+
# These Llama Index objects are not safe to encode as string, because their __str__
|
118
|
+
# method consumes the stream and make it unusable.
|
119
|
+
# E.g. https://github.com/run-llama/llama_index/blob/54f2da61ba8a573284ab8336f2b2810d948c3877/llama-index-core/llama_index/core/base/response/schema.py#L120-L127
|
120
|
+
from llama_index.core.base.response.schema import (
|
121
|
+
AsyncStreamingResponse,
|
122
|
+
StreamingResponse,
|
123
|
+
)
|
124
|
+
from llama_index.core.chat_engine.types import StreamingAgentChatResponse
|
125
|
+
|
126
|
+
if isinstance(
|
127
|
+
obj,
|
128
|
+
(AsyncStreamingResponse, StreamingResponse, StreamingAgentChatResponse),
|
129
|
+
):
|
130
|
+
return False
|
131
|
+
except ImportError:
|
132
|
+
pass
|
133
|
+
|
134
|
+
return True
|
135
|
+
|
136
|
+
|
137
|
+
@lru_cache(maxsize=1)
|
138
|
+
def encode_span_id(span_id: int) -> str:
|
139
|
+
"""
|
140
|
+
Encode the given integer span ID to a 16-byte hex string.
|
141
|
+
# https://github.com/open-telemetry/opentelemetry-python/blob/9398f26ecad09e02ad044859334cd4c75299c3cd/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py#L507-L508
|
142
|
+
# NB: We don't add '0x' prefix to the hex string here for simpler parsing in backend.
|
143
|
+
# Some backend (e.g. Databricks) disallow this prefix.
|
144
|
+
"""
|
145
|
+
return trace_api.format_span_id(span_id)
|
146
|
+
|
147
|
+
|
148
|
+
@lru_cache(maxsize=1)
|
149
|
+
def encode_trace_id(trace_id: int) -> str:
|
150
|
+
"""
|
151
|
+
Encode the given integer trace ID to a 32-byte hex string.
|
152
|
+
"""
|
153
|
+
return trace_api.format_trace_id(trace_id)
|
154
|
+
|
155
|
+
|
156
|
+
def decode_id(span_or_trace_id: str) -> int:
|
157
|
+
"""
|
158
|
+
Decode the given hex string span or trace ID to an integer.
|
159
|
+
"""
|
160
|
+
return int(span_or_trace_id, 16)
|
161
|
+
|
162
|
+
|
163
|
+
def build_otel_context(trace_id: int, span_id: int) -> trace_api.SpanContext:
|
164
|
+
"""
|
165
|
+
Build an OpenTelemetry SpanContext object from the given trace and span IDs.
|
166
|
+
"""
|
167
|
+
return trace_api.SpanContext(
|
168
|
+
trace_id=trace_id,
|
169
|
+
span_id=span_id,
|
170
|
+
# NB: This flag is OpenTelemetry's concept to indicate whether the context is
|
171
|
+
# propagated from remote parent or not. We don't support distributed tracing
|
172
|
+
# yet so always set it to False.
|
173
|
+
is_remote=False,
|
174
|
+
)
|
175
|
+
|
176
|
+
|
177
|
+
def deduplicate_span_names_in_place(spans: list[LiveSpan]):
|
178
|
+
"""
|
179
|
+
Deduplicate span names in the trace data by appending an index number to the span name.
|
180
|
+
|
181
|
+
This is only applied when there are multiple spans with the same name. The span names
|
182
|
+
are modified in place to avoid unnecessary copying.
|
183
|
+
|
184
|
+
E.g.
|
185
|
+
["red", "red"] -> ["red_1", "red_2"]
|
186
|
+
["red", "red", "blue"] -> ["red_1", "red_2", "blue"]
|
187
|
+
|
188
|
+
Args:
|
189
|
+
spans: A list of spans to deduplicate.
|
190
|
+
"""
|
191
|
+
span_name_counter = Counter(span.name for span in spans)
|
192
|
+
# Apply renaming only for duplicated spans
|
193
|
+
span_name_counter = {name: 1 for name, count in span_name_counter.items() if count > 1}
|
194
|
+
# Add index to the duplicated span names
|
195
|
+
for span in spans:
|
196
|
+
if count := span_name_counter.get(span.name):
|
197
|
+
span_name_counter[span.name] += 1
|
198
|
+
span._span._name = f"{span.name}_{count}"
|
199
|
+
|
200
|
+
|
201
|
+
def aggregate_usage_from_spans(spans: list[LiveSpan]) -> Optional[dict[str, int]]:
|
202
|
+
"""Aggregate token usage information from all spans in the trace."""
|
203
|
+
input_tokens = 0
|
204
|
+
output_tokens = 0
|
205
|
+
total_tokens = 0
|
206
|
+
has_usage_data = False
|
207
|
+
|
208
|
+
span_id_to_spans = {span.span_id: span for span in spans}
|
209
|
+
for span in spans:
|
210
|
+
# Get usage attribute from span
|
211
|
+
if usage := span.get_attribute(SpanAttributeKey.CHAT_USAGE):
|
212
|
+
# If the parent span is also LLM/Chat span and has the token usage data,
|
213
|
+
# it tracks the same usage data by multiple flavors e.g. LangChain ChatOpenAI
|
214
|
+
# and OpenAI tracing. We should avoid double counting the usage data.
|
215
|
+
if (
|
216
|
+
span.parent_id
|
217
|
+
and (parent_span := span_id_to_spans.get(span.parent_id))
|
218
|
+
and parent_span.get_attribute(SpanAttributeKey.CHAT_USAGE)
|
219
|
+
):
|
220
|
+
continue
|
221
|
+
|
222
|
+
input_tokens += usage.get(TokenUsageKey.INPUT_TOKENS, 0)
|
223
|
+
output_tokens += usage.get(TokenUsageKey.OUTPUT_TOKENS, 0)
|
224
|
+
total_tokens += usage.get(TokenUsageKey.TOTAL_TOKENS, 0)
|
225
|
+
has_usage_data = True
|
226
|
+
|
227
|
+
# If none of the spans have token usage data, we shouldn't log token usage metadata.
|
228
|
+
if not has_usage_data:
|
229
|
+
return None
|
230
|
+
|
231
|
+
return {
|
232
|
+
TokenUsageKey.INPUT_TOKENS: input_tokens,
|
233
|
+
TokenUsageKey.OUTPUT_TOKENS: output_tokens,
|
234
|
+
TokenUsageKey.TOTAL_TOKENS: total_tokens,
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
def get_otel_attribute(span: trace_api.Span, key: str) -> Optional[str]:
|
239
|
+
"""
|
240
|
+
Get the attribute value from the OpenTelemetry span in a decoded format.
|
241
|
+
|
242
|
+
Args:
|
243
|
+
span: The OpenTelemetry span object.
|
244
|
+
key: The key of the attribute to retrieve.
|
245
|
+
|
246
|
+
Returns:
|
247
|
+
The attribute value as decoded string. If the attribute is not found or cannot
|
248
|
+
be parsed, return None.
|
249
|
+
"""
|
250
|
+
try:
|
251
|
+
return json.loads(span.attributes.get(key))
|
252
|
+
except Exception:
|
253
|
+
_logger.debug(f"Failed to get attribute {key} with from span {span}.", exc_info=True)
|
254
|
+
|
255
|
+
|
256
|
+
def _try_get_prediction_context():
|
257
|
+
# NB: Tracing is enabled in mlflow-skinny, but the pyfunc module cannot be imported as it
|
258
|
+
# relies on numpy, which is not installed in skinny.
|
259
|
+
try:
|
260
|
+
from mlflow.pyfunc.context import get_prediction_context
|
261
|
+
except ImportError:
|
262
|
+
return
|
263
|
+
|
264
|
+
return get_prediction_context()
|
265
|
+
|
266
|
+
|
267
|
+
def maybe_get_request_id(is_evaluate=False) -> Optional[str]:
|
268
|
+
"""Get the request ID if the current prediction is as a part of MLflow model evaluation."""
|
269
|
+
context = _try_get_prediction_context()
|
270
|
+
if not context or (is_evaluate and not context.is_evaluate):
|
271
|
+
return None
|
272
|
+
|
273
|
+
if not context.request_id and is_evaluate:
|
274
|
+
_logger.warning(
|
275
|
+
f"Missing request_id for context {context}. request_id can't be None when "
|
276
|
+
"is_evaluate=True. This is likely an internal error of MLflow, please file "
|
277
|
+
"a bug report at https://github.com/mlflow/mlflow/issues."
|
278
|
+
)
|
279
|
+
return None
|
280
|
+
|
281
|
+
return context.request_id
|
282
|
+
|
283
|
+
|
284
|
+
def maybe_get_dependencies_schemas() -> Optional[dict[str, Any]]:
|
285
|
+
context = _try_get_prediction_context()
|
286
|
+
if context:
|
287
|
+
return context.dependencies_schemas
|
288
|
+
|
289
|
+
|
290
|
+
def maybe_get_logged_model_id() -> Optional[str]:
|
291
|
+
"""
|
292
|
+
Get the logged model ID associated with the current prediction context.
|
293
|
+
"""
|
294
|
+
if context := _try_get_prediction_context():
|
295
|
+
return context.model_id
|
296
|
+
|
297
|
+
|
298
|
+
def exclude_immutable_tags(tags: dict[str, str]) -> dict[str, str]:
|
299
|
+
"""Exclude immutable tags e.g. "mlflow.user" from the given tags."""
|
300
|
+
return {k: v for k, v in tags.items() if k not in IMMUTABLE_TAGS}
|
301
|
+
|
302
|
+
|
303
|
+
def generate_trace_id_v3(span: OTelSpan) -> str:
|
304
|
+
"""
|
305
|
+
Generate a trace ID for the given span (V3 trace schema).
|
306
|
+
|
307
|
+
The format will be "tr-<trace_id>" where the trace_id is hex-encoded Otel trace ID.
|
308
|
+
"""
|
309
|
+
return TRACE_REQUEST_ID_PREFIX + encode_trace_id(span.context.trace_id)
|
310
|
+
|
311
|
+
|
312
|
+
def generate_request_id_v2() -> str:
|
313
|
+
"""
|
314
|
+
Generate a request ID for the given span.
|
315
|
+
|
316
|
+
This should only be used for V2 trace schema where we use a random UUID as
|
317
|
+
request ID. In the V3 schema, "request_id" is renamed to "trace_id" and
|
318
|
+
we use the otel-generated trace ID with encoding.
|
319
|
+
"""
|
320
|
+
return uuid.uuid4().hex
|
321
|
+
|
322
|
+
|
323
|
+
def construct_full_inputs(func, *args, **kwargs) -> dict[str, Any]:
|
324
|
+
"""
|
325
|
+
Construct the full input arguments dictionary for the given function,
|
326
|
+
including positional and keyword arguments.
|
327
|
+
"""
|
328
|
+
signature = inspect.signature(func)
|
329
|
+
# this does not create copy. So values should not be mutated directly
|
330
|
+
arguments = signature.bind_partial(*args, **kwargs).arguments
|
331
|
+
|
332
|
+
if "self" in arguments:
|
333
|
+
arguments.pop("self")
|
334
|
+
|
335
|
+
return arguments
|
336
|
+
|
337
|
+
|
338
|
+
@contextmanager
|
339
|
+
def maybe_set_prediction_context(context: Optional["Context"]):
|
340
|
+
"""
|
341
|
+
Set the prediction context if the given context
|
342
|
+
is not None. Otherwise no-op.
|
343
|
+
"""
|
344
|
+
if not IS_TRACING_SDK_ONLY and context:
|
345
|
+
from mlflow.pyfunc.context import set_prediction_context
|
346
|
+
|
347
|
+
with set_prediction_context(context):
|
348
|
+
yield
|
349
|
+
else:
|
350
|
+
yield
|
351
|
+
|
352
|
+
|
353
|
+
def set_span_chat_messages(
|
354
|
+
span: LiveSpan,
|
355
|
+
messages: list[Union[dict[str, Any], ChatMessage]],
|
356
|
+
append=False,
|
357
|
+
):
|
358
|
+
"""
|
359
|
+
Set the `mlflow.chat.messages` attribute on the specified span. This
|
360
|
+
attribute is used in the UI, and also by downstream applications that
|
361
|
+
consume trace data, such as MLflow evaluate.
|
362
|
+
|
363
|
+
Args:
|
364
|
+
span: The LiveSpan to add the attribute to
|
365
|
+
messages: A list of standardized chat messages (refer to the
|
366
|
+
`spec <../llms/tracing/tracing-schema.html#chat-completion-spans>`_
|
367
|
+
for details)
|
368
|
+
append: If True, the messages will be appended to the existing messages. Otherwise,
|
369
|
+
the attribute will be overwritten entirely. Default is False.
|
370
|
+
This is useful when you want to record messages incrementally, e.g., log
|
371
|
+
input messages first, and then log output messages later.
|
372
|
+
|
373
|
+
Example:
|
374
|
+
|
375
|
+
.. code-block:: python
|
376
|
+
:test:
|
377
|
+
|
378
|
+
import mlflow
|
379
|
+
from mlflow.tracing import set_span_chat_messages
|
380
|
+
|
381
|
+
|
382
|
+
@mlflow.trace
|
383
|
+
def f():
|
384
|
+
messages = [{"role": "user", "content": "hello"}]
|
385
|
+
span = mlflow.get_current_active_span()
|
386
|
+
set_span_chat_messages(span, messages)
|
387
|
+
return 0
|
388
|
+
|
389
|
+
|
390
|
+
f()
|
391
|
+
"""
|
392
|
+
from mlflow.types.chat import ChatMessage
|
393
|
+
|
394
|
+
sanitized_messages = []
|
395
|
+
for message in messages:
|
396
|
+
if isinstance(message, dict):
|
397
|
+
ChatMessage.validate_compat(message)
|
398
|
+
sanitized_messages.append(message)
|
399
|
+
elif isinstance(message, ChatMessage):
|
400
|
+
# NB: ChatMessage is used for both request and response messages. In OpenAI's API spec,
|
401
|
+
# some fields are only present in either the request or response (e.g., tool_call_id).
|
402
|
+
# Those fields should not be recorded unless set explicitly, so we set
|
403
|
+
# exclude_unset=True here to avoid recording unset fields.
|
404
|
+
sanitized_messages.append(message.model_dump_compat(exclude_unset=True))
|
405
|
+
|
406
|
+
if append:
|
407
|
+
existing_messages = span.get_attribute(SpanAttributeKey.CHAT_MESSAGES) or []
|
408
|
+
sanitized_messages = existing_messages + sanitized_messages
|
409
|
+
|
410
|
+
span.set_attribute(SpanAttributeKey.CHAT_MESSAGES, sanitized_messages)
|
411
|
+
|
412
|
+
|
413
|
+
def set_span_chat_tools(span: LiveSpan, tools: list[ChatTool]):
|
414
|
+
"""
|
415
|
+
Set the `mlflow.chat.tools` attribute on the specified span. This
|
416
|
+
attribute is used in the UI, and also by downstream applications that
|
417
|
+
consume trace data, such as MLflow evaluate.
|
418
|
+
|
419
|
+
Args:
|
420
|
+
span: The LiveSpan to add the attribute to
|
421
|
+
tools: A list of standardized chat tool definitions (refer to the
|
422
|
+
`spec <../llms/tracing/tracing-schema.html#chat-completion-spans>`_
|
423
|
+
for details)
|
424
|
+
|
425
|
+
Example:
|
426
|
+
|
427
|
+
.. code-block:: python
|
428
|
+
:test:
|
429
|
+
|
430
|
+
import mlflow
|
431
|
+
from mlflow.tracing import set_span_chat_tools
|
432
|
+
|
433
|
+
tools = [
|
434
|
+
{
|
435
|
+
"type": "function",
|
436
|
+
"function": {
|
437
|
+
"name": "add",
|
438
|
+
"description": "Add two numbers",
|
439
|
+
"parameters": {
|
440
|
+
"type": "object",
|
441
|
+
"properties": {
|
442
|
+
"a": {"type": "number"},
|
443
|
+
"b": {"type": "number"},
|
444
|
+
},
|
445
|
+
"required": ["a", "b"],
|
446
|
+
},
|
447
|
+
},
|
448
|
+
}
|
449
|
+
]
|
450
|
+
|
451
|
+
|
452
|
+
@mlflow.trace
|
453
|
+
def f():
|
454
|
+
span = mlflow.get_current_active_span()
|
455
|
+
set_span_chat_tools(span, tools)
|
456
|
+
return 0
|
457
|
+
|
458
|
+
|
459
|
+
f()
|
460
|
+
"""
|
461
|
+
from mlflow.types.chat import ChatTool
|
462
|
+
|
463
|
+
if not isinstance(tools, list):
|
464
|
+
raise MlflowTracingException(
|
465
|
+
f"Invalid tools type {type(tools)}. Expected a list of ChatTool.",
|
466
|
+
error_code=BAD_REQUEST,
|
467
|
+
)
|
468
|
+
|
469
|
+
sanitized_tools = []
|
470
|
+
for tool in tools:
|
471
|
+
if isinstance(tool, dict):
|
472
|
+
ChatTool.validate_compat(tool)
|
473
|
+
sanitized_tools.append(tool)
|
474
|
+
elif isinstance(tool, ChatTool):
|
475
|
+
sanitized_tools.append(tool.model_dump_compat(exclude_unset=True))
|
476
|
+
|
477
|
+
span.set_attribute(SpanAttributeKey.CHAT_TOOLS, sanitized_tools)
|
478
|
+
|
479
|
+
|
480
|
+
def set_chat_attributes_special_case(span: LiveSpan, inputs: Any, outputs: Any):
|
481
|
+
"""
|
482
|
+
Set the `mlflow.chat.messages` and `mlflow.chat.tools` attributes on the specified span
|
483
|
+
based on the inputs and outputs of the function.
|
484
|
+
|
485
|
+
Usually those attributes are set by autologging integrations. This utility function handles
|
486
|
+
special cases where we want to set chat attributes for manually created spans via @mlflow.trace
|
487
|
+
decorator, such as ResponsesAgent tracing spans.
|
488
|
+
"""
|
489
|
+
try:
|
490
|
+
from mlflow.openai.utils.chat_schema import set_span_chat_attributes
|
491
|
+
from mlflow.types.responses import ResponsesAgentResponse, ResponsesAgentStreamEvent
|
492
|
+
|
493
|
+
if isinstance(outputs, ResponsesAgentResponse):
|
494
|
+
inputs = inputs["request"].model_dump_compat()
|
495
|
+
set_span_chat_attributes(span, inputs, outputs)
|
496
|
+
elif isinstance(outputs, list) and all(
|
497
|
+
isinstance(o, ResponsesAgentStreamEvent) for o in outputs
|
498
|
+
):
|
499
|
+
inputs = inputs["request"].model_dump_compat()
|
500
|
+
output_items = []
|
501
|
+
custom_outputs = None
|
502
|
+
for o in outputs:
|
503
|
+
if o.type == "response.output_item.done":
|
504
|
+
output_items.append(o.item)
|
505
|
+
if o.custom_outputs:
|
506
|
+
custom_outputs = o.custom_outputs
|
507
|
+
output = ResponsesAgentResponse(
|
508
|
+
output=output_items,
|
509
|
+
custom_outputs=custom_outputs,
|
510
|
+
)
|
511
|
+
set_span_chat_attributes(span, inputs, output)
|
512
|
+
except Exception:
|
513
|
+
pass
|
514
|
+
|
515
|
+
|
516
|
+
def _calculate_percentile(sorted_data: list[float], percentile: float) -> float:
|
517
|
+
"""
|
518
|
+
Calculate the percentile value from sorted data.
|
519
|
+
|
520
|
+
Args:
|
521
|
+
sorted_data: A sorted list of numeric values
|
522
|
+
percentile: The percentile to calculate (e.g., 0.25 for 25th percentile)
|
523
|
+
|
524
|
+
Returns:
|
525
|
+
The percentile value
|
526
|
+
"""
|
527
|
+
if not sorted_data:
|
528
|
+
return 0.0
|
529
|
+
|
530
|
+
n = len(sorted_data)
|
531
|
+
index = percentile * (n - 1)
|
532
|
+
lower = int(index)
|
533
|
+
upper = lower + 1
|
534
|
+
|
535
|
+
if upper >= n:
|
536
|
+
return sorted_data[-1]
|
537
|
+
|
538
|
+
# Linear interpolation between two nearest values
|
539
|
+
weight = index - lower
|
540
|
+
return sorted_data[lower] * (1 - weight) + sorted_data[upper] * weight
|
541
|
+
|
542
|
+
|
543
|
+
def add_size_stats_to_trace_metadata(trace: Trace):
|
544
|
+
"""
|
545
|
+
Calculate the stats of trace and span sizes and add it as a metadata to the trace.
|
546
|
+
|
547
|
+
This method modifies the trace object in place by adding a new tag.
|
548
|
+
|
549
|
+
Note: For simplicity, we calculate the size without considering the size metadata itself.
|
550
|
+
This provides a close approximation without requiring complex calculations.
|
551
|
+
|
552
|
+
This function must not throw an exception.
|
553
|
+
"""
|
554
|
+
from mlflow.entities import Trace, TraceData
|
555
|
+
|
556
|
+
try:
|
557
|
+
span_sizes = []
|
558
|
+
for span in trace.data.spans:
|
559
|
+
span_json = json.dumps(span.to_dict(), cls=TraceJSONEncoder)
|
560
|
+
span_sizes.append(len(span_json.encode("utf-8")))
|
561
|
+
|
562
|
+
# NB: To compute the size of the total trace, we need to include the size of the
|
563
|
+
# the trace info and the parent dicts for the spans. To avoid serializing spans
|
564
|
+
# again (which can be expensive), we compute the size of the trace without spans
|
565
|
+
# and combine it with the total size of the spans.
|
566
|
+
empty_trace = Trace(info=trace.info, data=TraceData(spans=[]))
|
567
|
+
metadata_size = len(empty_trace.to_json().encode("utf-8"))
|
568
|
+
|
569
|
+
# NB: the third term is the size of comma separators between spans (", ").
|
570
|
+
trace_size_bytes = sum(span_sizes) + metadata_size + (len(span_sizes) - 1) * 2
|
571
|
+
|
572
|
+
# Sort span sizes for percentile calculation
|
573
|
+
sorted_span_sizes = sorted(span_sizes)
|
574
|
+
|
575
|
+
size_stats = {
|
576
|
+
TraceSizeStatsKey.TOTAL_SIZE_BYTES: trace_size_bytes,
|
577
|
+
TraceSizeStatsKey.NUM_SPANS: len(span_sizes),
|
578
|
+
TraceSizeStatsKey.MAX_SPAN_SIZE_BYTES: max(span_sizes),
|
579
|
+
TraceSizeStatsKey.P25_SPAN_SIZE_BYTES: int(
|
580
|
+
_calculate_percentile(sorted_span_sizes, 0.25)
|
581
|
+
),
|
582
|
+
TraceSizeStatsKey.P50_SPAN_SIZE_BYTES: int(
|
583
|
+
_calculate_percentile(sorted_span_sizes, 0.50)
|
584
|
+
),
|
585
|
+
TraceSizeStatsKey.P75_SPAN_SIZE_BYTES: int(
|
586
|
+
_calculate_percentile(sorted_span_sizes, 0.75)
|
587
|
+
),
|
588
|
+
}
|
589
|
+
|
590
|
+
trace.info.trace_metadata[TraceMetadataKey.SIZE_STATS] = json.dumps(size_stats)
|
591
|
+
# Keep the total size as a separate metadata for backward compatibility
|
592
|
+
trace.info.trace_metadata[TraceMetadataKey.SIZE_BYTES] = str(trace_size_bytes)
|
593
|
+
except Exception:
|
594
|
+
_logger.warning("Failed to add size stats to trace metadata.", exc_info=True)
|
595
|
+
|
596
|
+
|
597
|
+
def update_trace_state_from_span_conditionally(trace, root_span):
|
598
|
+
"""
|
599
|
+
Update trace state from span status, but only if the user hasn't explicitly set
|
600
|
+
a different trace status.
|
601
|
+
|
602
|
+
This utility preserves user-set trace status while maintaining default behavior
|
603
|
+
for traces that haven't been explicitly configured. Used by trace processors when
|
604
|
+
converting traces to an exportable state.
|
605
|
+
|
606
|
+
Args:
|
607
|
+
trace: The trace object to potentially update
|
608
|
+
root_span: The root span whose status may be used to update the trace state
|
609
|
+
"""
|
610
|
+
from mlflow.entities.trace_state import TraceState
|
611
|
+
|
612
|
+
# Only update trace state from span status if trace is still IN_PROGRESS
|
613
|
+
# If the trace state is anything else, it means the user explicitly set it
|
614
|
+
# and we should preserve it
|
615
|
+
if trace.info.state == TraceState.IN_PROGRESS:
|
616
|
+
trace.info.state = TraceState.from_otel_status(root_span.status)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from mlflow.entities.trace_info import TraceInfo
|
2
|
+
from mlflow.exceptions import MlflowException
|
3
|
+
from mlflow.protos.databricks_pb2 import INTERNAL_ERROR
|
4
|
+
from mlflow.utils.mlflow_tags import MLFLOW_ARTIFACT_LOCATION
|
5
|
+
|
6
|
+
TRACE_DATA_FILE_NAME = "traces.json"
|
7
|
+
|
8
|
+
|
9
|
+
def get_artifact_uri_for_trace(trace_info: TraceInfo):
|
10
|
+
"""
|
11
|
+
Get the artifact uri for accessing the trace data.
|
12
|
+
|
13
|
+
The artifact root is specified in the trace tags, which is
|
14
|
+
set when logging the trace in the backend.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
trace_info: Either a TraceInfo or TraceInfoV3 object containing trace metadata.
|
18
|
+
|
19
|
+
Returns:
|
20
|
+
The artifact URI string for the trace data.
|
21
|
+
"""
|
22
|
+
# Both TraceInfo and TraceInfoV3 access tags the same way
|
23
|
+
if MLFLOW_ARTIFACT_LOCATION not in trace_info.tags:
|
24
|
+
raise MlflowException(
|
25
|
+
"Unable to determine trace artifact location.",
|
26
|
+
error_code=INTERNAL_ERROR,
|
27
|
+
)
|
28
|
+
return trace_info.tags[MLFLOW_ARTIFACT_LOCATION]
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from typing import Any, Optional
|
2
|
+
|
3
|
+
from mlflow.entities.span import LiveSpan, Span
|
4
|
+
from mlflow.exceptions import MlflowException
|
5
|
+
from mlflow.protos.databricks_pb2 import INVALID_STATE
|
6
|
+
from mlflow.tracing.trace_manager import InMemoryTraceManager
|
7
|
+
|
8
|
+
|
9
|
+
def copy_trace_to_experiment(
|
10
|
+
trace_dict: dict[str, Any], experiment_id: Optional[str] = None
|
11
|
+
) -> str:
|
12
|
+
"""
|
13
|
+
Copy the given trace to the current experiment.
|
14
|
+
The copied trace will have a new trace ID and location metadata.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
trace_dict: The trace dictionary returned from model serving endpoint.
|
18
|
+
This can be either V2 or V3 trace.
|
19
|
+
experiment_id: The ID of the experiment to copy the trace to.
|
20
|
+
If not provided, the trace will be copied to the current experiment.
|
21
|
+
"""
|
22
|
+
new_trace_id = None
|
23
|
+
new_root_span = None
|
24
|
+
trace_manager = InMemoryTraceManager.get_instance()
|
25
|
+
spans = [Span.from_dict(span_dict) for span_dict in trace_dict["data"]["spans"]]
|
26
|
+
|
27
|
+
# Create a copy of spans in the current experiment
|
28
|
+
for old_span in spans:
|
29
|
+
new_span = LiveSpan.from_immutable_span(
|
30
|
+
span=old_span,
|
31
|
+
parent_span_id=old_span.parent_id,
|
32
|
+
trace_id=new_trace_id,
|
33
|
+
experiment_id=experiment_id,
|
34
|
+
# Don't close the root span until the end so that we only export the trace
|
35
|
+
# after all spans are copied.
|
36
|
+
end_trace=old_span.parent_id is not None,
|
37
|
+
)
|
38
|
+
trace_manager.register_span(new_span)
|
39
|
+
if old_span.parent_id is None:
|
40
|
+
new_root_span = new_span
|
41
|
+
new_trace_id = new_span.trace_id
|
42
|
+
|
43
|
+
if new_trace_id is None:
|
44
|
+
raise MlflowException(
|
45
|
+
"Root span not found in the trace. Perhaps the trace data is corrupted.",
|
46
|
+
error_code=INVALID_STATE,
|
47
|
+
)
|
48
|
+
|
49
|
+
user_tags = {k: v for k, v in trace_dict["info"]["tags"].items() if not k.startswith("mlflow.")}
|
50
|
+
with trace_manager.get_trace(trace_id=new_trace_id) as trace:
|
51
|
+
trace.info.tags.update(user_tags)
|
52
|
+
|
53
|
+
# Close the root span triggers the trace export.
|
54
|
+
new_root_span.end(end_time_ns=spans[0].end_time_ns)
|
55
|
+
return new_trace_id
|