def create_queries(out_dir, all_facts, templates, qid_names, qid_numfacts,
                   min_year, max_year, train_frac, val_frac,
                   max_subject_per_relation):
  """Construct queries for most popular subjects for each relation.

  Args:
    out_dir: Path to store all queries as well as yearly slices.
    all_facts: a list of facts.
    templates: a dict mapping relation IDs to templates.
    qid_names: dict mapping wikidata QIDs to canonical names.
    qid_numfacts: dict mapping wikidata QIDs to number of facts.
    min_year: an int, starting year to map.
    max_year: an int, ending year to map.
    train_frac: a float, fraction of subjects to reserve for the train set.
    val_frac: a float, fraction of subjects to reserve for the val set.
    max_subject_per_relation: number of subjects to keep per relation.
  """

  def _create_entity_obj(qid):
    return {"wikidata_id": qid, "name": qid_names[qid]}

  def _create_implicit_query(subj, tmpl):
    return tmpl.replace("<subject>", qid_names[subj]).replace("<object>", Y_TOK)

  def _most_frequent_answer(year2obj):
    counts = collections.defaultdict(int)
    for _, obj in year2obj.items():
      counts[obj] += 1
    return max(counts.items(), key=lambda x: x[1])[0]

  def _most_recent_answer(yr2obj):
    recent = max(yr2obj.keys())
    return yr2obj[recent]

  # Group by relation and by sort by subject
  logging.info("Keeping only facts with templates.")
  rel2subj = {}
  for fact in tqdm(all_facts):
    if fact[0] not in templates:
      continue
    if fact[0] not in rel2subj:
      rel2subj[fact[0]] = {}
    if fact[1] not in rel2subj[fact[0]]:
      rel2subj[fact[0]][fact[1]] = []
    rel2subj[fact[0]][fact[1]].append(fact)

  logging.info("Sorting subjects by 'popularity' resolving multiple objects.")
  sorted_rel2subj = {}
  for relation in rel2subj:
    sorted_subjs = sorted(
        rel2subj[relation].keys(),
        key=lambda x: qid_numfacts.get(x, 0),
        reverse=True)
    sorted_rel2subj[relation] = [
        (s, resolve_objects(rel2subj[relation][s])) for s in sorted_subjs
    ]

  logging.info("Keep only subjects with multiple objects.")
  total_facts = 0
  filt_rel2subj = {}
  for rel, subj2facts in sorted_rel2subj.items():
    filt_subj2facts = list(filter(lambda x: len(x[1]) > 1, subj2facts))
    if filt_subj2facts:
      filt_rel2subj[rel] = filt_subj2facts
      total_facts += sum([len(f) for _, f in filt_rel2subj[rel]])
  logging.info("# facts after filtering = %d", total_facts)

  logging.info("Keep only %d subjects per relation, split into train/val/test",
               max_subject_per_relation)
  train_queries, val_queries, test_queries = [], [], []
  tot_queries, tot_subj = 0, 0
  for relation, subj2facts in filt_rel2subj.items():
    num_subj = 0
    for subj, facts in subj2facts:
      year2obj = _map_years_to_objects(facts, qid_numfacts, min_year, max_year)
      p = random.random()  # to decide which split this subject belongs to.
      for yr, obj in year2obj.items():
        query = {
            "query":
                _create_implicit_query(subj, templates[relation]),
            "answer":
                _create_entity_obj(obj),
            "date":
                str(yr),
            "id":
                subj + "_" + relation + "_" + str(yr),
            "most_frequent_answer":
                _create_entity_obj(_most_frequent_answer(year2obj)),
            "most_recent_answer":
                _create_entity_obj(_most_recent_answer(year2obj)),
            "relation":
                relation,
        }
        if p < train_frac:
          train_queries.append(query)
        elif p < train_frac + val_frac:
          val_queries.append(query)
        else:
          test_queries.append(query)
        tot_queries += 1
      num_subj += 1
      if num_subj == max_subject_per_relation:
        break
    logging.info("%s: # subjects = %d # train = %d # val = %d # test = %d",
                 relation, len(subj2facts), len(train_queries),
                 len(val_queries), len(test_queries))
    tot_subj += num_subj

  # Save all queries as a json.
  split2qrys = {
      "train": train_queries,
      "val": val_queries,
      "test": test_queries
  }
  tf.io.gfile.makedirs(out_dir)
  logging.info("Saving all queries to %s", out_dir)
  for split in ["train", "val", "test"]:
    with tf.io.gfile.GFile(os.path.join(out_dir, f"{split}.jsonl"), "w") as f:
      for qry in split2qrys[split]:
        f.write(json.dumps(qry) + "\n")

  # Make subdirectories and store each split.
  for year in range(min_year, max_year + 1):
    subd = os.path.join(out_dir, "yearly", str(year))
    tf.io.gfile.makedirs(subd)
    logging.info("Saving queries for %d to %s", year, subd)
    counts = collections.defaultdict(int)
    for split in ["train", "val", "test"]:
      with tf.io.TFRecordWriter(os.path.join(subd, f"{split}.tf_record")) as f:
        for qry in split2qrys[split]:
          if qry["date"] == str(year):
            f.write(_build_example(qry).SerializeToString())
            counts[split] += 1
Construct queries for most popular subjects for each relation.

  Args:
    out_dir: Path to store all queries as well as yearly slices.
    all_facts: a list of facts.
    templates: a dict mapping relation IDs to templates.
    qid_names: dict mapping wikidata QIDs to canonical names.
    qid_numfacts: dict mapping wikidata QIDs to number of facts.
    min_year: an int, starting year to map.
    max_year: an int, ending year to map.
    train_frac: a float, fraction of subjects to reserve for the train set.
    val_frac: a float, fraction of subjects to reserve for the val set.
    max_subject_per_relation: number of subjects to keep per relation.
  
language/templama/templama.py