Nodes/smart_word_filter/Smart Word Filter (Pos/Neg)
ComfyUI Node

Smart Word Filter (Pos/Neg)

Click + and − on your tags once, never hand-write that negative list again

By mohsensd1373·Created 5 days ago·Updated 5 days ago· 0
Smart Word Filter (Pos/Neg)
    • filtered_positive
    • negative_words
    ◄text►
    ◄filter_mode▾►
    ◄negative_output▾►
    ◄append_missing_positivesfalse►
    ◄separator, ►
    ◄rules{"pos": [], "neg": [], "seen": []}►

    Here's a workflow most of us have: paste a fat booru-style prompt into a text box and decide, by hand, which tags belong positive and which deserve the negative. You do it with the same thirty tags every time, because the vocabulary is stable and your taste is stable - and yet nothing in ComfyUI remembers it for you.

    Smart Word Filter fixes exactly that. It reads the tags out of a prompt, lets you click + or − on each one, and saves the pos/neg pair as a named profile you can reuse anywhere. It's the authoring half of the smart_word_filter pack; the split/replace node is the other.

    How it works

    The node renders a custom board with three sections: tags found in your input text, a green positive list, a red negative list. Every chip in the text section has two buttons - + marks it positive, − negative, clicking again returns it to neutral. A tag lives in one list at a time.

    Those lists serialise into a hidden rules widget as JSON, so they travel inside your workflow - save the PNG and they go with it. It also means that when the frontend extension fails to load, the board vanishes and you're staring at a raw JSON box.

    Saved profiles are separate storage: Save as new POSTs to /smart_word_filter/profiles, which writes profiles.json into ComfyUI's user directory (ComfyUI/user/smart_word_filter/). That profile survives restarts and appears in the pack's Profile Tools node in every workflow - but it's not in your workflow file, so back the JSON up. Load replaces the current list, Merge adds to it; that's the distinction people miss.

    The inputs you'll actually touch

    text is the prompt being mined for tags - paste it or wire it from a string node.

    filter_mode sets what output one is. remove_negatives keeps everything except your − tags: a scrubber. only_positives keeps only tags in your + list, turning it into an allow-list - the setting for "just the descriptive tags, drop the aesthetic boilerplate."

    negative_output decides output two: found_in_text emits only the negatives actually present, all_in_list dumps your whole list regardless. Handy for a standing negative prompt - but wire it to a negative CLIP Text Encode and your negative never changes, no matter what you typed positive.

    append_missing_positives appends any + tag that wasn't in the text - how you force a consistent quality block onto every prompt. Watch the form, though: appended tags come out as stored and lowercased, minus any weight you didn't type. Store blue_shirt and it appends blue_shirt, precisely the underscore form the booru crowd says costs you quality.

    separator (default , ) is what the outputs are joined with. Splitting always happens on commas and newlines regardless.

    Outputs are two strings: filtered_positive and negative_words. Wire the first into your positive CLIP Text Encode, the second into the negative one - and keep the CFG caveat in mind. A negative prompt does nothing at CFG 1, so on distilled or turbo models that second output is decorative. This node earns its keep on the SDXL-lineage booru models - Illustrious, NoobAI, WAI - where the negative branch is still being computed.

    It's registered as an output node, so it runs on every queue even when nothing downstream needs it. It also returns the extracted tags to the UI, which is why the chip board fills in from a linked text input after one run.

    Install

    No pip dependencies, no model files, nothing to download beyond the repo:

    cd ComfyUI/custom_nodes
    git clone https://github.com/mohsensd1373/smart_word_filter
    

    Restart ComfyUI, then hard-refresh (Ctrl+F5) - the board is a frontend extension, so a soft refresh can leave you with the node and no UI. It's on the Comfy Registry, so ComfyUI Manager finds it under smart_word_filter too.

    Where people get burned

    Chips are empty though text is in the box. If text is linked, tags only appear after a run.

    The board renders as nothing. Almost always the extension JS didn't load. Hard refresh; if it persists, check the console for a failed fetch of js/word_filter.js.

    An edit to a saved profile didn't change an open workflow. The rules are a snapshot in the widget. Editing the profile on disk changes the profile, not nodes that already loaded it - hit Load or Merge again.

    Profile names starting with ★ are rejected. The star is reserved for the folder-driven built-in lists; the API refuses to save over them, and the node offers to rename yours instead.

    Weights survive the filter. (green:1.2) is compared as green, which is generous - but the segment you keep is the text you typed, weight and all.

    If you want the node to act on the prompt rather than annotate it, that's Profile Tools (Split / Replace by Profile) in the same pack. And if what you actually want is randomised variation from a tag library, Impact Pack's __wildcard__ syntax is the incumbent: this node filters, it doesn't roll dice.

    Categoryutils/text

    Inputs (6)

    NameTypeDefaultDescription
    textSTRING—
    filter_modeCOMBO2 options: remove_negatives, only_positives
    negative_outputCOMBO2 options: all_in_list, found_in_text
    append_missing_positivesBOOLEANfalse—
    separatorSTRING, —
    rulesSTRING{"pos": [], "neg": [], "seen": []}—

    Outputs (2)

    NameTypeDescription
    filtered_positiveSTRING—
    negative_wordsSTRING—