code: def invert_trade_subtokenization(
      original_seq: str,
      trade_seq: str,
      token_exceptions: Dict[str, str] = TOKEN_EXCEPTIONS,
      pattern_exceptions: Dict[str, str] = PATTERN_EXCEPTIONS,
      subtoken_special_chrs: List[str] = [" -", " _"],
  ) -> str:
      """
      Invert all trade subtokenizations in a string given the original sequence.
  
      Arguments
      ---------
      original_seq: str
          The original sequence.
      trade_seq: str
          The sequence that has been pre-processed by trade.
      token_exceptions: dict, keys are str, values are str
          A dictionary to map merged token to their correct counterpart. E.g.
          child -s is merged into childs, but the correct token is children.
      pattern_exceptions: dict, keys are str, values are str
          A dictionary to map patterns to their correct counterpart. E.g.
          after the pre-processing "b&bs" is mapped to "bed and breakfast -s",
          making the search of breakfasts impossible if not handled by such
          exceptions.
      subtoken_special_chrs: list of str
          List containing the special characters that are used for subtokens.
  
      Returns
      -------
      corrected_seq: str
          The sequence corrected, i.e. subtokens replaced by tokens.
      """
      regex = "|".join(subtoken_special_chrs)
      subtoken_pieces = re.split(regex, trade_seq, maxsplit=1)
      search_after: int = 0
      while len(subtoken_pieces) > 1:
          # example: 'the wind is moderate -ly strong'
          # split: ['the wind is moderate ', 'ly strong']
          # split[0]: 'the wind is moderate' --> split on whitespace ['the', 'wind', 'is', 'moderate']
          left_side = subtoken_pieces[0].split()
          subtoken_left = left_side[-1]
          # split[1]: 'ly strong' --> split on whitespace ['ly', 'strong']
          right_side = subtoken_pieces[1].split()
          subtoken_right = right_side[0]
          # try merging the subtoken parts to form a token, i.e. moderate + ly
          token = "".join([subtoken_left, subtoken_right])
  
          if token in token_exceptions:
              # if you match an exception, replace the token with the exception
              token = token_exceptions[token]
  
          # assume there are no tokens on left and right side of the subtokens' pieces
          left_token = None  # if token is at the beginnig
          right_token = None  # if token is at the end
          # try looking for them
          if len(left_side) > 1:
              left_token = left_side[-2]
          if len(right_side) > 1:
              right_token = right_side[1]
  
          # start from a complete match, and progressively remove left and right
          # tokens to counter TRADE preprocessing of some tokens
          # The order is
          # 1. True, True
          # 2. True, False
          # 3. False, True
          # 4. False, False
          # basically, at the end you try looking only for the merged token
          pattern: str = ""
          idx: int = -1
          for use_left, use_right in product(
              (True, False), (True, False)
          ):
              pattern = token
              if (left_token is not None) and use_left:
                  pattern = " ".join([left_token, pattern])
              if right_token is not None and use_right:
                  pattern = " ".join([pattern, right_token])
  
              # check if the pattern is in the exceptions
              if pattern in pattern_exceptions:
                  pattern = pattern_exceptions[pattern]
              # Search the pattern
              idx = original_seq[search_after:].lower().find(pattern)
              if idx > -1:
                  break
  
          error: str = f"""
              Pattern search failed in the following case:
              PATTERN =  \t{pattern}
              LEFT SIDE = \t{left_side}
              RIGHT SIDE = \t{right_side}
              ORIG SEQ = \t{original_seq[search_after:]}
  
              This may be due to further TRADE pre-processing, or not correct merging operation.
              To solve this, add a special rule for the token that breaks the code either as a
              token_exception or a pattern_exception.
          """
  
          assert idx > -1, error
          # move the index to avoid perfect matches with the same token
          # TODO is probably better to move it of len(left_token + token) or
          # len(token) depending on the match
          search_after += idx + 1
          # reconstruct the sentence with the matched pattern
          trade_seq = " ".join(
              [*left_side[:-1], token, *right_side[1:]]
          )
  
          # try splitting the sentence again and repeat the process
          subtoken_pieces = re.split(regex, trade_seq, maxsplit=1)
      # Good, no subtokens found: return trade seq
      return trade_seq
  
imports: from itertools import product
  from statistics import mean
  from typing import Any, Dict, List, Optional, Set, Tuple
  import json
  import logging
  import os
  import re
  import shutil
  from tqdm import tqdm
  from speechbrain.utils.data_utils import download_file
label_desc: Use image node_id 12 for calling a global function with example usage: invert_trade_subtokenization(original_seq, trade_seq, token_exceptions, pattern_exceptions, subtoken_special_chrs) and returns: trade_seq