ComfyUI Node

Group Tags

Turn a wall of 60 commas into a prompt you can actually read

By alchemine·Created about a year ago·Updated a day ago· 2
Group Tags
    • processed_text
    text
    special_firsttrue
    cap0
    prefix_tagsfur-trimmed, lace-trimmed, ribbon-trimmed, frilled
    special_pattern

    What it is

    Group Tags takes one flat comma-separated prompt and lays it out in themed groups, one per line. Tags that share their last word gather together - falling back to a shared first word when there's no shared last word - and anything unique stays where it is. Then it hoists the person and relationship tags (1girl, 2boys, multiple girls, couple, hetero, yuri) to a leading line of their own.

    Here's the example from the node's own docs:

    1girl, blue eyes, red eyes, standing, solo
        →  1girl, solo,
           blue eyes, red eyes,
           standing
    

    (One thing that example glosses: with the built-in pattern solo isn't a "special" tag, so it lands in a group of its own unless you put it in special_pattern. Treat the hoisted line as "whatever your pattern matches".)

    Two reasons to care, one for you and one for the model. For you: a 50-tag booru prompt is a single line you scroll sideways through, and when something's wrong you can't see the problem - grouped by theme, it's five lines you can scan. For the model: the ordering is functional. On CLIP-family models earlier tokens carry more attention, which is why a 1boy at position 40 doesn't behave like a 1boy at position 1. The node's docstring is explicit that this hoisting is the job a separate sort_special node used to do upstream, and that grouping rewrites tag order wholesale, so an earlier sort won't survive it.

    Worth knowing what it isn't: it keeps the commas inside a line and only changes the whitespace between groups, so the encoder sees the same syntax with different word order. It is not a prompt-format translator.

    How the grouping actually decides

    For each tag it looks at the parsed words - weights stripped first, so (areola slip:1.1) still groups with areola slip. If the tag's last word appears in at least one other tag, they group by that word; otherwise if its first word repeats, they group by that; otherwise it's alone. Groups keep the order their first member appeared in.

    Which means blue eyes, red eyes group by eyes, not by blue, and a stray blue shirt might join neither. It's a cheap heuristic, not a semantic classifier - cheap is the right tradeoff here, because the tag vocabulary is a genuinely weird place to write rules.

    Inputs and the one output

    Required:

    • text - a forced STRING input, so wire it from a TextPrompt, a CLIP text encode, or the output of a filter node. You can't type into the node itself.
    • special_first (default true) - hoist that person/relationship line to the top. Turn it off only if you have a reason.

    Optional:

    • cap (INT, 0–100, default 0) - 0 means no cap, not "cap everything at zero". Anything above zero trims each group to at most that many tags, and it does it smartly: colour-bearing tags go first (from a fixed list - blue, red, aqua, and friends), then it trims from the tail. It runs last in the chain, so it counts what survived your blacklist rather than reserving slots for tags about to be dropped. This is your blunt instrument against prompt dilution: past roughly 75–100 effective tokens models start to drift, so cap=6 on a 60-tag generated prompt is often a straight quality win.
    • prefix_tags (default "fur-trimmed, lace-trimmed, ribbon-trimmed, frilled") - a per-prefix cap. When cap is set, each of these prefixes is limited to cap tags of its own. It's aimed squarely at the habit tag generators have of stacking trim words, which eat budget and add almost nothing.
    • special_pattern (default empty) - a regex override for what counts as "special". Empty uses the built-in pattern, which is the numbered/multiple-person tags plus couple, hetero and yuri; if your own vocabulary keeps landing in the wrong place, this is where you say so.

    One output: processed_text, a STRING with the grouped, newline-separated text - straight into a CLIP Text Encode.

    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. No model files, no keys, no extra packs. The only dependency is python-dotenv, which the pack's API and Grok nodes use. It's pure string work.

    Where to put it, and where it bites

    Put it last in your tag chain - after the blacklist filter and subtag dedupe. The pack's own ProcessTags node bundles filtering into one step, and Group Tags belongs downstream of it, because its cap is only meaningful once the dropped tags are actually gone.

    The gotcha list is short, because there isn't much to break. Your prompt will come out reordered - if you've tuned word order by hand, grouping rewrites the order within lines, and that's the cost of using it. And don't chase exact reproduction of your typing: it groups by shared words, so a prompt with no repeated words comes back one tag per line. That's the heuristic telling you there was nothing to group.

    CategoryAlcheminePack/Prompt

    Inputs (5)

    NameTypeDefaultDescription
    textSTRING
    special_firstBOOLEANtrue
    capoptINT00–100
    prefix_tagsoptSTRINGfur-trimmed, lace-trimmed, ribbon-trimmed, frilled
    special_patternoptSTRING

    Outputs (1)

    NameTypeDescription
    processed_textSTRING