DirectorNode: lock + seed control + custom intro modes + next_seed output

This commit is contained in:
zeeoale
2026-02-07 15:06:51 +01:00
parent 9a911d86a4
commit 6a2fc4ef0e
2 changed files with 92 additions and 32 deletions
+44 -22
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import random
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Tuple
def _pick(arr: Any, fallback: str = "") -> str:
@@ -14,33 +14,57 @@ def _join_nonempty(parts: List[str]) -> str:
return ", ".join([p.strip() for p in parts if p and p.strip()])
def _select_custom_intro(
world: Dict[str, Any],
mode: str = "auto",
index: Optional[int] = None,
) -> str:
ci = world.get("CUSTOM_INTRO")
if not isinstance(ci, dict) or not ci:
return ""
# Normalizza keys/values in stringhe
keys = list(ci.keys())
values = [str(ci[k]) for k in keys if ci.get(k) is not None]
if not values:
return ""
mode = (mode or "auto").lower().strip()
if mode == "index":
if index is None:
return ""
k = str(index)
return str(ci.get(k, "")) if k in ci else ""
if mode == "random":
return str(random.choice(values))
# auto: prova 0..6, altrimenti random
for k in ["0", "1", "2", "3", "4", "5", "6"]:
if k in ci:
return str(ci[k])
return str(random.choice(values))
def build_prompt_from_world(
world: Dict[str, Any],
seed: Optional[int] = None,
custom_intro_mode: str = "auto",
custom_intro_index: Optional[int] = None,
) -> str:
) -> Tuple[str, str]:
if seed is not None:
random.seed(seed)
# 1) system prompt (se ti serve per debug/log o per ritorni futuri)
system_prompt = str(world.get("SYSTEM_PROMPT", "")).strip()
# 2) prendi un custom_intro (se c’è)
custom_intro = ""
ci = world.get("CUSTOM_INTRO")
if isinstance(ci, dict) and ci:
if custom_intro_index is not None and str(custom_intro_index) in ci:
custom_intro = str(ci[str(custom_intro_index)])
else:
# prova 0..6, altrimenti random tra valori
for k in ["0", "1", "2", "3", "4", "5", "6"]:
if k in ci:
custom_intro = str(ci[k])
break
if not custom_intro:
custom_intro = str(random.choice(list(ci.values())))
custom_intro = _select_custom_intro(
world,
mode=custom_intro_mode,
index=custom_intro_index,
)
# 3) selezioni modulari (liste)
outfits = _pick(world.get("OUTFITS"), "simple dark outfit")
lighting = _pick(world.get("LIGHTING"), "low ambient light")
backgrounds = _pick(world.get("BACKGROUNDS"), "intimate interior")
@@ -51,8 +75,7 @@ def build_prompt_from_world(
atmos = _pick(world.get("ATMOSPHERES"), "quiet cinematic mood")
accessories = _pick(world.get("ACCESSORIES"), "")
# 4) compone una frase unica (poi la raffiniamo nello step successivo)
core = _join_nonempty([
prompt = _join_nonempty([
custom_intro,
outfits,
lighting,
@@ -65,5 +88,4 @@ def build_prompt_from_world(
accessories,
])
# system_prompt lo teniamo separato: qui ritorniamo solo il prompt “artistico”
return core.strip(), system_prompt
return (prompt.strip(), system_prompt)
+48 -10
View File
@@ -1,3 +1,7 @@
from __future__ import annotations
import random
from ..core.world_registry import WorldRegistry
from ..core.prompt_engine import build_prompt_from_world
@@ -13,22 +17,56 @@ class DirectorNode:
"required": {
"world": (names,),
"seed": ("INT", {"default": 0, "min": 0, "max": 2**31 - 1}),
},
"optional": {
"lock": ("BOOLEAN", {"default": False}),
"control_after_generate": (["keep", "increment", "randomize"],),
"custom_intro_mode": (["auto", "index", "random"],),
"custom_intro_index": ("INT", {"default": -1, "min": -1, "max": 6}),
},
}
}
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("prompt", "system_prompt")
RETURN_TYPES = ("STRING", "STRING", "INT")
RETURN_NAMES = ("prompt", "system_prompt", "next_seed")
FUNCTION = "run"
CATEGORY = "PFN/Director"
def run(self, world: str, seed: int, custom_intro_index: int = -1):
def run(
self,
world: str,
seed: int,
lock: bool,
control_after_generate: str,
custom_intro_mode: str,
custom_intro_index: int,
):
w = WorldRegistry.get(world)
if not w:
return ("(world not found)", "")
return ("(world not found)", "", seed)
idx = None if custom_intro_index < 0 else int(custom_intro_index)
prompt, system_prompt = build_prompt_from_world(w, seed=seed, custom_intro_index=idx)
return (prompt, system_prompt)
# Seed effettivo per generare
effective_seed = int(seed)
# Custom intro index valido solo in modalità index
idx = None
if (custom_intro_mode == "index") and (custom_intro_index is not None) and (int(custom_intro_index) >= 0):
idx = int(custom_intro_index)
prompt, system_prompt = build_prompt_from_world(
w,
seed=effective_seed,
custom_intro_mode=custom_intro_mode,
custom_intro_index=idx,
)
# Next seed (utile da collegare ad altri nodi)
if lock:
next_seed = effective_seed
else:
mode = (control_after_generate or "keep").lower().strip()
if mode == "increment":
next_seed = (effective_seed + 1) % (2**31)
elif mode == "randomize":
next_seed = random.randint(0, 2**31 - 1)
else:
next_seed = effective_seed
return (prompt, system_prompt, next_seed)