Illustrious Epoch Sample Gallery
A contact sheet of your checkpoints, because the last epoch is rarely the best
- epoch_images
- sample_report
Training runs overfit. That's not a maybe - it's the normal outcome of running too many epochs at too high a learning rate, and it's why the standard advice is to save every epoch and pick the one that still obeys your prompts instead of the one with the lowest loss. The problem is that "pick the best epoch" means looking at twenty images, and the pack's answer to that is IllustriousEpochSamples: it turns the sample images your training run already wrote into one batched IMAGE you can preview in about three seconds.
What it's reading
IllustriousSDXLLoRATrain renders one sample per epoch when the advanced options enable sampling, saving sample_epoch_001.png and a matching JSON with the prompt, seed, sampler, steps and CFG. That list of paths lives inside the string the trainer returns. This node parses training_report, pulls the samples array out of it, and loads every image.
Each file is checked hard before it's loaded: the path has to resolve inside ComfyUI/output/illustrious_native, the extension has to be .png, the filename has to start with sample_epoch_, and the image can't exceed 1536×1536. Then each is padded onto a 384×384 white canvas and stacked into a single batch, in epoch order. Over 100 samples and it refuses rather than building an enormous batch.
If the list is empty - because sampling was off, or because the run failed before its first epoch finished - you don't get an exception. You get a single black 256×256 frame and a report where status is NO_SAMPLES, with a message the author clearly got tired of writing: "No epoch images yet; black placeholder is not a generated sample." Sensible. A black square in a gallery is ambiguous; a black square that says NO_SAMPLES is not.
Inputs and outputs
There's one input. training_report is a STRING, and it's declared as a forced input - it's meant to be wired from the trainer's training_report output, not typed by hand. Yes, you can technically paste the JSON in; no, you don't want to, it's thousands of characters with paths in it.
epoch_images (IMAGE) is the batch - wire it to ComfyUI's core Preview Image, or Save Image if you want the sheet on disk. It's a genuine batched tensor, so a Preview node will show you frames you can click through, one per epoch.
sample_report (STRING) is the machine-readable version: status is either SAMPLES or NO_SAMPLES, and on success it lists the actual files in order. That file order is the same order as the frames, which is how you know that frame 7 is epoch 7. Handy, because the thumbnails are padding-fit and don't carry the epoch number in them.
The part that annoys people
The gallery appears after training finishes, not while it runs. The PNGs are written to disk during training - one per epoch - but a ComfyUI node's downstream consumers don't execute until the node returns, and training doesn't return until the last epoch is done. So this is a post-mortem contact sheet, not a live monitor. If you want live progress, watch the node's text output and the progress bar; ComfyUI runs nodes in a queue, not a stream, and no node in this pack can change that.
Second annoyance: sampling costs VRAM and time, and if sample generation fails it stops the whole job rather than skipping a frame. That's the standard low-VRAM trap - a run that trains fine with sampling off will fall over at the end of epoch 1 with it on. Turn samples off in the advanced options, re-queue, and you get the adapter you wanted plus a NO_SAMPLES placeholder here. Not ideal, but honest, and much better than silently missing samples with no explanation.
Install
Manager, searching ComfyUI-IllustriousLoRATools (listed as Illustrious LoRA Tools), or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/katorikonoe-ai/ComfyUI-IllustriousLoRATools
pip install -r ComfyUI-IllustriousLoRATools/requirements.txt
Use ComfyUI's own Python so the CUDA PyTorch build is preserved - the pack pulls diffusers, transformers, peft, accelerate, bitsandbytes, onnxruntime and friends. This node needs torch and Pillow, both already present in a ComfyUI install. Keep native/, web/ and crop_routes.py together, restart the server, and look for it under Katori/Illustrious Native Training.
Using the sheet for something
Compare epochs on prompt obedience, not prettiness. Early epochs produce a blurry generic anime girl that ignores your trigger; late epochs reproduce your training images almost exactly and stop responding to clothing or pose tags. The right epoch is usually somewhere in the middle, and it's the one where changing a tag visibly changes the picture. Copy that epoch's epoch_###.safetensors out of output/illustrious_native/<dataset_run>/<training_run>/ into ComfyUI/models/loras/ and test it in a normal generation graph - with CLIP skip 2, which anime SDXL LoRAs generally want.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| training_report | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| epoch_images | IMAGE | — |
| sample_report | STRING | — |