JoyAI_Image_Understand
The half of JoyAI-Image nobody talks about — the VLM that talks back
- clip
- image
- response
"JoyAI" in the name isn't just branding - the model genuinely has two halves, and this node is the half that understands. Feed it an image and a question or instruction, and instead of conditioning tensors you get back a plain string answer. It's a full vision-language chat turn using the same Qwen3-VL text encoder the generation side runs on, which is why the pack's example workflow wires the second JoyAI_Image_SM_Clip loader into this node alongside the generation branch. It's a captioner, a spatial-relationship question answerer, and a prompt-engineering assistant rolled into one.
The mechanism is a plain autoregressive generation pass: your image is resized and tokenized as <image> content, your prompt becomes the user turn in a Qwen3 chat template, and the model samples tokens one at a time under the usual decoding knobs until it hits the stop. Because it's real text generation rather than embedding extraction, it's surprisingly memory-hungry for a "just answer a question" node - the whole VLM has to be live for the pass, not just its encoder front-end. If the generation half of the workflow is already taxing your card, running this at the same time will feel it.
Inputs that matter
clip- the Qwen3-VL fromJoyAI_Image_SM_Clip. Required.image- required here (unlike the ENCODER, where it's optional). This node is pointless without something to look at.prompt- the question or instruction. The default, "Turn the plate blue", is the pack's edit demo prompt leaking in; for the understanding mode you'd more likely ask "What color is the plate?" or "Describe the spatial layout."max_new_tokens(default 2048) - how long an answer it's allowed to write. Crank down for short factual answers; you don't need a 2048-token essay to learn the plate is blue.temperature(0.7),top_p(0.8),top_k(50) - the usual decoding knobs. Lower temperature for deterministic descriptions; you'll rarely touch the others.infer_device-cudaorcpu. CPU works for short generations but it's slow; if the generation branch is hogging the GPU, this is your escape hatch.
What you actually get
One output: response, a STRING. Wire it into any text display or preview node. There's a genuinely useful loop here: ask the model what's in an image, feed that description back into the ENCODER as a better prompt, and generation quality jumps - you're using the understanding half to feed the generation half, which is exactly what a unified model is for.
Install
Same as every node in the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_JoyAI_Image
cd ComfyUI_JoyAI_Image
pip install -r requirements.txt
restart ComfyUI, and make sure the text encoder weights are present (JoyAI-Image-Und-merger_bf16.safetensors in models/clips, or the Q6_K GGUF in models/gguf). The transformers>=4.57,<4.58 pin matters double here, because the VLM loads through transformers - a version drift is the most likely reason this node errors while the rest of the pack works.
Where people get burned
The most common mistake is treating it as a captioner for arbitrary images and expecting surgical accuracy on tiny details - VLMs at this size hallucinate on small text and fine textures, same as any 4B-class vision model. Ask about spatial relationships and object layout, which is what JoyAI-Image was trained to excel at, and it's genuinely impressive. Also: because it shares the encoder with the generation side, a second JoyAI_Image_SM_Clip instance means two copies of a multi-GB model resident unless you're careful with offload - one loader feeding both nodes through a reroute is the leaner setup.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| image | IMAGE | — | |
| prompt | STRING | Turn the plate blue | — |
| max_new_tokens | INT | 2048256–16384 | — |
| temperature | FLOAT | 0.700–1 | — |
| top_p | FLOAT | 0.800–1 | — |
| top_k | INT | 501–200 | — |
| infer_device | COMBO | 2 options: cuda, cpu |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| response | STRING | — |