71 lines
2.6 KiB
Python
71 lines
2.6 KiB
Python
"""Internal seed utilities extracted from the retired Universal Project Config.
|
|
|
|
Seed resolution and saved-metadata behavior are unchanged.
|
|
"""
|
|
|
|
import random
|
|
import logging
|
|
import threading
|
|
from datetime import datetime
|
|
from typing import Any, Dict, Optional
|
|
|
|
|
|
SEED_MIN = 0
|
|
SEED_MAX = 0xffffffff # 2**32 - 1
|
|
LOG_PREFIX = "PortraitConfig"
|
|
|
|
|
|
def _log(prefix: str, message: str) -> None:
|
|
logging.getLogger("PortraitUtils.seed").info("[%s] %s", prefix, message)
|
|
|
|
|
|
def _clamp_seed(value: Any) -> int:
|
|
try:
|
|
candidate = int(value)
|
|
except Exception:
|
|
return SEED_MIN
|
|
return max(SEED_MIN, min(SEED_MAX, candidate))
|
|
|
|
|
|
_seed_rng = random.Random(datetime.now().timestamp())
|
|
_seed_rng_lock = threading.Lock()
|
|
|
|
|
|
def _new_random_seed() -> int:
|
|
with _seed_rng_lock:
|
|
return _seed_rng.randint(SEED_MIN, SEED_MAX)
|
|
|
|
|
|
def _update_workflow_widgets(extra_pnginfo: Dict[str, Any], node_id: Any, original_seed: Any, new_seed: int) -> None:
|
|
workflow = extra_pnginfo.get("workflow", {}) if isinstance(extra_pnginfo, dict) else {}
|
|
nodes = workflow.get("nodes", []) if isinstance(workflow.get("nodes", []), list) else []
|
|
workflow_node = next((node for node in nodes if str(node.get("id")) == str(node_id)), None)
|
|
if not workflow_node or "widgets_values" not in workflow_node:
|
|
_log(LOG_PREFIX, "Unable to store seed in workflow metadata (node not found).")
|
|
else:
|
|
# Preserve the existing first-integer-match metadata behavior.
|
|
for index, value in enumerate(workflow_node["widgets_values"]):
|
|
if isinstance(value, int) and value == original_seed:
|
|
workflow_node["widgets_values"][index] = new_seed
|
|
break
|
|
|
|
|
|
def _update_prompt_inputs(prompt_nodes: Dict[str, Any], node_id: Any, new_seed: int) -> None:
|
|
prompt_node = prompt_nodes.get(str(node_id)) if isinstance(prompt_nodes, dict) else None
|
|
if not prompt_node or "inputs" not in prompt_node or "seed" not in prompt_node["inputs"]:
|
|
_log(LOG_PREFIX, "Unable to store seed in prompt metadata (node not found).")
|
|
else:
|
|
prompt_node["inputs"]["seed"] = new_seed
|
|
|
|
|
|
def _resolve_seed(seed: int, prompt: Optional[Dict[str, Any]], extra_pnginfo: Optional[Dict[str, Any]], unique_id: Optional[Any]) -> int:
|
|
if seed in (-1, -2, -3):
|
|
original_seed = seed
|
|
seed = _new_random_seed()
|
|
if unique_id is not None:
|
|
if extra_pnginfo is not None:
|
|
_update_workflow_widgets(extra_pnginfo, unique_id, original_seed, seed)
|
|
if prompt is not None:
|
|
_update_prompt_inputs(prompt, unique_id, seed)
|
|
return seed
|