code: def search_in_index(
      ngram2phrases: Dict[str, List[Tuple[int, int, int, float]]],
      phrases: List[str],
      letters: Union[str, List[str]],
  ) -> Tuple[np.ndarray, List[Set[str]]]:
      """Function used to search in index
  
      Args:
          ngram2phrases: dict where key=ngram, value=list of tuples (phrase_id, begin_pos, size, logprob)
          phrases: List of all phrases in custom vocabulary. Position corresponds to phrase_id.
          letters: list of letters of ASR-hypothesis. Should not contain spaces - real spaces should be replaced with underscores.
  
      Returns:
          phrases2positions: a matrix of size (len(phrases), len(letters)).
              It is filled with 1.0 (hits) on intersection of letter n-grams and phrases that are indexed by these n-grams, 0.0 - elsewhere.
              It is used later to find phrases with many hits within a contiguous window - potential matching candidates.
          position2ngrams: positions in ASR-hypothesis mapped to sets of ngrams starting from that position.
              It is used later to check how well each found candidate is covered by n-grams (to avoid cases where some repeating n-gram gives many hits to a phrase, but the phrase itself is not well covered).
      """
  
      if " " in letters:
          raise ValueError(
              "letters should not contain space: " + str(letters)
          )
  
      phrases2positions = np.zeros(
          (len(phrases), len(letters)), dtype=float
      )
      # positions mapped to sets of ngrams starting from that position
      position2ngrams = [set() for _ in range(len(letters))]
  
      begin = 0
      for begin in range(len(letters)):
          for end in range(begin + 1, min(len(letters) + 1, begin + 7)):
              ngram = " ".join(letters[begin:end])
              if ngram not in ngram2phrases:
                  continue
              for phrase_id, b, size, lp in ngram2phrases[ngram]:
                  phrases2positions[phrase_id, begin:end] = 1.0
              position2ngrams[begin].add(ngram)
      return phrases2positions, position2ngrams
  
imports: import json
  import math
  import random
  import re
  from collections import defaultdict, namedtuple
  from typing import Dict, List, Set, Tuple, Union
  import numpy
  from numba import jit
label_desc: Use image node_id 7 for calling a global function with example usage: search_in_index(ngram2phrases, phrases, letters) and returns: phrases2positions,  position2ngrams