ComfyUI Node

Tags Generator

Let 5.48 Million Danbooru Posts Finish Your Prompt

By alchemine·Created 3 days ago·Updated 3 days ago· 5
Tags Generator
    • text
    text
    n15
    characterstrue
    characters_share0.10
    posetrue
    pose_share0.30
    expressionstrue
    expressions_share0.20
    bodytrue
    body_share0.10
    clothestrue
    clothes_share0.20
    backgroundtrue
    background_share0.10
    lift_threshold0.10
    momentum0.50
    repetition_penalty2.0
    ratingall
    temperature1.00
    top_k0
    top_p0.95
    min_p0.05
    min_count100
    replace_underscorestrue
    filter_tagstrue
    filter_subtagstrue
    filter_copyrighttrue
    order_tagstrue
    blacklist
    seed0

    The single most repeated piece of advice for anime models is also the least actionable: use real Danbooru tags, because the model understands them so much better than your sentences. Great. Now which tags? You know 1girl. You may not know that the wall of furniture you keep getting is because you typed bar and Danbooru spells it bar_(place).

    Tags Generator answers that by counting. Feed it a prompt and it appends 15 tags that statistically travel with what you wrote. No LLM, no API key, no model load - arithmetic over a co-occurrence table built from 5.48M Danbooru posts.

    What it actually does

    The name says generator; the mechanism is a sampler. Tags are drawn one at a time, the way a language model emits tokens: score(t) = log P(t) + Σ log lift(t, context). That's naive Bayes over the corpus. A tag is only a candidate if something already in the prompt pulls it - positive attraction, not merely high frequency - and it's ranked by how much rarer than chance that attraction is. Rare tags get penalised by log P(t), the vocabulary is capped at 20,811 tags, and anything outside it is ignored silently. Each pick then joins the context and re-conditions the next one, which is why the output reads like one scene instead of a shopping list.

    The same statistic that powers the pack's conflict filter runs in reverse here: lift well below 1 means two tags avoid each other, so those candidates get masked and the output can't contradict itself. Rating works on both halves of the table - the numbers come from the matching corpus slice, and tags rated above your request are masked outright.

    It's genuinely the difference between this and the click-and-play prompt pages people share: theirs is a list someone liked, this is measured against your exact prompt.

    The inputs you'll actually touch

    text is a socket (forceInput), so you wire a String primitive or another node's output into it. Its tags condition every pick and are never filtered - they just have to be spelled the way the corpus spells them.

    n (default 15, 0–100) is how many tags get added, counted after post-processing. Set it to 0 and the length is drawn from the corpus, with generation stopping early once nothing is clearly better than chance. Good default for exploring.

    The six category toggles and shares are the real steering wheel, and they work relatively, not as fractions: switch a category off and its share is handed to the ones still on, so you rarely get fewer tags. Defaults are pose 0.3, expressions 0.2, clothes 0.2, characters 0.1, body 0.1, background 0.1; -1 means allowed with no cap. Two gotchas: characters owns the subject itself (1girl, solo), so turning it off removes the gender anchor everything downstream conditions on; and background is really the whole scene - objects and compositions draw on its single budget, which exists precisely to stop an unrestricted draw filling your prompt with furniture.

    momentum (0.5) decides how much each new tag conditions the next: low and the tags have nothing to do with each other, high and it reads as one scene that can wander off into its own subject.

    rating (all by default) is a ceiling, not a target - a nude prompt draws explicit tags, a school uniform one draws none. random rolls the cap from the seed, so a new seed rerolls it.

    The rest of the widgets are for when the output is wrong in one specific way - hover them, the author wrote real tooltips.

    Outputs, install, and the 106MB

    One output, a STRING. The README calls it processed_text; the shipped node names it text - wire that into your positive CLIP Text Encode. Your original tags come first, the drawn ones appended after.

    Install via ComfyUI Manager (search ComfyUI-Generator-Pack), or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/alchemine/comfyui-generator-pack
    

    No pip dependencies, Python ≥3.12. The data is the real install: nothing ships in the repo, and the first run pulls suggest_v1.1.npz at ~106MB from the pack's GitHub releases, plus a 14MB avoidance table and a few small files, each pinned by sha256. The pack's other two nodes - Group Tags (themed lines) and Classify Tags (splits a prompt into buckets) - share the label data and never touch that 106MB.

    Where people get burned

    First run looks hung, then the node does nothing. That's the download - over 100MB, with the only sign a console line, so give it outbound access to github.com once. If the suggestion table is missing or fails to verify, you'll see suggest artifact not found; passing through and your prompt comes back unchanged: the node degrades instead of erroring, so identical output means read the console, not the graph.

    Shorter than n. You'll see only X of Y tags after N rounds -- lower lift_threshold or min_count, or relax blacklist and categories. Causes, in order: a share that ran out of material, a category you switched off, filter_subtags eating a pick because another tag already implies it (keeping white dog over dog), or an aggressive blacklist. Loosen the smallest thing first.

    Every pick is the same idea respelled - blue skin, pale skin, dark skin. That's repetition_penalty, or momentum pulling along the axis it just moved on. Raise the penalty, or lower momentum.

    Tags your model has never learned. Raise min_count above the 100 default; counts are counted within the requested rating tier, so a milder rating already shrinks the pool.

    Same tags every run. That's reproducibility, and the seed reverts it: put the seed on randomize in control_after_generate, and set ComfyUI's "widget control mode" to Before so the number in the box is the one that actually ran. If changing the seed does nothing at all, check temperature - at 0 the node always takes the best candidate and the seed is irrelevant.

    CategoryGeneratorPack/Tags

    Inputs (30)

    NameTypeDefaultDescription
    textSTRINGThe prompt to extend. Its tags condition every pick and are never filtered themselves. Tags outside the 20,811-tag vocabulary are ignored silently -- Danbooru spells a bar 'bar_(place)', not 'bar'.
    nINT150–100How many tags to add, counted after post-processing. 0 = auto: the length is drawn from the corpus and generation also stops early once nothing is clearly better than chance.
    charactersBOOLEANtrueAllow characters tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    characters_shareFLOAT0.10-1–1How much of the output characters may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    poseBOOLEANtrueAllow pose tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    pose_shareFLOAT0.30-1–1How much of the output pose may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    expressionsBOOLEANtrueAllow expressions tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    expressions_shareFLOAT0.20-1–1How much of the output expressions may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    bodyBOOLEANtrueAllow body tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    body_shareFLOAT0.10-1–1How much of the output body may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    clothesBOOLEANtrueAllow clothes tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    clothes_shareFLOAT0.20-1–1How much of the output clothes may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    backgroundBOOLEANtrueAllow background tags at all. Switching it off hands its share to the categories still on rather than shrinking the output.
    background_shareFLOAT0.10-1–1How much of the output background may take, relative to the other categories that are on: with only pose 0.2 and expressions 0.1, ten tags come back 7 and 3. -1 = allowed with no share of its own.
    lift_thresholdFLOAT0.100–0.5Veto strength. A candidate is banned when the corpus expected it alongside a prompt tag often enough (>= 15 posts) and it still came in below this fraction of chance. Raise it when the output contradicts the prompt in ways the data merely discourages; 0.1 only catches pairs that essentially never co-occur.
    momentumFLOAT0.500–1How much each generated tag conditions the ones after it. 0 = every tag answers to the prompt alone and they have nothing to do with each other. 1 = a pick counts as much as a prompt tag, so the output reads as one scene but can wander off into its own subject.
    repetition_penaltyFLOAT2.01–10Divide a tag's odds by this for every tag already in the prompt that varies along the same axis -- the same last word ('<colour> skin'), or the same half of a linking word ('hands on own face' / 'hands on own head'). 2.0 halves them each time, so a second needs twice the evidence the first did and a third needs four times; 1.0 turns it off. Counters momentum, which pulls hardest along the axis it just moved on. Exact repeats are blocked outright and are not what this controls.
    ratingCOMBOallExplicitness ceiling, on both halves of the statistic: the co-occurrence tables come from the matching corpus slice, and tags rated above the request are masked. It is a ceiling, not a target, so a named rating also gets a nudge toward itself -- 'explicit' would otherwise merely permit rather than lean. 'all' caps and favours nothing, leaving the prompt to decide: a nude prompt draws explicit tags, a school uniform one draws none. 'random' picks one of the four from the seed instead, each equally likely -- a capped draw every time, but a different cap on the next seed.
    temperatureFLOAT1.000–5Sampling randomness. 0 = always take the best candidate, which makes the seed irrelevant and every run identical. Higher spreads the picks over weaker candidates.
    top_kINT00–500Sample from this many best candidates per step. 0 = no limit. Ignored at temperature 0.
    top_pFLOAT0.950–1Keep the best candidates adding up to this much probability. 1.0 = no limit. Watch out for 0, which leaves exactly one candidate and turns sampling back into greedy picking.
    min_pFLOAT0.050–1Drop candidates below this fraction of the best candidate's probability. 0 = off.
    min_countINT100100–1000000Ignore tags with fewer than this many posts in the requested rating tier. The default is the vocabulary floor, i.e. no filtering. Raise it when a prompt keeps surfacing tags too obscure for your model to have learned.
    replace_underscoresoptBOOLEANtrueWrite tags as 'blue eyes' rather than 'blue_eyes'.
    filter_tagsoptBOOLEANtrueDrop duplicates and blacklisted tags from the finished prompt.
    filter_subtagsoptBOOLEANtrueDrop tags another tag already implies, keeping 'white dog' over 'dog'. It can eat a pick the sampler just made, which is why the node asks for replacements until n survive.
    filter_copyrightoptBOOLEANtrueDrop candidate tags owned by one character or one franchise -- a tag whose posts mostly carry the same character (crescent hat ornament) or the same copyright (mini hakkero). Keeps a library from turning into Patchouli's library. Tags you typed yourself are never dropped.
    order_tagsoptBOOLEANtrueReturn the added tags grouped by kind -- subject, body, expressions, pose, clothes, scene -- so the same settings put the same kinds of tag in the same place. Off keeps the order they were drawn. The input prompt is never reordered.
    blacklistoptSTRINGRegex matched against each candidate tag in spaced form, case-insensitively: 'hair|eyes' drops every hair and eye tag. It filters candidates rather than results, so n tags still come back. Use '|', not commas.
    seedoptINT00–18446744073709550000Reproducibility. The same seed and settings always give the same tags -- unless temperature is 0, where the seed does nothing at all.

    Outputs (1)

    NameTypeDescription
    textSTRING