FL PenguinVL Batch Image Query
One prompt, a whole batch of images, answers for each
- model
- images
- text
FL PenguinVL Batch Image Query is the same idea as the single-image node, minus the manual labor: feed it a whole batch of images and one prompt, and it queries every image independently, then returns all the answers joined into one text blob. This is the node you reach for when you've just rendered ten variations of a character and want each one captioned, or when you're pre-labeling a small dataset for LoRA training and don't want to run a loop by hand.
How it works
It's Image Query with a for loop around it. For each frame in the batch, the node converts the tensor to PIL, applies the resize if you set one, builds the same system-prompt-plus-image-plus-prompt message, runs generation, and appends the result. Then it joins everything with the separator string - default \n---\n - and returns the lot as one STRING, with a progress bar that tracks how many images you've burned through.
Two things worth internalizing. It is sequential: each image gets its own full generation pass, so N images costs roughly N times the time of a single query. It is not a batched forward pass, and you should not expect dataset-tool throughput. For a few dozen images it's great; for thousands you'll want to script it or accept the wait. And because everything lands in one string, you parse results by that separator downstream - which is why touching the separator to something you can split on cleanly is a legit move.
Inputs that matter
Required: model, images (the whole IMAGE batch - unlike the single-image node, this one genuinely walks every frame), and prompt.
The optional set overlaps Image Query, with two differences worth flagging:
- separator - the string placed between each image's result. Default
\n---\n; make it something unambiguous if you're going to split it programmatically. The tooltip says it plainly: "Separator between results for each image." - max_new_tokens defaults lower here (256 vs 512 on the single node), and that's a sensible call - one verbose 1000-token caption would drown the other results in a joined string. Raise it per-batch if your answers are truncating.
- max_long_side - same 512 default, same 0 = no resize, and even more worth setting sensibly here since every image in the batch pays the resize cost. Large images slow the whole batch down.
- system_prompt, temperature, top_p, do_sample - identical semantics to the single-image node; flip
do_sampleto False if you want the same label for the same image across runs.
Output is text: one STRING, all results separated.
Getting the images in
Any node that outputs an IMAGE batch works - that's how you pass in a folder of renders or the frames of a video if you want to caption frames. The install is the pack install: ComfyUI Manager → "FL PenguinVL", or git clone https://github.com/filliptm/comfyui-fl-penguinvl into custom_nodes, pip install -r requirements.txt, restart.
Where people trip up
The batch is only as fast as its slowest member - a 4K image at default settings bogs the whole run down, so trim max_long_side first. And remember the model swap: if you batch with the 8B variant on a small card, you're not just slow, you're likely out of VRAM. Drop to the 2B for bulk work and it'll chew through the batch comfortably. Also don't be surprised the output is one block rather than per-image nodes - that's the design, and the separator is the split point. It's a blunt instrument compared to a real labeling pipeline, but for "caption all ten of these right now," it's the fastest path in the pack.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| model | FL_PENGUINVL_MODEL | — | |
| images | IMAGE | — | |
| prompt | STRING | Describe this image. | — |
| system_promptopt | STRING | — | |
| max_new_tokensopt | INT | 2561–4096 | — |
| temperatureopt | FLOAT | 0.700–2 | — |
| top_popt | FLOAT | 0.900–1 | — |
| do_sampleopt | BOOLEAN | true | — |
| separatoropt | STRING | --- | Separator between results for each image |
| max_long_sideopt | INT | 5120–2048 | Resize long side of each image to this value. 0 = no resize. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |