LM Studio
Draft Better Prompts With a Local LLM That Never Leaves Your Machine
- image
- STRING
The name is honest about the location: this node talks to a locally running LM Studio server, not the cloud. You get a full LLM/VLM call inside your graph - prompt drafting, prompt enhancement, even asking a vision model what's in the image - and not a single token leaves your machine. After the LLMVISION malware scare in 2024, "talks to my own localhost server" is exactly the boring, safe version of a ComfyUI LLM node you want. No API key, no account, nothing uploaded anywhere.
This is the pattern people actually run: LM Studio as a prompt enhancer sitting in front of a Z-Image or SDXL workflow, so the model writes your prompt and you paste it into the text encoder. The common setup I see in the wild is one generation model plus a small local LLM that gets unloaded right after it answers, precisely so it isn't hogging VRAM during the actual image gen. This node's load/unload toggles were built for that workflow.
How it works
Under the hood it's an OpenAI-compatible chat request, which is why there's no requests dependency in the pack - the whole thing is Python's stdlib urllib POSTing to http://localhost:1234/v1/chat/completions. Give it an image and it base64-encodes it as PNG and sends a proper vision (VLM) request instead of a text one. It also calls LM Studio's own /api/v1/models/load and /api/v1/models/unload endpoints to handle the load-lifecycle toggles.
Nice touch: it doesn't crash your graph on failure. If the server is down or the model name is wrong, it returns the error as its STRING output - wire the output into a Preview Text node and you can read "Error: Could not reach ..." right in the UI instead of hunting through the console. It's marked IS_CHANGED, so it re-executes every queue run rather than caching.
The inputs that matter
model- the model identifier exactly as LM Studio lists it, no default. Copy it from the model dropdown in LM Studio; getting this wrong (or using a nickname) is the #1 failure mode.prompt- your user message (multiline).system_prompt- defaults to "You are a helpful assistant."; this is where you steer prompt-rewriting behavior.load_model/unload_model- both default on. Turnunload_modeloff if you're calling the same model repeatedly in one session to skip the reload churn.image(optional) - wire an IMAGE in and the call becomes a VLM request; leave it disconnected for plain text.
Output is a single STRING, ready for a text preview or any downstream text consumer.
Installing and pointing it at your server
Install the pack through ComfyUI Manager (search ComfyUI-Bricolage) or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/sheldongriffin/ComfyUI-Bricolage
Then restart ComfyUI. The pack's own requirements are just Pillow and torchvision. The real dependency is LM Studio itself, which you install separately: load a model, then start the local server from LM Studio's Developer tab. The default port is 1234, which is what this node assumes.
Where people get burned: the base URL is not a UI field. It's hardcoded to http://localhost:1234 in src/lm_studio.py as LM_STUDIO_BASE_URL, so if you changed LM Studio's port, or you're running it on a different machine, you edit that line and restart ComfyUI. Also make sure the model string in the node matches LM Studio's exact identifier - org-prefixed names like qwen3-8b won't match a bare qwen3. One more: this is a personal-repo pack with a "no support, no roadmap" README, so if it breaks after a ComfyUI update, the fix is on you.
Worth knowing before you fall in love: there's no streaming, no temperature control, and a hardcoded 300-second timeout per call. For quick prompt enhancement it's plenty; for anything chatty you'll want a purpose-built LLM integration.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| model | STRING | — | |
| prompt | STRING | — | |
| system_prompt | STRING | You are a helpful assistant. | — |
| load_model | BOOLEAN | true | — |
| unload_model | BOOLEAN | true | — |
| imageopt | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |