Files
slahiriandClaude Opus 4.5 0012ad531b feat: v4.2.1 - Modular prompt generator with enhanced LLM modes
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>
2025-12-31 00:23:50 +05:30

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