Nodes/Kinburg-Nodes/Ouroboros (Self-Correcting Sampler) 🐍
ComfyUI Node

Ouroboros (Self-Correcting Sampler) 🐍

Self-correcting text→image loop: an LLM expands the prompt, an image is sampled, a vision critic scores it and advises how to improve the prompt, and it repeats until the target score (or max iterations). Outputs the whole trajectory (wire images/prompts/judge_data straight into Image Compare) plus the best image/prompt.

By KinburgΒ·Created 2 months agoΒ·Updated 3 days agoΒ· 1
Ouroboros (Self-Correcting Sampler) 🐍
  • model
  • clip
  • vae
  • latent
  • enhancer_settings
  • critic_settings
  • sampler_settings
  • model_negative
  • images
  • prompts
  • judge_data
  • best_image
  • best_prompt
  • best_score
  • report
  • iterations
  • captions
  • times
  • settings_data
β—„user_promptβ–Ί
β—„negativeβ–Ί
β—„target_score4.0β–Ί
β—„max_iterations6β–Ί
β—„low_vramtrueβ–Ί
β—„enhancer_history4β–Ί
β—„trigger_wordsβ€”β–Ί
β—„full_console_logtrueβ–Ί
β—„log_modestreamingβ–Ί
CategoryKinburg-Nodes/Bestiary/Ouroboros

Inputs (17)

NameTypeDefaultDescription
modelMODELβ€”
clipCLIPβ€”
vaeVAEβ€”
latentLATENTStarting latent β€” sets the image dimensions (wire an Empty Latent, matching your model: SD/SDXL vs SD3/Flux). For img2img/hires-feedback, feed a real latent and set denoise<1 in Sampler Settings. Reused each iteration so only the prompt varies.
user_promptSTRINGYour intent β€” what you want. The enhancer improves it; the critic anchors advice to it.
negativeSTRINGBase negative prompt; the critic's flaw terms accumulate onto it each iteration.
enhancer_settingsKINBURG_LLM_CONFIGA 'Local LLM Settings (GGUF)' for the prompt-enhancer LLM β€” its model/temperature AND its system_prompt define how the prompt is expanded. On low VRAM, point it at the SAME model file as the critic.
critic_settingsKINBURG_CRITICA 'Ouroboros Critic Settings 🐍' bundle β€” the vision judge + scoring rules.
sampler_settingsKINBURG_SAMPLER_CFGA 'Sampler Settings' bundle β€” OR a chain of them (wire Sampler Settings nodes in series). One = classic single pass. Two or more = REFINE mode: each iteration runs the stages in order (stage 1 drafts, later stages polish the previous latent with their own denoise / sampler / eta); the critic judges only the FINAL image.
target_scoreFLOAT4.00–100The loop stops once the overall score reaches this (on the critic's score_min..score_max scale).
max_iterationsINT61–100Hard cap on refinement rounds.
low_vramBOOLEANtrueLow-VRAM mode (default ON). ON: strictly one model in VRAM at a time β€” frees ComfyUI models before each LLM call, unloads the LLM worker after it, and AUTO-SIZES each LLM's context (n_ctx) to what the request actually needs, so the n_ctx set on the LLM Settings nodes becomes the MAXIMUM. Best when the GPU can't hold the diffusion model + the LLM at once. OFF: keep everything resident (fastest, no reloads) and use the full n_ctx from the Settings nodes β€” for GPUs with VRAM to spare. NOTE: inside the loop this overrides the unload_* toggles on the LLM Settings nodes.
model_negativeoptMODELSecond model for the UNCONDITIONAL (negative) pass β€” for checkpoints shipped as a model + uncond-model pair, such as Ideogram. The loop builds the dual-model guider itself on every iteration, so the freshly rewritten prompt is still what gets encoded (wiring a ready-made 'Dual Model CFG Guider' node here instead would freeze the conditioning and defeat the whole loop). NOTE: at cfg 1.0 the guider skips the uncond pass entirely and this model does nothing β€” give the Sampler Settings a cfg above 1.
enhancer_historyoptINT40–50How many of the most recent iterations (prompt + score) are recapped to the enhancer LLM as 'already tried, do not repeat' context. Higher = more memory of what failed (longer prompt, more tokens); 0 = no history (each rewrite sees only the intent, current prompt and the latest critic advice). The latest advice is always sent regardless.
trigger_wordsoptSTRINGComma-separated words ALWAYS appended to the enhanced prompt (e.g. LoRA triggers from Lora Unlim Accumulator's 'triggers' output), so the LLM rewrite can't drop them.
full_console_logoptBOOLEANtrueConsole/terminal verbosity only (not the Live Log node or 'report'). On: per iteration also prints the enhanced prompt, advice and negative additions. Off: just a one-line score per iteration. The full trace is always in the 'report' output and the Live Log node.
log_modeoptCOMBOstreamingHow the Ouroboros Live Log node updates: 'streaming' is like 'per step' but the enhancer's prompt types out token by token as it's written (the critic's verdict still arrives whole β€” it simply isn't wired to the log that way); 'per step' posts each stage the moment it finishes (enhanced prompt β†’ generated image β†’ critic verdict), each timestamped; 'per iteration' posts one combined entry after the whole iteration (the older behaviour).

Outputs (11)

NameTypeDescription
imagesIMAGEβ€”
promptsSTRINGβ€”
judge_dataSTRINGβ€”
best_imageIMAGEβ€”
best_promptSTRINGβ€”
best_scoreFLOATβ€”
reportSTRINGβ€”
iterationsINTβ€”
captionsSTRINGβ€”
timesSTRINGβ€”
settings_dataGEN_SETTINGSβ€”