ComfyUI Node

LLM Node

One rough idea in, an enhanced prompt plus two search queries out

By Santat2023·Created 12 months ago·Updated 26 days ago· 0
LLM Node
  • clip
  • cond
  • pose_query
  • style_query
user_initial_promptEnter your prompt here

The LLM Node is the front half of a local RAG experiment, and it's the node with the ideas. You type "female warrior standing on a cliff at sunset" and a local LLM - Ollama running qwen2:7b by default - rewrites that into a proper SD/SDXL prompt, then splits off two separate short search queries: one describing only the pose, one describing only the style. Those queries feed the pack's DB Load Node, which retrieves a pose reference and a style reference to drive ControlNet and IP-Adapter respectively.

That split is the clever part, and it's a genuinely different take on RAG. Most prompt-enhancer nodes (and there are a lot of them now - local LLM prompt enhancement is a mainstream ComfyUI pattern) just rewrite your text into something the encoder likes. This one treats your prompt as a search problem too: instead of one generic retrieval, you get functionally different queries targeting two different reference pools. An LLM writing an instruction for an LLM-based encoder is the standard trick; an LLM decomposing a request into ControlNet-shaped and IP-Adapter-shaped queries is the research-y part.

How it works

Under the hood (services/llm_service.py) it's a single HTTP call:

POST http://localhost:11434/api/generate

with your prompt wrapped in a big system-style instruction that demands JSON - exactly three fields: final_prompt, pose_query, style_query - at temperature 0.2, streaming off, 120-second timeout. The response gets scraped for the JSON object (it strips markdown fences and grabs between the first { and last }), validated, and both queries get truncated to 20 words if the model got chatty.

The node then does something that makes it a drop-in replacement for a CLIP Text Encode: it takes the clip input you wired in, tokenizes final_prompt, and encodes it straight to a CONDITIONING output. No extra encode node needed.

If Ollama is down, it degrades gracefully instead of crashing - the fallback returns your original prompt unchanged and uses it as both queries. You'll see [LLMService] Using fallback result in the console. It keeps the graph running, but with zero enhancement and two identical, generic queries.

The inputs and outputs

  • user_initial_prompt - multiline STRING, your rough idea. That's it for the prompt side.
  • clip - a CLIP input, wired from your checkpoint loader. Its tooltip is plain: "The CLIP model used for encoding the text." This is the encoder for the final prompt's conditioning.

Outputs:

  • cond (CONDITIONING) → positive input of a KSampler.
  • pose_query and style_query (STRING) → wire both into the DB Load Node.

Installing and running it

Manager search ComfyUiRagCustomNodes, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Santat2023/ComfyUiRagNodes.git

Restart, find the MyNodes category. Then you need Ollama and the model:

ollama pull qwen2:7b

Where people get burned

  • The config.json in the README does nothing. The README walks you through creating a config with Ollama/OpenAI/Yandex providers, but the shipped code never reads it. LLMService() is constructed with hardcoded defaults: http://localhost:11434 and qwen2:7b. If you want a different model or endpoint, you're editing the source in services/llm_service.py, not the config file. The README rots; the code is the truth.
  • It's a cold API call every run. Each execution waits on a full Ollama generation (up to 120s). A 7B model on a mid GPU is a few seconds, but a bigger model means a real pause before sampling even starts.
  • Output quality rides on JSON discipline. Small local models occasionally wrap the JSON in prose; the parser is defensive about it but a bad response can still raise. Watch the [LLMService] logs if output looks off.

This is a thesis demo, not a tool you'll keep installed - but if you're curious how prompt-splitting RAG could actually look inside a graph, it's the rare pack that shows the whole flow end to end.

CategoryMyNodes

Inputs (2)

NameTypeDefaultDescription
user_initial_promptSTRINGEnter your prompt here
clipCLIPThe CLIP model used for encoding the text.

Outputs (3)

NameTypeDescription
condCONDITIONING
pose_querySTRING
style_querySTRING