From ebc552627c1bb79c97ec6aa6c2aca10ab5f4faae Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Sat, 27 Jun 2026 08:28:29 +0200 Subject: [PATCH] Release 1.0.4: vision_position switch, prompt debug output - vision_position: place image tokens before/after the manual prompt - print_prompt: dump the assembled Qwen3-VL prompt to the console - new vlm_prompt STRING output: the full assembled prompt for inspection Co-Authored-By: Claude Opus 4.8 --- README.md | 5 +++++ nodes.py | 31 +++++++++++++++++++++++++++---- pyproject.toml | 2 +- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ef1ff2e..869a056 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,13 @@ downstream of this node — that works generically at the sampler level.) | `mask1…N` | MASK | Optional per-image mask; crops `imageN` to the masked bounding box. | | `mask_padding` | FLOAT | Context kept around the mask, as a fraction of image size per side (`0` = tight, default). | | `system_prompt` | STRING input | Optional. Wire a text node to override the system instruction; unconnected = Krea2's default descriptor. See below. | +| `vision_position` | CHOICE | Image tokens `before prompt` (default) or `after prompt` in the user turn. | +| `print_prompt` | BOOLEAN | Print the assembled Qwen3-VL prompt to the ComfyUI console (debug). | | `vision_megapixels` | FLOAT | Max size before the vision encoder; references are downscaled to this cap, never upscaled (default `1.0`). | +**Outputs:** `conditioning` (for the Krea2 sampler) and `vlm_prompt` (STRING — the full assembled +prompt as the Qwen3-VL encoder receives it; wire to a text-preview node to inspect it). + ## System prompt (making the prompt interact with the image) `system_prompt` is a connectable text **input**, not a widget — leave it unconnected to use diff --git a/nodes.py b/nodes.py index 572b834..5974552 100644 --- a/nodes.py +++ b/nodes.py @@ -88,10 +88,22 @@ class TextEncodeKrea2: "image size added on EACH side. 0 = tight crop to the mask; 0.1 = ~10% " "margin of surroundings. Only applies when a mask is connected.", }), + "vision_position": (["before prompt", "after prompt"], { + "default": "before prompt", + "tooltip": "Where the image (vision) tokens sit in the user turn relative to your " + "text. 'before prompt' = image then text (default); 'after prompt' = text " + "then image. No effect without an image. Experimental.", + }), + "print_prompt": ("BOOLEAN", { + "default": False, + "tooltip": "Print the full assembled prompt sent to the Qwen3-VL encoder (system " + "instruction + vision placeholders + your text) to the ComfyUI console.", + }), }, } - RETURN_TYPES = ("CONDITIONING",) + RETURN_TYPES = ("CONDITIONING", "STRING") + RETURN_NAMES = ("conditioning", "vlm_prompt") FUNCTION = "encode" CATEGORY = "model/conditioning/krea2" DESCRIPTION = ("Krea2 (K2) text conditioning with optional vision prompting. Reference images are " @@ -145,7 +157,8 @@ class TextEncodeKrea2: return image[:, y0:y1 + 1, x0:x1 + 1, :] def encode(self, clip, prompt, vision_megapixels=1.0, mask_padding=0.0, - system_prompt=KREA2_SYSTEM_DEFAULT, **kwargs): + system_prompt=KREA2_SYSTEM_DEFAULT, vision_position="before prompt", + print_prompt=False, **kwargs): images = self._collect_indexed(kwargs, "image") masks = self._collect_indexed(kwargs, "mask") ordered = sorted(images.keys()) @@ -176,7 +189,17 @@ class TextEncodeKrea2: system = system_prompt.strip() or KREA2_SYSTEM_DEFAULT template = ("<|im_start|>system\n" + system + "<|im_end|>\n" "<|im_start|>user\n{}<|im_end|>\n<|im_start|>assistant\n") - tokens = clip.tokenize(image_prompt + prompt, images=images_vl, llama_template=template) + text = (prompt + image_prompt) if vision_position == "after prompt" else (image_prompt + prompt) + # literal replace (not .format): safe with braces in the text/system prompt. + assembled = template.replace("{}", text, 1) + + if print_prompt: + print("\n========== Text Encode (Krea2) -> Qwen3-VL prompt ==========") + print(assembled) + print("---- references: {} ----".format(len(images_vl))) + print("===========================================================\n") + + tokens = clip.tokenize(text, images=images_vl, llama_template=template) try: conditioning = clip.encode_from_tokens_scheduled(tokens) except NotImplementedError as exc: @@ -193,7 +216,7 @@ class TextEncodeKrea2: "text-only prompts." ) from exc raise - return (conditioning,) + return (conditioning, assembled) class Krea2SystemPrompt: diff --git a/pyproject.toml b/pyproject.toml index ecc5a9a..9e8e34a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-krea2-text-encoder" description = "Vision-aware text conditioning for the Krea2 / K2 model. Feeds reference images through the Qwen3-VL-4B vision path with the Krea2 descriptor template; optional per-image mask crops to the masked region. No VAE (Krea2 has no reference-latent pathway). Auto-growing image+mask slots." -version = "1.0.3" +version = "1.0.4" license = "MIT" requires-python = ">=3.10" dependencies = []