class_docstr: 用于评测模型性能好坏的评测器；
  
  .. note::
  
      ``Evaluator`` 与 ``Trainer`` 类似，都是使用 ``Driver`` 作为底层来实现评测或者训练，因此大多数与 ``Trainer`` 同名的参数的意义和使用都与
      ``Trainer`` 中的参数相同，对于这些参数，您可以参考 ``Trainer`` 的文档来获取更详细的信息；详见 :class:`~fastNLP.core.controllers.trainer.Trainer`；
  
  :param model: 训练所需要的模型，例如 ``torch.nn.Module``，等价于 ``Trainer`` 中的 ``model`` 参数；
  :param dataloaders: 用于评测的数据集。如果为多个，您需要使用 ``dict`` 传入，即对每一个数据集标上用于标识它们的标签；也可以使用 evaluate_dataloaders
      作为参数的名称。
  :param metrics: 评测时使用的指标。注意该参数必须为 ``dict`` 类型，其中 ``key`` 为一个 ``metric`` 的名称，``value`` 为具体的 ``Metric`` 对象。目前支持以下 metrics：
  
      1. fastNLP 自己的 ``metric``：详见 :class:`~fastNLP.core.metrics.Metric`；
      2. torchmetrics；
      3. allennlp.training.metrics；
      4. paddle.metric；
  
  :param driver: 等价于 ``Trainer`` 中的 ``driver`` 参数；
  
      .. note::
  
          如果在您的脚本中在初始化 ``Evaluator`` 前也初始化了 ``Trainer`` 进行训练，那么强烈建议您直接将 ``trainer.driver`` 传入 ``Evaluator`` 当做该参数的值；
  
          .. code-block::
  
              # 初始化 Trainer
              trainer = Trainer(
                  ...
                  driver='torch',
                  device=[0,1]
              )
              trainer.run()
  
              # 此时再初始化 Evaluator 时应当直接使用 trainer.driver；
              evaluator = Evaluator(
                  ...
                  driver=trainer.driver
              )
  
  :param device: 等价于 ``Trainer`` 中的 ``device`` 参数；
  :param evaluate_batch_step_fn: 您可以传入该参数来定制每次评测一个 batch 的数据时所执行的函数。该函数应接受的两个参数为 ``evaluator`` 和 ``batch``，
      不需要有返回值；可以参考 :meth:`~fastNLP.core.controllers.loops.evaluate_batch_loop.EvaluateBatchLoop.batch_step_fn`；
  :param evaluate_fn: 用来控制 ``Evaluator`` 在评测的前向传播过程中调用的是哪一个函数，例如对于 pytorch 而言，通过该参数确定使用的是 :meth:`model.evaluate_step` 还是
      :meth:`model.forward` （不同训练框架所使用的的前向传播函数的方法名称不同）；
  
      1. 如果该值是 ``None``，那么我们会默认使用 ``evaluate_step`` 当做前向传播的函数，如果在模型中没有找到该方法，则使用训练框架默认的前向传播函数；
      2. 如果为 ``str`` 类型，例如为 ``'my_evaluate_step_fn'``，则尝试寻找 :meth:`model.my_evaluate_step_fn`，如果找不到则直接报错；
  
  :param input_mapping: 等价于 ``Trainer`` 中的 ``input_mapping`` 参数；对具体的用于评测一个 batch 的数据使用 ``input_mapping`` 处理之后再输入到 ``model`` 以及 ``metric`` 中。如果针对
      ``model`` 和 ``metric`` 需要不同的 ``mapping``，请考虑使用 ``evaluate_batch_step_fn`` 参数定制；也可以使用 evaluate_input_mapping 参数名传入。
  
      .. todo::
  
          之后链接上 参数匹配 的文档；
  
  :param output_mapping: 等价于 ``Trainer`` 中的 ``output_mapping`` 参数；对 ``model`` 输出的内容，将通过 ``output_mapping`` 处理之后再输入到 ``metric`` 中；
      也可以使用 evaluate_output_mapping 参数名传入。
  :param model_wo_auto_param_call: 等价于 ``Trainer`` 中的 ``model_wo_auto_param_call`` 参数；
  
      .. note::
  
          一个十分需要注意的问题在于 ``model_wo_auto_param_call`` 只会关闭部分的参数匹配，即指挥关闭前向传播时的参数匹配，但是由于 ``Evaluator`` 中
          ``metric`` 的计算都是自动化的，因此其一定需要参数匹配：根据 ``metric.update`` 的函数签名直接从字典数据中抽取其需要的参数传入进去；
  
  
  :param fp16: 是否在评测时使用 fp16 混合精度；
  :param verbose: 是否打印 evaluate 的结果；
  :kwargs:
      * *torch_kwargs* -- 等价于 ``Trainer`` 中的 ``torch_kwargs`` 参数；
      * *paddle_kwargs* -- 等价于 ``Trainer`` 中的 ``paddle_kwargs`` 参数；
      * *fairscale_kwargs* -- 等价于 ``Trainer`` 中的 ``fairscale_kwargs`` 参数；
      * *deepspeed_kwargs* -- 等价于 ``Trainer`` 中的 ``deepspeed_kwargs`` 参数；
      * *oneflow_kwargs* -- 等价于 ``Trainer`` 中的 ``oneflow_kwargs`` 参数；
      * *data_device* -- 等价于 ``Trainer`` 中的 ``data_device`` 参数；
      * *model_use_eval_mode* (``bool``) --
        是否在评测的时候将 ``model`` 的状态设置成 ``eval`` 状态。在 ``eval`` 状态下，``model`` 的
        ``dropout`` 与 ``batch normalization`` 将会关闭。默认为 ``True``。如果为 ``False``，``fastNLP`` 不会对 ``model`` 的 ``evaluate`` 状态做任何设置。无论
        该值是什么，``fastNLP`` 都会在评测后将 ``model`` 的状态设置为 ``train``；
      * *use_dist_sampler* --
        表示在 ``Evaluator`` 中在使用分布式的时候是否将保证 dataloader 的 ``sampler`` 替换为
        分布式的 ``sampler``，其特点是每个卡上的数据之间不重叠，所有卡上数据的加起来是整个数据集。若传入的 dataloader
        的 sampler 为：
        
          - 深度学习框架自带的默认 sampler ;
          - fastNLP 的 Sampler ；
        则将替换为 :class:`~fastNLP.UnrepeatedSequentialSampler`，如果这个行为不是期待的，请本参数设置为 ``False``，并针对每个卡控制其可以
        用到的数据。如果不是以上两类 sampler ，fastNLP 将报错。
      * *output_from_new_proc* -- 等价于 ``Trainer`` 中的 ``output_from_new_proc`` 参数；
      * *progress_bar* -- 等价于 ``Trainer`` 中的 ``progress_bar`` 参数；
      * *check_dataloader_legality* -- 是否检查 ``DataLoader`` 是否合法，默认为 ``True`` 。
docstr: 该函数是在 ``Evaluator`` 初始化后用于真正开始评测的函数；
  
  返回一个字典类型的数据，其中 key 为 metric 的名字，value 为对应 metric 的结果。
  
      1. 如果存在多个 metric ，一个 dataloader 的情况，key 的命名规则是
         ``metric_indicator_name#metric_name``；
      2. 如果存在多个数据集，一个metric的情况，key的命名规则是
         ``metric_indicator_name#metric_name#dataloader_name`` （其中 **#** 是默认的 separator ，可以通过 Evaluator 初始化参数修改）；
      3. 如果存在多个metric，多个dataloader的情况，key的命名规则是
         ``metric_indicator_name#metric_name#dataloader_name``，其中 metric_indicator_name 可能不存在；
  
  :param num_eval_batch_per_dl: 每个 dataloader 测试前多少个 batch 的数据，-1 为测试所有数据。
  :return: 评测得到的结果，是一个没有嵌套的字典；
code: def run(self, num_eval_batch_per_dl: int = -1) -> Dict:
      """
      该函数是在 ``Evaluator`` 初始化后用于真正开始评测的函数；
  
      返回一个字典类型的数据，其中 key 为 metric 的名字，value 为对应 metric 的结果。
  
          1. 如果存在多个 metric ，一个 dataloader 的情况，key 的命名规则是
             ``metric_indicator_name#metric_name``；
          2. 如果存在多个数据集，一个metric的情况，key的命名规则是
             ``metric_indicator_name#metric_name#dataloader_name`` （其中 **#** 是默认的 separator ，可以通过 Evaluator 初始化参数修改）；
          3. 如果存在多个metric，多个dataloader的情况，key的命名规则是
             ``metric_indicator_name#metric_name#dataloader_name``，其中 metric_indicator_name 可能不存在；
  
      :param num_eval_batch_per_dl: 每个 dataloader 测试前多少个 batch 的数据，-1 为测试所有数据。
      :return: 评测得到的结果，是一个没有嵌套的字典；
      """
      assert isinstance(
          num_eval_batch_per_dl, int
      ), "num_eval_batch_per_dl must be of int type."
      assert (
          num_eval_batch_per_dl > 0 or num_eval_batch_per_dl == -1
      ), "num_eval_batch_per_dl must be -1 or larger than 0."
  
      metric_results = {}
      self.reset()
      evaluate_context = self.driver.get_evaluate_context()
      self.driver.set_model_mode(
          mode="eval" if self.model_use_eval_mode else "train"
      )
      with evaluate_context():
          try:
              for (
                  dataloader_name,
                  dataloader,
              ) in self.dataloaders.items():
                  self.driver.barrier()
                  if num_eval_batch_per_dl != -1:
                      dataloader = _TruncatedDataLoader(
                          dataloader, num_eval_batch_per_dl
                      )
                  self.driver.set_sampler_epoch(dataloader, -1)
                  self.start_progress_bar(
                      total=len(dataloader),
                      dataloader_name=dataloader_name,
                  )
                  self.cur_dataloader_name = dataloader_name
                  results = self.evaluate_batch_loop.run(
                      self, dataloader
                  )
                  self.remove_progress_bar(dataloader_name)
                  metric_results[dataloader_name] = results
                  self.reset()
                  self.driver.barrier()
          except BaseException as e:
              self.driver.on_exception()
              raise e
          finally:
              self.finally_progress_bar()
      metric_results = flat_nest_dict(
          metric_results,
          separator=self.separator,
          compress_none_key=True,
          top_down=False,
      )
      if len(metric_results) > 0:  # 如果 metric 不为 None 需要 print 。
          # metric_results = flat_nest_dict(metric_results, separator=self.separator, compress_none_key=True, top_down=False)
          if self.verbose:
              if self.progress_bar == "rich":
                  f_rich_progress.print(metric_results)
              else:
                  logger.info(metric_results)
      self.driver.set_model_mode(mode="train")
  
      return metric_results
  
imports: from typing import Union, List, Optional, Dict, Callable, BinaryIO
  import os
  from pathlib import Path
  import io
  from dataclasses import is_dataclass
  from fastNLP.core.drivers import Driver, TorchDriver
  from ..drivers.choose_driver import choose_driver
  from .loops import Loop, EvaluateBatchLoop
  from fastNLP.core.utils import auto_param_call, dataclass_to_dict, match_and_substitute_params, f_rich_progress, flat_nest_dict, f_tqdm_progress
  from fastNLP.core.metrics import Metric
  from fastNLP.core.metrics.utils import _is_torchmetrics_metric, _is_paddle_metric, _is_allennlp_metric
  from fastNLP.core.controllers.utils.utils import _TruncatedDataLoader
  from fastNLP.core.utils.utils import _check_valid_parameters_number
  from fastNLP.core.log import logger
  from fastNLP.envs import FASTNLP_MODEL_FILENAME
label_desc: Use image node_id 3 for calling the Evaluator obj's underlying member method code with example usage: obj.run(num_eval_batch_per_dl) and returns: metric_results