code: def compute_spark_df_digest(df) -> str:
      """Computes a digest for the given Spark DataFrame. Retrieve a semantic hash of the
      DataFrame's logical plan, which is much more efficient and deterministic than hashing
      DataFrame records
  
      Args:
          df: A Spark DataFrame.
  
      Returns:
          A string digest.
  
      """
  
      import numpy as np
      import pyspark
  
      # Spark 3.1.0+ has a semanticHash() method on DataFrame
      if Version(pyspark.__version__) >= Version("3.1.0"):
          semantic_hash = df.semanticHash()
      else:
          semantic_hash = (
              df._jdf.queryExecution().analyzed().semanticHash()
          )
      return get_normalized_md5_digest([np.int64(semantic_hash)])
  
file_path: mlflow/mlflow/data/digest_utils.py
imports: from typing import Any, List
  from packaging.version import Version
  from mlflow.exceptions import MlflowException
  from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
  from mlflow.utils import insecure_hash
label_desc: Use image node_id 5 for calling a global function with example usage: compute_spark_df_digest(df) and returns: get_normalized_md5_digest