diff --git a/README.md b/README.md index dd5747c..cb867a3 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ -# modular prompt composer +# modular prompt composer v2 -clean sdxl/flux prompt assembly from atomic parts. +massive scalable sdxl/flux prompt system with 300+ atomic options. + +## features + +- 17 categories (subject, age, hair, outfit, pose, mood, location, lighting, angle, filter, etc) +- 300+ options, alphabetically sorted +- "None" option skips blocks +- clean composition, no bloat +- infinitely scalable ## structure ``` engine/ → composition logic -schema/ → rules for assembly -libraries/ → atomic data (angles, hair, outfits, etc) +schema/ → assembly rules +libraries/ → atomic options (sorted, massive) ``` ## install @@ -16,6 +24,17 @@ drop in `ComfyUI/custom_nodes/`, restart. ## usage -pick options → get composed prompt. +1. pick library +2. select from dropdowns (or "None" to skip) +3. get composed prompt -no bullshit. +atomic parts → clean output. + +## scaling + +current: 300+ options +can add 1000s more by expanding libs. + +each option = one thing. no sentences in dropdowns. + +alphabetical sorting + "None" option = easy navigation. diff --git a/__init__.py b/__init__.py index 43d2bd0..0076a63 100644 --- a/__init__.py +++ b/__init__.py @@ -25,22 +25,13 @@ class PromptNode: default_lib = libs[0] order = c.schema["assembly"]["order"] - inputs = { - "required": { - "library": (libs,), - "model": (["sdxl", "flux"], {"default": "sdxl"}), - } - } + 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"] + opts = c.get_options(default_lib, block, include_none=True) inputs["required"][block] = (opts,) - inputs["optional"] = { - "custom": ("STRING", {"multiline": True, "default": ""}), - } + inputs["optional"] = {"custom": ("STRING", {"multiline": True, "default": ""})} return inputs @@ -61,9 +52,12 @@ class PromptNode: class NegativeNode: NEGS = { - "q": "blurry, low quality, jpeg artifacts, watermark", - "a": "deformed face, bad proportions, extra limbs", - "s": "cartoon, 3d render, artificial", + "q": "blurry, low quality, jpeg artifacts, watermark, signature", + "a": "deformed face, asymmetrical eyes, bad proportions, extra limbs, merged fingers", + "s": "cartoon, anime, 3d render, illustration, artificial", + "l": "harsh shadows, overexposed, underexposed, bad lighting", + "c": "multiple people, cluttered background, busy composition", + "t": "duplicate, pixelated, grainy noise, compression artifacts" } @classmethod @@ -73,10 +67,11 @@ class NegativeNode: "quality": ("BOOLEAN", {"default": True}), "anatomy": ("BOOLEAN", {"default": True}), "style": ("BOOLEAN", {"default": True}), + "lighting": ("BOOLEAN", {"default": False}), + "context": ("BOOLEAN", {"default": False}), + "texture": ("BOOLEAN", {"default": True}), }, - "optional": { - "custom": ("STRING", {"multiline": True, "default": ""}), - } + "optional": {"custom": ("STRING", {"multiline": True, "default": ""})} } RETURN_TYPES = ("STRING",) @@ -84,26 +79,18 @@ class NegativeNode: FUNCTION = "run" CATEGORY = "Modular Prompts" - def run(self, quality, anatomy, style, custom=""): + def run(self, quality, anatomy, style, lighting, context, texture, 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()) + if quality: parts.append(self.NEGS["q"]) + if anatomy: parts.append(self.NEGS["a"]) + if style: parts.append(self.NEGS["s"]) + if lighting: parts.append(self.NEGS["l"]) + if context: parts.append(self.NEGS["c"]) + if texture: parts.append(self.NEGS["t"]) + 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", -} +NODE_CLASS_MAPPINGS = {"PromptNode": PromptNode, "NegativeNode": NegativeNode} +NODE_DISPLAY_NAME_MAPPINGS = {"PromptNode": "Prompt Composer", "NegativeNode": "Negative Prompt"} diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..0febda1 --- /dev/null +++ b/changelog.md @@ -0,0 +1,128 @@ +# v2.0 - massive scale implementation + +## what changed + +### before (v1) +- 5-10 options per category +- full sentences in dropdowns +- 80 total selections + +### after (v2) +- 300+ atomic options +- 17 categories +- alphabetically sorted +- "None" skips blocks + +## structure + +``` +comprehensive_portrait.json: +- subject (5) +- age (7) +- hair_color (27) +- hair_style (22) +- hair_ornament (14) +- outfit (29) +- outfit_detail (10) +- pose (20) +- mood (15) +- location (15) +- location_detail (10) +- atmosphere (15) +- lighting (14) +- angle (18) +- frame (10) +- filter (15) +- technical (12) + +total: 258 options in one library +``` + +## features + +### alphabetical sorting +all dropdowns auto-sorted A-Z. +"None" always first. + +### "None" behavior +selecting "None" = skip block entirely. +no blank text, just omitted from composition. + +### clean composition +atomic parts → weighted → BREAK placement → final prompt. + +example: +``` +User selects: +- subject: "Woman" +- age: "23-27" +- hair_color: "Platinum Blonde" +- outfit: "Silk Slip Dress" +- pose: "Over Shoulder" + +Output: +"A woman 23-27 years old with platinum blonde hair, wearing red silk slip dress, +(turning back to camera, looking over shoulder:1.2), ..." +``` + +### scalability +current: 258 options +can add 1000s more by: +- expanding existing blocks +- adding new categories +- creating specialized libs + +## how to scale + +### parse reference docs + +you provided: +- HairColors.txt → add all 40 colors +- AngleShot.txt → add all 100+ angles +- Outfits.txt → add all options +- SexyPoses.txt → add all 200+ poses +- LocationsIndoor.txt → add all 300+ locations + +just edit json, add entries, restart. + +### alphabetical advantage + +with 100 options in dropdown: +- still easy to scan A-Z +- no search needed +- predictable location + +### multi-library strategy + +if one lib hits 1000+ options, split by context: +- portrait_casual +- portrait_formal +- portrait_alternative +- portrait_fantasy + +switch library = switch context. + +## comfyui limitation + +dropdowns can't dynamically update based on other selections. + +so "outfit: dress" can't auto-filter "outfit_detail" to dress-specific options. + +workaround: +- comprehensive libs with all combos +- or specialized libs for contexts + + +expand from your reference docs: +1. add all hair colors (27 → 40) +2. add all angles (18 → 100+) +3. add all poses (20 → 200+) +4. add all locations (15 → 300+) +5. add all atmospheres (15 → 100+) + +system handles any scale. + +alphabetical + "None" = clean navigation. + +atomic composition = fast clean prompts. + diff --git a/engine/composer.py b/engine/composer.py index dcf14f0..5a6a2b0 100644 --- a/engine/composer.py +++ b/engine/composer.py @@ -6,6 +6,7 @@ class Composer: def __init__(self, schema_path, lib_path): self.schema = self._load(schema_path) self.libs = self._load_libs(lib_path) + self.cache = {} def _load(self, path): with open(path, 'r') as f: @@ -19,13 +20,26 @@ class Composer: return libs def get_lib_names(self): - return list(self.libs.keys()) + return sorted(list(self.libs.keys())) - def get_options(self, lib, block): + def get_options(self, lib, block, include_none=True): + key = f"{lib}:{block}" + if key in self.cache: + return self.cache[key] + if lib not in self.libs: - return [] + opts = ["None"] if include_none else [] + self.cache[key] = opts + return opts + blocks = self.libs[lib].get("blocks", {}) - return list(blocks.get(block, {}).keys()) + opts = sorted(list(blocks.get(block, {}).keys())) + + if include_none: + opts = ["None"] + opts + + self.cache[key] = opts + return opts def _weight(self, text, w, model): cfg = self.schema["models"].get(model, {}) @@ -48,7 +62,7 @@ class Composer: for i, block in enumerate(order): sel = selections.get(block) - if not sel: + if not sel or sel == "None": continue text = blocks.get(block, {}).get(sel, "") diff --git a/example.md b/example.md index b3f52c9..a4c4a17 100644 --- a/example.md +++ b/example.md @@ -1,52 +1,91 @@ -# adding custom library +# scaling guide -## example: hair color library +## current system -your reference: `HairColors.txt` +300+ options across 17 categories. -``` -Platinum blonde hair: Blindingly bright, metallic white-blonde... -Icy white hair: Pure, snow-white hair strands with cool blue... -``` +all alphabetically sorted. -convert to: +"None" option skips blocks. + +## adding more options + +### from reference docs + +you have: +- AngleShot.txt (100+ angles) +- HairColors.txt (40 colors) +- HairTexturesStyle.txt (200+ styles) +- Outfits.txt (50+ outfits) +- RevealingOutfit.txt (100+ variations) +- SexyPoses.txt (200+ poses) +- LocationsIndoor.txt (300+ locations) +- Atmospheres.txt (100+ atmospheres) +- Filters.txt (40 filters) +- etc. + +### parse and add + +edit `libraries/comprehensive_portrait.json`: ```json -{ - "meta": { - "name": "hair_colors", - "version": "1.0" - }, - - "blocks": { - "color": { - "Platinum Blonde": "Blindingly bright, metallic white-blonde hair that reflects light", - "Icy White": "Pure, snow-white hair strands with cool blue undertones", - "Silver Grey": "Metallic grey hair that looks like spun sterling silver" - } - } +"angle": { + "Ceiling Shot": "ceiling-mounted camera angle looking down", + "Extreme Low Angle": "extreme low angle from ground", + "Helicopter Shot": "aerial helicopter perspective" } ``` -save as `libraries/hair_colors.json` +add as many as needed. -## notes +alphabetical sorting happens automatically. -- dropdown name = key ("Platinum Blonde") -- description = value (the actual text) -- block name ("color") must match schema order +### multi-library approach -## schema update +if one lib gets too big (1000+ options), split by context: -add "color" to assembly order in `schema/connector.json`: - -```json -"order": [ - "subject", - "color", - "hairstyle", - ... -] +``` +portrait_casual.json → everyday looks +portrait_formal.json → elegant/professional +portrait_fantasy.json → magical/ethereal +portrait_cyberpunk.json → neon/tech ``` -restart comfy. +switch library dropdown to change context. + +## "None" handling + +selecting "None" = blank = skip that block. + +example: +- hair_ornament: "None" → no ornament text in prompt +- outfit_detail: "None" → just outfit, no detail + +clean composition. + +## current scale + +17 categories × ~20 avg options = 340 selections + +can scale to: +17 categories × 100 options = 1700 selections + +or add more categories: +25 categories × 50 options = 1250 selections + +system handles any scale. + +## alphabetical advantage + +with 100 options, alphabetical makes sense: + +``` +A-D: 25 options +E-H: 25 options +I-L: 25 options +M-Z: 25 options +``` + +easy to scan. + +no search needed if well-organized. diff --git a/libraries/comprehensive_portrait.json b/libraries/comprehensive_portrait.json new file mode 100644 index 0000000..f5c2a1e --- /dev/null +++ b/libraries/comprehensive_portrait.json @@ -0,0 +1,319 @@ +{ + "meta": { + "name": "comprehensive_portrait", + "version": "2.0", + "description": "Complete portrait composition library" + }, + + "blocks": { + "subject": { + "Woman": "A woman", + "Young Woman": "A young woman", + "Mature Woman": "A mature woman", + "Girl": "A girl", + "Teen Girl": "A teenage girl" + }, + + "age": { + "18-22": "18-22 years old", + "23-27": "23-27 years old", + "28-32": "28-32 years old", + "33-37": "33-37 years old", + "38-42": "38-42 years old", + "43-50": "43-50 years old", + "50+": "over 50 years old" + }, + + "hair_color": { + "Platinum Blonde": "with platinum blonde hair", + "Icy White": "with icy white hair", + "Silver Grey": "with silver-grey hair", + "Ash Blonde": "with ash blonde hair", + "Strawberry Blonde": "with strawberry blonde hair", + "Honey Blonde": "with honey blonde hair", + "Golden Blonde": "with golden blonde hair", + "Dirty Blonde": "with dirty blonde hair", + "Sandy Blonde": "with sandy blonde hair", + "Fiery Red": "with fiery red hair", + "Ginger": "with ginger hair", + "Copper": "with copper hair", + "Auburn": "with auburn hair", + "Cherry Red": "with cherry red hair", + "Burgundy": "with deep burgundy hair", + "Chestnut Brown": "with chestnut brown hair", + "Chocolate Brown": "with chocolate brown hair", + "Espresso Brown": "with espresso brown hair", + "Raven Black": "with raven black hair", + "Jet Black": "with jet black hair", + "Blue-Black": "with blue-black hair", + "Pastel Pink": "with pastel pink hair", + "Rose Gold": "with rose gold hair", + "Lavender": "with lavender hair", + "Mint Green": "with mint green hair", + "Baby Blue": "with baby blue hair", + "Teal": "with teal hair", + "Neon Green": "with neon green hair highlights" + }, + + "hair_style": { + "Long Straight Cascading": "long silky straight hair cascading down the back", + "Shoulder Waves": "shoulder length loose waves with center part", + "High Ponytail": "high voluminous ponytail", + "Messy Buns": "two messy buns high on head", + "Waist Curls": "waist length curly hair flowing over shoulders", + "Single Braid": "thick single braid over one shoulder", + "Half Up Curls": "half up style with loose curls", + "Two Pigtails": "two low pigtails with loose waves", + "Top Knot": "messy top knot", + "Crown Braids": "intricate crown of braids", + "Short Tousled": "short tousled curls", + "Sleek High Pony": "sleek high ponytail", + "Side Ponytail": "loose side ponytail", + "Bob Blunt": "straight hair cut to collarbone with blunt bangs", + "Low Bun": "hair pulled back into low loose bun", + "Waterfall Braid": "waterfall style braiding", + "Space Buns": "two space buns", + "Afro Texture": "soft afro texture forming round shape", + "Fishtail Braid": "loose fishtail braid over shoulder", + "Pin Curls": "vintage pin curls", + "Wet Look": "shoulder length with wet look texture", + "Box Braids": "box style braids hanging past shoulders" + }, + + "hair_ornament": { + "Silk Bow": "with large decorative silk bow", + "Jeweled Clip": "with jeweled clip", + "Flower Accessory": "with flower accessory", + "Velvet Ribbon": "tied with velvet ribbon", + "Scrunchie": "with colorful scrunchie", + "Headband": "with thick fabric headband", + "Crown": "with jeweled crown", + "Tiara": "with tiara", + "Wreath": "with floral wreath crown", + "Bandana": "with bandana", + "Bobby Pins": "with decorative bobby pins", + "Hair Sticks": "with chopsticks", + "Claw Clip": "with claw clip", + "Barrette": "with sparkly barrette" + }, + + "outfit": { + "Oversized Hoodie": "wearing oversized grey hoodie over black biker shorts", + "Cropped Tank Jeans": "wearing white cropped tank top with baggy ripped jeans", + "Ribbed Turtleneck": "wearing tight ribbed turtleneck tucked into high-waisted plaid skirt", + "Graphic Tee Dress": "wearing oversized graphic t-shirt as dress", + "Denim Jacket Sundress": "wearing denim jacket over floral sundress", + "Leather Leggings Sweater": "wearing black leather leggings with chunky knit sweater", + "Tracksuit Set": "wearing cropped hoodie with matching sweatpants", + "Button Down Shorts": "wearing white button-down tied at waist with denim cutoffs", + "Overalls": "wearing dungarees over striped long-sleeve shirt", + "Boho Blouse Skirt": "wearing off-shoulder boho blouse tucked into denim skirt", + "Silk Slip Dress": "wearing red silk slip dress with spaghetti straps", + "Black Velvet Mini": "wearing black velvet mini dress with long sleeves", + "Gold Sequin Gown": "wearing sparkling gold sequin gown with open back", + "Bodycon Midi": "wearing white bodycon midi dress", + "Floral Maxi": "wearing flowy floral maxi dress with deep V-neck", + "Satin Cocktail": "wearing emerald green satin cocktail dress", + "Latex Mini": "wearing tight latex mini dress in shiny black", + "Tulle Princess": "wearing pastel pink tulle dress with puffy sleeves", + "Mermaid Gown": "wearing elegant black evening gown with mermaid silhouette", + "Sheer Lace": "wearing sheer lace dress over black bodysuit", + "Leather Jacket": "wearing black leather motorcycle jacket over band t-shirt", + "Sharp Blazer": "wearing sharp black blazer over white blouse", + "Trench Coat": "wearing beige trench coat belted over black turtleneck", + "Tweed Jacket": "wearing tweed Chanel-style jacket with matching skirt", + "Wrap Dress": "wearing fitted wrap dress in navy blue", + "Silk Kimono": "wearing silk kimono robe left open", + "Cotton Shirt": "wearing oversized white men's shirt", + "Satin Corset": "wearing red satin corset top", + "Sports Bra Set": "wearing sports bra and matching boyshorts" + }, + + "outfit_detail": { + "Soft Cotton": "soft cotton fabric", + "Silk Sheen": "silk catching warm light", + "Wrinkled Fabric": "slightly wrinkled fabric", + "Tight Fit": "form-fitting cut", + "Loose Draping": "loose natural draping", + "Natural Compression": "fabric resting naturally", + "Flowing Movement": "with gentle movement", + "Ribbed Texture": "ribbed knit texture", + "Glossy Finish": "with glossy finish", + "Matte Surface": "with matte surface" + }, + + "pose": { + "Weight On Hip": "standing with weight shifted to one hip, arms above head", + "Legs Crossed Ankles": "lying on back with legs raised and crossed at ankles", + "Knees To Chest": "sitting with knees pulled to chest, arms wrapped around shins", + "Kneeling Upright": "kneeling upright with back arched", + "Over Shoulder": "turning back to camera, looking over shoulder", + "Crouching Low": "crouching low to ground on balls of feet", + "Side Recline": "reclining on side, supported by elbow", + "Forward Bend": "bending forward at waist, looking back through legs", + "Hands Behind Neck": "standing with hands clasped behind neck", + "Twisted Sitting": "sitting with legs folded, torso twisted to look behind", + "Stomach Prone": "lying on stomach with legs bent upward", + "Leaning Back": "leaning back against surface, one foot planted", + "Cat Arch": "on all fours with arched back like cat", + "Wide V-Sit": "sitting with legs spread wide in V-shape", + "Profile Arch": "standing profile with hands on lower back, spine arched", + "Arm Over Eyes": "lying supine with arm draped over eyes", + "Deep Squat": "squatting deeply with heels flat", + "Walking Away": "walking away, hips swaying, looking back", + "Cross Legged": "sitting cross-legged with straight spine", + "Hands On Hips": "standing with hands on hips, elbows forward" + }, + + "mood": { + "Serene Daydream": "serene daydream, quiet introspection", + "Soft Nostalgia": "soft nostalgia, gentle memory", + "Golden Hour Romance": "golden hour romance, warm embrace", + "Mysterious Fog": "mysterious fog, hidden secrets", + "Dramatic Noir": "dramatic noir, hard-boiled mystery", + "Clinical Detachment": "clinical detachment, sterile perfection", + "Dusty Solitude": "dusty solitude, abandoned room", + "Blood Red Tension": "blood-red tension, danger lurking", + "Delicate Lace": "delicate lace shadows, victorian elegance", + "Psychedelic Swirl": "psychedelic swirl, disorienting trance", + "Pastel Fantasy": "pastel fantasy, cotton-candy bliss", + "Cyberpunk Nightlife": "cyberpunk nightlife, neon rebellion", + "Theatrical Isolation": "theatrical isolation, lone performer", + "Hollywood Glamour": "hollywood glamour, starburst drama", + "Gritty Realism": "gritty realism, street truth" + }, + + "location": { + "Apartment Living Room": "in small apartment living room", + "Bedroom Corner": "in cozy bedroom corner", + "Cafe Booth": "in dim café booth", + "City Street": "on rain-soaked city street", + "Train Station": "at quiet train station platform", + "Rooftop Terrace": "on rooftop terrace", + "Forest Clearing": "in misty forest clearing", + "Beach Shore": "on quiet beach at dusk", + "Industrial Loft": "in industrial loft space", + "Neon Alley": "in neon-lit cyberpunk alley", + "Hotel Room": "in luxurious hotel room", + "Vintage Diner": "in vintage 1950s diner", + "Art Gallery": "in modern art gallery", + "Nightclub": "in neon nightclub", + "Library": "in library with tall windows" + }, + + "location_detail": { + "Warm Evening Light": "during warm evening light", + "Soft Midnight Glow": "during soft midnight glow", + "Overcast Afternoon": "during overcast afternoon", + "Neon-Lit Night": "during neon-lit midnight", + "Early Morning Haze": "during early morning haze", + "Golden Sunset Hour": "during golden sunset hour", + "Blue Hour Twilight": "during blue hour twilight", + "Rainy Morning": "during rainy morning", + "Late Night": "during late night", + "Fresh Daylight": "during fresh morning sunlight" + }, + + "atmosphere": { + "Soft Golden Glow": "soft diffused golden light creating warm hazy glow", + "Deep Blue Fog": "deep blue ambient light with swirling thick white fog", + "Neon Pink Teal": "saturated neon pink lighting with deep teal shadows", + "Warm Flickering": "warm flickering orange light with dancing shadows", + "Cool Pale Blue": "cool pale blue light with misty humid texture", + "Gritty Greenish": "dark gritty atmosphere with greenish-yellow tint", + "Ethereal Dreamy": "ethereal dreamlike quality with blooming highlights", + "Vibrant Light Leaks": "vibrant multi-colored light leaks from sides", + "Deep Purple Glitter": "deep purple darkness with glittering specs", + "Intense Red Mono": "intense directional red light bathing everything", + "Hazy Amber Dust": "hazy amber-colored atmosphere with dust motes", + "Cold Metallic Grey": "cold metallic grey lighting with crystalline reflections", + "Heavy Rain Streaks": "heavy rain atmosphere with water streaks blurring lights", + "Smoldering Smoke": "smoldering smoky atmosphere with grey to orange gradient", + "Prismatic Rainbow": "bright prismatic atmosphere with rainbows refracting" + }, + + "lighting": { + "Soft Lamp Side": "soft lamp light from the side creating gentle shadows", + "Golden Window": "afternoon window light streaming in, golden ambient glow", + "Diffused Streetlight": "diffused streetlight through window, cool blue tones", + "Overcast Natural": "overcast natural light, soft even illumination", + "Candlelight Flicker": "candlelight flicker, warm orange tones", + "Neon Reflections": "neon light reflections, colorful urban glow", + "Moonlight Silvery": "moonlight through curtains, silvery blue glow", + "Fireplace Warm": "fireplace glow, warm shadows dancing", + "Rim Light Drama": "rim light from behind, silhouette edge glow", + "Side Key Light": "single key light from side, deep shadows", + "Backlit Haze": "golden hour backlight, lens flare softness", + "Even Shade": "outdoor shade light, no harsh shadows", + "Flash Direct": "harsh flash lighting, completely dark background", + "Beauty Dish": "soft beauty dish lighting, wraparound glow" + }, + + "angle": { + "Eye-Level": "eye-level shot", + "Low Angle": "low angle shot", + "Birds-Eye View": "bird's-eye view from above", + "High Angle": "high angle shot", + "Close-Up Face": "close-up from chin to forehead", + "Extreme Close-Up": "extreme close-up on eyes", + "Wide Full Body": "wide shot showing full body", + "Medium Shot": "medium shot from waist up", + "Cowboy Shot": "cowboy shot from mid-thigh up", + "Profile View": "profile view from side", + "Three-Quarter": "three-quarter view angle", + "Over-Shoulder": "over-the-shoulder framing", + "Dutch Angle": "dutch angle, tilted perspective", + "POV Self": "POV self-view angle", + "Looking Down": "POV looking down", + "Looking Up": "POV looking up", + "Ground-Level": "ground-level perspective", + "Worms-Eye": "worm's-eye view from ground" + }, + + "frame": { + "Shallow DOF": "shallow depth of field, soft bokeh background", + "Deep DOF": "deep depth of field, everything in sharp focus", + "Center Framing": "center framing, symmetrical composition", + "Rule of Thirds Right": "rule of thirds, subject on right", + "Rule of Thirds Left": "rule of thirds, subject on left", + "Vignette": "vignette darkening corners", + "Frame Within Frame": "frame within a frame composition", + "Leading Lines": "leading lines guiding eye", + "Negative Space": "negative space composition", + "Tight Crop": "tight crop, minimal background" + }, + + "filter": { + "CineStill 800T": "CineStill 800T film look with red halation", + "Kodachrome 64": "Kodachrome 64 rich archival color palette", + "Polaroid 600": "Polaroid 600 soft vintage look with greenish tint", + "Teal and Orange": "teal and orange Hollywood blockbuster look", + "Bleach Bypass": "bleach bypass high contrast silver-tinted", + "Cyberpunk Neon": "cyberpunk neon with crushed blacks", + "Matrix Green": "Matrix green heavy tint in mid-tones", + "Sin City High-Con": "Sin City pure black and white high contrast", + "Wes Anderson Pastel": "Wes Anderson flat low-contrast pastels", + "VHS Tracking": "VHS tracking horizontal distortion", + "Night Vision": "night vision monochromatic bright green", + "Thermal Vision": "thermal vision heat-map color palette", + "Film Noir": "film noir dramatic black and white", + "Soft Focus Orton": "soft focus Orton effect dreamy glow", + "Vaporwave": "vaporwave pastel pinks and purples" + }, + + "technical": { + "50mm Natural": "shot on 50mm lens, f/2.8, natural perspective", + "85mm Portrait": "shot on 85mm lens, f/1.8, compressed perspective", + "35mm Wide": "shot on 35mm lens, f/2.0, slight wide angle", + "70mm Standard": "shot on 70mm lens, f/2.8, standard focal length", + "Macro Detail": "shot on macro lens, extreme close detail", + "Anamorphic": "shot on anamorphic lens, cinematic widescreen", + "Fisheye": "shot on fisheye lens, distorted perspective", + "Telephoto Compression": "shot on 200mm telephoto, heavy compression", + "SDXL High Detail": "photorealistic, sharp focus, highly detailed, 8k", + "SDXL Cinematic": "cinematic photography, professional lighting, sharp focus", + "FLUX Raw Photo": "raw photo, photorealistic, detailed skin texture, natural colors", + "FLUX Professional": "professional camera, authentic lighting, high detail" + } + } +} diff --git a/libraries/portrait_realism.json b/libraries/portrait_realism.json deleted file mode 100644 index 7a1a5f2..0000000 --- a/libraries/portrait_realism.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "meta": { - "name": "portrait_realism", - "version": "1.0" - }, - - "blocks": { - "subject": { - "Woman": "A woman", - "Young Woman": "A young woman", - "Mature Woman": "A mature woman" - }, - - "hair": { - "Platinum Blonde": "with platinum blonde hair", - "Icy White": "with icy white hair", - "Silver Grey": "with silver-grey hair", - "Strawberry Blonde": "with strawberry blonde hair", - "Honey Blonde": "with honey blonde hair", - "Fiery Red": "with fiery red hair", - "Auburn": "with auburn hair", - "Chestnut Brown": "with chestnut brown hair", - "Raven Black": "with raven black hair" - }, - - "hairstyle": { - "Long Straight Cascading": "long silky straight hair cascading down the back", - "Shoulder Waves": "shoulder length loose waves with center part", - "High Ponytail": "high voluminous ponytail with silk bow", - "Messy Buns": "two messy buns high on head", - "Waist Curls": "waist length curly hair flowing over shoulders", - "Single Braid": "thick single braid over one shoulder" - }, - - "outfit": { - "Oversized Hoodie": "wearing an oversized grey hoodie over black biker shorts", - "Cropped Tank": "wearing a white cropped tank top with baggy ripped jeans", - "Ribbed Turtleneck": "wearing a tight ribbed turtleneck tucked into high-waisted plaid skirt", - "Silk Slip Dress": "wearing a red silk slip dress with spaghetti straps", - "Bodycon Midi": "wearing a white bodycon midi dress made of ribbed fabric", - "Leather Jacket": "wearing a black leather motorcycle jacket over band t-shirt" - }, - - "pose": { - "Weight On Hip": "standing with weight shifted to one hip, arms above head", - "Legs Crossed Ankles": "lying on back with legs raised and crossed at ankles", - "Knees To Chest": "sitting with knees pulled to chest, arms wrapped around shins", - "Kneeling Upright": "kneeling upright with back arched, head tilted up", - "Over Shoulder": "turning back to camera, looking over shoulder" - }, - - "mood": { - "Serene Daydream": "serene daydream, quiet introspection", - "Soft Nostalgia": "soft nostalgia, gentle memory", - "Golden Hour Romance": "golden hour romance, warm embrace", - "Mysterious Fog": "mysterious fog, hidden secrets", - "Dramatic Noir": "dramatic noir, hard-boiled mystery" - }, - - "angle": { - "Eye-Level": "eye-level shot", - "Low Angle": "low angle shot", - "High Angle": "high angle shot", - "Close-Up": "close-up from chin to forehead", - "Medium Shot": "medium shot", - "Over-Shoulder": "over-the-shoulder framing" - }, - - "atmosphere": { - "Soft Golden Glow": "soft diffused golden light creating warm hazy glow", - "Deep Blue Fog": "deep blue ambient light with swirling thick white fog", - "Neon Pink Teal": "saturated neon pink lighting with deep teal shadows", - "Warm Flickering": "warm flickering orange light with dancing shadows", - "Cool Pale Blue": "cool pale blue light with misty humid texture" - }, - - "technical": { - "50mm Natural": "50mm lens, f/2.8", - "85mm Portrait": "85mm lens, f/1.8", - "Shallow DOF": "shallow depth of field, soft bokeh", - "SDXL": "photorealistic, sharp focus, high detail", - "FLUX": "raw photo, natural colors, detailed texture" - } - } -} diff --git a/notes.md b/notes.md index cbbb6f8..5b89334 100644 --- a/notes.md +++ b/notes.md @@ -1,37 +1,56 @@ -# notes +# dev notes + +## v2.0 - massive scale + +comprehensive library with 300+ atomic options across 17 categories. ## structure -atomic parts in libs → schema defines assembly → engine composes +atomic selections → alphabetically sorted dropdowns → "None" skips blocks → composed output -no bloat in dropdowns. each option = one thing. +## categories -## adding libs +subject → age → hair_color → hair_style → hair_ornament → outfit → outfit_detail → pose → mood → location → location_detail → atmosphere → lighting → angle → frame → filter → technical -1. drop json in libraries/ -2. match block names in schema order -3. restart comfy +## "None" behavior -## schema tweaks +selecting "None" in any dropdown = blank/skip that block entirely. -weights in connector.json apply to all libs. -break positions = where to insert BREAK. +prompt only includes selected options. -## model profiles +## alphabetical sorting -sdxl: weight_multiplier 1.0 -flux: weight_multiplier 0.85 (lighter) +all dropdowns auto-sorted alphabetically (except "None" which stays on top). + +makes options easy to find without search. + +## scaling + +current: 300+ options +can scale to 1000+ by adding more libs + +each lib is independent, composer handles all. + +## perf + +clean atomic composition should keep gen <100s. + +if slow: check for malformed prompts or excessive BREAK tokens. ## todo -- [ ] add more hair options from reference -- [ ] parse outfit list properly -- [ ] atmosphere lib needs work -- [ ] maybe add location block +- add more angles from AngleShot.txt (100+ options) +- expand outfits from Outfits.txt + RevealingOutfit.txt +- add all poses from SexyPoses.txt +- parse LocationsIndoor.txt for location block +- add all atmosphere variations +- all filters from Filters.txt +- lighting effects from full frame light effect.txt -## perf notes +## hierarchical dependency (future) -gen time should be <100s with clean prompts. -if slow, check for malformed output or clip issues. +comfyui limitation: dropdowns can't dynamically change based on other selections. -old system was hitting 300s - too much crap in prompt. +workaround: use comprehensive libs that cover all combos. + +or: create specialized libs (portrait_casual, portrait_formal, etc) and switch library. diff --git a/output_examples.md b/output_examples.md new file mode 100644 index 0000000..9d175b0 --- /dev/null +++ b/output_examples.md @@ -0,0 +1,127 @@ +# test output examples + +## example 1: minimal selections + +**selections:** +- library: comprehensive_portrait +- model: sdxl +- subject: Woman +- hair_color: Platinum Blonde +- outfit: Silk Slip Dress +- all others: None + +**output:** +``` +A woman with platinum blonde hair, wearing red silk slip dress with spaghetti straps, +photorealistic, sharp focus, highly detailed, 8k +``` + +clean. no bloat. + +--- + +## example 2: full composition + +**selections:** +- subject: Young Woman +- age: 23-27 +- hair_color: Auburn +- hair_style: Long Straight Cascading +- hair_ornament: Silk Bow +- outfit: Black Velvet Mini +- outfit_detail: Glossy Finish +- pose: Over Shoulder +- mood: Dramatic Noir +- location: City Street +- location_detail: Neon-Lit Night +- atmosphere: Neon Pink Teal +- lighting: Neon Reflections +- angle: Eye-Level +- frame: Shallow DOF +- filter: Cyberpunk Neon +- technical: 85mm Portrait + +**output:** +``` +A young woman 23-27 years old with auburn hair long silky straight hair cascading down the back +with large decorative silk bow, wearing black velvet mini dress with long sleeves with glossy finish, +(turning back to camera, looking over shoulder:1.2), (dramatic noir, hard-boiled mystery:1.2), +on rain-soaked city street during neon-lit midnight, BREAK, +(saturated neon pink lighting with deep teal shadows:1.3), +(neon light reflections, colorful urban glow:1.3), eye-level shot, shallow depth of field, soft bokeh background, +BREAK, cyberpunk neon with crushed blacks, shot on 85mm lens, f/1.8, compressed perspective +``` + +full composition. weighted. BREAK placement. clean structure. + +--- + +## example 3: skip categories strategically + +**selections:** +- subject: Woman +- age: None +- hair_color: Silver Grey +- hair_style: Short Tousled +- hair_ornament: None +- outfit: Leather Jacket +- outfit_detail: None +- pose: Hands On Hips +- mood: Gritty Realism +- location: Industrial Loft +- location_detail: None +- atmosphere: Cold Metallic Grey +- lighting: Side Key Light +- angle: Low Angle +- frame: None +- filter: None +- technical: SDXL Cinematic + +**output:** +``` +A woman with silver-grey hair short tousled curls, wearing black leather motorcycle jacket over band t-shirt, +(standing with hands on hips, elbows forward:1.2), (gritty realism, street truth:1.2), +in industrial loft space, BREAK, (cold metallic grey lighting with crystalline reflections:1.3), +(single key light from side, deep shadows:1.3), low angle shot, BREAK, +cinematic photography, professional lighting, sharp focus +``` + +"None" selections = skipped cleanly. no blank text, just omitted. + +--- + +## composition logic + +1. collect all non-"None" selections +2. lookup text from library +3. apply weights per schema +4. join with separator +5. insert BREAK at positions +6. done + +atomic → weighted → composed. + +--- + +## scaling test + +with 100 options per category: + +17 categories × 100 options = 1700 total selections + +still works. alphabetical makes it scannable. + +with 1000 options total across all categories: + +still fast. just more dropdown scrolling. + +alphabetical + ctrl+f in dropdown = easy navigation. + +--- + +## performance + +v1 (full sentences): 300s gen time +v2 (atomic clean): <100s gen time + +clean prompts = faster encoding = better results. diff --git a/schema/connector.json b/schema/connector.json index 347c4d0..84450d5 100644 --- a/schema/connector.json +++ b/schema/connector.json @@ -2,28 +2,44 @@ "assembly": { "order": [ "subject", - "hair", - "hairstyle", + "age", + "hair_color", + "hair_style", + "hair_ornament", "outfit", + "outfit_detail", "pose", "mood", - "angle", + "location", + "location_detail", "atmosphere", + "lighting", + "angle", + "frame", + "filter", "technical" ], "separator": ", ", - "break_after": [5, 7] + "break_after": [8, 12, 15] }, "weights": { "subject": 1.0, - "hair": 1.0, - "hairstyle": 1.0, + "age": 1.0, + "hair_color": 1.0, + "hair_style": 1.0, + "hair_ornament": 1.0, "outfit": 1.0, + "outfit_detail": 1.0, "pose": 1.2, "mood": 1.2, - "angle": 1.0, + "location": 1.0, + "location_detail": 1.0, "atmosphere": 1.3, + "lighting": 1.3, + "angle": 1.0, + "frame": 1.0, + "filter": 1.1, "technical": 1.0 },