DAAM Tag Explorer
Click a tag, watch the model's attention light up on the image
- clip
- heatmaps
- images
What it is
DAAM Tag Explorer is the half of the DAAM pair you actually look at. It takes the heatmaps that Sampler Custom (DAAM) captured, plus the prompt and the decoded image, and turns the node body into an interactive viewer: hover the image and a bar chart shows each tag's share of the attention at whatever spot the cursor is on; click a tag and its heatmap is overlaid on the picture; click several and they average.
It's an OUTPUT node with no outputs at all - it renders in the node and changes nothing downstream. Think of it as a stethoscope rather than a tool: you wire it up when a prompt is misbehaving, read the answer, and unwire it. Concrete uses, all of which I've hit on SDXL anime models:
blue eyesshows a cold map andblack eyesis hot - your tag isn't being ignored, it's being outvoted.standinglights up the whole figure instead of the pose - the tag isn't binding the way you assumed.- Two tags light up the same blob, which is attribute bleed: the failure that prompt word order is supposed to fix.
How it works
The prompt gets re-tokenized the way ComfyUI's BREAK-aware text encoder does it: split on BREAK, tokenize each chunk separately, concatenate. That's what makes the token axis line up with the conditioning the sampler actually saw. Embeddings complicate it, because tokenizing embedding:name replaces it with raw vectors and throws the name away - the node stashes the names on the way through and reads them back, so an embedding shows up as [emb] name instead of silently vanishing.
Then it walks that flat token stream and cuts it at comma tokens (found by tokenizing a bare ,) into tags. A "tag" here is literally whatever sits between commas, and each tag's map is the mean over its own token indices. On SDXL the split follows the CLIP-L token stream, so what you're reading is CLIP-L's view of your prompt.
Per image in the batch it writes a PNG plus one .npy of the stacked tag maps at the native image/16 grid into the temp directory, and all the interaction runs client-side. That's a deliberate trade: full-resolution maps for every tag would be hundreds of megabytes per image, this is a few hundred kilobytes, and the bar chart updates without a server round trip.
In the viewer, the tiers are relative to an even split rather than fixed numbers - with N tags, an indifferent attention cell gives every tag 1/N, so blue means over 2/N and yellow over 1/N. That's right, since a fixed cutoff would change meaning with prompt length. The overlay is a jet colormap blended at constant alpha (the original DAAM look), with strength and smooth sliders and a grid of the attention cells so a reading in the side panel maps to a cell you can point at.
Inputs that matter
clip- the CLIP model that encoded the prompt. Use the same one the sampler used.text- the same prompt string that was encoded, BREAK separators included. It's a forced input, so you wire it; you can't type it.heatmaps-pos_heatmapsfrom Sampler Custom (DAAM).images- the decoded images, i.e. the far end ofoutput→ VAE Decode → this.
No outputs.
The one trap worth memorising
text must be the exact string that got encoded. Not the version after your tag processor expanded wildcards, not the one with the blacklist applied, not the one with underscores swapped - the same string. The node builds a tag → token-index mapping by tokenizing, and if the string differs by even one tag, every label lands on the wrong row of the heatmap and you'll draw confident, wrong conclusions. Feed the explorer and the CLIPTextEncode from the same upstream node, not two nodes that are supposed to produce the same text.
Install
ComfyUI Manager: search ComfyUI-Alchemine-Pack, or:
cd ComfyUI/custom_nodes
git clone https://github.com/alchemine/comfyui-alchemine-pack
cd comfyui-alchemine-pack
pip install -r requirements.txt
Restart ComfyUI. Nothing to download - no models, no keys, no server. The pack's only declared dependency is python-dotenv, which belongs to its API and Grok nodes. Requires Python 3.12+ per the pack metadata.
Troubleshooting
"DAAM: no attention heatmaps were collected during sampling." The heatmaps socket is empty. Check that pos_heatmaps is actually connected from Sampler Custom (DAAM) - this is also what you'll see if the sampler skipped capture because nothing was wired at queue time.
"DAAM: could not split the prompt into tags." The node dumps diagnostics with it (tokenizer stream, chunk count, token and content-token counts, the first token ids). In practice it means the text isn't a comma-separated prompt, or the CLIP you plugged in isn't the family that encoded it.
Everything is one flat smear. Usually a very long prompt: dozens of tags each holding a small share of every cell, so nothing looks hot. Trim to the five tags you care about and re-read - a tidy 8-tag prompt is what this tool is good at. And if the node body renders as an empty box, the pack's frontend script didn't load; check the browser console.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | The CLIP model that encoded the prompt. | |
| text | STRING | The same prompt that was encoded for sampling, BREAK separators included. | |
| heatmaps | HEATMAP | pos_heatmaps from 'Sampler Custom (DAAM)'. | |
| images | IMAGE | The decoded images. |
Outputs (0)
No outputs