From fee136e98c78378027c504b344ffeef178049757 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Sat, 27 Jun 2026 10:49:37 +0200 Subject: [PATCH] Expose long-text fields as input sockets (forceInput) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit axes, reference_description, system_prompt, user_prompt now render as INPUT SOCKETS (forceInput) so they can be wired from other nodes — e.g. describe's canonical output -> compare's reference_description, or a text node -> chat prompts. Small config (report_dir, run_tag, model_path, ...) stays as typeable fields. Unconnected sockets fall back to sensible defaults; the agent/bridge can still set them by value via the API. Dropped the now-socket fields from the example workflows; bumped their max_new_tokens to 2048. Co-Authored-By: Claude Opus 4.8 --- README.md | 7 ++++--- nodes/qwen_judge.py | 24 ++++++++++++------------ workflow/workflow_api.json | 6 ++---- workflow/workflow_describe_api.json | 3 +-- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f077520..6ba91bc 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,15 @@ can act on it. | `model_select` | dropdown (model name) | 4B local | **which judge** (transformers/safetensors, auto-downloaded): Qwen3-VL 4B/8B/30B-A3B, **Qwen3.5-9B**, **Qwen3.6-27B/35B-A3B** (newer, natively multimodal). Param size shown in the label | | `precision` | bf16 / fp8 / nf4 | bf16 | **the quant** — applies to the selected model (VRAM table below) | | `model_path` | STRING | "" (empty) | **manual override** of the dropdown — local dir, HF repo id, or alias (`8b`/`30b-a3b`/`3.5-9b`/`3.6-27b`/`3.6-35b`). Empty = use `model_select` | -| `axes` | STRING | "" (empty) | **override** the profile's axis set with a custom comma/newline list; empty = use `profile` | +| `axes` | STRING **input** | — | (socket) optional override of the profile's axis set; wire a text node or leave unconnected to use `profile` | | `max_new_tokens` | INT | 2048 | raise it if a reasoning model (Qwen3.5/3.6) gets cut off before finishing | | `temperature` | FLOAT | 0.0 | 0 = greedy/repeatable | | `swap_eval` | BOOL | true | run twice with images swapped, average → cuts position bias | | `keep_loaded` | BOOL | true | cache weights across loop iterations | | `auto_download` | BOOL | true | if `model_path` is a repo id/alias and not local, fetch it from HF into `models/prompt_generator/` | -| `system_prompt` | STRING | "" | **chat mode**: your system prompt | -| `user_prompt` | STRING | "Describe this image." | **chat mode**: your instruction over the image(s) | +| `system_prompt` | STRING **input** | — | (socket) chat mode: wire your system prompt from a text node | +| `user_prompt` | STRING **input** | — | (socket) chat mode: wire your instruction from a text node | +| `reference_description` | STRING **input** | — | (socket) compare: wire describe's canonical output here to anchor the reference | **Auto-download:** set `model_path` to `30b-a3b` (alias) or any `org/name` repo id and leave `auto_download` on — the node snapshot-downloads it on first run (into ComfyUI's diff --git a/nodes/qwen_judge.py b/nodes/qwen_judge.py index 965027b..27c5ad9 100644 --- a/nodes/qwen_judge.py +++ b/nodes/qwen_judge.py @@ -795,34 +795,34 @@ class QwenVLImageJudge: {"default": list(MODEL_PRESETS.keys())[0]}), "model_path": ("STRING", {"default": ""}), # manual override (local dir / HF repo / alias) "precision": (["bf16", "fp8", "nf4"], {"default": "bf16"}), - "axes": ("STRING", {"default": "", "multiline": True}), "max_new_tokens": ("INT", {"default": 2048, "min": 64, "max": 8192}), "temperature": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.5, "step": 0.05}), "swap_eval": ("BOOLEAN", {"default": True}), "keep_loaded": ("BOOLEAN", {"default": True}), "auto_download": ("BOOLEAN", {"default": True}), - # The agent reads the analysis from these files after each queue. + # Small config values stay as typeable fields. "report_dir": ("STRING", {"default": ""}), "run_tag": ("STRING", {"default": ""}), - # compare: canonical reference text (from describe). When set, compare - # anchors on it instead of re-reading the reference image each time. - "reference_description": ("STRING", {"default": "", "multiline": True}), - # chat mode: use the node as a general VLM with your own prompts. - "system_prompt": ("STRING", {"default": "", "multiline": True}), - "user_prompt": ("STRING", {"default": "Describe this image.", "multiline": True}), }, - # Only genuine node-to-node wires stay optional (widgets in `optional` render - # as input sockets instead of editable fields in some ComfyUI frontends). + # Long text content is exposed as INPUT SOCKETS (forceInput) so it can be wired + # from other nodes — e.g. describe's canonical output -> reference_description, a + # text node -> system_prompt/user_prompt. Left unconnected, sensible defaults apply + # (empty axes -> profile; empty reference_description -> two-image compare). The + # agent/bridge can still set them by value via the API. "optional": { "generated_image": ("IMAGE",), # required for compare, ignored for describe/chat + "axes": ("STRING", {"forceInput": True}), + "reference_description": ("STRING", {"forceInput": True}), + "system_prompt": ("STRING", {"forceInput": True}), + "user_prompt": ("STRING", {"forceInput": True}), }, } - def judge(self, reference_image, mode, model_path, precision, axes, + def judge(self, reference_image, mode, model_path, precision, max_new_tokens, temperature, swap_eval, profile="general", model_select=MANUAL_CHOICE, generated_image=None, keep_loaded=True, auto_download=True, - report_dir="", run_tag="", reference_description="", + report_dir="", run_tag="", axes="", reference_description="", system_prompt="", user_prompt="Describe this image."): # `axes` overrides the profile when provided; otherwise use the profile's axis set. axis_list = [a.strip() for a in re.split(r"[,\n]", axes) if a.strip()] diff --git a/workflow/workflow_api.json b/workflow/workflow_api.json index 089e70a..7e86cac 100644 --- a/workflow/workflow_api.json +++ b/workflow/workflow_api.json @@ -68,15 +68,13 @@ "model_path": "/media/p5/qwen3vl_4b_abliterated_comfy_convert/hf_bf16", "precision": "bf16", "profile": "general", - "axes": "", - "max_new_tokens": 512, + "max_new_tokens": 2048, "temperature": 0.0, "swap_eval": true, "keep_loaded": true, "auto_download": true, "report_dir": "/media/p5/Comfyui/output/calibrator", - "run_tag": "", - "reference_description": "" + "run_tag": "" }, "_meta": { "title": "Qwen3-VL Image Judge (Calibrator)" } } diff --git a/workflow/workflow_describe_api.json b/workflow/workflow_describe_api.json index d59fb3f..2aa4cd1 100644 --- a/workflow/workflow_describe_api.json +++ b/workflow/workflow_describe_api.json @@ -12,8 +12,7 @@ "profile": "general", "model_path": "/media/p5/qwen3vl_4b_abliterated_comfy_convert/hf_bf16", "precision": "bf16", - "axes": "", - "max_new_tokens": 1024, + "max_new_tokens": 2048, "temperature": 0.0, "swap_eval": false, "keep_loaded": true,