def evaluate_questions(caption_file, vocab, question_file, params=None):
  """Evaluate QA-based metrics on predicted captions.

  If multiple captions are associated with an image/question pair, the average
  max metric score with the answer set is taken.

  Args:
    caption_file: Path to predicted captions.
    vocab: Instance of text_utils.Vocab.
    question_file: Path to dataset questions.
    params: Dictionary of model parameters.

  Returns:
    results: Dictionary of indicator, exact_match, and F1 scores.
  """
  results = {}

  tf.logging.info("Loading predictions...")

  # 1) Load full captions.
  captions = load_predictions(caption_file, vocab)

  # 2) Generate spans.
  span_file = os.path.splitext(caption_file)[0] + ".question_spans"
  tf.logging.info("Computing spans...")
  reward_utils.write_spans(
      caption_file=caption_file,
      question_file=question_file,
      output_file=span_file,
      vocab=vocab,
      params=params)

  # 3) Load spans from disk.
  tf.logging.info("Loading spans...")
  spans = load_spans(span_file, vocab)
  question_ids = set()
  for qas in spans.values():
    for qid in qas.keys():
      question_ids.add(qid)

  # 4) Compute QA scores.
  tf.logging.info("Loading answers...")
  answers = load_answers(question_ids, question_file, vocab)

  tf.logging.info("Computing QA score...")
  results.update(qa_score(spans, answers))

  tf.logging.info("Computing indicator score...")
  results.update(indicator_score(captions, answers))

  return results
Evaluate QA-based metrics on predicted captions.

  If multiple captions are associated with an image/question pair, the average
  max metric score with the answer set is taken.

  Args:
    caption_file: Path to predicted captions.
    vocab: Instance of text_utils.Vocab.
    question_file: Path to dataset questions.
    params: Dictionary of model parameters.

  Returns:
    results: Dictionary of indicator, exact_match, and F1 scores.
  
language/capwap/utils/metric_utils.py