Files
ComfyAssets-ComfyUI-KikoTools/kikotools/tools/checkpoint_folder_iterator/node.py
T
Vito Sansevero c5e00c130b feat(xyz_helpers): add Checkpoint Folder Iterator and Model Compare Sheet
- Checkpoint Folder Iterator loads one checkpoint per queued run from a
  folder (relative to models/checkpoints or absolute), so a whole folder
  can be swept with only one model in memory at a time
- Model Compare Sheet saves each run's image as a tile under
  output/model_compare/<run_name>/ and rebuilds a labeled contact sheet
  from disk every run, so the grid survives between independent prompts
- Starting a sweep at index 0 archives stale tiles to a timestamped folder
- Running past the last checkpoint raises a clear error instead of
  wrapping, so an over-queued batch never restarts and archives a
  finished sweep
- Checkpoints load from the scanned absolute path, so folders outside the
  configured roots work as the tooltip promises
- Extract the LoRA Folder Batch folder-scanning, natural-sort and regex
  filter helpers into kikotools/base/model_folders.py so both tools share
  one implementation
2026-10-16 08:08:00 -07:00

81 lines
2.8 KiB
Python

"""Checkpoint Folder Iterator node for ComfyUI."""
from typing import Tuple
from ...base.base_node import ComfyAssetsBaseNode
from .logic import label_for, list_checkpoint_entries, pick_checkpoint
class CheckpointFolderIteratorNode(ComfyAssetsBaseNode):
"""
Load one checkpoint from a folder per queued run.
Set index to 0 with "increment" and queue as many runs as there are
checkpoints: each run loads the next file, so only one model is in
memory at a time. A run past the last checkpoint fails with a clear
error rather than wrapping around, so over-queuing never restarts the
sweep. Pairs with Model Compare Sheet to build a labeled grid.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"folder": (
"STRING",
{
"default": ".",
"multiline": False,
"tooltip": "Folder relative to models/checkpoints (or absolute)",
},
),
"index": (
"INT",
{
"default": 0,
"min": 0,
"max": 9999,
"control_after_generate": True,
"tooltip": "Which checkpoint to load; errors past the end",
},
),
},
"optional": {
"include_pattern": (
"STRING",
{"default": "", "tooltip": "Regex to include (empty = all)"},
),
"exclude_pattern": (
"STRING",
{"default": "", "tooltip": "Regex to exclude (empty = none)"},
),
},
}
RETURN_TYPES = ("MODEL", "CLIP", "VAE", "STRING", "STRING", "INT", "INT")
RETURN_NAMES = ("model", "clip", "vae", "ckpt_name", "label", "index", "count")
FUNCTION = "load"
CATEGORY = "🫶 ComfyAssets/🧰 xyz-helpers"
def load(
self,
folder: str,
index: int,
include_pattern: str = "",
exclude_pattern: str = "",
) -> Tuple[object, object, object, str, str, int, int]:
import folder_paths
import comfy.sd
entries = list_checkpoint_entries(folder, include_pattern, exclude_pattern)
ckpt_name, ckpt_path = pick_checkpoint(entries, index)
self.log_info(f"Loading {index + 1}/{len(entries)}: {ckpt_name}")
model, clip, vae = comfy.sd.load_checkpoint_guess_config(
ckpt_path,
output_vae=True,
output_clip=True,
embedding_directory=folder_paths.get_folder_paths("embeddings"),
)[:3]
return model, clip, vae, ckpt_name, label_for(ckpt_name), index, len(entries)