ComfyUI Node

Tags Extractor

Write a sentence, get back the Danbooru tags the model actually knows

By alchemine·Created 12 days ago·Updated a day ago· 5
Tags Extractor
    • processed_text
    • table
    ◄text►
    ◄max_tags20►
    ◄min_count100►
    ◄subjecttrue►
    ◄translatefalse►
    ◄blacklist►

    If you prompt Illustrious, NoobAI or Pony with a sentence, you're speaking the wrong language. Those models learned Danbooru's tag vocabulary, and they understand a real tag far better than the same idea written out as prose. The usual fix - hand the sentence to an LLM and ask for tags - is how you end up with delicate strands of hair, a phrase Danbooru has never seen in its life.

    Tags Extractor goes the other way. It looks your sentence up against the actual tag list, so every tag it returns exists, and nothing comes back that your sentence didn't say.

    What it's actually for

    Translation, mostly. You think in prose, the model thinks in tags. "A girl sitting on a chair by the window at sunset" comes back as 1girl, solo, sitting, on chair, window, sunset - real tags, in the order a Danbooru-trained model wants them.

    The second job is debugging: when a tag keeps appearing out of nowhere, the table output shows every match with the spelling it arrived through, its post count and whether it survived. Almost nothing else gives you that.

    It's also the front end of a chain that ships in the same pack: extract tags here, feed them to Tags Generator to grow the scene, or to Tags Conflict Filter to check them against tags you've pinned.

    How it works

    The vocabulary loads into two in-memory SQLite FTS5 tables - one as written, one under the Porter stemmer - built with the standard library, so no dependency is added. Your sentence is cut into every 1-to-3-word run, and each run is matched only against a tag's whole name, which is why ponytail doesn't drag in high ponytail while low ponytail still lands as one tag. Longer runs claim their words first. The stemmed table is consulted only for inflected runs, because stemming also folds short into shorts. Danbooru's half-alias habit (blonde → blonde hair, sitting on → sitting on person) is trusted only at the end of a run, since sitting on a chair carries on and means something else.

    People are counted, not searched: a girl and two boys becomes 1girl, 2boys, and a lone person also gets solo. no, not and without open a negated span up to the next and/but/with or punctuation - tried as a tag in its own right first, which is why without a hat contributes no hat while no hat returns missing headwear. Object pronouns after a verb read as another (looking at him → looking at another) and take solo away.

    Anything the vocabulary can't spell gets a second pass against first sentences from Danbooru wiki pages, most-posted tag first - leftovers of two words or more only, never single words, because a definition names the things around its tag (chair lives in the definition of sitting).

    Inputs that matter

    • text - the sentence.
    • min_count - default 100, and the knob you'll actually turn. Tags below it are dropped. The author's own example: taking off reaches takeoff (130 posts, an airplane) through the alias take-off; raise it to 500 and the wiki pass gets its turn and returns undressing.
    • max_tags - a ceiling, default 20, applied after the blacklist.
    • subject - the person-count tags. Leave it on for tag models.
    • translate - Google Translate first, via googletrans, one request per run. English gets rewritten too, which helps when you've typed sloppily.
    • blacklist (optional) - a regex matched case-insensitively against each found tag in spaced form. male focus is the canonical use.

    Outputs

    processed_text goes into your CLIP text encoder: comma-joined, always sorted by kind (subject, body, expressions, pose, clothes, background) so the person tags lead.

    table is for you, not the graph: phrase | tag | via | posts | verdict, with verdicts of kept, below min_count, blacklisted or subject off.

    Installing it

    ComfyUI Manager → search ComfyUI-Generator-Pack, restart. Or:

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

    Then restart ComfyUI. It needs Python 3.12+. The pack's only requirement is googletrans, and it's imported inside a try/except - without it everything works except translate, which tells you plainly to install it. If ComfyUI runs in its own venv, that's where it has to land.

    Nothing ships in the repo. Every table and list downloads into custom_nodes/comfyui-generator-pack/resources/ the first time a node needs it, sha256-pinned. Small files come as one ~2MB archive; bigger statistics tables travel separately.

    Where people get tripped up

    • The first run pauses. No progress bar, just a console line. If GitHub is blocked, the wiki pass silently doesn't happen and spelling search still works - the node degrades instead of failing the workflow.
    • A tag seems to come from nowhere. Read the table: a via value other than - means an alias did it, via = wiki means a definition did it.
    • The wiki pass is the junk source. Definitions mention surrounding objects, so on surface can reach condensation. Documented, not a bug - and the table tells you it happened.
    • It can't invent. If Danbooru has no tag for your idea, nothing comes back for it. That's the point of the node - but it won't rescue a concept the vocabulary doesn't cover.
    CategoryGeneratorPack/Tags

    Inputs (6)

    NameTypeDefaultDescription
    textSTRINGA sentence or two describing the scene. Words the vocabulary does not spell are skipped; 'no', 'not' and 'without' drop what follows them.
    max_tagsINT201–100At most this many tags, in reading order.
    min_countINT1000–1000000Ignore tags with fewer than this many posts. 100 is Tags Generator's vocabulary floor; the dump goes down to 20. Raise it when a rare tag's alias catches a phrase -- 'taking off' reaches takeoff (130 posts) through 'take-off'.
    subjectBOOLEANtruePut the person count in front: 'a girl' is 1girl and solo, 'a girl and two boys' is 1girl and 2boys. The person nouns are never searched either way.
    translateBOOLEANfalseRun the text through Google Translate into English first, whatever language it is in (googletrans, one request per run). Rewrites English too, which straightens grammar the search would trip on.
    blacklistoptSTRINGRegex matched against each found tag in spaced form, case-insensitively: 'male focus' drops the tag the alias 'man' reaches. Dropped before max_tags is counted.

    Outputs (2)

    NameTypeDescription
    processed_textSTRING—
    tableSTRING—