VLM Input Embedding Export
Export the raw embeddings your VLM encoder actually computes
- clip
- State Dict
- Embeddings
Most people never need to see the raw token embeddings their text encoder computes. If you're doing custom conditioning, probing attention, or building training data, you're the exception - and this is the node that hands them to you. UC_VLMInputEmbeds runs a Qwen3-VL encoder on your text and images, and exports the input embeddings as a 2D tensor and a state dict, or saves them straight to disk as a .safetensors file.
What it is
An embedding exporter for supported VLM encoders (the Qwen3-VL family via the pack's UC_Qwen3VLInputEmbeds base). You give it a clip, a text prompt, a list of image_paths, and a list of file_names, and it returns the raw embeddings the encoder would feed into its transformer - before any model layers run. That's the distinction to hold onto: these are input embeddings, not text-encoder output conditioning.
How it works
One important design detail up front: the prompt skips any template wrapping. The tooltip says it plainly - this is the raw prompt, tokenized directly, no <|im_start|> chat scaffolding. If you need the template, that's the job of a different node; this one is for people who want the bare tokens.
The image list and the file-name list must map 1-to-1, line by line. If you supply paths and names for the same images, each image gets tokenized at your chosen vlm_resolution (from the Fast 384 default up to 1536 and Original), and the embeddings are saved under models/embeddings using your file names (subfolders allowed, no .safetensors extension needed). slice_visual_tokens controls whether the first validated visual-token span is stripped from the output or kept in the full interleaved sequence - leave it off to preserve everything.
The node is safety-conscious in a way that matters: it validates every image path before starting any processing, so a typo aborts cleanly instead of half-writing files and leaving your VRAM in a weird state. And it calls clip.load_model() explicitly so the model registers properly as active.
The inputs and outputs that matter
- clip - a Qwen3-VL encoder.
- prompt - raw text, no template wrapping.
- image_paths / file_names - 1-to-1 line-separated lists.
- vlm_resolution - image analysis size.
- slice_visual_tokens - strip the first visual-token span (default off).
- Outputs: State Dict (a dict of
{key_name: tensor_2d}) and Embeddings (the raw[num_tokens, hidden_size]2D tensor).
Installing it
Part of ComfyUI-UtilsCollection:
cd ComfyUI/custom_nodes
git clone https://github.com/silveroxides/ComfyUI-UtilsCollection
Restart ComfyUI (or use Manager, search "ComfyUI-UtilsCollection"). No model downloads beyond the Qwen3-VL encoder you already load, minimal Python deps, and it needs a current ComfyUI.
Common issues
The count-mismatch error is the one everyone hits first - image_paths and file_names must have the same number of lines, exactly. The second is treating this as a conditioning node: it's not. It exports input embeddings for you to do something with; wire the outputs to a probe, a custom patcher, or just save-and-inspect. And mind the VRAM at high vlm_resolution - 1536 on an 8B Qwen3-VL alongside a diffusion model is a real ask. If you only need the saved files, don't bother keeping the outputs wired to anything heavy.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| prompt | STRING | Input text prompt. Important: skips any template wrapping. | |
| image_paths | STRING | Line-separated list of paths to image files. Must map 1-to-1 with file_names. | |
| vlm_resolution | COMBO | Fast (384) | Resolution of the image passed to the VLM (semantic path). |
| file_names | STRING | Line-separated list of file names to save as (without .safetensors). Can include nested subfolders. Must map 1-to-1 with image_paths. | |
| slice_visual_tokens | BOOLEAN | false | If True, removes the first validated visual-token span. If False, preserves the full interleaved sequence. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| State Dict | * | Dictionary structure: {key_name: tensor_2d} of shape [num_tokens, hidden_size] |
| Embeddings | * | Raw PyTorch 2D tensor of shape [num_tokens, hidden_size] |