LLM Dialogue Cycle
LLM Dialogue Cycle makes models argue productively
- transcript_text
You've probably seen the trick where you paste model A's answer into model B and ask it to rip it apart. LLM Dialogue Cycle automates that loop inside a single ComfyUI node - two local GGUF models talk to each other, no copy-paste, no API keys, no external runtime. The reason you'd reach for it over wiring up two chat nodes with a cyclic graph is that ComfyUI is genuinely bad at cycles. This node runs the whole A→B→A→B exchange in one call, so your workflow stays a straight line.
It's the same engine as LLM Session Chat (llama-cpp-python running GGUF weights out of models/LLM/), but aimed at a different job: critique-and-revise loops, red-teaming a prompt, or simulating a conversation to check whether your role settings actually behave before you set them loose on a real user. It ships with the pack's own opinion baked in - initial_user_text goes to Model A only, and from there each model's output feeds the other's next turn.
How it works
The cycles input is the turn counter: 1 means A then B - a single round trip. Bump it and the ball keeps bouncing, up to 50. Each role gets its own persistent history, so session_id is really a base: A's history lives at {id}_A, B's at {id}_B, and the full transcript is appended to {id}.txt on disk. The node returns the whole transcript as a string out of transcript_text, which is the output you'd wire into a text preview or a save node.
Because the models run inside one execution, the pack keeps both model managers loaded when runtime_cache is KV_cache or LlamaTrieCache (the defaults), so the dialogue doesn't reload weights between turns. That's also why the newer Unload LLM Model node exists - after a big two-model run you can free the VRAM without restarting ComfyUI.
The inputs that matter
You mostly set four things and ignore the rest:
modelA/modelB- dropdowns populated from GGUF files inComfyUI/models/LLM/. If they read(No GGUF models found in models/LLM/), that's your problem right there.system_prompt_A/system_prompt_B- role definitions. A sharedsystem_promptapplies to both unless the per-role one is filled in, which overrides it.cycles- how many round trips before it stops.n_gpu_layers-0is pure CPU (slow for anything past a few billion params),-1offloads everything.
The mmprojA / mmprojB projector slots exist for future image-capable dialogue; dialogue is currently text-only, so set both to (Not required) and move on. Everything else - temperature, top_p, max_tokens, n_ctx, the summarization and cache knobs - is standard sampling and history management, and the defaults are sane.
Installing it
The usual two paths. Via ComfyUI Manager, search for ComfyUI-LLM-Session. Or clone it manually:
cd ComfyUI/custom_nodes
git clone https://github.com/kantan-kanto/ComfyUI-LLM-Session.git
pip install pillow numpy
pip install llama-cpp-python
Then restart ComfyUI. Drop your GGUF files into ComfyUI/models/LLM/. Plain PyPI llama-cpp-python works for most text-only models; the newer multimodal families (Qwen3-VL, Gemma 4) need a recent JamePeng build matching your OS, Python version, and GPU backend - the README's COMPATIBILITY.md walks through it.
Where people get burned
Two local models means two sets of weights. A 12B GGUF on an 8GB card is already a squeeze; running A and B back-to-back is where you'll first feel the VRAM ceiling. Keep the quant ladder honest - Q4_K_M or so per model, and lean on n_gpu_layers for partial offload. And remember the histories persist: rerun with the same session_id and the models keep talking where they left off. That's a feature for testing prompts, but a trap if you expected a clean slate - flip reset_session when you want one.
Inputs (34)
| Name | Type | Default | Description |
|---|---|---|---|
| initial_user_text | STRING | Initial user message (sent to Model A only) | |
| session_id | STRING | default | Base session id. A uses {id}_A, B uses {id}_B, transcript uses {id}.txt |
| cycles | INT | 11–50 | Number of round trips. 1 = A then B. |
| modelA | COMBO | (No GGUF models found in models/LLM/) | GGUF model for role A |
| mmprojA | COMBO | (Auto-detect) | Projector reserved for image-capable dialogue workflows. For current text-only dialogue, use (Not required). |
| modelB | COMBO | (No GGUF models found in models/LLM/) | GGUF model for role B |
| mmprojB | COMBO | (Auto-detect) | Projector reserved for image-capable dialogue workflows. For current text-only dialogue, use (Not required). |
| system_prompt | STRING | You are a helpful assistant. | Shared system prompt for both roles |
| system_prompt_A | STRING | Role-specific system prompt for model A (overrides shared prompt if set) | |
| system_prompt_B | STRING | Role-specific system prompt for model B (overrides shared prompt if set) | |
| max_tokens | INT | 5121–32768 | — |
| temperature | FLOAT | 0.700–2 | — |
| top_p | FLOAT | 0.900.05–1 | — |
| n_gpu_layers | INT | 0-1–200 | — |
| n_ctx | INT | 4096512–131072 | — |
| max_turnsopt | INT | 120–200 | — |
| summarize_old_historyopt | BOOLEAN | true | — |
| summary_chunk_turnsopt | INT | 31–50 | — |
| max_tokens_summaryopt | INT | 12816–2048 | — |
| summary_max_charsopt | INT | 1500200–20000 | — |
| dynamic_max_tokensopt | BOOLEAN | true | — |
| min_generation_tokensopt | INT | 961–4096 | — |
| safety_margin_tokensopt | INT | 640–2048 | — |
| persistent_cacheopt | COMBO | off | Persistent cache backend. LlamaDiskCache stores cache data under separate cache directories for each session id. |
| runtime_cacheopt | COMBO | LlamaTrieCache | 4 options: KV_cache, LlamaRAMCache, LlamaTrieCache, off |
| repeat_penaltyopt | FLOAT | 1.121–2 | — |
| repeat_last_nopt | INT | 2560–4096 | — |
| rewrite_continueopt | BOOLEAN | true | — |
| log_levelopt | COMBO | timing | 3 options: minimal, timing, debug |
| suppress_backend_logsopt | BOOLEAN | true | — |
| history_diropt | STRING | Optional history directory. Empty => output/llm_session_sessions/. Disk caches are also stored there, separated by session id. | |
| reset_sessionopt | BOOLEAN | false | If true, resets both {id}_A and {id}_B histories (transcript file is not deleted). Session disk caches are kept. |
| stream_to_consoleopt | BOOLEAN | false | Stream tokens to console while generating. |
| enable_thinkingopt | BOOLEAN | false | Enable model thinking/reasoning output for supported chat formats. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| transcript_text | STRING | — |