code: def save_model(
      lc_model,
      path,
      conda_env=None,
      code_paths=None,
      mlflow_model=None,
      signature: ModelSignature = None,
      input_example: ModelInputExample = None,
      pip_requirements=None,
      extra_pip_requirements=None,
      metadata=None,
      loader_fn=None,
      persist_dir=None,
      example_no_conversion=False,
  ):
      """
      Save a LangChain model to a path on the local file system.
  
      Args:
          lc_model: A LangChain model, which could be a
              `Chain <https://python.langchain.com/docs/modules/chains/>`_,
              `Agent <https://python.langchain.com/docs/modules/agents/>`_,
              `retriever <https://python.langchain.com/docs/modules/data_connection/retrievers/>`_,
              or `RunnableSequence <https://python.langchain.com/docs/modules/chains/foundational/sequential_chains#using-lcel>`_.
          path: Local path where the serialized model (as YAML) is to be saved.
          conda_env: {{ conda_env }}
          code_paths: A list of local filesystem paths to Python file dependencies (or directories
              containing file dependencies). These files are *prepended* to the system
              path when the model is loaded.
          mlflow_model: :py:mod:`mlflow.models.Model` this flavor is being added to.
          signature: :py:class:`ModelSignature <mlflow.models.ModelSignature>`
              describes model input and output :py:class:`Schema <mlflow.types.Schema>`.
              If not specified, the model signature would be set according to
              `lc_model.input_keys` and `lc_model.output_keys` as columns names, and
              `DataType.string` as the column type.
              Alternatively, you can explicitly specify the model signature.
              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 import infer_signature
  
                  chain = LLMChain(llm=llm, prompt=prompt)
                  prediction = chain.run(input_str)
                  input_columns = [
                      {"type": "string", "name": input_key} for input_key in chain.input_keys
                  ]
                  signature = infer_signature(input_columns, 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.
          loader_fn: A function that's required for models containing objects that aren't natively
              serialized by LangChain.
              This function takes a string `persist_dir` as an argument and returns the
              specific object that the model needs. Depending on the model,
              this could be a retriever, vectorstore, requests_wrapper, embeddings, or
              database. For RetrievalQA Chain and retriever models, the object is a
              (`retriever <https://python.langchain.com/docs/modules/data_connection/retrievers/>`_).
              For APIChain models, it's a
              (`requests_wrapper <https://python.langchain.com/docs/modules/agents/tools/integrations/requests>`_).
              For HypotheticalDocumentEmbedder models, it's an
              (`embeddings <https://python.langchain.com/docs/modules/data_connection/text_embedding/>`_).
              For SQLDatabaseChain models, it's a
              (`database <https://python.langchain.com/docs/modules/agents/toolkits/sql_database>`_).
          persist_dir: The directory where the object is stored. The `loader_fn`
              takes this string as the argument to load the object.
              This is optional for models containing objects that aren't natively
              serialized by LangChain. MLflow logs the content in this directory as
              artifacts in the subdirectory named `persist_dir_data`.
  
              Here is the code snippet for logging a RetrievalQA chain with `loader_fn`
              and `persist_dir`:
  
              .. code-block:: python
  
                  qa = RetrievalQA.from_llm(llm=OpenAI(), retriever=db.as_retriever())
  
  
                  def load_retriever(persist_directory):
                      embeddings = OpenAIEmbeddings()
                      vectorstore = FAISS.load_local(persist_directory, embeddings)
                      return vectorstore.as_retriever()
  
  
                  with mlflow.start_run() as run:
                      logged_model = mlflow.langchain.log_model(
                          qa,
                          artifact_path="retrieval_qa",
                          loader_fn=load_retriever,
                          persist_dir=persist_dir,
                      )
  
              See a complete example in examples/langchain/retrieval_qa_chain.py.
          example_no_conversion: {{ example_no_conversion }}
      """
      import langchain
      from langchain.schema import BaseRetriever
  
      lc_model = _validate_and_wrap_lc_model(lc_model, loader_fn)
  
      _validate_env_arguments(
          conda_env, pip_requirements, extra_pip_requirements
      )
  
      path = os.path.abspath(path)
      _validate_and_prepare_target_save_path(path)
      code_dir_subpath = _validate_and_copy_code_paths(code_paths, path)
  
      if signature is None:
          if input_example is not None:
              wrapped_model = _LangChainModelWrapper(lc_model)
              signature = _infer_signature_from_input_example(
                  input_example, wrapped_model
              )
          else:
              if hasattr(lc_model, "input_keys"):
                  input_columns = [
                      ColSpec(type=DataType.string, name=input_key)
                      for input_key in lc_model.input_keys
                  ]
                  input_schema = Schema(input_columns)
              else:
                  input_schema = None
              if (
                  hasattr(lc_model, "output_keys")
                  and len(lc_model.output_keys) == 1
                  and not isinstance(lc_model, BaseRetriever)
              ):
                  output_columns = [
                      ColSpec(type=DataType.string, name=output_key)
                      for output_key in lc_model.output_keys
                  ]
                  output_schema = Schema(output_columns)
              else:
                  # TODO: empty output schema if multiple output_keys or is a retriever. fix later!
                  # https://databricks.atlassian.net/browse/ML-34706
                  output_schema = None
  
              signature = (
                  ModelSignature(input_schema, output_schema)
                  if input_schema or output_schema
                  else None
              )
  
      if mlflow_model is None:
          mlflow_model = Model()
      if signature is not None:
          mlflow_model.signature = signature
  
      if input_example is not None:
          _save_example(
              mlflow_model, input_example, path, example_no_conversion
          )
      if metadata is not None:
          mlflow_model.metadata = metadata
  
      model_data_kwargs = _save_model(
          lc_model, path, loader_fn, persist_dir
      )
  
      pyfunc.add_to_model(
          mlflow_model,
          loader_module="mlflow.langchain",
          conda_env=_CONDA_ENV_FILE_NAME,
          python_env=_PYTHON_ENV_FILE_NAME,
          code=code_dir_subpath,
          **model_data_kwargs,
      )
      flavor_conf = {
          _MODEL_TYPE_KEY: lc_model.__class__.__name__,
          **model_data_kwargs,
      }
      mlflow_model.add_flavor(
          FLAVOR_NAME,
          langchain_version=langchain.__version__,
          code=code_dir_subpath,
          **flavor_conf,
      )
      if size := get_total_file_size(path):
          mlflow_model.model_size_bytes = size
      mlflow_model.save(os.path.join(path, MLMODEL_FILE_NAME))
  
      if conda_env is None:
          if pip_requirements is None:
              default_reqs = get_default_pip_requirements()
              inferred_reqs = mlflow.models.infer_pip_requirements(
                  str(path), FLAVOR_NAME, fallback=default_reqs
              )
              default_reqs = sorted(
                  set(inferred_reqs).union(default_reqs)
              )
          else:
              default_reqs = None
          (
              conda_env,
              pip_requirements,
              pip_constraints,
          ) = _process_pip_requirements(
              default_reqs, pip_requirements, extra_pip_requirements
          )
      else:
          (
              conda_env,
              pip_requirements,
              pip_constraints,
          ) = _process_conda_env(conda_env)
  
      with open(os.path.join(path, _CONDA_ENV_FILE_NAME), "w") as f:
          yaml.safe_dump(conda_env, stream=f, default_flow_style=False)
  
      if pip_constraints:
          write_to(
              os.path.join(path, _CONSTRAINTS_FILE_NAME),
              "\n".join(pip_constraints),
          )
  
      write_to(
          os.path.join(path, _REQUIREMENTS_FILE_NAME),
          "\n".join(pip_requirements),
      )
  
      _PythonEnv.current().to_yaml(
          os.path.join(path, _PYTHON_ENV_FILE_NAME)
      )
  
imports: import logging
  import os
  from typing import Any, Dict, List, Optional, Union
  import pandas
  import yaml
  import mlflow
  from mlflow import pyfunc
  from mlflow.environment_variables import _MLFLOW_TESTING
  from mlflow.langchain.runnables import _load_runnables, _save_runnables
  from mlflow.langchain.utils import _BASE_LOAD_KEY, _MODEL_LOAD_KEY, _RUNNABLE_LOAD_KEY, _load_base_lcs, _save_base_lcs, _validate_and_wrap_lc_model, lc_runnables_types
  from mlflow.models import Model, ModelInputExample, ModelSignature
  from mlflow.models.model import MLMODEL_FILE_NAME
  from mlflow.models.signature import _infer_signature_from_input_example
  from mlflow.models.utils import _save_example
  from mlflow.tracking._model_registry import DEFAULT_AWAIT_MAX_SLEEP_SECONDS
  from mlflow.tracking.artifact_utils import _download_artifact_from_uri
  from mlflow.types.schema import ColSpec, DataType, Schema
  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, _validate_env_arguments
  from mlflow.utils.file_utils import get_total_file_size, write_to
  from mlflow.utils.model_utils import _add_code_from_conf_to_system_path, _get_flavor_configuration, _validate_and_copy_code_paths, _validate_and_prepare_target_save_path
  from mlflow.utils.requirements_utils import _get_pinned_requirement
label_desc: Use image node_id 3 for calling a global function with example usage: save_model(lc_model, path, conda_env, code_paths, mlflow_model, signature, input_example, pip_requirements, extra_pip_requirements, metadata, loader_fn, persist_dir, example_no_conversion) without return types