content: import os
  from typing import Union, List, Optional
  import json
  import regex as re
  import ast
  import random
  
  def fix_json(input_str):
      # Add double quotes around keys using regex
      fixed_str = re.sub(r'(\w+):', r'"\1":', input_str)
      
      # Add double quotes around string values if necessary and wrap int/float values in []
      def format_value(match):
          key, value, comma = match.groups()
          value = value.strip()
          # Check if value is an integer or float
          if re.match(r'^-?\d+(\.\d+)?$', value):
              value = f'[{value}]'
          # Check if value is a boolean or null
          elif re.match(r'^(true|false|null)$', value, re.IGNORECASE):
              pass  # leave as is
          else:
              # Add quotes around string values
              value = f'"{value}"'
          return f'{key}: {value}{comma}'
      
      fixed_str = re.sub(r'(".*?"):(.*?)(,|})', format_value, fixed_str)
      
      return fixed_str
  
  def read_file_to_string(file_path):
      """
      Reads the contents of a text file and returns it as a string.
  
      :param file_path: The path to the text file.
      :return: A string containing the contents of the file.
      """
      try:
          with open(file_path, 'r', encoding='utf-8') as file:
              return file.read()
      except FileNotFoundError:
          print(f"The file {file_path} was not found.")
          return None
      except Exception as e:
          print(f"An error occurred: {e}")
          return None
  
  def read_files_to_string(file_paths):
      """
      Reads the contents of multiple text files and returns them as a single string,
      with each file's contents separated by a newline.
  
      :param file_paths: A list of paths to text files.
      :return: A string containing the concatenated contents of the files.
      """
      all_contents = []  # List to hold the contents of each file
  
      for file_path in file_paths:
          try:
              with open(file_path, 'r', encoding='utf-8') as file:
                  all_contents.append(file.read())
          except FileNotFoundError:
              print(f"The file {file_path} was not found.")
          except Exception as e:
              print(f"An error occurred while reading {file_path}: {e}")
  
      # Join all the contents with a newline character
      return "\n".join(all_contents)
  
  def get_file_path(filename: Union[str, os.PathLike], search_from: Union[str, os.PathLike] = "."):
      """
      Search for a file across a directory and return its absolute path.
  
      Args:
          filename (Union[str, os.PathLike]): The name of the file to search for.
          search_from (Union[str, os.PathLike], optional): The directory from which to start the search. Defaults to ".".
  
      Returns:
          str: Absolute path to the found file.
  
      Raises:
          FileNotFoundError: If the file is not found.
      """
      for root, dirs, files in os.walk(search_from):
          for name in files:
              if name == filename:
                  return os.path.abspath(os.path.join(root, name))
      raise FileNotFoundError(filename, "not found.")
  
  
  
  #+=========================================================================================
  def verify(s, target_sequence):
      # Count the occurrences of the target sequence
      count = s.count(target_sequence)
  
      # Check if the target sequence appears exactly twice
      return count == 2
  
  
  def is_int_between_0_and_10(s):
      try:
          num = int(s)
          return 0 <= num <= 10
      except ValueError:
          return False
      
  def is_str_a_list_of_ints_0_to_10(s):
      try:
          # Attempt to parse the string as a Python literal (list, dict, etc.)
          parsed = ast.literal_eval(s)
  
          # Check if the parsed object is a list
          if not isinstance(parsed, list):
              return False
  
          # Check if all elements are integers and between 0 to 10
          return all(isinstance(item, int) and 0 <= item <= 10 for item in parsed)
  
      except (ValueError, SyntaxError):
          # If parsing fails or any other error occurs
          return False
      
  def is_str_valid_score_format_brackets(s):
      try:
          # Removing brackets and splitting the string by commas
          content = s.strip("[]").split(',')
  
          length = len(content)
  
          # Parsing each element and checking the format and range
          scores = {}
          for item in content:
              key, value = item.split(':')
              key = key.strip()
              value = int(value.strip())
  
              # Check if the key starts with 'score' and the value is in the correct range
              if not key.startswith("score") or not 0 <= value <= 10:
                  return False
  
              scores[key] = value
  
          fetch_words = [f"score{i+1}" for i in range(length)]
          # Check if at least 'score1' and 'score2' are present
          return all(key in scores for key in fetch_words)
  
      except (ValueError, SyntaxError):
          # If any parsing error occurs
          return False
  
  
  #+=========================================================================================
  def mllm_output_to_dict(input_string, give_up_parsing=False):
      """
      Args:
          input_string (str): actually the output of the mllm model to be parsed
          output_file_name (str): The name of the output file.
      """
      # Catch for gpt4v rate_limit_exceeded error
      if input_string == "rate_limit_exceeded":
          return "rate_limit_exceeded"
  
      # Define the delimiters
      delimiter = '||V^=^V||'
  
      if input_string.count(delimiter) == 2:
          if not verify(input_string, delimiter):
              print("The required delimiters were not found correctly in the string.")
              return False
          # Extract the content between the delimiters
          start_index = input_string.find(delimiter) + len(delimiter)
          end_index = input_string.rfind(delimiter)
      else:
          # find the json mannually
          # some mllm tends not to output the delimiters, but it does output the json contents
          # so we will find the json content mannually
          start_index = input_string.find('{')
          end_index = input_string.rfind('}') + 1
          if start_index == -1 or end_index == 0:
              # json not found
              # some mllm tends to output only a list of scores like [6, 0], 
              # this time we will just get the scores and ignore the reasoning (other part of the json)
              start_index = input_string.find('[')
              end_index = input_string.rfind(']') + 1
              if give_up_parsing: # if we want to give up parsing
                  guessed_value = random.randint(0, 10)
                  print(f"Failed to find the json content in the string. Guess a value : {guessed_value}.")
                  json_content = {'score': [guessed_value], "reasoning": f"guess_if_cannot_parse | {input_string}"}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              elif re.match(r'^\[\d+, ?\d+\]$', input_string[start_index:end_index]):
                  scores = json.loads(input_string[start_index:end_index])
                  if not isinstance(scores, list):
                      scores = [scores]
                  json_content = {'score': scores, "reasoning": "System: output is simply a list of scores"}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              elif is_int_between_0_and_10(input_string): # if output is simply a number
                  scores = [int(input_string)]
                  json_content = {'score': scores, "reasoning": "System: output is simply a number"}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              else:
                  print("Failed to find the json content in the string.")
                  return False
      
      # Check if we found two delimiters
      if start_index != -1 and end_index != -1 and start_index != end_index:
          # Extract the JSON string
          json_str = input_string[start_index:end_index].strip()
          json_str = json_str.replace("\n", "")
          # Parse the JSON string into a dictionary
          try:
              new_data = json.loads(json_str)
              if not isinstance(new_data['score'], list):
                  new_data['score'] = [new_data['score']]
          except:
              print("Now fixing: ", json_str)
              try:
                  new_data = json.loads(fix_json(json_str))
                  return new_data
              except:
                  print("Error: Cannot fix", json_str)
                  return False
          return new_data
      else:
          print("The required delimiters were not found correctly in the string.")
          return False
  
  def write_entry_to_json_file(input_string, uid, prompt_input, vision_input, output_file_name, give_up_parsing=False):
      """
      Args:
          input_string (str): actually the output of the mllm model to be parsed
          uid (str): The unique identifier for the each item in the test data
          prompt_input (str): The prompt input for the entry. text prompt.
          vision_input (str): The vision input for the entry. image links.
          output_file_name (str): The name of the output file.
      """
      # Catch for gpt4v rate_limit_exceeded error
      if input_string == "rate_limit_exceeded":
          return "rate_limit_exceeded"
  
      # Define the delimiters
      delimiter = '||V^=^V||'
  
      if input_string.count(delimiter) == 2:
          if not verify(input_string, delimiter):
              print("The required delimiters were not found correctly in the string.")
              return False
          # Extract the content between the delimiters
          start_index = input_string.find(delimiter) + len(delimiter)
          end_index = input_string.rfind(delimiter)
      else:
          # find the json mannually
          # some mllm tends not to output the delimiters, but it does output the json contents
          # so we will find the json content mannually
          start_index = input_string.find('{')
          end_index = input_string.rfind('}') + 1
          if start_index == -1 or end_index == 0:
              # json not found
              # some mllm tends to output only a list of scores like [6, 0], 
              # this time we will just get the scores and ignore the reasoning (other part of the json)
              start_index = input_string.find('[')
              end_index = input_string.rfind(']') + 1
              if give_up_parsing: # if we want to give up parsing
                  guessed_value = random.randint(0, 10)
                  print(f"Failed to find the json content in the string. Guess a value : {guessed_value}.")
                  json_content = {'score': [guessed_value], "reasoning": f"guess_if_cannot_parse | {input_string}"}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              elif re.match(r'^\[\d+, ?\d+\]$', input_string[start_index:end_index]):
                  scores = json.loads(input_string[start_index:end_index])
                  json_content = {'score': scores, "reasoning": None}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              elif is_int_between_0_and_10(input_string): # if output is simply a number
                  scores = [int(input_string)]
                  json_content = {'score': scores, "reasoning": None}
                  json_str = json.dumps(json_content)
                  input_string = json_str
                  start_index = 0
                  end_index = len(json_str)
              else:
                  print("Failed to find the json content in the string.")
                  return False
      
      # Check if we found two delimiters
      if start_index != -1 and end_index != -1 and start_index != end_index:
          # Extract the JSON string
          json_str = input_string[start_index:end_index].strip()
          json_str = json_str.replace("\n", "")
          try:
              # Parse the JSON string into a dictionary
              new_data = json.loads(json_str)
              
              # Ensure the directory exists
              os.makedirs(os.path.dirname(output_file_name), exist_ok=True)
              
              # Initialize or load existing data
              if os.path.exists(output_file_name):
                  with open(output_file_name, 'r') as json_file:
                      data = json.load(json_file)
              else:
                  data = {}
              
              # If the additional key is already in the data, add or update notes
              if uid in data:
                  data[uid].update(new_data)  # Update with new data
                  if prompt_input:  # If there are new notes, update or add them
                      data[uid]['prompt_input'] = prompt_input
                  if vision_input:  # If there are new notes, update or add them
                      data[uid]['vision_input'] = vision_input
              else:
                  # If it's a new key, add the entry to the dictionary
                  data[uid] = new_data
                  if prompt_input:
                      data[uid]['prompt_input'] = prompt_input
                  if vision_input:
                      data[uid]['vision_input'] = vision_input
              
              # Write the updated data to the file
              with open(output_file_name, 'w') as json_file:
                  json.dump(data, json_file, indent=4)
              
              print(f"Data was successfully updated in {output_file_name}")
              return True
          except json.JSONDecodeError as e:
              print(f"An error occurred while parsing the JSON content: {e}")
              return False
      else:
          print("The required delimiters were not found correctly in the string.")
          return False
  
  
  def check_key_in_json(file_path, key):
      try:
          with open(file_path, 'r') as json_file:
              data = json.load(json_file)
          
          # Check if the key exists at the top level of the JSON structure
          if key in data:
              return True
          else:
              return False
      except FileNotFoundError:
          print(f"The file {file_path} was not found.")
      except json.JSONDecodeError as e:
          print(f"Error reading {file_path}: {e}")
      except Exception as e:
          print(f"An error occurred with {file_path}: {e}")
      return False