code: def log_artifacts(self, trainer: ITrainer) -> None:
      if not self.is_local_rank_0:
          return None
      batch = next(iter(trainer.validation_loader))
      batch = to_device(batch, trainer.device)
      original = batch[INPUT_KEY]
      model = trainer.model
      if not isinstance(model, GeneratorMixin):
          msg = "`GeneratorCallback` is only compatible with `GeneratorMixin`"
          raise ValueError(msg)
      is_conditional = getattr(model, "is_conditional", False)
      labels = None if not is_conditional else batch[LABEL_KEY]
      image_folder = self._prepare_folder(trainer)
      # original
      save_images(original, os.path.join(image_folder, "original.png"))
      # reconstruct
      if model.can_reconstruct:
          with eval_context(model):
              reconstructed = model.reconstruct(original, labels=labels)
          save_images(
              reconstructed,
              os.path.join(image_folder, "reconstructed.png"),
          )
      # sample
      with eval_context(model):
          sampled = model.sample(len(original))
      save_images(sampled, os.path.join(image_folder, "sampled.png"))
      # interpolation
      with eval_context(model):
          interpolations = model.interpolate(self.num_interpolations)
      save_images(
          interpolations,
          os.path.join(image_folder, "interpolations.png"),
      )
      # conditional sampling
      if getattr(model, "num_classes", None) is None:
          return None
      cond_folder = os.path.join(image_folder, "conditional")
      os.makedirs(cond_folder, exist_ok=True)
      with eval_context(model):
          for i in range(model.num_classes or 0):
              sampled = model.sample(len(original), class_idx=i)
              interpolations = model.interpolate(
                  len(original), class_idx=i
              )
              save_images(
                  sampled, os.path.join(cond_folder, f"sampled_{i}.png")
              )
              path = os.path.join(
                  cond_folder, f"interpolations_{i}.png"
              )
              save_images(interpolations, path)
  
file_path: carefree-learn/cflearn/callbacks/generator.py
imports: import os
  from cftool.cv import save_images
  from cftool.array import to_device
  from .general import ImageCallback
  from ..misc.toolkit import eval_context
  from ..schema import ITrainer
  from ..schema import TrainerCallback
  from ..constants import INPUT_KEY
  from ..constants import LABEL_KEY
  from ..models.schemas.cv import GeneratorMixin
label_desc: Use image node_id 2 for calling the GeneratorCallback obj's underlying member method code with example usage: obj.log_artifacts(trainer) and returns: None, None