Expose seed control summary
This commit is contained in:
@@ -331,11 +331,11 @@ prompt result. Manual fields and explicitly fixed per-axis or character-slot
|
||||
seeds still override the global seed for those parts.
|
||||
|
||||
`SxCP Seed Control` outputs `seed_config`, which can be connected to the prompt
|
||||
builder's optional `seed_config` input. When an axis is set to `random`, the
|
||||
visible seed value is materialized before the workflow queues, and that exact
|
||||
value is used for the queued prompt. The mode returns to `random` after queueing
|
||||
so the next run can reroll. Use `Lock Random Seeds Now` on the node when you want
|
||||
to convert the current random axes into fixed reusable seeds.
|
||||
builder's optional `seed_config` input. It also outputs a `summary` string with
|
||||
the resolved value for every axis. When an axis is set to `random`, the widget
|
||||
can stay at `-1`, but the emitted `seed_config` and `summary` contain the
|
||||
concrete seed used for that queued prompt. Use `Lock Random Seeds Now` on the
|
||||
node when you want to convert the current random axes into fixed reusable seeds.
|
||||
|
||||
`SxCP Seed Locker` is the fast version for iteration. Set `base_seed` to a seed
|
||||
you like, choose one `reroll_axis`, and connect its `seed_config`. All other
|
||||
@@ -866,10 +866,12 @@ axis has its own mode plus seed value:
|
||||
- `follow_main`: always follows the final generator's main `seed` input and
|
||||
ignores the entered axis seed.
|
||||
- `fixed`: always uses the entered axis seed.
|
||||
- `random`: generates a fresh visible axis seed when the workflow queues.
|
||||
- `random`: generates a fresh resolved axis seed when the workflow queues.
|
||||
|
||||
The `Lock Random Seeds Now` button turns every current `random` axis into a
|
||||
visible concrete seed and switches those axes to `fixed`.
|
||||
The `summary` output lists the resolved value for every axis, including random
|
||||
axes whose visible widget value remains `-1`. The `Lock Random Seeds Now` button
|
||||
turns every current `random` axis into a visible concrete seed and switches
|
||||
those axes to `fixed`.
|
||||
|
||||
For exact prompt reproduction, `SxCP Global Seed` is the shortest path:
|
||||
|
||||
|
||||
@@ -192,7 +192,10 @@ Seed routing is centralized in `seed_config.py` around `SEED_AXIS_SALTS`,
|
||||
`SxCP Global Seed`, `SxCP Seed Control`, and `SxCP Seed Locker` all feed
|
||||
`seed_config`. Values below zero mean the row's main seed still drives that
|
||||
axis. Fixed axis seeds allow changing only one road, for example changing
|
||||
`pose`/`role` while keeping person, scene, and category stable.
|
||||
`pose`/`role` while keeping person, scene, and category stable. `SxCP Seed
|
||||
Control` keeps `seed_config` as its first output and also emits a `summary`
|
||||
showing resolved per-axis values, including random-mode seeds whose widget value
|
||||
may still be `-1`.
|
||||
|
||||
## Seed Playbook
|
||||
|
||||
|
||||
+39
-22
@@ -76,8 +76,8 @@ class SxCPSeedControl:
|
||||
required[f"{axis}_seed"] = ("INT", seed_spec)
|
||||
return {"required": required}
|
||||
|
||||
RETURN_TYPES = (SXCP_SEED_CONFIG,)
|
||||
RETURN_NAMES = ("seed_config",)
|
||||
RETURN_TYPES = (SXCP_SEED_CONFIG, "STRING")
|
||||
RETURN_NAMES = ("seed_config", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
@@ -88,6 +88,21 @@ class SxCPSeedControl:
|
||||
return random.random()
|
||||
return tuple(args), tuple(sorted(kwargs.items()))
|
||||
|
||||
@classmethod
|
||||
def _summary(cls, config_json):
|
||||
try:
|
||||
config = json.loads(config_json)
|
||||
except (TypeError, ValueError, json.JSONDecodeError):
|
||||
return "invalid seed config"
|
||||
parts = []
|
||||
for axis in cls.SEED_AXES:
|
||||
try:
|
||||
value = int(config.get(f"{axis}_seed", -1))
|
||||
except (TypeError, ValueError):
|
||||
value = -1
|
||||
parts.append(f"{axis}={'follow_main' if value < 0 else value}")
|
||||
return "resolved seeds: " + "; ".join(parts)
|
||||
|
||||
def build(
|
||||
self,
|
||||
category_seed_mode,
|
||||
@@ -109,27 +124,29 @@ class SxCPSeedControl:
|
||||
composition_seed_mode,
|
||||
composition_seed,
|
||||
):
|
||||
config = build_seed_config_json(
|
||||
category_seed=category_seed,
|
||||
subcategory_seed=subcategory_seed,
|
||||
content_seed=content_seed,
|
||||
person_seed=person_seed,
|
||||
scene_seed=scene_seed,
|
||||
pose_seed=pose_seed,
|
||||
role_seed=role_seed,
|
||||
expression_seed=expression_seed,
|
||||
composition_seed=composition_seed,
|
||||
category_seed_mode=category_seed_mode,
|
||||
subcategory_seed_mode=subcategory_seed_mode,
|
||||
content_seed_mode=content_seed_mode,
|
||||
person_seed_mode=person_seed_mode,
|
||||
scene_seed_mode=scene_seed_mode,
|
||||
pose_seed_mode=pose_seed_mode,
|
||||
role_seed_mode=role_seed_mode,
|
||||
expression_seed_mode=expression_seed_mode,
|
||||
composition_seed_mode=composition_seed_mode,
|
||||
)
|
||||
return (
|
||||
build_seed_config_json(
|
||||
category_seed=category_seed,
|
||||
subcategory_seed=subcategory_seed,
|
||||
content_seed=content_seed,
|
||||
person_seed=person_seed,
|
||||
scene_seed=scene_seed,
|
||||
pose_seed=pose_seed,
|
||||
role_seed=role_seed,
|
||||
expression_seed=expression_seed,
|
||||
composition_seed=composition_seed,
|
||||
category_seed_mode=category_seed_mode,
|
||||
subcategory_seed_mode=subcategory_seed_mode,
|
||||
content_seed_mode=content_seed_mode,
|
||||
person_seed_mode=person_seed_mode,
|
||||
scene_seed_mode=scene_seed_mode,
|
||||
pose_seed_mode=pose_seed_mode,
|
||||
role_seed_mode=role_seed_mode,
|
||||
expression_seed_mode=expression_seed_mode,
|
||||
composition_seed_mode=composition_seed_mode,
|
||||
),
|
||||
config,
|
||||
self._summary(config),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5225,6 +5225,7 @@ def smoke_node_utility_registration() -> None:
|
||||
seed_inputs = seed_control.INPUT_TYPES().get("required") or {}
|
||||
_expect("category_seed_mode" in seed_inputs, "Seed Control lost category seed mode input")
|
||||
_expect("tooltip" in seed_inputs["category_seed_mode"][1], "Seed Control tooltip injection missing")
|
||||
_expect(seed_control.RETURN_NAMES == ("seed_config", "summary"), "Seed Control lost visible summary output")
|
||||
_expect(
|
||||
node_tooltips._tooltip_for_input("SxCPSeedControl", "category_seed_mode")
|
||||
== "auto/follow_main follows the main seed; fixed uses category_seed; random rerolls this axis each queue.",
|
||||
@@ -5234,6 +5235,40 @@ def smoke_node_utility_registration() -> None:
|
||||
"Autoscaling switch input" in node_tooltips._tooltip_for_input("SxCPIndexSwitch", "input_12"),
|
||||
"Node tooltip policy lost autoscaling input fallback",
|
||||
)
|
||||
seed_control_config, seed_control_summary = seed_control().build(
|
||||
"fixed",
|
||||
-1,
|
||||
"follow_main",
|
||||
-1,
|
||||
"random",
|
||||
-1,
|
||||
"auto",
|
||||
123,
|
||||
"auto",
|
||||
-1,
|
||||
"fixed",
|
||||
777,
|
||||
"follow_main",
|
||||
888,
|
||||
"auto",
|
||||
-1,
|
||||
"fixed",
|
||||
999,
|
||||
)
|
||||
parsed_seed_control = json.loads(seed_control_config)
|
||||
_expect(parsed_seed_control.get("category_seed") == 0, "Seed Control fixed mode did not clamp negative seed")
|
||||
_expect(parsed_seed_control.get("subcategory_seed") == -1, "Seed Control follow_main mode should emit -1")
|
||||
_expect(int(parsed_seed_control.get("content_seed", -1)) >= 0, "Seed Control random mode did not emit resolved seed")
|
||||
_expect(parsed_seed_control.get("person_seed") == 123, "Seed Control auto mode did not preserve explicit value")
|
||||
_expect(parsed_seed_control.get("pose_seed") == 777, "Seed Control fixed mode did not preserve positive seed")
|
||||
_expect(parsed_seed_control.get("role_seed") == -1, "Seed Control follow_main role did not emit -1")
|
||||
_expect(parsed_seed_control.get("composition_seed") == 999, "Seed Control fixed composition seed changed")
|
||||
_expect("category=0" in seed_control_summary, "Seed Control summary lost fixed resolved seed")
|
||||
_expect("subcategory=follow_main" in seed_control_summary, "Seed Control summary lost follow_main marker")
|
||||
_expect(
|
||||
f"content={parsed_seed_control['content_seed']}" in seed_control_summary,
|
||||
"Seed Control summary lost random resolved seed value",
|
||||
)
|
||||
|
||||
seed, seed_config, summary = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPGlobalSeed"]().build(12345)
|
||||
parsed_seed = json.loads(seed_config)
|
||||
|
||||
Reference in New Issue
Block a user