LM Studio Image Caption
The captioning node that doesn't run a model — it borrows your LM Studio
- image
- caption
This node sends whatever image you feed it to a local LM Studio server and puts the caption it gets back onto the graph as a plain string. The name is a mild lie in a good way: it doesn't call any cloud API, needs no key, and downloads no model weights into ComfyUI. LM Studio does all the heavy lifting; this node is just a polite HTTP client in a node-shaped costume.
The name's other half is the intended use. Slartibart23 built it around HauhauCS/Qwen3.5-35B-A3B-Uncensored-HauhauCS-Aggressive, a Qwen3.5 vision model, and the README makes the pitch unsubtle: in his testing, this stack captioned adult content "stronger" than JoyCaption Beta One, the usual community default for uncensored natural-language captions. You can point it at any vision model in LM Studio, though - the model field is just a string.
Why reach for it? Two jobs, straight out of the LLM-in-the-graph playbook: captioning a dataset for LoRA training (natural language, the right call for FLUX and the other LLM-encoded checkpoints), and seeding an img2img or image-to-video prompt from a reference image. A local captioner keeps everything on your machine, which matters when your content would get bounced by an API filter. It's the JoyCaption argument, with the twist that you can swap in whatever vision model you like without waiting for a node pack to support it.
How it works
Under the hood it's about as simple as a Comfy node gets. Your IMAGE tensor becomes a PIL image, gets base64-encoded (default data_uri_jpeg), and is POSTed to http://127.0.0.1:1234/v1/chat/completions, LM Studio's OpenAI-compatible endpoint. The response's choices[0].message.content is what comes back as caption. The only dependency is requests, which you already have. There's no key; the auth header is the literal string Bearer lm-studio.
The inputs that actually matter
The node dumps a dozen inputs on you, but most have sane defaults. Set these three first:
model- the exact model ID LM Studio reports. Ask its server:Invoke-RestMethod http://127.0.0.1:1234/v1/models | ConvertTo-Json -Depth 10and paste theidin.prompt- here's a trap: the default is in German, asking for a 1–3 sentence German caption. The author is German. If you want English or FLUX-style output, write your own, or copy theprompts/flux_image_to_prompt_template.txtfrom the repo.server_url- only touch it if LM Studio isn't on the default port.
Then two switches decide whether you get clean output. thinking_mode: no_think prepends /no_think to the prompt, stopping reasoning models from burning every token on deliberation - this node's real job is taming a reasoner, because the recommended model wants to think. fallback_mode: final_or_reasoning uses content and falls back to reasoning_content when the final answer comes back empty, which happens on quantized Qwen models more often than anyone admits.
temperature (0.1–0.4 for captioning), max_tokens (4096), and the seed trio are worth a glance but leave them alone initially - and keep send_seed_to_lmstudio off, since some vision models return empty content when handed a seed. Output is one caption string; wire it into anything that takes text - a save node, a prompt builder, or a training-set writer.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/Slartibart23/comfyui-lmstudio-qwen35-captioning.git
Restart ComfyUI completely - the path must be custom_nodes/comfyui-lmstudio-qwen35-captioning/__init__.py, and the repo warns specifically about the wrong-folder mistake. You can also find it in ComfyUI Manager under the pack title. It's MIT-licensed with no heavy deps: no model download, just requests.
The real install cost is on the LM Studio side. The recommended 35B-A3B MoE is a big vision model - the README says RTX 5090 class GPU, and it means it. Anything smaller should grab a smaller or more heavily quantized vision GGUF instead. In LM Studio: load the model, open Developer, start the local server, leave it running, and paste the model ID into the node.
Where people get burned
- Node missing after install - wrong folder or no full restart; check the console for import errors.
- "Invalid url" from LM Studio - use
image_format: data_uri_jpeg, notraw_base64; some setups reject the bare base64. - Empty caption / reasoning bleed - you're hitting the reasoner problem.
no_think+final_or_reasoning+max_tokens: 4096is the fix the README prescribes. - Cut-off or over-analytical output - the model spent its token budget thinking. Raise
max_tokensand LM Studio's context length (16384+), and simplify the prompt to demand only the final caption.
One honest caveat before you wire it into a big training run: it's a brand-new, near-zero-install pack from a single author, and this ecosystem has seen a malicious "LLM vision" node before. That said, this one is as boring as they get - all it does is POST to a URL you specify, defaulting to localhost. Read it, use it, and keep the README's note in mind: legal, consenting-adult captioning only.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Input image from ComfyUI. The image is sent to LM Studio without resizing. | |
| server_url | STRING | http://127.0.0.1:1234/v1/chat/completions | LM Studio OpenAI-compatible chat completions endpoint. |
| model | STRING | DEINE_MODEL_ID_HIER_EINTRAGEN | Exact model ID as reported by LM Studio, for example from /v1/models. |
| prompt | STRING | Erstelle eine deutsche Bildcaption in 1 bis 3 Sätzen. Keine Analyse. Keine Stichpunkte. Nur die finale Caption. | Instruction sent to the vision model together with the image. |
| thinking_mode | COMBO | no_think | no_think prepends /no_think to the prompt. This helps some Qwen reasoning models output final content. Use normal for models that do not understand /no_think. |
| image_format | COMBO | data_uri_jpeg | How the image is embedded in the request. data_uri_jpeg sends data:image/jpeg;base64,... data_uri_png sends data:image/png;base64,... raw_base64 sends plain base64 only; your LM Studio setup previously rejected this. |
| seed_mode | COMBO | fixed | fixed keeps the same seed value. random creates a new seed on every run and also helps force ComfyUI to re-execute the node. |
| seed | INT | 420–2147483647 | Seed value used when seed_mode is fixed. |
| send_seed_to_lmstudio | COMBO | off | If off, the seed is only used inside ComfyUI. Recommended: off, because some local vision models return empty content when seed is sent. |
| temperature | FLOAT | 0.200–2 | Controls randomness. Lower values are more deterministic. For captioning, 0.1 to 0.4 is usually good. |
| max_tokens | INT | 409632–262144 | Maximum number of output tokens. For reasoning models, use 2048-4096 so the model can finish after reasoning. Actual usable size depends on LM Studio context length. |
| debug_response | COMBO | on | Print the full LM Studio JSON response to the ComfyUI console. |
| fallback_mode | COMBO | final_or_reasoning | final_only uses choices[0].message.content only. final_or_reasoning uses content and falls back to reasoning_content if content is empty. reasoning_only always outputs reasoning_content. german_draft_from_reasoning tries to extract a German draft section from reasoning_content. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| caption | STRING | Caption text returned by LM Studio. |