class_docstr: This class matches the question with one of the templates
  to extract entity substrings and define which relations
  corresponds to the question
class_docstr_tok: ["This","class","matches","the","question","with","one","of","the","templates","to","extract","entity","substrings","and","define","which","relations","corresponds","to","the","question"]
code: def __call__(
      self, question: str, entities_from_ner: List[str]
  ) -> Tuple[
      Union[List[str], list],
      list,
      Union[list, Any],
      Union[list, Any],
      Union[str, Any],
      Union[list, Any],
      Union[str, Any],
      Union[list, Any],
      Union[str, Any],
  ]:
      question = question.lower()
      question = self.sanitize(question)
      question_length = len(question)
      entities, types, relations, relation_dirs = [], [], [], []
      query_type = ""
      template_found = ""
      entity_types = []
      template_answer = ""
      answer_types = []
      results = self.pool.map(RegexpMatcher(question), self.templates)
      results = functools.reduce(lambda x, y: x + y, results)
      replace_tokens = [
          ("the uk", "united kingdom"),
          ("the us", "united states"),
      ]
      if results:
          min_length = 100
          for result in results:
              found_ent, template = result
              positions_entity_tokens = template[
                  "positions_entity_tokens"
              ]
              positions_type_tokens = template["positions_type_tokens"]
              positions_unuseful_tokens = template[
                  "positions_unuseful_tokens"
              ]
              template_len = template["template_len"]
              template_found = template["template"]
              entities_cand = [
                  found_ent[pos].replace("?", "")
                  for pos in positions_entity_tokens
              ]
              types_cand = [
                  found_ent[pos].replace("?", "").split(",")[0]
                  for pos in positions_type_tokens
              ]
              unuseful_tokens = [
                  found_ent[pos].replace("?", "")
                  for pos in positions_unuseful_tokens
              ]
              entity_lengths = [len(entity) for entity in entities_cand]
              entity_num_tokens = all(
                  [
                      len(entity.split(" ")) < 6
                      for entity in entities_cand
                  ]
              )
              type_lengths = [
                  len(entity_type) for entity_type in types_cand
              ]
              unuseful_tokens_len = sum(
                  [
                      len(unuseful_tok)
                      for unuseful_tok in unuseful_tokens
                  ]
              )
              log.debug(f"found template: {template}, {found_ent}")
              match, entities_cand = self.match_template_and_ner(
                  entities_cand, entities_from_ner, template_found
              )
              if match and (
                  0 not in entity_lengths
                  or 0 not in type_lengths
                  and entity_num_tokens
              ):
                  cur_len = sum(entity_lengths) + sum(type_lengths)
                  log.debug(
                      f"lengths: entity+type {cur_len}, question {question_length}, "
                      f"template {template_len}, unuseful tokens {unuseful_tokens_len}"
                  )
                  if (
                      cur_len < min_length
                      and unuseful_tokens_len + template_len + cur_len
                      == question_length
                  ):
                      entities = entities_cand
                      for old_token, new_token in replace_tokens:
                          entities = [
                              entity.replace(old_token, new_token)
                              for entity in entities
                          ]
                      types = types_cand
                      relations = template["relations"]
                      relation_dirs = template["rel_dirs"]
                      query_type = template["template_type"]
                      entity_types = template.get("entity_types", [])
                      template_answer = template.get(
                          "template_answer", ""
                      )
                      answer_types = template.get("answer_types", [])
                      min_length = cur_len
  
      return (
          entities,
          types,
          relations,
          relation_dirs,
          query_type,
          entity_types,
          template_answer,
          answer_types,
          template_found,
      )
  
file_path: DeepPavlov/deeppavlov/models/kbqa/template_matcher.py
imports: import functools
  import json
  import multiprocessing
  import re
  from logging import getLogger
  from typing import Any, Tuple, List, Union
  from deeppavlov.core.common.registry import register
  from deeppavlov.core.models.serializable import Serializable
label_desc: Use image node_id 4 for calling the TemplateMatcher obj's underlying member method code with example usage: obj.__call__(question, entities_from_ner) and returns: entities,  types,  relations,  relation_dirs,  query_type,  entity_types,  template_answer,  answer_types,  template_found