class_docstr: This class takes as input entity substrings, defines the template of the query and
  fills the slots of the template with candidate entities and relations.
class_docstr_tok: ["This","class","takes","as","input","entity","substrings",",","defines","the","template","of","the","query","and","fills","the","slots","of","the","template","with","candidate","entities","and","relations","."]
code: def sparql_template_parser(
      self,
      question: str,
      entity_ids: List[List[str]],
      type_ids: List[List[str]],
      answer_types: Set[str],
      rels_from_template: Optional[List[Tuple[str]]] = None,
      rel_dirs_from_template: Optional[List[str]] = None,
  ) -> Union[List[Dict[str, Any]], list]:
      candidate_outputs = []
      if isinstance(self.template_nums, str):
          self.template_nums = [self.template_nums]
      template_log_list = [
          str([elem["query_template"], elem["template_num"]])
          for elem in self.template_queries.values()
          if elem["template_num"] in self.template_nums
      ]
      log.debug(
          f"(find_candidate_answers)self.template_nums: {' --- '.join(template_log_list)}"
      )
      init_templates = []
      for template_num in self.template_nums:
          for num, template in self.template_queries.items():
              if (
                  num == template_num and self.syntax_structure_known
              ) or (
                  template["template_num"] == template_num
                  and not self.syntax_structure_known
              ):
                  init_templates.append(template)
      templates = [
          template
          for template in init_templates
          if (
              not self.syntax_structure_known
              and [len(entity_ids), len(type_ids)]
              == template["entities_and_types_num"]
          )
          or self.syntax_structure_known
      ]
      if not templates:
          templates = [
              template
              for template in init_templates
              if (
                  not self.syntax_structure_known
                  and [len(entity_ids), 0]
                  == template["entities_and_types_num"]
              )
              or self.syntax_structure_known
          ]
      if not templates:
          return candidate_outputs
      if rels_from_template is not None:
          query_template = {}
          for template in templates:
              if template["rel_dirs"] == rel_dirs_from_template:
                  query_template = template
          if query_template:
              candidate_outputs = self.query_parser(
                  question,
                  [query_template],
                  entity_ids,
                  type_ids,
                  answer_types,
                  rels_from_template,
              )
      else:
          candidate_outputs = []
          for priority in range(1, 3):
              pr_templates = [
                  template
                  for template in templates
                  if template["priority"] == priority
              ]
              candidate_outputs = self.query_parser(
                  question,
                  pr_templates,
                  entity_ids,
                  type_ids,
                  answer_types,
                  rels_from_template,
              )
              if candidate_outputs:
                  return candidate_outputs
  
          if not candidate_outputs:
              alt_template_nums = templates[0].get(
                  "alternative_templates", []
              )
              log.debug(
                  f"Using alternative templates {alt_template_nums}"
              )
              alt_templates = [
                  self.template_queries[num]
                  for num in alt_template_nums
              ]
              candidate_outputs = self.query_parser(
                  question,
                  alt_templates,
                  entity_ids,
                  type_ids,
                  answer_types,
                  rels_from_template,
              )
              if candidate_outputs:
                  return candidate_outputs
  
      log.debug(
          "candidate_rels_and_answers:\n"
          + "\n".join([str(output) for output in candidate_outputs[:5]])
      )
      return candidate_outputs
  
imports: import itertools
  import json
  from logging import getLogger
  from typing import Tuple, List, Dict, Optional, Union, Any, Set
  from bs4 import BeautifulSoup
  from whapi import search, get_html
  from deeppavlov.core.commands.utils import expand_path
  from deeppavlov.core.common.file import read_json
  from deeppavlov.core.models.component import Component
  from deeppavlov.core.models.serializable import Serializable
  from deeppavlov.models.entity_extraction.entity_linking import EntityLinker
  from deeppavlov.models.kbqa.rel_ranking_infer import RelRankerInfer
  from deeppavlov.models.kbqa.template_matcher import TemplateMatcher
  from deeppavlov.models.kbqa.utils import preprocess_template_queries
label_desc: Use image node_id 6 for calling the QueryGeneratorBase obj's underlying member method code with example usage: obj.sparql_template_parser(question, entity_ids, type_ids, answer_types, rels_from_template, rel_dirs_from_template) and returns: candidate_outputs, candidate_outputs, candidate_outputs, candidate_outputs