code: def save_model(
      spark_model,
      path,
      mlflow_model=None,
      conda_env=None,
      code_paths=None,
      dfs_tmpdir=None,
      sample_input=None,
      signature: ModelSignature = None,
      input_example: ModelInputExample = None,
      pip_requirements=None,
      extra_pip_requirements=None,
      metadata=None,
      store_license=False,
  ):
      """
      Save a Spark johnsnowlabs Model to a local path.
  
      By default, this function saves models using the Spark MLlib persistence mechanism.
      Additionally, if a sample input is specified using the ``sample_input`` parameter, the model
      is also serialized in MLeap format and the MLeap flavor is added.
  
      Args:
          store_license: If True, the license will be stored with the model and used and
              re-loading it.
          spark_model: Either a pyspark.ml.pipeline.PipelineModel or nlu.NLUPipeline object to be
              saved. `Every johnsnowlabs model <https://nlp.johnsnowlabs.com/models>`_
              is a PipelineModel and loadable as nlu.NLUPipeline.
          path: Local path where the model is to be saved.
          mlflow_model: MLflow model config this flavor is being added to.
          conda_env: Either a dictionary representation of a Conda environment or the path to a
              Conda environment yaml file. If provided, this describes the environment
              this model should be run in. At minimum, it should specify the dependencies
              contained in :func:`get_default_conda_env()`. If `None`, the default
              :func:`get_default_conda_env()` environment is added to the model.
              The following is an *example* dictionary representation of a Conda
              environment::
  
                  {
                      'name': 'mlflow-env',
                      'channels': ['defaults'],
                      'dependencies': [
                          'python=3.8.15',
                          'johnsnowlabs'
                      ]
                  }
          dfs_tmpdir: Temporary directory path on Distributed (Hadoop) File System (DFS) or local
              filesystem if running in local mode. The model is be written in this
              destination and then copied to the requested local path. This is necessary
              as Spark ML models read from and write to DFS if running on a cluster. All
              temporary files created on the DFS are removed if this operation
              completes successfully. Defaults to ``/tmp/mlflow``.
          sample_input: A sample input that is used to add the MLeap flavor to the model.
              This must be a PySpark DataFrame that the model can evaluate. If
              ``sample_input`` is ``None``, the MLeap flavor is not added.
          signature: :py:class:`ModelSignature <mlflow.models.ModelSignature>`
              describes model input and output :py:class:`Schema <mlflow.types.Schema>`.
              The model signature can be :py:func:`inferred <mlflow.models.infer_signature>`
              from datasets with valid model input (e.g. the training dataset with target
              column omitted) and valid model output (e.g. model predictions generated on
              the training dataset), for example:
  
              .. code-block:: python
  
                  from mlflow.models.signature import infer_signature
  
                  train = df.drop_column("target_label")
                  predictions = ...  # compute model predictions
                  signature = infer_signature(train, predictions)
          input_example: {{ input_example }}
          pip_requirements: {{ pip_requirements }}
          extra_pip_requirements: {{ extra_pip_requirements }}
          metadata: Custom metadata dictionary passed to the model and stored in the MLmodel file.
  
              .. Note:: Experimental: This parameter may change or be removed in a future
                  release without warning.
  
      .. code-block:: python
          :caption: Example
  
          from johnsnowlabs import nlp
          import mlflow
          import os
  
          # Write your raw license.json string into the 'JOHNSNOWLABS_LICENSE_JSON' env variable
          creds = {
              "AWS_ACCESS_KEY_ID": "...",
              "AWS_SECRET_ACCESS_KEY": "...",
              "SPARK_NLP_LICENSE": "...",
              "SECRET": "...",
          }
          os.environ["JOHNSNOWLABS_LICENSE_JSON"] = json.dumps(creds)
  
          # Download & Install Jars/Wheels if missing and Start a spark Session
          nlp.start()
  
          # load a model
          model = nlp.load("en.classify.bert_sequence.covid_sentiment")
          model.predict(["I hate covid", "I love covid"])
  
          # Save model as pyfunc and johnsnowlabs format
          mlflow.johnsnowlabs.save_model(model, "saved_model")
          model = mlflow.johnsnowlabs.load_model("saved_model")
          # Predict with reloaded model,
          # supports datatypes defined in https://nlp.johnsnowlabs.com/docs/en/jsl/predict_api#supported-data-types
          model.predict(["I hate covid", "I love covid"])
      """
      _validate_env_vars()
      if mlflow_model is None:
          mlflow_model = Model()
      if metadata is not None:
          mlflow_model.metadata = metadata
      # Spark ML stores the model on DFS if running on a cluster
      # Save it to a DFS temp dir first and copy it to local path
      if dfs_tmpdir is None:
          dfs_tmpdir = MLFLOW_DFS_TMP.get()
      tmp_path = generate_tmp_dfs_path(dfs_tmpdir)
  
      _unpack_and_save_model(spark_model, tmp_path)
      sparkml_data_path = os.path.abspath(
          str(Path(path) / _JOHNSNOWLABS_MODEL_PATH_SUB)
      )
      # We're copying the Spark model from DBFS to the local filesystem if (a) the temporary DFS URI
      # we saved the Spark model to is a DBFS URI ("dbfs:/my-directory"), or (b) if we're running
      # on a Databricks cluster and the URI is schemeless (e.g. looks like a filesystem absolute path
      # like "/my-directory")
      copying_from_dbfs = is_valid_dbfs_uri(tmp_path) or (
          databricks_utils.is_in_cluster()
          and posixpath.abspath(tmp_path) == tmp_path
      )
      if (
          copying_from_dbfs
          and databricks_utils.is_dbfs_fuse_available()
      ):
          tmp_path_fuse = dbfs_hdfs_uri_to_fuse_path(tmp_path)
          shutil.move(src=tmp_path_fuse, dst=sparkml_data_path)
      else:
          _HadoopFileSystem.copy_to_local_file(
              tmp_path, sparkml_data_path, remove_src=True
          )
      _save_model_metadata(
          dst_dir=path,
          spark_model=spark_model,
          mlflow_model=mlflow_model,
          sample_input=sample_input,
          conda_env=conda_env,
          code_paths=code_paths,
          signature=signature,
          input_example=input_example,
          pip_requirements=pip_requirements,
          extra_pip_requirements=extra_pip_requirements,
          store_license=store_license,
      )
  
imports: import json
  import logging
  import os
  import posixpath
  import shutil
  import sys
  from pathlib import Path
  from typing import Any, Dict, Optional
  import yaml
  import mlflow
  from mlflow import mleap, pyfunc
  from mlflow.environment_variables import MLFLOW_DFS_TMP
  from mlflow.models import Model
  from mlflow.models.model import MLMODEL_FILE_NAME
  from mlflow.models.signature import ModelSignature
  from mlflow.models.utils import ModelInputExample, _save_example
  from mlflow.spark import _HadoopFileSystem, _maybe_save_model, _mlflowdbfs_path, _should_use_mlflowdbfs
  from mlflow.store.artifact.databricks_artifact_repo import DatabricksArtifactRepository
  from mlflow.tracking._model_registry import DEFAULT_AWAIT_MAX_SLEEP_SECONDS
  from mlflow.tracking.artifact_utils import _download_artifact_from_uri, _get_root_uri_and_artifact_path
  from mlflow.utils import databricks_utils
  from mlflow.utils.annotations import experimental
  from mlflow.utils.docstring_utils import LOG_MODEL_PARAM_DOCS, format_docstring
  from mlflow.utils.environment import _CONDA_ENV_FILE_NAME, _CONSTRAINTS_FILE_NAME, _PYTHON_ENV_FILE_NAME, _REQUIREMENTS_FILE_NAME, _mlflow_conda_env, _process_conda_env, _process_pip_requirements, _PythonEnv
  from mlflow.utils.file_utils import TempDir, get_total_file_size, shutil_copytree_without_file_permissions, write_to
  from mlflow.utils.model_utils import _add_code_from_conf_to_system_path, _get_flavor_configuration_from_uri, _validate_and_copy_code_paths
  from mlflow.utils.requirements_utils import _get_pinned_requirement
  from mlflow.utils.uri import append_to_uri_path, dbfs_hdfs_uri_to_fuse_path, generate_tmp_dfs_path, get_databricks_profile_uri_from_artifact_uri, is_local_uri, is_valid_dbfs_uri
label_desc: Use image node_id 8 for calling a global function with example usage: save_model(spark_model, path, mlflow_model, conda_env, code_paths, dfs_tmpdir, sample_input, signature, input_example, pip_requirements, extra_pip_requirements, metadata, store_license) without return types