feat: add support batch images. v1.3.0

This commit is contained in:
KingManiya
2026-04-23 20:27:06 +04:00
parent 512c3f6906
commit a04d1eae2b
4 changed files with 26 additions and 20 deletions
+8 -5
View File
@@ -6,14 +6,16 @@ Qwen3-VL, Qwen3.5, Qwen3.6, Gemma 4, and gpt-oss.
This extension adds a local LLM node for prompt writing, prompt rewriting,
translation, captioning, extraction, and other text processing tasks inside
ComfyUI. It discovers local GGUF models from `ComfyUI/models/LLM`, and it can
also accept an image for multimodal models that use an external `mmproj`.
also accept a single image or a ComfyUI image batch for multimodal models that
use an external `mmproj`.
![Node UI](https://raw.githubusercontent.com/KingManiya/ComfyUI-LLM-text-processor/refs/heads/images/images/node.png)
## Features
- Text generation and text transformation with local GGUF models
- Optional image input for multimodal llama.cpp models that use `mmproj`
- Optional image input for multimodal llama.cpp models that use `mmproj`,
including multi-image batches
- Separate `RESPONSE` and `REASONING` outputs
- System prompt presets from text files
- Recursive model discovery from `ComfyUI/models/LLM`
@@ -106,7 +108,8 @@ The `model` dropdown shows model `.gguf` files. The `mmproj` dropdown shows
vision projector files and `none`.
For image workflows, choose the `mmproj` file that belongs to the selected
model. The node uses only the first image from a ComfyUI image batch.
model. You can connect either one image or a ComfyUI image batch; batch items
are sent together in the same llama.cpp request.
## System Prompt Presets
@@ -204,7 +207,7 @@ Reference: [gpt-oss docs](https://github.com/openai/gpt-oss)
| Input | Description |
| --- | --- |
| `model` | GGUF model file from `ComfyUI/models/LLM`. |
| `mmproj` | Vision projector GGUF. Required when using image input. |
| `mmproj` | Vision projector GGUF. Required when using image input, whether it is one image or a batch. |
| `system_prompt` | Prompt preset from `models/LLM/prompts`, or `none`. |
| `prompt` | User prompt sent to the selected model. |
| `max_tokens` | Maximum generated tokens. |
@@ -219,7 +222,7 @@ Reference: [gpt-oss docs](https://github.com/openai/gpt-oss)
| `seed` | Random seed. Use `-1` for a random seed. |
| `timeout_seconds` | Maximum runtime before generation is stopped. |
| `reasoning` | Reasoning output mode: `auto`, `on`, or `off`. |
| `image` | Optional ComfyUI image input. Uses the first image in a batch. |
| `image` | Optional image input. Accepts a single image or a ComfyUI batch, and sends the batch together to llama.cpp. |
| `enable_processing` | When enabled, the node runs normally. When disabled, the node forwards `prompt` directly to `RESPONSE` and skips all model checks and llama.cpp execution. |
| `extra_args` | Optional advanced llama.cpp parameters. Leave empty for normal use. |
+13 -10
View File
@@ -27,14 +27,10 @@ LLAMA_SEED_MODULUS = 2**32
MAX_LLAMA_SEED = LLAMA_SEED_MODULUS - 1
def tensor_to_temp_png(image) -> Path:
def _tensor_to_temp_png(tensor) -> Path:
import numpy as np
from PIL import Image
# ComfyUI IMAGE is normally B,H,W,C. The node uses the first batch item in v1.
tensor = image
if hasattr(tensor, "dim") and tensor.dim() == 4:
tensor = tensor[0]
array = (tensor.detach().cpu().numpy() * 255).clip(0, 255).astype(np.uint8)
pil_image = Image.fromarray(array)
fd, path = tempfile.mkstemp(prefix="llm-text-processor-", suffix=".png")
@@ -43,6 +39,13 @@ def tensor_to_temp_png(image) -> Path:
return Path(path)
def tensor_to_temp_pngs(image) -> list[Path]:
# ComfyUI IMAGE is normally B,H,W,C. Each batch item becomes one CLI image.
if hasattr(image, "dim") and image.dim() == 4:
return [_tensor_to_temp_png(tensor) for tensor in image]
return [_tensor_to_temp_png(image)]
def _write_temp_text_file(prefix: str, text: str) -> Path:
fd, path = tempfile.mkstemp(prefix=prefix, suffix=".txt")
os.close(fd)
@@ -92,12 +95,12 @@ def build_command(
) -> tuple[list[str], tuple[Path | None, ...]]:
cleanup_paths = []
cli_paths = ensure_llama_cli_paths()
image_path = None
image_paths = []
if image is not None:
if mmproj_path is None:
raise ValueError("Image input requires a selected mmproj GGUF file.")
image_path = tensor_to_temp_png(image)
cleanup_paths.append(image_path)
image_paths = tensor_to_temp_pngs(image)
cleanup_paths.extend(image_paths)
prompt_path = _write_prompt_file(prompt)
cleanup_paths.append(prompt_path)
@@ -128,9 +131,9 @@ def build_command(
command.extend(["-f", str(prompt_path)])
if image_path:
if image_paths:
command.extend(["--mmproj", str(mmproj_path)])
command.extend(["--image", str(image_path)])
command.extend(["--image", ",".join(str(path) for path in image_paths)])
if extra_args:
command.extend(extra_args)
+4 -4
View File
@@ -27,7 +27,7 @@ class LLMTextProcessor:
}),
"mmproj": (mmproj_options(), {
"default": NO_MMPROJ,
"tooltip": "Vision projector GGUF. Required when an image is connected.",
"tooltip": "Vision projector GGUF. Required when one or more images are connected.",
}),
"system_prompt": (system_prompt_options(), {
"tooltip": "System prompt preset from ComfyUI/models/LLM/prompts, or none.",
@@ -74,9 +74,9 @@ class LLMTextProcessor:
"ctx_size": ("INT", {
"default": 8192,
"min": 512,
"max": 131072,
"max": 1048576,
"step": 512,
"tooltip": "Context window size in tokens.",
"tooltip": "Context window size in tokens. Use a value supported by the selected GGUF; larger context uses more VRAM.",
}),
"memory_mode": ([
"auto",
@@ -121,7 +121,7 @@ class LLMTextProcessor:
},
"optional": {
"image": ("IMAGE", {
"tooltip": "Optional ComfyUI image input. Uses the first image in the batch.",
"tooltip": "Optional image input. A single image or ComfyUI batch is passed to llama.cpp.",
}),
"enable_processing": ("BOOLEAN", {
"default": True,
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "ComfyUI-LLM-text-processor"
description = "Process text and images with GGUF LLMs in ComfyUI using llama.cpp, including Qwen3-VL, Qwen3.5, Qwen3.6, Gemma 4, and gpt-oss."
version = "1.2.0"
version = "1.3.0"
license = {file = "LICENSE"}
dependencies = ["numpy", "Pillow"]