Add semantic tagging, search, favourite/NSFW filtering, and LLM job queue

Replaces old list-format tags (which duplicated prompt content) with structured
dict tags per category (origin_series, outfit_type, participants, style_type,
scene_type, etc.). Tags are now purely organizational metadata — removed from
the prompt pipeline entirely.

Adds is_favourite and is_nsfw columns to all 8 resource models. Favourite is
DB-only (user preference); NSFW is mirrored in JSON tags for rescan persistence.
All library pages get filter controls and favourites-first sorting.

Introduces a parallel LLM job queue (_enqueue_task + _llm_queue_worker) for
background tag regeneration, with the same status polling UI as ComfyUI jobs.
Fixes call_llm() to use has_request_context() fallback for background threads.

Adds global search (/search) across resources and gallery images, with navbar
search bar. Adds gallery image sidecar JSON for per-image favourite/NSFW metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Aodhan Collins
2026-03-21 03:22:09 +00:00
parent 7d79e626a5
commit 32a73b02f5
72 changed files with 3163 additions and 2212 deletions

View File

@@ -21,6 +21,7 @@ Structure:
"feet": "string (foot position)",
"additional": "string (extra details)"
},
"suppress_wardrobe": false,
"lora": {
"lora_name": "WILL_BE_REPLACED",
"lora_weight": 1.0,
@@ -28,8 +29,16 @@ Structure:
"lora_weight_max": 1.0,
"lora_triggers": "WILL_BE_REPLACED"
},
"tags": ["string", "string"]
"tags": {
"participants": "string (e.g. 'solo', '1girl 1boy', '2girls', '3girls 1boy')",
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true for sexual, explicit, or fetish actions.
- `suppress_wardrobe`: when true, no wardrobe/clothing prompts are injected during generation. Use for actions like nudity, bathing, or undressing where clothing tags would conflict.
Use the provided LoRA filename and HTML context as clues to what the action/pose represents.
IMPORTANT: Look for suggested LoRA strength/weight (e.g. 'Strength of 0.7', 'recommended weight: 0.8', 'use at 0.6-0.8'), trigger words (e.g. 'Trigger: xyz'), and recommended/optional prompt tags in the HTML text. Use these found values to populate 'lora_weight', 'lora_triggers', and the descriptive fields.
- If the HTML suggests a specific weight (e.g. 0.7), set 'lora_weight' to that value and set 'lora_weight_min' to max(0.0, weight - 0.1) and 'lora_weight_max' to min(2.0, weight + 0.1).

View File

@@ -50,6 +50,13 @@ Structure:
"lora_weight_max": 1.0,
"lora_triggers": ""
},
"tags": ["string", "string"]
"tags": {
"origin_series": "string (the franchise/series the character is from, e.g. 'Fire Emblem', 'Spy x Family', 'Mario'. Use 'Original' if the character is not from any series)",
"origin_type": "string (one of: Anime, Video Game, Cartoon, Movie, Comic, Original)",
"nsfw": false
}
}
Fill the fields based on the user's description. Use the tools to ensure the quality and validity of the tags.
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set the `nsfw` field in tags to true if the character is primarily from adult/NSFW content or if the description implies NSFW usage.
Fill the fields based on the user's description. Use the tools to ensure the quality and validity of the prompt field tags (identity, wardrobe, etc). The `tags` object contains semantic metadata — not Danbooru tags.

View File

@@ -16,9 +16,16 @@ Structure:
"steps": 25,
"cfg": 5.0,
"sampler_name": "euler_ancestral",
"vae": "integrated"
"vae": "integrated",
"tags": {
"art_style": "string (one of: Anime, Realistic, Cartoon, Semi-Realistic)",
"base_model": "string (one of: Illustrious, Noob — determined from the checkpoint path)",
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true if the checkpoint is specifically designed for NSFW content. Determine `base_model` from the checkpoint path (e.g. 'Illustrious/model.safetensors' → 'Illustrious').
Field guidance:
- "base_positive": Comma-separated tags that improve output quality for this specific model. Look for recommended positive prompt tags in the HTML.
- "base_negative": Comma-separated tags to suppress unwanted artifacts. Look for recommended negative prompt tags in the HTML.

View File

@@ -18,8 +18,16 @@ Structure:
"lora_weight_min": 0.7,
"lora_weight_max": 1.0,
"lora_triggers": "WILL_BE_REPLACED"
},
"tags": {
"associated_resource": "string (one of: General, Looks, Styles, Faces, NSFW — use 'General' for quality/detail enhancers that apply broadly)",
"adetailer_targets": ["string (which ADetailer regions this affects: face, hands, body, nsfw)"],
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true for sexually explicit detail enhancers. For `adetailer_targets`, list which regions the detailer should be applied to. Detailers marked as 'General' associated_resource should target all regions.
Use the provided LoRA filename and HTML context as clues to what refinement it provides.
IMPORTANT: Look for suggested LoRA strength/weight (e.g. 'Strength of 0.7', 'recommended weight: 0.8', 'use at 0.6-0.8'), trigger words (e.g. 'Trigger: xyz'), and recommended/optional prompt tags in the HTML text. Use these found values to populate 'lora_weight', 'lora_triggers', and the descriptive fields.
- If the HTML suggests a specific weight (e.g. 0.7), set 'lora_weight' to that value and set 'lora_weight_min' to max(0.0, weight - 0.1) and 'lora_weight_max' to min(2.0, weight + 0.1).

View File

@@ -23,8 +23,15 @@ Structure:
"lora_weight_max": 1.0,
"lora_triggers": "WILL_BE_REPLACED"
},
"tags": ["string", "string"]
"tags": {
"origin_series": "string (the franchise/series the character look is from, e.g. 'Fire Emblem', 'Dragon Ball'. Use 'Original' if not from any series)",
"origin_type": "string (one of: Anime, Video Game, Cartoon, Movie, Comic, Original)",
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true if the look is primarily NSFW.
Use the provided LoRA filename and HTML context as clues to what the character look represents.
IMPORTANT: Look for suggested LoRA strength/weight (e.g. 'Strength of 0.7', 'recommended weight: 0.8', 'use at 0.6-0.8'), trigger words (e.g. 'Trigger: xyz'), and recommended/optional prompt tags in the HTML text. Use these found values to populate 'lora_weight', 'lora_triggers', and the 'positive'/'negative' fields.
- If the HTML suggests a specific weight (e.g. 0.7), set 'lora_weight' to that value and set 'lora_weight_min' to max(0.0, weight - 0.1) and 'lora_weight_max' to min(2.0, weight + 0.1).

View File

@@ -30,6 +30,12 @@ Structure:
"lora_weight_max": 1.0,
"lora_triggers": ""
},
"tags": ["string", "string"]
"tags": {
"outfit_type": "string (one of: Formal, Casual, Swimsuit, Lingerie, Underwear, Nude, Cosplay, Uniform, Fantasy, Armor, Traditional)",
"nsfw": false
}
}
Fill the fields based on the user's description. Use the tools to ensure the quality and validity of the tags.
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true for lingerie, underwear, nude, or sexually suggestive outfits.
Fill the fields based on the user's description. Use the tools to ensure the quality and validity of the prompt field tags (wardrobe fields). The `tags` object contains semantic metadata — not Danbooru tags.

View File

@@ -35,6 +35,7 @@ Structure:
"action": {
"action_id": "specific_id | random | null",
"use_lora": true,
"suppress_wardrobe": null,
"fields": { "base": true, "head": true, "upper_body": true, "lower_body": true, "hands": true, "feet": false, "additional": true }
},
"style": { "style_id": "specific_id | random | null", "use_lora": true },
@@ -54,6 +55,8 @@ Guidelines:
- Set entity IDs to "random" when the user wants variety, null when they want to skip that resource, or a specific ID string when they reference something by name.
- Set field toggles to "random" for fields that should vary across generations, true for fields that should always contribute, false for fields that should never contribute.
- The `tags` array is for extra freeform positive prompt tags (Danbooru-style, underscores). Validate them with the tools.
- `suppress_wardrobe` in the action block: null = use the action's own setting, true = always suppress, false = never suppress, "random" = randomly decide. When suppressed, no wardrobe/clothing prompts are injected.
- The `resolution` object sets image dimensions. Set `random` to true to pick a random aspect ratio each generation. When `random` is false, `width` and `height` are used directly. Common sizes: 1024x1024 (1:1), 1152x896 (4:3 L), 896x1152 (4:3 P), 1344x768 (16:9 L), 768x1344 (16:9 P).
- Leave `preset_id` and `preset_name` as-is — they will be replaced by the application.
- This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Consider NSFW compatibility when selecting entity combinations.
- Output ONLY valid JSON. No explanations, no markdown fences.

View File

@@ -0,0 +1,48 @@
You are a tag regeneration assistant for an AI image generation tool. You will receive existing JSON data for a resource and must regenerate all prompt/tag fields with fresh, high-quality Danbooru-style tags.
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set the `nsfw` field in tags appropriately based on the content.
You have access to the `danbooru-tags` tools (`search_tags`, `validate_tags`, `suggest_tags`).
You MUST use these tools to ensure all prompt field tags are valid Danbooru tags.
- Use `search_tags` or `suggest_tags` to discover the most relevant and popular tags for each field.
- Use `validate_tags` to check your final selection.
- Prefer tags with high post counts as they provide a stronger signal to the image generation model.
- Use Danbooru-style tags (underscores instead of spaces, e.g., 'long_hair', 'blue_eyes').
- Keep values concise.
- Use empty strings "" for fields that are not applicable — never use words like "none" or "n/a".
Rules:
1. Output ONLY valid JSON. Do not wrap in markdown blocks.
2. PRESERVE these fields exactly as-is from the input: all *_id, *_name, lora (entire block), suppress_wardrobe, participants (in the data object, NOT in tags), character_id (on looks).
3. REGENERATE all prompt/descriptive fields with fresh, validated Danbooru tags.
4. REGENERATE the `tags` object using the structured format below (NOT a list of strings).
5. Use the resource name and any existing values as context clues, but improve and validate them.
6. Return the complete JSON object with the same structure as the input.
IMPORTANT: The `tags` field must be a JSON OBJECT (dict), not a list. Use the appropriate schema based on the resource type:
For characters:
"tags": { "origin_series": "series name or Original", "origin_type": "Anime|Video Game|Cartoon|Movie|Comic|Original", "nsfw": bool }
For looks:
"tags": { "origin_series": "series name or Original", "origin_type": "Anime|Video Game|Cartoon|Movie|Comic|Original", "nsfw": bool }
For outfits:
"tags": { "outfit_type": "Formal|Casual|Swimsuit|Lingerie|Underwear|Nude|Cosplay|Uniform|Fantasy|Armor|Traditional", "nsfw": bool }
For actions:
"tags": { "participants": "solo|1girl 1boy|2girls|etc", "nsfw": bool }
For styles:
"tags": { "style_type": "Anime|Realistic|Western|Artistic|Sketch|Watercolor|Digital|Pixel Art", "nsfw": bool }
For scenes:
"tags": { "scene_type": "Indoor|Outdoor|Fantasy|Urban|Nature|Abstract", "nsfw": bool }
For detailers:
"tags": { "associated_resource": "General|Looks|Styles|Faces|NSFW", "adetailer_targets": ["face"|"hands"|"body"|"nsfw"], "nsfw": bool }
For checkpoints:
"tags": { "art_style": "Anime|Realistic|Cartoon|Semi-Realistic", "base_model": "Illustrious|Noob", "nsfw": bool }
Determine the resource type from the input JSON structure (presence of character_id, outfit_id, action_id, etc.).

View File

@@ -27,8 +27,14 @@ Structure:
"lora_weight_max": 1.0,
"lora_triggers": "WILL_BE_REPLACED"
},
"tags": ["string", "string"]
"tags": {
"scene_type": "string (one of: Indoor, Outdoor, Fantasy, Urban, Nature, Abstract)",
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true if the scene is inherently NSFW (e.g. love hotel, dungeon).
Use the provided LoRA filename and HTML context as clues to what the scene represents.
IMPORTANT: Look for suggested LoRA strength/weight (e.g. 'Strength of 0.7', 'recommended weight: 0.8', 'use at 0.6-0.8'), trigger words (e.g. 'Trigger: xyz'), and recommended/optional prompt tags in the HTML text. Use these found values to populate 'lora_weight', 'lora_triggers', and the descriptive fields.
- If the HTML suggests a specific weight (e.g. 0.7), set 'lora_weight' to that value and set 'lora_weight_min' to max(0.0, weight - 0.1) and 'lora_weight_max' to min(2.0, weight + 0.1).

View File

@@ -21,8 +21,15 @@ Structure:
"lora_weight_min": 0.7,
"lora_weight_max": 1.0,
"lora_triggers": "WILL_BE_REPLACED"
},
"tags": {
"style_type": "string (one of: Anime, Realistic, Western, Artistic, Sketch, Watercolor, Digital, Pixel Art)",
"nsfw": false
}
}
This tool generates content for both SFW and NSFW image generation. NSFW content is permitted and expected. Set `nsfw` to true if the style is primarily used for NSFW content.
Use the provided LoRA filename and HTML context as clues to what artist or style it represents.
IMPORTANT: Look for suggested LoRA strength/weight (e.g. 'Strength of 0.7', 'recommended weight: 0.8', 'use at 0.6-0.8'), trigger words (e.g. 'Trigger: xyz'), and recommended/optional prompt tags in the HTML text. Use these found values to populate 'lora_weight' and 'lora_triggers'.
- If the HTML suggests a specific weight (e.g. 0.7), set 'lora_weight' to that value and set 'lora_weight_min' to max(0.0, weight - 0.1) and 'lora_weight_max' to min(2.0, weight + 0.1).