Major Features: - New modular prompt generator architecture (core/prompt_generator/) - 15+ taggers/analyzers: WD14, PixAI, JoyTag, NudeNet, Places365, etc. - Decision engine for intelligent prompt construction - Template-based prompt building with dynamic sections Standard Mode Enhancements: - Tag injection for unmapped high-confidence tags - Scene-specific prompts (20 scene groups from Places365) - Animal-specific prompts (20+ animal types) - Clothing-specific prompts (30+ clothing types) - Tag-driven detail enhancements (40+ tag mappings) - Semantic inclusion analysis using sentence-transformers Detailed Mode (API with reasoning): - 3-pass LLM generation with full enhancements - Falls back to Standard mode for local models - Comprehensive metadata with pass-by-pass details Removed: - Extreme mode (consolidated into Detailed mode) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
27 KiB
27 KiB
SID_PromptGenerator Design (4.2.1)
Node Interface
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ SID_PromptGenerator │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ INPUTS (3 dot connectors only) │
│ ├── image (IMAGE) ─────────────────── Required │
│ ├── llm_model (LLM_MODEL) ─────────── Optional (dot connector) │
│ └── user_prompt (STRING) ──────────── Optional (dot connector, NOT text box) │
│ │
│ OUTPUTS (2) │
│ ├── prompt (STRING) ───────────────── Final prompt for image generation │
│ └── prompt_metadata (STRING/JSON) ─── Detailed JSON of all captured information │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
Input Priority Logic
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ INPUT PRIORITY FLOW │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ user_prompt provided? │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ │ YES NO │ │
│ ▼ ▼ │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ OVERRIDE MODE │ │ NORMAL PROCESSING │ │
│ │ │ │ │ │
│ │ • Skip ALL processing │ │ llm_model provided? │ │
│ │ • No taggers │ │ │ │ │
│ │ • No Florence │ │ ┌────┴────┐ │ │
│ │ • No LLM calls │ │ NO YES │ │
│ │ │ │ │ │ │ │
│ │ OUTPUT: │ │ ▼ ▼ │ │
│ │ • prompt = user_prompt│ │ Florence LLM Mode │ │
│ │ • metadata = { │ │ Mode │ │
│ │ "mode": "override"│ └───────────────────────┘ │
│ │ "source": "user" │ │
│ │ } │ │
│ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
Mode Selection Matrix
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ MODE DECISION TREE │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ user_prompt provided? │
│ │ │
│ ┌────┴────┐ │
│ YES NO │
│ │ │ │
│ ▼ ▼ │
│ OVERRIDE llm_model provided? │
│ MODE │ │
│ │ ┌────┴────┐ │
│ │ NO YES │
│ │ │ │ │
│ │ ▼ ▼ │
│ │ FLORENCE analysis_mode? │
│ │ MODE │ │
│ │ │ ┌────┴────┬─────────┬─────────┐ │
│ │ │ │ │ │ │ │
│ │ │ QUICK STANDARD DETAILED EXTREME │
│ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Pass │ │Flor- │ │Single│ │Single│ │2-3 │ │Multi │ │
│ │thru │ │ence │ │LLM │ │LLM + │ │pass │ │pass │ │
│ │ │ │only │ │call │ │tags │ │LLM │ │LLM │ │
│ │No │ │ │ │ │ │decide│ │ │ │ │ │
│ │exec │ │No │ │No │ │prompt│ │Tags │ │Tags │ │
│ │ │ │tags │ │tags │ │ │ │decide│ │decide│ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
Mode Specifications
1. OVERRIDE MODE (user_prompt provided)
INPUT: user_prompt = "A beautiful woman in red dress"
OUTPUT:
prompt = "A beautiful woman in red dress"
prompt_metadata = {
"mode": "override",
"source": "user_prompt",
"processing": "none",
"taggers_executed": false,
"llm_executed": false,
"florence_executed": false
}
2. FLORENCE MODE (no llm_model, no user_prompt)
EXECUTION:
1. Load Florence VLM (PromptGen v2.0)
2. Run MORE_DETAILED_CAPTION
3. Output florence_description as prompt
OUTPUT:
prompt = "{florence_description}"
prompt_metadata = {
"mode": "florence",
"source": "florence_description",
"model": "MiaoshouAI/Florence-2-large-PromptGen-v2.0",
"taggers_executed": false,
"llm_executed": false,
"florence_executed": true,
"florence_output": "{raw florence output}"
}
3. QUICK MODE (llm_model provided, analysis_mode=Quick)
EXECUTION:
1. NO taggers executed
2. Single-shot detailed prompt to LLM (Local or API)
3. LLM describes image directly
LLM PROMPT:
"Describe this image in detail for AI image generation.
Include: subject, appearance, clothing, pose, environment,
lighting, composition. Write as flowing natural sentences."
OUTPUT:
prompt = "{llm_output}"
prompt_metadata = {
"mode": "quick",
"source": "llm_single_shot",
"llm_provider": "anthropic|openai|local|...",
"llm_model": "claude-sonnet-4-20250514",
"taggers_executed": false,
"llm_executed": true,
"llm_passes": 1,
"florence_executed": false
}
4. STANDARD MODE (llm_model provided, analysis_mode=Standard)
EXECUTION:
1. Execute 22 taggers/analyzers
2. Tags used to CHERRY-PICK prompt questions (not in prompt)
3. Build template prompt based on detected content
4. Single LLM call with template prompt
TAGS → DECISIONS:
WD14: "1girl" → subject_type=WOMAN → ask about appearance
NudeNet: suggestive → ask about body details
Shot Type: MS → ask about pose (body visible)
Places365: studio → skip environment detail questions
TEMPLATE PROMPT (built from decisions):
"Describe this woman in detail:
- Her appearance (ethnicity, hair color/style, eye color, face, skin)
- Her clothing (style, color, fabric, fit, accessories)
- Her pose and expression
- The lighting and mood
Write as a single flowing paragraph for image generation."
OUTPUT:
prompt = "{llm_output}"
prompt_metadata = {
"mode": "standard",
"source": "llm_template",
"llm_provider": "local",
"llm_model": "Qwen3-VL-4B",
"taggers_executed": true,
"llm_executed": true,
"llm_passes": 1,
"florence_executed": false,
"decisions": {
"subject_type": "WOMAN",
"gender": "female",
"nsfw_level": "SUGGESTIVE",
"shot_type": "MS",
"scene_type": "STUDIO",
"template_sections": ["appearance", "clothing", "pose", "lighting"]
},
"taggers": {
"wd14": {"1girl": 0.98, "long hair": 0.92, "dress": 0.88, ...},
"pixai": {...},
"nudenet": {...},
"shot_type": {"MS": 0.82},
"places365": {"studio": 0.75},
...
}
}
5. DETAILED MODE (llm_model with supports_reasoning=True, analysis_mode=Detailed)
REQUIREMENTS:
- llm_model.supports_reasoning == True
- Typically: Claude, GPT-4, Gemini (not local models)
EXECUTION:
1. Execute 22 taggers/analyzers
2. Tags cherry-pick which components to analyze
3. LLM executed in 2-3 passes (component-by-component)
PASSES:
Pass 1: Subject + Appearance
Pass 2: Clothing + Pose + Environment
Pass 3: Lighting + Composition + Final assembly
OUTPUT:
prompt = "{assembled_from_passes}"
prompt_metadata = {
"mode": "detailed",
"source": "llm_multi_pass",
"llm_provider": "anthropic",
"llm_model": "claude-sonnet-4-20250514",
"taggers_executed": true,
"llm_executed": true,
"llm_passes": 3,
"florence_executed": false,
"decisions": {...},
"taggers": {...},
"pass_outputs": {
"pass_1": "{subject + appearance description}",
"pass_2": "{clothing + pose + environment}",
"pass_3": "{lighting + composition + final}"
}
}
6. EXTREME MODE (llm_model with supports_reasoning=True, analysis_mode=Extreme)
REQUIREMENTS:
- llm_model.supports_reasoning == True
- Maximum detail extraction
EXECUTION:
1. Execute 22 taggers/analyzers
2. Tags cherry-pick ALL possible components
3. LLM executed in MANY passes (one per component)
PASSES (example for WOMAN subject):
Pass 1: Subject identification
Pass 2: Ethnicity analysis
Pass 3: Hair description
Pass 4: Face description
Pass 5: Eyes description
Pass 6: Body/Figure description
Pass 7: Clothing description
Pass 8: Accessories description
Pass 9: Pose description
Pass 10: Expression description
Pass 11: Environment description
Pass 12: Lighting description
Pass 13: Composition/Framing
Pass 14: Final assembly
OUTPUT:
prompt = "{maximum_detail_assembled}"
prompt_metadata = {
"mode": "extreme",
"source": "llm_extreme_multi_pass",
"llm_provider": "anthropic",
"llm_model": "claude-sonnet-4-20250514",
"taggers_executed": true,
"llm_executed": true,
"llm_passes": 14,
"florence_executed": false,
"decisions": {...},
"taggers": {...},
"component_outputs": {
"subject": "...",
"ethnicity": "...",
"hair": "...",
"face": "...",
"eyes": "...",
"body": "...",
"clothing": "...",
"accessories": "...",
"pose": "...",
"expression": "...",
"environment": "...",
"lighting": "...",
"composition": "..."
}
}
Prompt Library (Tag-Based Templates)
Templates are selected based on detected tags. Tags are NEVER included in the final prompt.
Subject Detection → Template Selection
# prompt_templates.yaml
templates:
# =========================================================================
# WOMAN SUBJECT
# =========================================================================
woman:
trigger_tags: ["1girl", "woman", "female", "lady"]
base_prompt: |
Describe this woman in detail for AI image generation.
sections:
appearance:
trigger: always
prompt: |
Describe her appearance: ethnicity, age impression,
hair (color, length, style), eye color, facial features,
skin tone and texture.
clothing:
trigger_tags: ["dress", "shirt", "outfit", "wearing", "clothed"]
prompt: |
Describe her clothing in detail: garment type, color,
fabric/material, pattern, fit, style, any visible accessories.
body:
trigger_conditions:
- shot_type: ["MS", "MFS", "FS", "MLS", "LS"]
- nsfw_level: ["SUGGESTIVE", "EXPLICIT"]
prompt: |
Describe her body and figure: build, proportions,
any notable physical features visible.
pose:
trigger_conditions:
- shot_type: ["MCU", "MS", "MFS", "FS", "MLS", "LS"]
prompt: |
Describe her pose: body position, arm placement,
leg position, weight distribution, overall stance.
expression:
trigger: always
prompt: |
Describe her expression and gaze: facial expression,
emotion conveyed, eye direction, mood.
environment:
trigger_conditions:
- places365_confidence: "> 0.5"
- not_tags: ["simple background", "plain background"]
prompt: |
Describe the environment/setting: location type,
background elements, atmosphere, time of day if visible.
lighting:
trigger: always
prompt: |
Describe the lighting: quality (soft/harsh), direction,
color temperature (warm/cool), shadows, mood created.
composition:
trigger: always
prompt: |
Describe the framing and composition: shot type,
camera angle, subject placement in frame.
assembly_template: |
{style_quality}. {subject_intro} {appearance}. {clothing}.
{body}. {pose}. {expression}. {environment}. {lighting}.
{composition}.
# =========================================================================
# MAN SUBJECT
# =========================================================================
man:
trigger_tags: ["1boy", "man", "male", "gentleman"]
# Similar structure to woman...
# =========================================================================
# LANDSCAPE SUBJECT
# =========================================================================
landscape:
trigger_tags: ["no humans", "scenery", "landscape", "nature"]
trigger_conditions:
- places365_category: ["outdoor", "nature", "beach", "mountain", "forest"]
sections:
terrain:
trigger: always
prompt: |
Describe the terrain and land features: type of landscape,
geological features, vegetation, water bodies.
sky:
trigger: always
prompt: |
Describe the sky: cloud formations, sun/moon position,
color gradients, weather conditions.
atmosphere:
trigger: always
prompt: |
Describe the atmosphere and mood: time of day, season,
weather, light quality, emotional tone.
composition:
trigger: always
prompt: |
Describe the composition: foreground/midground/background
elements, depth, focal point, framing.
# =========================================================================
# ANIMAL SUBJECT
# =========================================================================
animal:
trigger_conditions:
- wildlife_detected: true
# Similar structure...
# =========================================================================
# VEHICLE SUBJECT
# =========================================================================
vehicle:
trigger_tags: ["car", "motorcycle", "vehicle", "automobile"]
# Similar structure...
# =========================================================================
# PRODUCT SUBJECT
# =========================================================================
product:
trigger_tags: ["product", "object", "item", "merchandise"]
# Similar structure...
Tag → Decision Mappings
# tag_decisions.yaml
subject_detection:
WOMAN:
tags: ["1girl", "woman", "female", "lady", "female_focus"]
priority: 1
MAN:
tags: ["1boy", "man", "male", "gentleman", "male_focus"]
priority: 1
LANDSCAPE:
tags: ["no_humans", "scenery", "landscape"]
places365: ["outdoor", "nature", "mountain", "beach", "forest"]
priority: 2
ANIMAL:
wildlife_detected: true
priority: 1
VEHICLE:
tags: ["car", "motorcycle", "vehicle", "train", "airplane"]
priority: 1
gender_detection:
female:
tags: ["1girl", "woman", "female", "lady", "she"]
nudenet: ["female"]
male:
tags: ["1boy", "man", "male", "gentleman", "he"]
nudenet: ["male"]
nsfw_detection:
SAFE:
nudenet_max_exposure: 0
SUGGESTIVE:
nudenet_parts: ["cleavage", "covered_breast", "bare_shoulders"]
nudenet_max_exposure: 0.3
EXPLICIT:
nudenet_parts: ["exposed_breast", "exposed_genitalia"]
nudenet_max_exposure: 0.5
shot_type_mapping:
ECU: "extreme close-up focusing on face"
CU: "close-up portrait"
MCU: "medium close-up from chest up"
MS: "medium shot from waist up"
MFS: "medium full shot from thighs up"
FS: "full body shot"
MLS: "medium long shot showing full body with environment"
LS: "long shot with prominent environment"
ELS: "extreme long shot with vast environment"
section_triggers:
body_details:
enabled_when:
- shot_type: ["MS", "MFS", "FS", "MLS", "LS"]
- OR nsfw_level: ["SUGGESTIVE", "EXPLICIT"]
pose_details:
enabled_when:
- shot_type: ["MCU", "MS", "MFS", "FS", "MLS", "LS"]
environment_details:
enabled_when:
- places365_confidence: "> 0.5"
- NOT tags: ["simple_background", "white_background", "plain_background"]
clothing_details:
enabled_when:
- tags: ["dress", "shirt", "outfit", "clothed", "wearing"]
- OR fashion_detected: true
Summary Table
| Condition | Mode | Taggers | LLM Passes | Output |
|---|---|---|---|---|
user_prompt provided |
Override | No | 0 | Pass-through |
No llm_model |
Florence | No | 0 | Florence description |
llm_model + Quick |
Quick | No | 1 | LLM single-shot |
llm_model + Standard |
Standard | Yes (22) | 1 | LLM + template |
llm_model + Detailed + reasoning |
Detailed | Yes (22) | 2-3 | LLM multi-pass |
llm_model + Extreme + reasoning |
Extreme | Yes (22) | 10+ | LLM component-by-component |
Output Schema
prompt (STRING)
The final prompt text for image generation.
prompt_metadata (JSON)
{
"mode": "standard",
"source": "llm_template",
"processing": {
"taggers_executed": true,
"florence_executed": false,
"llm_executed": true,
"llm_passes": 1
},
"llm": {
"provider": "local",
"model": "Qwen3-VL-4B-Instruct",
"supports_reasoning": false
},
"decisions": {
"subject_type": "WOMAN",
"gender": "female",
"nsfw_level": "SUGGESTIVE",
"shot_type": "MS",
"scene_type": "STUDIO",
"quality_level": "PROFESSIONAL",
"lighting_mood": "DRAMATIC",
"template_sections": ["appearance", "clothing", "body", "pose", "lighting"]
},
"taggers": {
"wd14": {
"1girl": 0.98,
"long_hair": 0.92,
"black_hair": 0.88,
"brown_eyes": 0.85,
"dress": 0.91,
"red_dress": 0.87,
"standing": 0.82,
"looking_at_viewer": 0.79
},
"pixai": {...},
"joytag": {...},
"nudenet": {
"parts": ["cleavage"],
"nsfw_level": "SUGGESTIVE",
"exposure_score": 0.25
},
"pose": {
"body_position": "standing",
"arm_position": "at_sides",
"facing": "front"
},
"photography": {
"low_key": 0.72,
"warm_tones": 0.65,
"contrast": 0.58
},
"iqa": {
"aesthetic_score": 7.2,
"technical_score": 8.1
},
"shot_type": {
"MS": 0.82,
"MCU": 0.12
},
"places365": {
"photo_studio": 0.78,
"indoor": 0.85
},
"clip_scene": {
"photo_style": "portrait",
"mood": "intimate"
},
"lighting": {
"direction": "side",
"quality": "soft",
"shadows": "present"
},
"fashion_color": [
{"color": "red", "percentage": 0.45},
{"color": "black", "percentage": 0.30}
],
"deepfashion": {
"fabric": "silk",
"fit": "fitted",
"style": "elegant"
}
},
"template": {
"selected": "woman",
"sections_used": ["appearance", "clothing", "body", "pose", "expression", "lighting", "composition"],
"sections_skipped": ["environment"]
},
"timing": {
"taggers_ms": 2500,
"llm_ms": 1200,
"total_ms": 3700
}
}
Node Implementation Sketch
class SID_PromptGenerator:
CATEGORY = "SID Nodes"
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("prompt", "prompt_metadata")
FUNCTION = "generate"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
},
"optional": {
"llm_model": ("LLM_MODEL",), # Dot connector
"user_prompt": ("STRING",), # Dot connector (not text box)
"analysis_mode": (["Quick", "Standard", "Detailed", "Extreme"],),
},
}
def generate(self, image, llm_model=None, user_prompt=None, analysis_mode="Standard"):
metadata = {}
# Priority 1: Override mode
if user_prompt is not None and user_prompt.strip():
return (user_prompt, json.dumps({
"mode": "override",
"source": "user_prompt",
"processing": {"taggers_executed": False, "llm_executed": False}
}))
# Priority 2: Florence mode (no LLM)
if llm_model is None:
prompt, florence_meta = self._execute_florence(image)
return (prompt, json.dumps({
"mode": "florence",
"source": "florence_description",
**florence_meta
}))
# Priority 3: LLM modes
if analysis_mode == "Quick":
return self._execute_quick(image, llm_model)
elif analysis_mode == "Standard":
return self._execute_standard(image, llm_model)
elif analysis_mode == "Detailed":
return self._execute_detailed(image, llm_model)
elif analysis_mode == "Extreme":
return self._execute_extreme(image, llm_model)
Files to Create
core/prompt_generator/
├── __init__.py
├── generator.py # Main SID_PromptGenerator node
├── modes/
│ ├── __init__.py
│ ├── override.py # Pass-through mode
│ ├── florence.py # Florence-only mode
│ ├── quick.py # Single LLM call (no tags)
│ ├── standard.py # Tags + single LLM call
│ ├── detailed.py # Tags + 2-3 LLM passes
│ └── extreme.py # Tags + many LLM passes
├── templates/
│ ├── __init__.py
│ ├── loader.py # Load templates from YAML
│ ├── selector.py # Select template based on tags
│ └── builder.py # Build prompt from template
├── decisions/
│ ├── __init__.py
│ ├── subject.py # Subject type detection
│ ├── gender.py # Gender detection
│ ├── nsfw.py # NSFW level detection
│ ├── sections.py # Section trigger logic
│ └── quality.py # Quality level detection
└── config/
├── prompt_templates.yaml
└── tag_decisions.yaml