ComfyUI Node

AQ_Qwen

Run Qwen2.5-VL locally — vision, JSON mode, no API key

By 2frames·Created about a year ago·Updated 6 months ago· 1
AQ_Qwen
  • qwen_model
  • image
  • response
  • formatted_response
prompt
system_messageYou are a helpful assistant.
temperature0.10
max_tokens256
top_p0.001
repetition_penalty1.05
min_pixels224
max_pixels1280
enable_jsonfalse
json_format{ "type": "object", "properties": { "user_idea": { "type": "string" }, "new_scene_description": { "type": "string" }, "new_image_type":{ "type": "string" }, "new_style":{ "type": "string" } }, "required": [ "user_idea", "new_scene_description", "new_image_type", "new_style" ] }
result_template{json[new_scene_description]} in style {json[new_style]}, {json[new_image_type]}

The local-LLM heart of the pack. AQ_QwenLoader gets a Qwen2.5-VL model into VRAM; this node runs inference on it - text or image input, JSON mode, template-formatted output - entirely on your machine. No key, no monthly bill, and your prompts never leave your GPU. Qwen2.5-VL is a vision-language model: it reads images, answers questions about them, and follows instructions, which makes it the natural choice for captioning, describing, and structured extraction inside a ComfyUI workflow.

What it's good at

The defaults tell you what the author built it for: the sample json_format/result_template turns a "user idea" into "new_scene_description in style new_style, new_image_type" - a ready-made idea → image-prompt transformer. Feed it an image and ask for a new scene, and it hands you a prompt string you can pipe straight into a text encoder. But it's a general vision-LLM node; captioning and metadata extraction work just as well.

How it works

It uses HuggingFace transformers (Qwen2_5_VLForConditionalGeneration + AutoProcessor). Images get saved to a temp PNG and loaded via qwen-vl-utils' process_vision_info, so it uses Qwen's own vision processing. Two interesting knobs:

  • min_pixels / max_pixels control the image token budget (the values are squared internally - 224 means 224² = ~50k pixels). Raise max_pixels if the model seems to miss details in large images; lower min_pixels to save memory.
  • enable_json appends your json_format schema into the prompt itself. That's prompt-level JSON, not constrained decoding - a weaker model may not obey. Then result_template formats the parsed JSON with {json[field]} placeholders; a missing field produces a helpful error string instead of a crash.

Generation uses temperature (default 0.1), top_p (default 0.001 - near-greedy), repetition_penalty (1.05), and max_tokens (256).

Inputs

qwen_model (from AQ_QwenLoader - this node doesn't load models), prompt, system_message, temperature, max_tokens, top_p, repetition_penalty, min_pixels, max_pixels, enable_json, json_format, result_template, and an optional image.

Outputs

response (raw text) and formatted_response (template-applied).

Install

Part of AQnodes:

cd ComfyUI/custom_nodes
git clone https://github.com/2frames/ComfyUI-AQnodes
cd ComfyUI-AQnodes
pip install -r requirements.txt

or search "AQnodes" in ComfyUI Manager and restart. The requirements include transformers>=4.51.3, accelerate, qwen-vl-utils, and qwen-vl-utils[decord] - decord is the video-loading extra and one of the more finicky wheels to install.

Gotchas

This is the heavy one. The model sits in VRAM for the whole session, and the 7B/32B 4-bit variants are real memory hogs (32B needs ~20GB+). It doesn't ride ComfyUI's text-encoder VRAM management, so plan around it. JSON is prompt-guided, not guaranteed - if formatted_response comes back with a KeyError message, that's the model ignoring the schema. And the near-deterministic default settings (temperature 0.1, top_p 0.001) make outputs very stable; raise temperature if everything starts to feel samey.

CategoryAQ/LLM

Inputs (13)

NameTypeDefaultDescription
qwen_modelQWEN_MODEL
promptSTRING
system_messageSTRINGYou are a helpful assistant.
temperatureFLOAT0.100–2
max_tokensINT2561–2048
top_pFLOAT0.0010–1
repetition_penaltyFLOAT1.051–2
min_pixelsINT22416–1280
max_pixelsINT1280224–2048
enable_jsonBOOLEANfalse
json_formatSTRING{ "type": "object", "properties": { "user_idea": { "type": "string" }, "new_scene_description": { "type": "string" }, "new_image_type":{ "type": "string" }, "new_style":{ "type": "string" } }, "required": [ "user_idea", "new_scene_description", "new_image_type", "new_style" ] }
result_templateSTRING{json[new_scene_description]} in style {json[new_style]}, {json[new_image_type]}
imageoptIMAGE

Outputs (2)

NameTypeDescription
responseSTRING
formatted_responseSTRING