sd-forge-prompt-workshop
An Anima Workshop tab for Haoming02/sd-webui-forge-classic (the neo branch), designed for use with the Anima image model.
Anima expects prompts written in a specific order:
…with a few format rules: tags are lowercase, words are separated by spaces (not underscores), every artist tag must begin with @, and the score_N quality tags keep their underscore. The extension provides one box per section, builds prompts in the correct order on demand, and can also pull a random post's tags from Danbooru or Gelbooru and rewrite them into Anima's format for you.
What the tab contains
A new top-level tab called Anima Workshop, placed between img2img and Extras.
Prompt builder
- Six category boxes, one per section of the Anima tag order: Quality/Meta/Year/Safety, Subject (1girl etc.), Character, Series, Artist, General. Fill in whichever ones you need, in any order.
- Build Prompt consolidates all six into a single comma-separated prompt in the correct order. Duplicate tags across boxes are automatically dropped (Anima uses tag dropout during training, so repeating a tag does not strengthen it).
- Send to txt2img Prompt appends the consolidated prompt to the txt2img positive prompt field and switches to that tab. It always appends, never replaces, so existing text in the txt2img prompt is preserved.
- Per-category Send buttons (one for each of the six category boxes) append just that one box's contents to txt2img. These do not switch tabs, so you can send several categories in a row.
- Clear All Fields wipes every input on the tab, including grabber state, but leaves your Gelbooru credentials alone.
Booru random tag grabber
Pulls a random post from Danbooru or Gelbooru, reads its tags, and rewrites them into Anima format. Parentheses in tags (like the (blue archive) in mutsuki (blue archive)) are backslash-escaped automatically so Forge / A1111 doesn't read them as prompt-weighting syntax — you'll see mutsuki \(blue archive\) and @asura \(asurauser\) in the output.
- Source — Danbooru or Gelbooru.
- Rating filter —
All ratings,Safe / General,Sensitive,Questionable, orExplicit. - Search tag(s) — restrict the random pick to posts that contain specific tags. You can type tags Anima-style (
long hair) or booru-style (long_hair); both work. Multiple tags go in comma-separated. Important: anonymous Danbooru limits searches to 2 tags total (including the rating tag). The extension checks this before making any request and tells you if you've exceeded it. Gelbooru has no such limit. - Blacklist tags — a comma-separated list of tags. These are filtered out of the grabbed output (the post still gets pulled, but those tags don't appear in your prompt).
- Blacklist categories — checkboxes for the six tag categories. Ticking one means that whole section is dropped from the grab. For example, ticking Artist lets you study a post's general tagging without copying its artist into your prompt.
- Filter tags by post count — when ticked, each tag on the grabbed post is checked against the booru's reported
post_countusing the comparator (≥,≤,=) and threshold you set. Tags that fail the check are dropped. Common use case:≥ 50drops obscure artists, one-off characters, and other long-tail tags so they don't bleed into your prompt. Rating text is exempt; tags the booru doesn't recognise are treated as count 0 (so a≥filter drops them). Off by default — no extra API calls are made when off. - Grab Random Tags — runs the grab with the above settings.
- 🔗 Open Post in New Tab — opens the source post on the booru's website so you can see the image.
- Grab from specific post ID (collapsible section) — if you already know the post ID of a specific Danbooru or Gelbooru post you want to learn from, paste it here. Uses the same Source radio as the random grab. Rating filter and search tag don't apply (you've already picked the exact post).
The grabbed tags are shown in a copyable box. A separate button distributes them back into the six category fields so you can edit them before building.
Gelbooru API credentials
Gelbooru changed its API in mid-2022 and now requires an api_key and user_id on every API call. Without them, every request returns 401 Unauthorized. The credentials are free.
- Log in to Gelbooru.
- Go to Account → Options (direct link) and scroll to API Access Credentials near the bottom of the page. Copy the
api_keyanduser_idvalues. - On the Anima Workshop tab, expand the Gelbooru API credentials section, paste both values, and click Save Credentials. The section is open by default until credentials are saved.
Credentials are written to a file called config.json next to the extension, and are only ever sent to gelbooru.com. Danbooru does not require credentials.
Tag autocomplete compatibility
If you have the a1111-sd-webui-tagcomplete extension installed, Anima Workshop ships a small bridge file (javascript/tagcomplete_compat.js) that tries to enable tag autocomplete on the ten text-input fields in this tab: the six category boxes, the Consolidated Prompt and Grabbed Tags boxes, the booru search-tag input, and the blacklist-tags input.
How it works. Tagcomplete attaches autocomplete to a fixed list of textareas it knows about (txt2img prompt, img2img prompt, and a few specific third-party extensions it has built-in support for). It does not provide a public API for other extensions to register their own textareas. The bridge in this extension does a best-effort hook: after tagcomplete finishes setting up the standard textareas, it monkey-patches tagcomplete's internal identifier function so it recognises Anima Workshop's fields, then attaches the same listeners tagcomplete uses internally.
When it will work. Older versions of tagcomplete and most forks expose their helper functions as top-level globals on window. The bridge can hook into those and autocomplete should work on all ten Anima Workshop fields without any further setup.
When it won't work. Newer modular versions of tagcomplete may wrap their helpers inside a module so they aren't accessible from outside. In that case the bridge will log a clear message to the browser console explaining the situation. If this happens, the only way to get autocomplete in Anima Workshop is for tagcomplete itself to add the field IDs (pw_quality, pw_subject, pw_character, pw_series, pw_artist, pw_general, pw_consolidated, pw_grabbed, pw_search_tag, pw_blacklist_tags) to its supported textarea list. You can open a feature request at the tagcomplete issues page to ask for this.
Checking whether it worked. Open the browser developer console after the UI loads. You'll see one of these messages:
[anima-workshop:tagcomplete] enabled tagcomplete on N Anima Workshop textareas— working.[anima-workshop:tagcomplete] tagcomplete is installed and active on txt2img/img2img, but its helper functions aren't exposed on window in your version.— bridge can't hook in on your version of tagcomplete.[anima-workshop:tagcomplete] tagcomplete not detected after 15s.— tagcomplete isn't installed (this is the normal no-op message when you don't use tagcomplete).
The bridge is completely isolated from the main extension. If it can't hook in, every other Anima Workshop feature continues to work normally.
Tag format rules applied automatically
Whether you type tags or grab them from a booru, the extension applies the rules from the Anima model card:
| Input | Output |
|---|---|
Oomuro_Sakurako |
oomuro sakurako |
long_hair |
long hair |
score_7 |
score_7 (underscore preserved — Anima's only exception) |
nnn yryr (in the artist box) |
@nnn yryr |
@@artist |
@artist |
Booru rating values are mapped onto Anima's vocabulary: Danbooru's g/s/q/e and Gelbooru's general/sensitive/questionable/explicit both become safe, sensitive, nsfw, or explicit in the prompt.
Subject-count tags (1girl, 2boys, multiple girls, no humans, solo, etc.) are automatically split out of the general bucket into the Subject field, since the Anima tag order treats them as a separate section.
For Danbooru, the extension uses the API's per-category tag fields directly. For Gelbooru, the API only returns a flat tag list per post, so the extension makes one additional call to look up each tag's category (general, artist, copyright/series, character, or meta).
Install
-
Place the extension folder inside Forge's
extensions/directory. Final layout:
Both the
scripts/andjavascript/subfolders are required. Forge only discovers Python files insidescripts/, and only auto-loads JS fromjavascript/. - Fully close and restart
webui-user.bat. The first startup is what registers the new tab; Reload UI is only enough for re-rendering. -
The console should show, in order:
And in the browser's developer console after the UI loads:
Troubleshooting
No script file is being imported line at startup → Forge isn't finding the file. Either the folder structure is wrong or the extension is disabled in Settings → Extensions.
script file is being imported shows but no UI tab built → an exception fired while building the UI. There will be a traceback right after; it's almost always a Gradio version mismatch or a typo somewhere.
The tab appears at the far right instead of between img2img and Extras → the JavaScript that does the reordering didn't run, or ran before the UI had finished mounting. Check the browser developer console for [anima-workshop] messages. You can also reorder tabs manually under Settings → User interface → Tab order.
Booru grab returns [Gelbooru API credentials not set ...] → Gelbooru requires credentials. See the Gelbooru API credentials section above.
Booru grab returns [error fetching from Gelbooru (count): 401 Unauthorized ...] → the credentials are entered but Gelbooru is rejecting them. Double-check that the api_key and user_id were copied exactly from your account options page (no extra spaces, no missing characters), then click Save Credentials again.
Booru grab returns [Danbooru's anonymous search is limited to 2 tags ...] → this is working as intended. Anonymous Danbooru caps queries at 2 tags total. Use fewer search tags, set Rating filter to All ratings, or switch the source to Gelbooru.
Booru grab returns [no Danbooru/Gelbooru posts matched that search ...] → your search tags combined with the rating filter returned zero hits. Loosen the search or change the rating.
Booru grab returns [error fetching from ...] for any other reason → the WebUI machine couldn't reach danbooru.donmai.us or gelbooru.com. This could be a firewall, DNS, or captive portal issue. The post is fetched server-side from the Forge process, not the browser. The error text in the box is the exception message and usually identifies the problem (ConnectionError, Timeout, 429 Too Many Requests, and so on).
Grab returns nothing or empty tags from Gelbooru → the random page-id occasionally lands on a post with no indexed tags. Click Grab Random Tags again.
Notes on rate limits
- Danbooru's public rate limit is 10 requests per second; the extension makes at most one request per button click.
- Gelbooru has no documented public limit but rate-limits aggressive scrapers. Each random grab does one post fetch plus a small number of batched tag-category lookups (up to 40 tag names per call). Do not loop the Grab button.
- Both APIs are called with a descriptive
User-Agentheader so the boorus can identify and contact the extension's source if there's ever a problem.
Credits
- Anima by tdrussell / circlestone-labs — the model this extension is built around.
- Forge classic / neo by Haoming02 — the host environment.
sd-forge-anima-resolutions
Forge Neo extension for Anima. Four features:
- Resolution picker inserted below the txt2img seed row (preset dropdown + 8 quick buttons).
- img2img "Resize by" auto-adjuster — on Send to img2img / Send to inpaint, picks a scale so the upscaled W+H lands in 3072 – 3264.
- Randomize toggle — when on, every txt2img generation picks a random resolution from the preset list.
- Session prompt history — every Generate click silently logs the current positive prompt into a 100-entry session ring; the dropdown right below the preset dropdown updates only when you click ↻ Refresh.
txt2img picker constraints
- All preset dimensions are multiples of 64.
- W + H ≤ 2176 for every preset.
- Each dimension ≥ 640 for ultra-wide / ultra-tall presets; ≥ 896 for moderate ones.
- All standard SDXL ~1MP buckets included (1024², 1152×896 / 896×1152, 1216×832 / 832×1216, 1344×768 / 768×1344, 1536×640 / 640×1536) plus Anima-tuned higher-pixel-count presets.
The dropdown, the Randomize roll, and the send-to-img2img Resize-by all share the single RESOLUTIONS list at the top of scripts/anima_resolutions.py. To add or remove presets, edit just that list — every feature picks it up automatically.
img2img Resize-by target
- Post-upscale W + H ∈ [3072, 3264], snapped to slider step 0.05.
- Never downscales (scale ≥ 1.0).
- Source dimensions come from the displayed image's PNG metadata (the hidden
generation_info_txt2imgtextbox), not from the txt2img W/H sliders. This matters when Randomize is on, because in that case the sliders hold whatever the user picked but the image was actually generated at the rolled-random resolution. Reading from metadata always reflects what was actually generated. - Parser uses the WebUI's
parse_generation_parameters(extractsSize-1/Size-2keys), with a plain regex onSize: WxHas fallback.
Randomize feature
A scripts.Script subclass (AlwaysVisible) runs before_process(p) on every txt2img generation. When the inline "Randomize resolution each generation" checkbox is on, it picks random.choice(RESOLUTIONS) and overwrites p.width / p.height before the noise is sampled. Console will log e.g. randomized 1024x1024 -> 768x1408.
One Generate click → one random res (all iterations in batch_count share that res, all images in batch_size definitely share it since SD requires matching dims in a batch). Each click is a fresh roll.
The Script creates a small empty "Anima random resolution" section in the txt2img scripts accordion — a cosmetic side-effect of AlwaysVisible. The actual control is the inline checkbox; the accordion section can be ignored or collapsed.
Prompt history
- Logs every Generate click's positive prompt to a session-only list (
_prompt_historymodule variable). - LRU dedup — if you regenerate the same prompt later, its existing entry is removed and re-added at the top, so the dropdown stays clean.
- Cap 100 — once the list hits 100, oldest entries drop off when new ones come in.
- Session only — cleared when the webui process exits (no on-disk storage).
- Preview — dropdown labels show the first ~160 characters with whitespace collapsed; selecting fills the full prompt into the textbox.
- Refresh-driven — the dropdown only updates when you click the ↻ Refresh button. Logging happens silently in the background on every Generate click; the UI just doesn't reflect it until you ask.
Negative prompts are not logged (per your spec).
UI layout
Install
Extract into extensions/. Final layout:
Then fully restart the webui.
Console output to expect
When you click a send button, you'll also see: