class_docstr: Callback for evaluating an agent.
  
  :param eval_env: (Union[gym.Env, VecEnv]) The environment used for initialization
  :param callback_on_new_best: (Optional[BaseCallback]) Callback to trigger
      when there is a new best model according to the `mean_reward`
  :param n_eval_episodes: (int) The number of episodes to test the agent
  :param eval_freq: (int) Evaluate the agent every eval_freq call of the callback.
  :param log_path: (str) Path to a folder where the evaluations (`evaluations.npz`)
      will be saved. It will be updated at each evaluation.
  :param best_model_save_path: (str) Path to a folder where the best model
      according to performance on the eval env will be saved.
  :param deterministic: (bool) Whether the evaluation should
      use a stochastic or deterministic actions.
  :param render: (bool) Whether to render or not the environment during evaluation
  :param verbose: (int)
class_docstr_tok: ["Callback","for","evaluating","an","agent",".",":","param","eval_env",":","(","Union","[","gym.Env",",","VecEnv","]",")","The","environment","used","for","initialization",":","param","callback_on_new_best",":","(","Optional","[","BaseCallback","]",")","Callback","to","trigger","when","there","is","a","new","best","model","according","to","the","`","mean_reward","`",":","param","n_eval_episodes",":","(","int",")","The","number","of","episodes","to","test","the","agent",":","param","eval_freq",":","(","int",")","Evaluate","the","agent","every","eval_freq","call","of","the","callback",".",":","param","log_path",":","(","str",")","Path","to","a","folder","where","the","evaluations","(","`","evaluations.npz","`",")","will","be","saved",".","It","will","be","updated","at","each","evaluation",".",":","param","best_model_save_path",":","(","str",")","Path","to","a","folder","where","the","best","model","according","to","performance","on","the","eval","env","will","be","saved",".",":","param","deterministic",":","(","bool",")","Whether","the","evaluation","should","use","a","stochastic","or","deterministic","actions",".",":","param","render",":","(","bool",")","Whether","to","render","or","not","the","environment","during","evaluation",":","param","verbose",":","(","int",")"]
code: def _on_step(self) -> bool:
      if self.eval_freq > 0 and self.n_calls % self.eval_freq == 0:
          # Sync training and eval env if there is VecNormalize
          sync_envs_normalization(self.training_env, self.eval_env)
  
          episode_rewards, episode_lengths = evaluate_policy(
              self.model,
              self.eval_env,
              n_eval_episodes=self.n_eval_episodes,
              render=self.render,
              deterministic=self.deterministic,
              return_episode_rewards=True,
          )
  
          if self.log_path is not None:
              self.evaluations_timesteps.append(self.num_timesteps)
              self.evaluations_results.append(episode_rewards)
              self.evaluations_length.append(episode_lengths)
              np.savez(
                  self.log_path,
                  timesteps=self.evaluations_timesteps,
                  results=self.evaluations_results,
                  ep_lengths=self.evaluations_length,
              )
  
          mean_reward, std_reward = np.mean(episode_rewards), np.std(
              episode_rewards
          )
          mean_ep_length, std_ep_length = np.mean(
              episode_lengths
          ), np.std(episode_lengths)
          # Keep track of the last evaluation, useful for classes that derive from this callback
          self.last_mean_reward = mean_reward
  
          if self.verbose > 0:
              print(
                  "Eval num_timesteps={}, "
                  "episode_reward={:.2f} +/- {:.2f}".format(
                      self.num_timesteps, mean_reward, std_reward
                  )
              )
              print(
                  "Episode length: {:.2f} +/- {:.2f}".format(
                      mean_ep_length, std_ep_length
                  )
              )
  
          if mean_reward > self.best_mean_reward:
              if self.verbose > 0:
                  print("New best mean reward!")
              if self.best_model_save_path is not None:
                  self.model.save(
                      os.path.join(
                          self.best_model_save_path, "best_model"
                      )
                  )
              self.best_mean_reward = mean_reward
              # Trigger callback if needed
              if self.callback is not None:
                  return self._on_event()
  
      return True
  
imports: import os
  from abc import ABC
  import warnings
  import typing
  from typing import Union, List, Dict, Any, Optional
  import gym
  import numpy
  from stable_baselines.common.vec_env import VecEnv, sync_envs_normalization, DummyVecEnv
  from stable_baselines.common.evaluation import evaluate_policy
  from stable_baselines import logger
label_desc: Use image node_id 3 for calling the EvalCallback obj's underlying member method code with example usage: obj._on_step() and returns: True, self