code: def solution_annotation_pass(
      gm: torch.fx.GraphModule,
      solution: List[int],
      strategies_constructor: StrategiesConstructor,
  ):
      """
      This method is used to stick the solution strategy to the nodes and add the information
      required in runtime into graph as placeholder nodes.
      """
      mod_graph = gm.graph
  
      nodes = [
          strategies_vector.node
          for strategies_vector in strategies_constructor.leaf_strategies
      ]
      no_strategy_nodes = strategies_constructor.no_strategy_nodes
  
      # the dict to get origin sharding spec of node
      origin_node_sharding_spec_dict = {}
      for node_index, (node, strategy_index) in enumerate(
          zip(nodes, solution)
      ):
          strategies_vector = node.strategies_vector
          # stick the solution strategy to the corresponding node
          setattr(
              node, "best_strategy", strategies_vector[strategy_index]
          )
          setattr(
              node,
              "sharding_spec",
              strategies_vector[
                  strategy_index
              ].get_sharding_spec_by_name(str(node)),
          )
          origin_node_sharding_spec_dict[
              node_index
          ] = strategies_vector[
              strategy_index
          ].get_sharding_spec_by_name(
              str(node)
          )
  
          # attach the corresponding metainfo if node has the attribute `strategies_info`
          if hasattr(node, "strategies_info"):
              setattr(
                  node,
                  "best_strategy_info",
                  node.strategies_info[strategy_index],
              )
  
      # the dict to get input sharding specs of user node
      sharding_spec_convert_dict = {}
      # the dict to record comm actions of nodes
      comm_actions_dict = {}
      for index, node in enumerate(nodes):
          target_sharding_specs = []
          for user_node in node.strategies_vector.successor_nodes:
              if user_node in no_strategy_nodes:
                  target_sharding_spec = (
                      node.best_strategy.get_sharding_spec_by_name(
                          str(node.name)
                      )
                  )
              else:
                  target_sharding_spec = (
                      user_node.best_strategy.get_sharding_spec_by_name(
                          str(node.name)
                      )
                  )
              target_sharding_specs.append(target_sharding_spec)
          sharding_spec_convert_dict[index] = target_sharding_specs
          setattr(node, "target_sharding_specs", target_sharding_specs)
  
          # the get_attr node strategy is kind of pending strategy, which means we will change it
          # to the same strategy of the user node.
          if node.op == "get_attr":
              assert (
                  len(target_sharding_specs) == 1
              ), f"sharing weight is not supported in current version."
              target_node = node.strategies_vector.successor_nodes[0]
              node_name = str(node)
              if (
                  target_node.op == "call_function"
                  and target_node.target in RESHAPE_FUNC_OP
              ):
                  node_name = str(target_node)
                  target_node = (
                      target_node.strategies_vector.successor_nodes[0]
                  )
              user_strategy = target_node.best_strategy
              op_data_in_user = user_strategy.get_op_data_by_name(
                  node_name
              )
              origin_pending_strategy = node.best_strategy
              origin_op_data = (
                  origin_pending_strategy.get_op_data_by_name(str(node))
              )
  
              new_communication_actions = {}
              if op_data_in_user in user_strategy.communication_actions:
                  new_communication_action = (
                      user_strategy.communication_actions.pop(
                          op_data_in_user
                      )
                  )
                  new_communication_action.arg_index = 0
                  new_communication_actions[
                      origin_op_data
                  ] = new_communication_action
              node.best_strategy.communication_actions = (
                  new_communication_actions
              )
  
          comm_action_dict = {}
          for (
              op_data,
              comm_action,
          ) in node.best_strategy.communication_actions.items():
              comm_action_dict[op_data.name] = comm_action
          comm_actions_dict[index] = comm_action_dict
  
      # add above dicts into graph
      for node in nodes:
          if node.op != "placeholder":
              with mod_graph.inserting_before(node):
                  input_specs_node = mod_graph.create_node(
                      "placeholder", target="sharding_spec_convert_dict"
                  )
                  origin_specs_node = mod_graph.create_node(
                      "placeholder",
                      target="origin_node_sharding_spec_dict",
                  )
                  comm_actions_dict_node = mod_graph.create_node(
                      "placeholder", target="comm_actions_dict"
                  )
              break
      return (
          gm,
          sharding_spec_convert_dict,
          origin_node_sharding_spec_dict,
          comm_actions_dict,
      )
  
file_path: ColossalAI/colossalai/auto_parallel/passes/runtime_preparation_pass.py
imports: import operator
  from typing import Dict, List, Union
  import torch
  from torch.fx.node import Node
  from colossalai._analyzer.fx.node_util import MetaInfo
  from colossalai.auto_parallel.tensor_shard.constants import RESHAPE_FUNC_OP
  from colossalai.auto_parallel.tensor_shard.sharding_strategy import CommType, OperationDataType
  from colossalai.auto_parallel.tensor_shard.solver.strategies_constructor import StrategiesConstructor
  from colossalai.device.device_mesh import DeviceMesh
  from colossalai.tensor.comm_spec import _all_reduce
  from colossalai.tensor.shape_consistency import ShapeConsistencyManager
  from colossalai.tensor.sharding_spec import ShardingSpec
  from .constants import SHAPE_ARGUMENT_OPS
label_desc: Use image node_id 2 for calling a global function with example usage: solution_annotation_pass(gm, solution, strategies_constructor) and returns: gm,  sharding_spec_convert_dict,  origin_node_sharding_spec_dict,  comm_actions_dict