code: def test_llm_lora_finetuning_merge_and_unload(
      tmpdir: str,
      csv_filename: str,
      backend: dict,
      target_modules: list[str] | set[str] | None,
      merge_adapter_into_base_model: bool,
      expected_lora_in_features: int,
      expected_lora_out_features: int,
      expected_file_names: list[str],
  ):
      from peft.tuners.lora.config import LoraConfig
      from peft.tuners.lora.model import LoraModel
  
      finetune_strategy: str = "lora"
  
      adapter_args: dict = {
          POSTPROCESSOR: {
              MERGE_ADAPTER_INTO_BASE_MODEL: merge_adapter_into_base_model,
          },
      }
      # If "target_modules" is None, then ["q_proj", "v_proj"] is used (HuggingFace Transformers/PEFT internal default).
      if target_modules:
          adapter_args[TARGET_MODULES] = target_modules
  
      train_df, prediction_df, config = _prepare_finetuning_test(
          csv_filename=csv_filename,
          finetune_strategy=finetune_strategy,
          backend=backend,
          adapter_args=adapter_args,
      )
  
      output_directory: str = str(tmpdir)
      model_directory: str = (
          pathlib.Path(output_directory)
          / "api_experiment_run"
          / "model"
      )
      model_weights_directory: str = (
          pathlib.Path(output_directory)
          / "api_experiment_run"
          / "model"
          / "model_weights"
      )
  
      model = LudwigModel(config)
      model.train(
          dataset=train_df,
          output_directory=output_directory,
          skip_save_processed_input=False,
      )
  
      # Get actual "target_modules" from trained model (to be used in assertions).
      lora_model: LoraModel = model.model.model.base_model
      peft_config: dict = lora_model.peft_config
      lora_config: LoraConfig = peft_config["default"]
      target_modules = lora_config.target_modules
  
      _verify_lm_lora_finetuning_layers(
          attention_layer=model.model.model.base_model.model.transformer.h[
              1
          ].attn,
          target_modules=target_modules,
          merge_adapter_into_base_model=merge_adapter_into_base_model,
          model_weights_directory=model_weights_directory,
          expected_lora_in_features=expected_lora_in_features,
          expected_lora_out_features=expected_lora_out_features,
          expected_file_names=expected_file_names,
      )
  
      # Make sure we can load the saved model and verify that the LoRA layers have expected shapes.
      model = LudwigModel.load(str(model_directory), backend=backend)
      _verify_lm_lora_finetuning_layers(
          attention_layer=model.model.model.base_model.model.transformer.h[
              1
          ].attn,
          target_modules=target_modules,
          merge_adapter_into_base_model=merge_adapter_into_base_model,
          model_weights_directory=model_weights_directory,
          expected_lora_in_features=expected_lora_in_features,
          expected_lora_out_features=expected_lora_out_features,
          expected_file_names=expected_file_names,
      )
  
imports: from __future__ import annotations
  import copy
  import json
  import os
  import pathlib
  from typing import Any
  import numpy
  import pandas
  import pytest
  import torch
  import ludwig.error
  from ludwig.api import LudwigModel
  from ludwig.constants import ADAPTER, BACKEND, BASE_MODEL, BATCH_SIZE, COMBINER, EPOCHS, GENERATION, INPUT_FEATURES, MERGE_ADAPTER_INTO_BASE_MODEL, MODEL_ECD, MODEL_LLM, MODEL_TYPE, OUTPUT_FEATURES, POSTPROCESSOR, PREPROCESSING, PRETRAINED_ADAPTER_WEIGHTS, PROGRESSBAR, PROMPT, QUANTIZATION, TARGET_MODULES, TRAINER, TYPE
  from ludwig.models.llm import LLM
  from ludwig.schema.model_types.base import ModelConfig
  from ludwig.utils.fs_utils import list_file_names_in_directory
  from ludwig.utils.types import DataFrame
  from tests.integration_tests.utils import category_feature, generate_data, text_feature
label_desc: Use image node_id 17 for calling a global function with example usage: test_llm_lora_finetuning_merge_and_unload(tmpdir, csv_filename, backend, target_modules, merge_adapter_into_base_model, expected_lora_in_features, expected_lora_out_features, expected_file_names) without return types