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.
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)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | β | |
| clip | CLIP | β | |
| vae | VAE | β | |
| latent | LATENT | Starting 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_prompt | STRING | Your intent β what you want. The enhancer improves it; the critic anchors advice to it. | |
| negative | STRING | Base negative prompt; the critic's flaw terms accumulate onto it each iteration. | |
| enhancer_settings | KINBURG_LLM_CONFIG | A '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_settings | KINBURG_CRITIC | A 'Ouroboros Critic Settings π' bundle β the vision judge + scoring rules. | |
| sampler_settings | KINBURG_SAMPLER_CFG | A '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_score | FLOAT | 4.00β100 | The loop stops once the overall score reaches this (on the critic's score_min..score_max scale). |
| max_iterations | INT | 61β100 | Hard cap on refinement rounds. |
| low_vram | BOOLEAN | true | Low-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_negativeopt | MODEL | Second 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_historyopt | INT | 40β50 | How 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_wordsopt | STRING | Comma-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_logopt | BOOLEAN | true | Console/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_modeopt | COMBO | streaming | How 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)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | β |
| prompts | STRING | β |
| judge_data | STRING | β |
| best_image | IMAGE | β |
| best_prompt | STRING | β |
| best_score | FLOAT | β |
| report | STRING | β |
| iterations | INT | β |
| captions | STRING | β |
| times | STRING | β |
| settings_data | GEN_SETTINGS | β |