π Categorized Prompt Analyzer
Is your prompt actually doing what you think? Count it.
- analysis_summary
- total_matched_count
- details
- unmatched_tags
Here's a scenario you've definitely been in: a workflow keeps producing images with the wrong hair color, or no quality tag at all, and you can't tell whether the prompt is broken or the model is ignoring you. The π Categorized Prompt Analyzer is the "show your work" node - it takes a prompt, counts how many tags match a list of targets, and reports back. It doesn't generate or change anything. It just tells you what's actually in the string, which makes it a surprisingly useful debugging tool.
The name oversells it a bit. It's a counter, not an NLP engine - no models, no inference, just string matching against your YAML categories. For prompt QA that's exactly what you want: fast, deterministic, and easy to reason about.
How it works
You give it a prompt, a comma-separated analyze_targets list, and a category_definition_file. Each target is resolved in one of two ways:
- If it matches a category name in your YAML, it counts every prompt tag belonging to that category.
- Otherwise it's treated as a literal tag to search for, weighted syntax handled -
(blue eyes:1.1)matches the targetblue eyes.
So analyze_targets: "quality, eyes, 1girl" means "count how many quality tags, how many eye tags, and how many exact 1girl tags are in this prompt." Matching honors the same options as the rest of the pack: case-insensitive and blue_eyes/blue eyes equivalent by default, both toggleable.
The outputs
analysis_summary- a one-liner likequality: 2, eyes: 1, 1girl: 1. This is the one you'll look at 95% of the time.total_matched_count- sum of all the counts. One caveat the README is upfront about: if a single input tag matches multiple targets (sayblue eyesmatches the literal target and theeyescategory), it counts toward each, so the total can exceed the number of distinct tags. Not a bug; just don't be surprised.details- only populated if you flipgenerate_detailed_outputon; lists which tags got counted per target, one per line.unmatched_tags- withgenerate_unmatched_outputon, everything in the prompt that matched nothing.
What you'd actually use it for
Honestly, the best use is a poor man's prompt validator in a generation pipeline. Put it after a wildcard generator or the pack's Random Formatter and before the encoder: if quality comes back 0 on a model that needs its quality tag, you know the generator failed before you've burned GPU time on garbage. It's also great for auditing old workflows - paste a prompt through it and you instantly see the two style tags you'd forgotten were in there fighting each other. There's no conditional-routing node here, so you still eyeball the summary yourself; think of it as a sensor, not a gate.
Installing
Via ComfyUI Manager (search "ComfyUI-Prompt-Formatter"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/xLegende/ComfyUI-Prompt-Formatter
Restart ComfyUI. PyYAML is the only dependency, no downloads, runs instantly.
Common issues
Two gotchas. First, the YAML file is required if any of your targets is a category - with no file, category targets silently match nothing and you get a wall of zeros. Second, a target that's neither a category nor present in the prompt just reports 0; the analyzer won't tell you that the category was missing vs. just empty, so check the console warnings if counts look wrong. Keep targets literal and specific and this node is boring in the best way - it just tells the truth about your prompt.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | β | |
| analyze_targets | STRING | quality, eyes, clothing | β |
| category_definition_file | STRING | prompt_categories.yaml | β |
| input_delimiteropt | STRING | , | β |
| target_delimiteropt | STRING | , | β |
| output_delimiteropt | STRING | , | β |
| case_sensitive_matchingopt | BOOLEAN | false | β |
| handle_weightsopt | BOOLEAN | true | β |
| match_underscores_spacesopt | BOOLEAN | true | β |
| generate_detailed_outputopt | BOOLEAN | false | β |
| generate_unmatched_outputopt | BOOLEAN | false | β |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| analysis_summary | STRING | β |
| total_matched_count | INT | β |
| details | STRING | β |
| unmatched_tags | STRING | β |