Nodes/ComfyUI_RS_NAI_API_Request/NAI WD Tagger Loader (PyTorch)
ComfyUI Node

NAI WD Tagger Loader (PyTorch)

The One Node in a NovelAI Pack That Never Phones Home

By raspie10032·Created about a year ago·Updated about 20 hours ago· 7
NAI WD Tagger Loader (PyTorch)
    • RS_WD_TAGGER
    device
    batch_size4

    Everything else in ComfyUI_RS_NAI_API_Request wants your NovelAI token and spends Anlas. This one doesn't. No prompt fields, no seed, no model dropdown, no NovelAI request at all - it just hands the rest of the pack a WD image tagger to think with. The point is the wiring: it lets the Detailer work out which of your character prompts belongs to a given face crop.

    Why anyone needs this

    NovelAI V4 and later take multiple character prompts with X/Y coordinates, and they're good at it - people keep asking r/comfyui how to get that multi-character handling locally. This pack ports the system over: up to five character slots, each with its own positive and negative prompt.

    Detailing is where it gets awkward. YOLO finds four faces and you have to inpaint each with the right character prompt. Hand them all the same prompt and the attributes bleed - hair color, outfit, who's wearing what - the oldest unsolved problem in multi-subject generation. NovelAI's coordinates don't rescue you, either: the README is explicit that full-image coordinates are not reused for a crop.

    So you need something that can look at a crop of a girl with purple hair and a bow and say "that's the purple hair, bow slot." That's a booru tag job. Set detail_mode=all and matching_mode=wd14 on a Detailer, wire this loader into its tagger socket, and each region gets matched to a slot automatically.

    How it works

    The loader runs SmilingWolf/wd-vit-tagger-v3 natively in PyTorch - no ONNX Runtime, which is why the author wrote a fresh implementation instead of reusing the WD14 nodes already out there. On the first match it pulls config, weights and tag vocabulary from one pinned HuggingFace revision into ComfyUI/models/rs_wd_tagger, then does the usual dance: composite the crop onto white, pad it square, run the ViT, sigmoid the outputs.

    It keeps only tag categories 0 and 4 - general and character. Artist, franchise and rating tags are dropped before matching sees them. The ranking compares your prompt's visible attributes against what's left, ignores tags shared across slots, discounts eye colors, and skips counts and quality words. Score above 0.25 with a 0.08 margin over the runner-up and the region is assigned; still ambiguous after one retry at a tighter crop, and the region is skipped, its pixels preserved. No manual mapping widget, no forced-ordering fallback.

    And the rule people get wrong: tagger scores never become prompt text. No purple_hair gets appended to your positive or negative. The match only picks a slot; the request then uses that slot's original prompt verbatim, franchise names and all, including for characters the tagger has never heard of.

    The two inputs, one output

    • device - auto (ComfyUI's selected torch device) or cpu. auto is fine on a normal GPU: the loader asks Comfy's model management for free memory before moving weights over, then offloads them back to CPU, so it isn't squatting in VRAM next to SAM.
    • batch_size - default 4, range 1–16. Region crops per forward pass. Lower it on a small card.

    The single output is RS_WD_TAGGER, wired into the tagger input of the pack's Detailer nodes (which also need matching_mode=wd14). Ordinary generation and shared-prompt detailing never touch any of this.

    Installing it

    Manager → search ComfyUI_RS_NAI_API_Request, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/raspie10032/ComfyUI_RS_NAI_API_Request.git
    pip install -r ComfyUI_RS_NAI_API_Request/requirements.txt
    

    The tagger is a separate, optional dependency set, and it has to go into the Python environment actually running ComfyUI:

    python -m pip install -r ComfyUI_RS_NAI_API_Request/requirements-tagger.txt
    

    That's timm, huggingface-hub and safetensors - deliberately not ONNX, reusing your existing torch. Weights download themselves on first use, into ComfyUI/models/rs_wd_tagger.

    Where people get burned

    The loader lies about failing. load() never imports timm. The error only fires on the first WD match, mid-run: WD matching requires requirements-tagger.txt in the ComfyUI Python environment. Portable build, venv, wrong interpreter - you'll meet it the moment you finally test the workflow.

    First match is slow and needs internet. Weights come off HuggingFace, and CPU inference afterwards isn't free. Do a throwaway run before queueing a batch.

    Changing batch_size or device rebuilds the tagger - the cached instance is keyed on those values. Harmless; just don't be alarmed when the log reloads it.

    v3's vocabulary has a cutoff - February 2024. Great on established Danbooru characters, useless on newer ones, so similar characters can stay ambiguous and get skipped rather than guessed. For eyes, the README suggests a face detector as primary and an eye detector on the refinement socket, so matching sees a head, not just an iris.

    It is not an interrogator. You can't get tag text out of this node - it emits a tagger object for the Detailer, full stop. For captioning, you want a different pack; probably a WD tagger plus Florence-2.

    Bottom line

    A boring node that solves the ugliest part of multi-character detailing: which face belongs to which prompt. Two widgets, one output, no API key. Install the optional deps in the right Python, expect a slow first match, and let the Detailer do the rest.

    CategoryRS_NovelAI_API/FaceDetailer

    Inputs (2)

    NameTypeDefaultDescription
    deviceCOMBO2 options: auto, cpu
    batch_sizeINT41–16

    Outputs (1)

    NameTypeDescription
    RS_WD_TAGGERRS_WD_TAGGER