Nougan LM Studio π§
Chat with a local LLM from inside ComfyUI β vision, audio, video included
- image
- audio
- video
- RESPONSE
- PROMPT
The local-LLM-in-the-graph pattern won. The KB's essay on LLMs in ComfyUI is blunt about why: an 8B local model isn't writing better English than a frontier API, but it's uncensored, offline, and free per call. NouganLMStudio is that local model, but it doesn't bolt on Ollama or a llama.cpp loader - it talks to LM Studio's dev server, the OpenAI-compatible local server you may already be running. Text in, streamed response out, with vision, audio, and video inputs on the side.
How it works
It calls /v1/chat/completions on your local LM Studio dev server (default http://127.0.0.1:1234), streaming tokens over the ComfyUI websocket to drive an on-node console and progress bar. The interesting part is the media handling: images get downscaled to a longest side (1024/768/512) and base64'd as JPEG content parts, audio becomes base64 WAV via input_audio, and video is either an IMAGE batch of frames or a file path sampled into evenly-spaced frames (video_frames, default 8). You can also drop or paste an image straight onto the node - it uploads to ComfyUI/input/nougan_lms/ and the reference survives save/reload.
There's a β³ button that auto-detects loaded models and fills model_name, and a stop button for interrupting. It's an output node, so it can terminate a graph on its own - which is also what saves you from ComfyUI's "prompt has no outputs" validation when you're just chatting.
The inputs that matter
server_url- LM Studio's dev-server URL. The default is right if you haven't moved it.model_name- auto-filled by β³, or type it.system_prompt/generate_prompt- the system role and your actual message.max_tokens- default 512;-1lets the model decide (the bar goes indeterminate).temperature,top_p- the usual sampling knobs.stream- token-by-token streaming, on by default; it drives the progress bar.image_size,video_frames- how big images get and how many frames video yields.prompt_override- a wired STRING replacesgenerate_prompt. This is how you feed the Prompt Box back in.
Outputs: RESPONSE (the model's answer) and PROMPT (the exact prompt that was sent).
Installing
The suite, one shot - Manager search Nougan, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Winnougan/Nougan_Nodes
# restart ComfyUI
Then in LM Studio: load a model, open the Developer tab, start the server. Sanity check: http://127.0.0.1:1234/v1/models should return JSON. The node itself needs almost nothing extra - one exception is decoding video files, which requires opencv-python; IMAGE batches of frames need nothing. That's the kind of dependency note to read before you blame the node.
Where people get burned
The KB's warning about LLM-in-graph nodes applies here too: any node that reaches the network by design is exactly the shape of thing you should install from a known source - this one is MIT-licensed, open, and read the repo if you care. Practical failures: the model returns the chat habits (role delimiters, preamble) into a raw prompt - that's why the PROMPT output exists, so you can inspect what actually went out. And VRAM: you're now running an LLM and a diffusion model. The node doesn't unload one for the other, so on a tight card budget the quantization of your chat model matters as much as its quality.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| server_url | STRING | http://127.0.0.1:1234 | LM Studio dev-mode server. Default http://127.0.0.1:1234 |
| model_name | STRING | local-model | Use the β³ button on the node to auto-detect loaded models. |
| system_prompt | STRING | You are a helpful assistant. | Instructions for the assistant (system role). |
| generate_prompt | STRING | β | |
| max_tokens | INT | 512-1β65536 | -1 lets the model decide. |
| temperature | FLOAT | 0.700β2 | β |
| top_p | FLOAT | 0.950β1 | β |
| stream | BOOLEAN | true | Token-by-token streaming drives the progress bar. |
| seed | INT | 00β18446744073709550000 | β |
| image_size | COMBO | 1024 | Longest side images/frames are downscaled to before encoding. |
| video_frames | INT | 81β32 | How many evenly-spaced frames to sample from a video. |
| imageopt | IMAGE | Single image or batch β every frame becomes a vision content part. | |
| audioopt | AUDIO | Sent as an input_audio part β needs an audio-capable model. | |
| videoopt | * | IMAGE batch of frames, a VHS video dict, or a file path string. | |
| prompt_overrideopt | STRING | Wired STRING replaces the generate_prompt widget (feed the Prompt Box back in here). | |
| embedded_imageopt | STRING | Internal β populated by the on-node image drop zone. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| RESPONSE | STRING | β |
| PROMPT | STRING | β |