Files
EricRollei-Local_LLM_Prompt…/save_prompt_node.py
T
Eric HissandClaude Fable 5.1 4459af9ea6 V2.0.0: wildcard engine, platform profiles, MiniMax H3 default, API models
Every node id, input name and existing widget position is unchanged, so saved
workflows load; new inputs are appended only.

Wildcards
- core/wildcards: Dynamic Prompts / Impact Pack grammar, tag queries, variables,
  conditionals, concept / verbatim / loose bindings, reproducible seeds.
  Wired into every enhancer node; reads ComfyUI/models/wildcards.
- New nodes: Wildcard Processor, Semantic Variation (direction axes),
  Concept Survival Check. Starter lists in wildcards/.
- Random choices use a private generator; global random state is untouched.

Platform profiles
- core/profiles + profiles/*.yaml: one file per model (format, length,
  negative prompt or none, quality tokens, text and dialogue syntax, vendor
  rewriter prompt fetched once and cached). profiles_user/ overrides by id.
- New node: Platform Prompt Rewriter (prose, tags, edit instructions, JSON,
  MiniMax H3 fields, Hailuo brackets), with validators for each format.
- Text-to-Image and Image-to-Image read profiles through platforms.py;
  corrected facts for FLUX, Kontext, Chroma, Wan, AuraFlow, Kolors, NoobAI,
  Qwen-Image, HunyuanImage. Negative prompt is empty for models without one.
- Hosted / API models: Seedream 5, Nano Banana, GPT Image, Midjourney V8,
  FLUX.2 pro, Ideogram 3, Recraft V4, Seedance 2.0 / 2.5, Kling 3.0, Veo 3.1,
  Gemini Omni Flash, Runway, Wan 3.0, Luma, hosted H3, Grok, Vidu, PixVerse.
  Reports say how to switch the vendor's own prompt rewriting off.
- Illustrious: spaced tags, quality tags last, 25-80 words (OnomaAI paper).

Video nodes
- target_model and duration_seconds appended to the three video expanders.
  Default target is MiniMax H3; wan22_video is the original path, unchanged.
  A workflow saved earlier loads with the default until the input is set.

Also included: the Alice, Ideogram Magic Prompt and prompt-database nodes that
were already registered in __init__.py but had not been committed.

Fixes: v1 {animal} / {label:a|b} wildcards were inert in the video nodes;
Image-to-Video save_to_file raised NameError; T2I padded short-prompt models.

.gitattributes added (text=auto) so CRLF working files stop showing as
whole-file changes. prompt_database.db and the cached Ideogram prompt are
git-ignored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VpCi6nw5UECMdZ7ayYJvN
2026-09-21 00:28:58 -07:00

125 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Save Prompt to Database Node
ComfyUI node that saves prompts to the local SQLite prompt database.
Passthrough design – outputs the same prompt it receives so it can be
inserted into any workflow without breaking connections.
Author: Eric Hiss (GitHub: EricRollei)
"""
import logging
from .prompt_database import PromptDatabase, PLATFORMS, CATEGORIES
logger = logging.getLogger(__name__)
class SavePromptToDatabase:
"""
Saves a prompt (and optional negative prompt) to the local prompt
database. The positive prompt is passed through unchanged so this
node can sit between a prompt-generating node and a sampler.
"""
def __init__(self):
self.db = PromptDatabase()
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"prompt_text": ("STRING", {
"multiline": True,
"default": "",
"tooltip": "The prompt to save. Connect this to the output of any prompt enhancer node.",
}),
"category": (CATEGORIES, {
"default": "any",
"tooltip": "Subject category for organisation.",
}),
"platform": (PLATFORMS, {
"default": "any",
"tooltip": "Target generation platform (Flux, SDXL, Pony, etc.).",
}),
"tags": ("STRING", {
"default": "",
"tooltip": "Comma-separated tags for easy searching later.",
}),
"rating": ("INT", {
"default": 0,
"min": 0,
"max": 5,
"step": 1,
"tooltip": "Quality rating 0-5 (0 = unrated).",
}),
"save_enabled": ("BOOLEAN", {
"default": True,
"tooltip": "Toggle saving on/off without disconnecting the node.",
}),
},
"optional": {
"negative_prompt": ("STRING", {
"multiline": True,
"default": "",
"forceInput": True,
"tooltip": "Optional negative prompt to store alongside.",
}),
"notes": ("STRING", {
"multiline": True,
"default": "",
"tooltip": "Free-form notes about this prompt.",
}),
"favorite": ("BOOLEAN", {
"default": False,
"tooltip": "Mark this prompt as a favorite.",
}),
},
}
RETURN_TYPES = ("STRING", "STRING", "INT", "STRING")
RETURN_NAMES = ("prompt_text", "negative_prompt", "prompt_id", "status")
FUNCTION = "save_prompt"
CATEGORY = "Eric Prompt Enhancers/Database"
OUTPUT_NODE = True
def save_prompt(
self,
prompt_text: str,
category: str,
platform: str,
tags: str,
rating: int,
save_enabled: bool,
negative_prompt: str = "",
notes: str = "",
favorite: bool = False,
):
if not save_enabled:
return (prompt_text, negative_prompt, 0, "Save disabled – passthrough only")
if not prompt_text.strip():
return (prompt_text, negative_prompt, 0, "Empty prompt – nothing saved")
try:
prompt_id = self.db.save_prompt(
prompt_text=prompt_text,
negative_prompt=negative_prompt,
category=category,
platform=platform,
tags=tags,
rating=rating,
source="manual",
notes=notes,
favorite=favorite,
)
stats = self.db.stats()
status = (
f"Saved as #{prompt_id} | "
f"DB total: {stats['total_prompts']} prompts"
)
logger.info(f"Prompt saved to database with id={prompt_id}")
return (prompt_text, negative_prompt, prompt_id, status)
except Exception as e:
logger.error(f"Error saving prompt: {e}")
return (prompt_text, negative_prompt, 0, f"Error: {e}")