WD Timm Tagger
WD tagging at 25x speed — the timm-powered tagger that makes dataset captioning painless
- image
- STRING
- RAW
If you train anime LoRAs or reverse-prompt images you like, you already know the WD taggers. SmilingWolf's v3 models are the standard way to turn an image into the Danbooru-style tags that Illustrious, NoobAI, and Pony actually understand - and this node is how you run them when you care about speed. The classic ComfyUI implementation (pythongosssss's WD14 Tagger) gets the job done, but it runs each image through ONNX one at a time. This one loads the same models natively through timm on the GPU ComfyUI already owns, and it batches. The author's benchmark on an RTX 5090 across 291 images with the eva02-large model: 226.99s for the WD14 node, 9.34s here. Take the exact ratio with a grain of salt, but that order of magnitude is real when the model fits on the card.
That's the whole pitch: same tags, roughly 25x faster. When you're about to caption an 800-image LoRA dataset, that's the difference between tagging all afternoon and tagging over a coffee.
How it works
It's a repackaging of neggles' wdv3-timm, so the mechanics are battle-tested. On first use with a given model, the node downloads the snapshot from HuggingFace into ComfyUI/models/wd_taggers/<model_name>/ - just the weights, config, tag CSV, and preprocess info, not the whole repo. The model loads via timm, wrapped in ComfyUI's ModelPatcher so it shares VRAM management with the rest of your graph. Preprocessing follows the WD routine: resize and pad to the model's input size, normalize, and flip to BGR for the models that expect it.
Scoring is where the model's own calibration kicks in. For every tag the effective threshold is max(best_threshold, your slider) - the per-tag threshold the model learned during training acts as a floor. So cranking general_threshold down to 0.05 doesn't dump garbage tags on you; the model quietly refuses to go below what it learned is meaningful. That also means you'll mostly be raising thresholds to clean up output, not lowering them to squeeze out more.
The inputs you'll actually touch are a small set:
model_name- defaults towd-eva02-large-tagger-v3, the best-quality WD v3 model (and heaviest).wd-vit-tagger-v3is the lightweight classic. The dropdown also includes the pixai-tagger and OppaiOracle models, which are fun to play with but less battle-tested.general_threshold(0.35) andcharacter_threshold(0.75) - character tags start higher because a wrong character is worse than a wrong adjective.add_rating- prepends the top rating tag (general/sensitive/nsfw/explicit) when on.exclude_tags- comma-separated, with glob support ("hatsune_miku, *bgm"), handy for stripping artist or copyright tags.batch_size- only does anything when you feed multiple images at once, e.g. from a batch loading node.
Outputs
Two of them, both lists when you feed a batch:
- STRING - the formatted tag line: rating (if enabled), then characters, then general tags, sorted by confidence. This is the one you wire into a display/text node or dump straight into training captions.
- RAW - a dict per image with
ratings,character, andgeneralscore maps, if you want to filter programmatically instead of eyeballing a string.
Install
ComfyUI Manager finds it as "ComfyUI-WD-Timm-Tagger" (display name "WD Timm Tagger"). Manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/bedovyy/ComfyUI-WD-Timm-Tagger
cd ComfyUI-WD-Timm-Tagger
pip install -r requirements.txt
then restart ComfyUI. The requirements file is tiny - timm>=1.0.0 and huggingface_hub>=0.23.0. The real download happens on first run, when the selected model pulls from HuggingFace; eva02-large is over a gigabyte, so give it a minute and make sure you're online.
Gotchas
- First run downloads the model. No internet, no tags. And it keeps its own copy under
models/wd_taggers/even if you already have the WD models from the WD14 node - though dropping an existing folder there makes it appear in the dropdown automatically. - The NaN guard. If a
dtypeproduces non-finite logits (fp16 does on some GPUs), the node hard-errors with a message telling you to try another dtype. Switch tobf16orautoand move on. - Thresholds are floors, not magic. Lowering them below the model's learned best threshold changes nothing - which is a feature, not a bug.
If you tag a handful of images, the classic WD14 node is fine and you don't need this. If you're about to caption a few hundred for training, this is the one that gets it done while you're still setting up your buckets.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| model_name | COMBO | wd-eva02-large-tagger-v3 | 7 options: wd-eva02-large-tagger-v3, wd-vit-large-tagger-v3, wd-vit-tagger-v3, wd-swinv2-tagger-v3, wd-convnext-tagger-v3, pixai-tagger-v0.9-timm, +1 |
| dtype | COMBO | auto | 3 options: auto, bf16, fp16 |
| general_threshold | FLOAT | 0.350–1 | — |
| character_threshold | FLOAT | 0.750–1 | — |
| add_rating | BOOLEAN | false | — |
| exclude_tags | STRING | Exclude tags via comma separation. Glob patterns supported. | |
| batch_size | INT | 41–32 | Only effective when processing image batches. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |
| RAW | DICT | — |