From 897b501b11f037658d06d718f0c9aca3de46fc01 Mon Sep 17 00:00:00 2001 From: GenorTG Date: Tue, 10 Nov 2026 09:59:24 +0100 Subject: [PATCH] Store sampler presets under models --- README.md | 2 +- pyproject.toml | 2 +- sampler.py | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e998a34..8b598e3 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ KSampler, KSampler (Advanced) and custom sigmas in one node, built on `comfy.sam - **Advanced**: `start_at_step`, `end_at_step`, `add_noise`. - **Recommended settings**: press `Use recommended settings` with a Loader's PIPE connected to fill sampler, scheduler, steps and cfg (nothing changes when you only connect the pipe). They come from the model's sidecar (the most common sampler, scheduler, steps and cfg of the author's example images; prompts are never read), then name hints (turbo / distilled -> 8 steps, cfg 1), then family defaults from community documentation (Krea 2: res_multistep/simple; MiniMax H3: euler/simple; LTX: the LTXV schedule). These are starting points, not official values. - **Step cache**: `step_cache` (off / auto / easycache / lazycache) wraps ComfyUI's own EasyCache and LazyCache, which skip model calls on steps where the output barely changes and work across architectures (including audio+video models). `auto` turns on easycache from 15 steps up; distilled 4-8 step runs should stay off. `cache_threshold` (higher = faster, softer), `cache_start` and `cache_end` set when it may skip. Measured on Anima, 30 steps, RTX 5080: easycache 0.1 skipped 15/30 steps (1.8x, similarity to uncached 0.991), 0.2 skipped 17 (2.05x, 0.978), 0.4 skipped 19 (2.4x, 0.971); lazycache 0.2 gave 2.05x at 0.988. Results vary by model. -- **Presets**: save, apply and delete named presets (steps, cfg, sampler, scheduler, denoise, runs, step cache). They are stored in ComfyUI's user folder under `promptforge/sampler_presets.json`. Connect the Loader's PIPE to the sampler and the preset list shows only presets for that model family and model, plus generic presets; `show all presets` reveals the rest. A saved preset records the connected family and model, so it keeps matching that model and does not clutter other models. +- **Presets**: save, apply and delete named presets (steps, cfg, sampler, scheduler, denoise, runs, step cache). They are stored in `models/PromptForge/sampler_presets.json`, so a models sync carries them to other machines; an old copy in `user/promptforge/` is read once as a fallback. Connect the Loader's PIPE to the sampler and the preset list shows only presets for that model family and model, plus generic presets; `show all presets` reveals the rest. A saved preset records the connected family and model, so it keeps matching that model and does not clutter other models. Tested starting points at about 1.5 MP (identity tests used a source picture through the edit graphs; every row was rendered and checked): diff --git a/pyproject.toml b/pyproject.toml index a114313..f1e118f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "ComfyUI-PromptForge" description = "ComfyUI prompt enhancement suite: model/config node with GPU-aware auto settings, prompt enhancer with a preset catalog, and a standalone config finder." -version = "1.28.15" +version = "1.28.16" license = { file = "LICENSE" } dependencies = [ "transformers", diff --git a/sampler.py b/sampler.py index 0108aa3..0e1c4f9 100644 --- a/sampler.py +++ b/sampler.py @@ -35,14 +35,20 @@ CACHES = {"easycache": nodes_easycache.EasyCacheNode, "lazycache": nodes_easycac def _preset_file(): + return Path(folder_paths.models_dir) / "PromptForge" / "sampler_presets.json" + + +def _legacy_preset_file(): return Path(folder_paths.get_user_directory()) / "promptforge" / "sampler_presets.json" def load_presets(): - try: - return json.loads(_preset_file().read_text(encoding="utf-8")) - except (OSError, ValueError): - return {} + for path in (_preset_file(), _legacy_preset_file()): + try: + return json.loads(path.read_text(encoding="utf-8")) + except (OSError, ValueError): + continue + return {} @PromptServer.instance.routes.get("/promptforge/sampler_presets")