class_docstr: ModelManager manages how to train models.
  
  Each type of models can have their own config type, implemented as
  `config_type()` class method. `__init__()` of the concrete class must take
  this type.
  
  To integrate training algorithms into the standard training workflow, you need:
  1. `build_trainer()`: Builds the ReAgentLightningModule
  2. `get_data_module()`: Defines how to create data module for this algorithm
  3. `build_serving_modules()`: Creates the TorchScript modules for serving
  4. `get_reporter()`: Returns the reporter to collect training/evaluation metrics
  5. `create_policy()`: (Optional) Creates Policy object for to interact with Gym
docstr: Train the model
  
  Returns partially filled RLTrainingOutput.
  The field that should not be filled are:
  - output_path
  
  Arguments:
      train/eval/test_dataset: what you'd expect
      data_module: [pytorch lightning only] a lightning data module that replaces the use of train/eval datasets
      num_epochs: number of training epochs
      reader_options: options for the data reader
      resource_options: options for training resources (currently only used for setting num_nodes in pytorch lightning trainer)
docstr_tok: ["Train","the","model","Returns","partially","filled","RLTrainingOutput",".","The","field","that","should","not","be","filled","are",":","-","output_path","Arguments",":","train\/eval\/test_dataset",":","what","you","'d","expect","data_module",":","[","pytorch","lightning","only","]","a","lightning","data","module","that","replaces","the","use","of","train\/eval","datasets","num_epochs",":","number","of","training","epochs","reader_options",":","options","for","the","data","reader","resource_options",":","options","for","training","resources","(","currently","only","used","for","setting","num_nodes","in","pytorch","lightning","trainer",")"]
code: def train(
      self,
      trainer_module: ReAgentLightningModule,
      train_dataset: Optional[Dataset],
      eval_dataset: Optional[Dataset],
      test_dataset: Optional[Dataset],
      data_module: Optional[ReAgentDataModule],
      num_epochs: int,
      reader_options: ReaderOptions,
      resource_options: ResourceOptions,
      checkpoint_path: Optional[str] = None,
  ) -> Tuple[RLTrainingOutput, pl.Trainer]:
      """
      Train the model
  
      Returns partially filled RLTrainingOutput.
      The field that should not be filled are:
      - output_path
  
      Arguments:
          train/eval/test_dataset: what you'd expect
          data_module: [pytorch lightning only] a lightning data module that replaces the use of train/eval datasets
          num_epochs: number of training epochs
          reader_options: options for the data reader
          resource_options: options for training resources (currently only used for setting num_nodes in pytorch lightning trainer)
      """
      if isinstance(trainer_module, MultiStageTrainer):
          assert (
              trainer_module.multi_stage_total_epochs == num_epochs
          ), (
              f"The sum of each stage's epoch ({trainer_module.trainer_epoch_mapping})"
              f" should be equal to num_epochs ({num_epochs})."
          )
  
      reporter = self.get_reporter()
      trainer_module.set_reporter(reporter)
      assert data_module is not None
  
      lightning_trainer = train_eval_lightning(
          train_dataset=train_dataset,
          eval_dataset=eval_dataset,
          test_dataset=test_dataset,
          trainer_module=trainer_module,
          data_module=data_module,
          num_epochs=num_epochs,
          logger_name=str(type(self)),
          reader_options=reader_options,
          checkpoint_path=checkpoint_path,
          resource_options=resource_options,
      )
  
      rank = get_rank()
      if rank == 0:
          trainer_logger = lightning_trainer.logger
          # pyre-fixme[16]: `Optional` has no attribute `line_plot_aggregated`.
          logger_data = trainer_logger.line_plot_aggregated
          # pyre-fixme[16]: `Optional` has no attribute `clear_local_data`.
          trainer_logger.clear_local_data()
          if reporter is None:
              training_report = None
          else:
              # pyre-ignore
              training_report = RLTrainingReport.make_union_instance(
                  reporter.generate_training_report()
              )
          return (
              RLTrainingOutput(
                  training_report=training_report,
                  logger_data=logger_data,
              ),
              lightning_trainer,
          )
      # Output from processes with non-0 rank is not used
      return RLTrainingOutput(), lightning_trainer
  
imports: import abc
  import logging
  from typing import Dict, List, Optional, Tuple
  import pytorch_lightning
  import torch
  from reagent.core.dataclasses import dataclass
  from reagent.core.parameters import NormalizationData
  from reagent.data.reagent_data_module import ReAgentDataModule
  from reagent.reporting.reporter_base import ReporterBase
  from reagent.training import MultiStageTrainer, ReAgentLightningModule
  from reagent.workflow.types import Dataset, ReaderOptions, ResourceOptions, RewardOptions, RLTrainingOutput, RLTrainingReport, TableSpec
  from reagent.workflow.utils import get_rank, train_eval_lightning
label_desc: Use image node_id 5 for calling the ModelManager obj's underlying member method code with example usage: obj.train(trainer_module, train_dataset, eval_dataset, test_dataset, data_module, num_epochs, reader_options, resource_options, checkpoint_path) and returns: RLTrainingOutput,  lightning_trainer, RLTrainingOutput,  lightning_trainer