code: def _construct_chain(
      cls, graph: Graph, node_list: List[List[Node]]
  ) -> Chain:
      input_tensors = cls._extract_input(graph)
      ftime, btime, ftmp, btmp = list(), list(), list(), list()
      xbar, x = [activation_size(input_tensors)], [
          activation_size(input_tensors)
      ]
  
      for node in node_list:
          node_info = cls._extract_node_info(node)
          ftime.append(node_info[0])
          btime.append(node_info[1])
          x.append(node_info[2])
          xbar.append(node_info[3])
          ftmp.append(node_info[4])
          btmp.append(node_info[5])
  
      # currently we view loss backward temp as zero
      btime.append(0)
      btmp.append(0)
  
      return Chain(ftime, btime, x, xbar, ftmp, btmp)
  
imports: from copy import deepcopy
  from typing import Any, List, Tuple
  from torch import Tensor
  from torch.fx import Graph, Node
  from colossalai.auto_parallel.passes.runtime_apply_pass import runtime_apply, runtime_comm_spec_apply
  from colossalai.fx.codegen.activation_checkpoint_codegen import _find_nested_ckpt_regions
  from colossalai.fx.profiler import activation_size, calculate_bwd_time, calculate_fwd_out, calculate_fwd_time, calculate_fwd_tmp
  from colossalai.logging import get_dist_logger
  from .ckpt_solver_base import CheckpointSolverBase
  from .operation import Backward, Chain, ForwardCheck, ForwardEnable, ForwardNograd, Loss, Sequence
label_desc: Use image node_id 5 for calling the CheckpointSolverRotor obj's underlying member method code with example usage: obj._construct_chain(cls, graph, node_list) and returns: Chain