code: def main(checkpoint_dir):
      config = (
          SACConfig()
          .environment("open_spiel_env")
          .framework("torch")
          .callbacks(partial(AddPolicyCallback, checkpoint_dir))
          .rollouts(
              num_rollout_workers=1,
              num_envs_per_worker=5,
              # We will be restoring a TF2 policy.
              # So tell the RolloutWorkers to enable TF eager exec as well, even if
              # framework is set to torch.
              enable_tf1_exec_eagerly=True,
          )
          .training(model={"fcnet_hiddens": [512, 512]})
          .multi_agent(
              # Initial policy map: Random and PPO. This will be expanded
              # to more policy snapshots taken from "main" against which "main"
              # will then play (instead of "random"). This is done in the
              # custom callback defined above (`SelfPlayCallback`).
              # Note: We will add the "opponent" policy with callback.
              policies={
                  MAIN_POLICY_ID
              },  # Our main policy, we'd like to optimize.
              # Assign agent 0 and 1 randomly to the "main" policy or
              # to the opponent ("random" at first). Make sure (via episode_id)
              # that "main" always plays against "random" (and not against
              # another "main").
              policy_mapping_fn=policy_mapping_fn,
              # Always just train the "main" policy.
              policies_to_train=[MAIN_POLICY_ID],
          )
      )
  
      stop = {
          "training_iteration": args.train_iteration,
      }
  
      # Train the "main" policy to play really well using self-play.
      tuner = tune.Tuner(
          "SAC",
          param_space=config.to_dict(),
          run_config=air.RunConfig(
              stop=stop,
              checkpoint_config=air.CheckpointConfig(
                  checkpoint_at_end=True,
                  checkpoint_frequency=10,
              ),
              verbose=2,
              progress_reporter=CLIReporter(
                  metric_columns={
                      "training_iteration": "iter",
                      "time_total_s": "time_total_s",
                      "timesteps_total": "ts",
                      "episodes_this_iter": "train_episodes",
                      "policy_reward_mean/main": "reward_main",
                  },
                  sort_by_metric=True,
              ),
          ),
      )
      tuner.fit()
  
file_path: ray/python/ray/rllib/examples/connectors/self_play_with_policy_checkpoint.py
imports: import argparse
  from functools import partial
  import os
  import tempfile
  import ray
  from ray import air, tune
  from ray.rllib.algorithms.callbacks import DefaultCallbacks
  from ray.rllib.algorithms.sac import SACConfig
  from ray.rllib.env.utils import try_import_pyspiel
  from ray.rllib.env.wrappers.open_spiel import OpenSpielEnv
  from ray.rllib.examples.connectors.prepare_checkpoint import create_open_spiel_checkpoint
  from ray.rllib.policy.policy import Policy
  from ray.tune import CLIReporter, register_env
label_desc: Use image node_id 2 for calling a global function with example usage: main(checkpoint_dir) without return types