class_docstr: Given a large set of sentences, this evaluator performs paraphrase (duplicate) mining and
  identifies the pairs with the highest similarity. It compare the extracted paraphrase pairs
  with a set of gold labels and computes the F1 score.
code: def __call__(
      self,
      model,
      output_path: str = None,
      epoch: int = -1,
      steps: int = -1,
  ) -> float:
      if epoch != -1:
          out_txt = (
              f" after epoch {epoch}:"
              if steps == -1
              else f" in epoch {epoch} after {steps} steps:"
          )
      else:
          out_txt = ":"
  
      logger.info(
          "Paraphrase Mining Evaluation on "
          + self.name
          + " dataset"
          + out_txt
      )
  
      # Compute embedding for the sentences
      pairs_list = paraphrase_mining(
          model,
          self.sentences,
          self.show_progress_bar,
          self.batch_size,
          self.query_chunk_size,
          self.corpus_chunk_size,
          self.max_pairs,
          self.top_k,
      )
  
      logger.info("Number of candidate pairs: " + str(len(pairs_list)))
  
      # Compute F1 score and Average Precision
      n_extract = n_correct = 0
      threshold = 0
      best_f1 = best_recall = best_precision = 0
  
      average_precision = 0
  
      for idx in range(len(pairs_list)):
          score, i, j = pairs_list[idx]
          id1 = self.ids[i]
          id2 = self.ids[j]
  
          # Compute optimal threshold and F1-score
          n_extract += 1
          if self.duplicates[id1][id2] or self.duplicates[id2][id1]:
              n_correct += 1
              precision = n_correct / n_extract
              recall = n_correct / self.total_num_duplicates
              f1 = 2 * precision * recall / (precision + recall)
              average_precision += precision
              if f1 > best_f1:
                  best_f1 = f1
                  best_precision = precision
                  best_recall = recall
                  threshold = (
                      pairs_list[idx][0]
                      + pairs_list[min(idx + 1, len(pairs_list) - 1)][0]
                  ) / 2
  
      average_precision = average_precision / self.total_num_duplicates
  
      logger.info(
          "Average Precision: {:.2f}".format(average_precision * 100)
      )
      logger.info("Optimal threshold: {:.4f}".format(threshold))
      logger.info("Precision: {:.2f}".format(best_precision * 100))
      logger.info("Recall: {:.2f}".format(best_recall * 100))
      logger.info("F1: {:.2f}\n".format(best_f1 * 100))
  
      if output_path is not None and self.write_csv:
          csv_path = os.path.join(output_path, self.csv_file)
          if not os.path.isfile(csv_path):
              with open(
                  csv_path, newline="", mode="w", encoding="utf-8"
              ) as f:
                  writer = csv.writer(f)
                  writer.writerow(self.csv_headers)
                  writer.writerow(
                      [
                          epoch,
                          steps,
                          best_precision,
                          best_recall,
                          best_f1,
                          threshold,
                          average_precision,
                      ]
                  )
          else:
              with open(
                  csv_path, newline="", mode="a", encoding="utf-8"
              ) as f:
                  writer = csv.writer(f)
                  writer.writerow(
                      [
                          epoch,
                          steps,
                          best_precision,
                          best_recall,
                          best_f1,
                          threshold,
                          average_precision,
                      ]
                  )
  
      return average_precision
  
file_path: sentence-transformers/sentence_transformers/evaluation/ParaphraseMiningEvaluator.py
imports: from .None import SentenceEvaluator
  import logging
  from sentence_transformers.util import paraphrase_mining
  import os
  import csv
  from typing import List, Tuple, Dict
  from collections import defaultdict
label_desc: Use image node_id 2 for calling the ParaphraseMiningEvaluator obj's underlying member method code with example usage: obj.__call__(model, output_path, epoch, steps) and returns: average_precision