Replaces and restructures prompt libraries and schema for a cleaner, more scalable architecture. Removes legacy documentation and libraries, adds new atomic libraries (portrait_realism, cyberpunk_neon), updates schema/connector.json to new block order and model profiles, and rewrites the engine and node interface for simplified, content-agnostic prompt composition. Documentation and examples updated to match the new system.
110 lines
2.8 KiB
Python
110 lines
2.8 KiB
Python
import os
|
|
import sys
|
|
|
|
node_path = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, node_path)
|
|
|
|
from engine.composer import Composer
|
|
|
|
SCHEMA = os.path.join(node_path, "schema", "connector.json")
|
|
LIBS = os.path.join(node_path, "libraries")
|
|
|
|
class PromptNode:
|
|
def __init__(self):
|
|
self.c = Composer(SCHEMA, LIBS)
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
inst = cls()
|
|
c = inst.c
|
|
|
|
libs = c.get_lib_names()
|
|
if not libs:
|
|
libs = ["default"]
|
|
|
|
default_lib = libs[0]
|
|
order = c.schema["assembly"]["order"]
|
|
|
|
inputs = {
|
|
"required": {
|
|
"library": (libs,),
|
|
"model": (["sdxl", "flux"], {"default": "sdxl"}),
|
|
}
|
|
}
|
|
|
|
for block in order:
|
|
opts = c.get_options(default_lib, block)
|
|
if not opts:
|
|
opts = ["None"]
|
|
inputs["required"][block] = (opts,)
|
|
|
|
inputs["optional"] = {
|
|
"custom": ("STRING", {"multiline": True, "default": ""}),
|
|
}
|
|
|
|
return inputs
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "run"
|
|
CATEGORY = "Modular Prompts"
|
|
|
|
def run(self, library, model, custom="", **kwargs):
|
|
sels = {k: v for k, v in kwargs.items() if v != "None"}
|
|
prompt = self.c.compose(library, sels, model)
|
|
|
|
if custom.strip():
|
|
prompt += ", BREAK, " + custom.strip()
|
|
|
|
return (prompt,)
|
|
|
|
|
|
class NegativeNode:
|
|
NEGS = {
|
|
"q": "blurry, low quality, jpeg artifacts, watermark",
|
|
"a": "deformed face, bad proportions, extra limbs",
|
|
"s": "cartoon, 3d render, artificial",
|
|
}
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"quality": ("BOOLEAN", {"default": True}),
|
|
"anatomy": ("BOOLEAN", {"default": True}),
|
|
"style": ("BOOLEAN", {"default": True}),
|
|
},
|
|
"optional": {
|
|
"custom": ("STRING", {"multiline": True, "default": ""}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("negative",)
|
|
FUNCTION = "run"
|
|
CATEGORY = "Modular Prompts"
|
|
|
|
def run(self, quality, anatomy, style, custom=""):
|
|
parts = []
|
|
if quality:
|
|
parts.append(self.NEGS["q"])
|
|
if anatomy:
|
|
parts.append(self.NEGS["a"])
|
|
if style:
|
|
parts.append(self.NEGS["s"])
|
|
if custom.strip():
|
|
parts.append(custom.strip())
|
|
|
|
return (", ".join(parts),)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"PromptNode": PromptNode,
|
|
"NegativeNode": NegativeNode,
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"PromptNode": "Prompt Composer",
|
|
"NegativeNode": "Negative Prompt",
|
|
}
|