π BV Prompt Encode
Turn tagged prompt markup into a tree you can filter β not another fragile string hack
- ast
- cleaned_prompt
BV Prompt Encode parses a tagged prompt into a structured AST (Abstract Syntax Tree) - a real tree of categories and text, not a string you slice with regexes. It's the entry point to the pack's whole AST prompting system: encode once here, then filter, switch, and inspect categories with dedicated nodes downstream.
Why does a tree beat string-slicing? The KB's prompt-engineering write-up has a whole section on the 2026 shift toward block-structured prompting - "your prompt is an instruction, not a token bag" - where people organize prompts into logical sections that stay stable across a workflow. The moment you want to conditionally include or exclude a section (show the "style" block in one run, hide it in the next), you're doing surgery on a string. That's fragile: one stray comma, one @@ too many, and your parser quietly breaks. This pack's bet is that a proper parser with a documented syntax is more robust, and honestly, for category-level filtering it is.
The syntax
The README is your spec. Three constructs, that's it:
@@style
cinematic lighting
@@subject
a woman in rain
- Block categories - a line starting with
@@opens a category block; everything until the next@@belongs to it.@@alone returns to the default block. - Inline categories -
@<eye> green eyes @@tags a span of text mid-sentence. - Comments -
## this is a commentis parsed into a comment node, kept in the AST but stripped from the plain output.
Two syntax rules bite everyone. Category names cannot contain spaces (use clothing_color, not clothing color), and inline category names must match [a-zA-Z0-9_-]+. Unclosed inline categories or stray @@ closers raise parse errors - the README explicitly shows @<clothing> long dress,@@@@ as invalid. If you get a parse error, that's the first thing to check.
Inputs and outputs
prompt(STRING, multiline) - the tagged prompt. The only input.
Outputs:
ast(BV_AST) - the parse tree. This is what you wire into BV Prompt Decode, BV Prompt Category Switch, or BV Prompt AST Debug.cleaned_prompt(STRING) - the same prompt with all markup and comments stripped, ready to feed a normal CLIP text encode. This is the "I just want plain text back" escape hatch.
So a minimal pipeline is: Prompt Encode β Prompt Decode/Category Switch β Prompt Encode again or straight to a text encoder. The AST survives the round trip, which is the whole point.
Install & gotchas
Pack standard: ComfyUI Manager β BV Node Pack, or clone https://github.com/BlackVortexAI/bv_nodepack into custom_nodes, restart. No models, no dependencies - the AST engine is pure Python, and there's no JS UI on this node, so no hard-refresh anxiety.
Real-world gotchas: unclosed inline spans and invalid category names throw errors rather than guessing, so a malformed prompt stops the run with a readable message pointing at the line - that's a feature, not a bug, but it means this node is stricter than the prompt-hacks you're used to. And remember cleaned_prompt strips all markup including inline @<cat> wrappers, which is what you want before a text encoder, but not what you want if you expected the tags preserved.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | β |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| ast | BV_AST | β |
| cleaned_prompt | STRING | β |