RuYi 提示词
A real prompt editor inside the graph, with 508k Danbooru tags working offline
- clip
- prompt_data
- positive
- negative
ComfyUI's stock prompt box is a textarea. That's fine until you're maintaining a six-way region setup with a shared quality block, an artist tag you keep toggling, and a permanent "don't draw these" list you paste into every negative. You end up with four CLIP Text Encode nodes and a mental model of which one is authoritative.
RuYi 提示词 is the other answer: one node holding both sides of the prompt as named, reorderable, switchable sections, plus the two CONDITIONING outputs a sampler needs. Prompt-writing nodes became their own genre in 2026; this one's angle is that its completion and spellcheck run entirely locally, in a browser worker, against a full Danbooru vocabulary, with no network calls.
How it works
The editor's state serializes into a single JSON string on the node, prompt_data. That's the whole trick: open the node's raw mode and you'll see this rather than prose -
{"version": 1,
"positive": [{"id": "positive-1", "title": "全局", "text": "", "enabled": true, "collapsed": false}],
"negative": [{"id": "negative-1", "title": "负面", "text": "", "enabled": true, "collapsed": false}],
"settings": {"negativeEnabled": true, "autocomplete": true, "spelling": true,
"underscores": false, "sources": ["local", "danbooru"], "customWords": []}}
At execution, compose_prompt() walks the positive and negative arrays in order, keeps the enabled sections with non-empty text, and joins them with newlines. Then trigger_words gets appended to the positive side, and both texts go through clip.encode_from_tokens_scheduled(clip.tokenize(text)) - the same encode path core CLIP Text Encode uses, so nothing is being reimplemented under you.
Inputs and outputs
clip (required) - your model's text encoder, from the usual Load Checkpoint / CLIPLoader / GGUF loader.
prompt_data (required, type RUYI_PROMPT) - that JSON blob. You never type into it directly; the node's own editor renders it.
trigger_words (optional, STRING) - a forced input, meant for a LoRA loader's trigger STRING. The pack's own multi-LoRA loader emits a deduplicated one, but rgthree's Power Lora Loader or any STRING node works. Enabled entries with trigger output enabled contribute; the text is appended to the positive prompt at run time, and leaving this unconnected changes nothing about how your LoRAs load.
Outputs: positive and negative, both CONDITIONING. Wire them straight into the sampler. That's the part people miss - this node does not output a STRING, so you can't chain it into a text-display or file-save node expecting prose.
The settings that actually matter
negativeEnabled is the interesting one: switch it off and the editor keeps your negative text but the negative output encodes an empty prompt. Samplers may still insist the socket is connected, so don't unplug it - and know that on a distilled model at CFG 1 your negative was doing nothing anyway. The KB's prompting doc has the receipts on that ("Negative prompts are legitimately dead at cfg 0"), and it applies here exactly as it applies to the stock node. On SDXL-lineage checkpoints, Pony, Illustrious and Anima Base, which run real CFG, the negative panel earns its place.
Also in settings: prompt font size (10–32px), underscore mode, vocabulary sources, CSV import, and custom words.
Completion, spellcheck, and where your CSVs go
The bundled vocabulary has 508,152 entries merging Danbooru exports, Chinese translations and a public snapshot, served from the pack folder as an 8 MB gzip and searched in a worker. Completion matches contiguous fragments in tag names or translations, ignores case, and treats spaces and underscores as the same character - so long_hair and long hair find each other. Aliases need an exact match, and dispersed letters don't fuzzy-match. English spelling checks run on the Typo.js dictionary after a pause in typing; known tags and available trigger words are exempt.
Imported CSVs live in your browser's IndexedDB. Custom words and section settings travel inside the workflow, but the imports do not - move to another browser or machine and you re-import. Same story as the empty-latent presets, and it surprises people exactly once.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/RuYi-Xiao/RuYi-Nodes.git
Or ComfyUI Manager, search RuYi-Nodes. No Python dependencies, no models to download, nothing to configure. Restart ComfyUI, then hard-refresh the browser with Ctrl+F5 - this node is mostly frontend, so a stale cache is the most likely reason it looks wrong. To update: git pull in the pack directory, restart, Ctrl+F5 again.
Troubleshooting
It errors with "not valid JSON" or "unsupported version". Your prompt_data got mangled - usually a hand-edit or a workflow JSON merged by something that didn't understand the field. The node requires a dict with version: 1 and lists for both sides.
Autocomplete is dead but everything else works. The vocabulary comes from a route the pack registers, reading data/prompt/vocabulary.json.gz inside the pack folder. If completion never loads, check the file is actually there - an install that stripped the data directory would do it.
You expected regional prompting. Sections concatenate text. They do not put anything in a spatial region. If that's what you want, you need an attention-couple or regional-conditioning pack, not this.
A caveat, honestly: RuYi-Nodes shipped 0.2.0 on 2026-10-02, and this node arrived with it. Tidy, dependency-free code - and two days old, with no community history behind it yet. Save your work.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| prompt_data | RUYI_PROMPT | {"version": 1, "positive": [{"id": "positive-1", "title": "全局", "text": "", "enabled": true, "collapsed": false}], "negative": [{"id": "negative-1", "title": "负面", "text": "", "enabled": true, "collapsed": false}], "settings": {"negativeEnabled": true, "autocomplete": true, "spelling": true, "underscores": false, "sources": ["local", "danbooru"], "customWords": []}} | — |
| trigger_wordsopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |