feat(seed): make explicit seed sending opt-in
This commit is contained in:
@@ -27,6 +27,7 @@ class MidjourneyCustomRequest(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("style_references"),
|
||||
bind("character_references"),
|
||||
|
||||
@@ -51,6 +51,7 @@ class MidjourneyV4Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
bind("custom_args"),
|
||||
@@ -111,6 +112,7 @@ class MidjourneyV5Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
@@ -171,6 +173,7 @@ class MidjourneyV6Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
@@ -233,6 +236,7 @@ class MidjourneyV7Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
bind("custom_args"),
|
||||
),
|
||||
@@ -281,6 +285,7 @@ class MidjourneyV8AlphaRequest(PromptDrivenNode):
|
||||
bind("aspect_ratio"),
|
||||
bind("batch"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("custom_args"),
|
||||
),
|
||||
image_capability_target="midjourney_v8_alpha",
|
||||
|
||||
@@ -28,6 +28,7 @@ class Niji5Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
@@ -88,6 +89,7 @@ class Niji4Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
bind("custom_args"),
|
||||
@@ -144,6 +146,7 @@ class Niji6Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("translate_weights"),
|
||||
@@ -198,6 +201,7 @@ class Niji7Request(PromptDrivenNode):
|
||||
bind("batch"),
|
||||
bind("tile"),
|
||||
bind("seed"),
|
||||
bind("send_explicit_seed"),
|
||||
bind("use_raw"),
|
||||
*IMAGINE_SUBMISSION_BINDINGS,
|
||||
bind("custom_args"),
|
||||
|
||||
@@ -212,6 +212,8 @@ def _render_batch_repeat(value: Any, _: NormalizedValues) -> str:
|
||||
|
||||
def _render_seed(value: Any, _: NormalizedValues) -> str:
|
||||
"""Render the seed flag when the seed is a non-negative integer."""
|
||||
if not _.get("send_explicit_seed"):
|
||||
return ""
|
||||
coerced_value = coerce_int(value)
|
||||
return (
|
||||
f" --seed {value}" if coerced_value is not None and coerced_value >= 0 else ""
|
||||
@@ -455,11 +457,31 @@ INPUT_SPECS: dict[str, InputSpec] = {
|
||||
"min": 0,
|
||||
"max": 4294967295,
|
||||
"step": 1,
|
||||
"tooltip": "Random seed for reproducibility (--seed)",
|
||||
"tooltip": (
|
||||
"Optional Midjourney seed value. Midjourney randomizes by "
|
||||
'default when no seed is sent. Enable "Send Explicit Seed" to '
|
||||
"include this value as --seed."
|
||||
),
|
||||
},
|
||||
role=InputRole.PROMPT_FLAG,
|
||||
renderer=_render_seed,
|
||||
),
|
||||
"send_explicit_seed": InputSpec(
|
||||
key="send_explicit_seed",
|
||||
field_name="send_explicit_seed",
|
||||
field_type="BOOLEAN",
|
||||
field_options={
|
||||
"default": False,
|
||||
"label_on": "Send Explicit Seed",
|
||||
"label_off": "Send Explicit Seed",
|
||||
"tooltip": (
|
||||
"When enabled, Mutiny sends the Seed value to Midjourney as "
|
||||
"--seed. Leave disabled to use Midjourney's default randomized "
|
||||
"seed behavior."
|
||||
),
|
||||
},
|
||||
role=InputRole.PROMPT_FLAG,
|
||||
),
|
||||
"use_raw": InputSpec(
|
||||
key="use_raw",
|
||||
field_name="use_raw",
|
||||
|
||||
@@ -228,6 +228,24 @@ def test_midjourney_v7_node_submits_prompt_images_through_runtime(
|
||||
assert len(image_inputs.prompt_images) == 1
|
||||
assert image_inputs.prompt_images[0].startswith("data:image/png;base64,")
|
||||
|
||||
|
||||
def test_midjourney_v7_node_sends_seed_only_when_explicitly_enabled(
|
||||
plugin_package, make_node, fake_runtime_service_factory
|
||||
):
|
||||
"""Submit ``--seed`` only when the explicit seed toggle is enabled."""
|
||||
node_class = plugin_package.NODE_CLASS_MAPPINGS["MidjourneyV7Request"]
|
||||
fake_runtime = fake_runtime_service_factory()
|
||||
node = make_node(node_class, _runtime_service=fake_runtime)
|
||||
|
||||
node.generate(
|
||||
prompt="cat",
|
||||
seed=42,
|
||||
send_explicit_seed=True,
|
||||
)
|
||||
|
||||
assert fake_runtime.imagine_calls[0]["prompt_text"] == "cat --seed 42 --v 7"
|
||||
|
||||
|
||||
def test_niji6_node_submits_batched_images_through_runtime(
|
||||
plugin_package, make_node, fake_runtime_service_factory
|
||||
):
|
||||
|
||||
@@ -92,6 +92,28 @@ def test_stylize_spec_omits_default_flag(plugin_package):
|
||||
assert renderer(250, {}) == " --stylize 250"
|
||||
|
||||
|
||||
def test_seed_spec_requires_explicit_send_toggle(plugin_package):
|
||||
"""Render the seed flag only when explicit seed sending is enabled."""
|
||||
specs_module = sys.modules[f"{plugin_package.__name__}.prompting.input_specs"]
|
||||
renderer = specs_module.INPUT_SPECS["seed"].renderer
|
||||
|
||||
assert renderer is not None
|
||||
assert renderer(42, {"send_explicit_seed": False}) == ""
|
||||
assert renderer(42, {"send_explicit_seed": True}) == " --seed 42"
|
||||
|
||||
|
||||
def test_send_explicit_seed_spec_declares_boolean_default(plugin_package):
|
||||
"""Expose the explicit-seed toggle with the approved UI contract."""
|
||||
specs_module = sys.modules[f"{plugin_package.__name__}.prompting.input_specs"]
|
||||
seed_toggle_spec = specs_module.INPUT_SPECS["send_explicit_seed"]
|
||||
|
||||
assert seed_toggle_spec.field_name == "send_explicit_seed"
|
||||
assert seed_toggle_spec.field_type == "BOOLEAN"
|
||||
assert seed_toggle_spec.field_options["default"] is False
|
||||
assert seed_toggle_spec.field_options["label_on"] == "Send Explicit Seed"
|
||||
assert seed_toggle_spec.field_options["label_off"] == "Send Explicit Seed"
|
||||
|
||||
|
||||
def test_use_raw_spec_renders_raw_mode_flag(plugin_package):
|
||||
"""Render the shared Raw Mode toggle as ``--raw`` for all supported nodes."""
|
||||
specs_module = sys.modules[f"{plugin_package.__name__}.prompting.input_specs"]
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_custom_request_prompt_builder_fixes_version_spacing(plugin_package):
|
||||
)
|
||||
|
||||
assert build_result.prompt_text == (
|
||||
"cat::1.4 --v 7 --no dog::0.5 --raw --chaos 5 --repeat 2 --tile --seed 9"
|
||||
"cat::1.4 --v 7 --no dog::0.5 --raw --chaos 5 --repeat 2 --tile"
|
||||
)
|
||||
assert build_result.build_controls["translate_weights"] is True
|
||||
assert build_result.submission_controls == {
|
||||
@@ -86,7 +86,7 @@ def test_v7_prompt_builder_renders_wrapped_image_metadata(plugin_package):
|
||||
|
||||
assert build_result.prompt_text == (
|
||||
"cat --no dog --stylize 250 --chaos 7 --weird 12 --p p123 --ar 16:9"
|
||||
" --q 2 --exp 5 --repeat 3 --tile --seed 42 --raw --stylize 900"
|
||||
" --q 2 --exp 5 --repeat 3 --tile --raw --stylize 900"
|
||||
" --iw 1.5 --sw 0 --sv 5 --ow 321"
|
||||
)
|
||||
assert build_result.submission_controls["images"] is wrapped_prompt_images
|
||||
@@ -113,6 +113,24 @@ def test_v7_prompt_builder_renders_bare_personalization(plugin_package):
|
||||
|
||||
assert build_result.prompt_text == "cat --p"
|
||||
|
||||
|
||||
def test_v7_prompt_builder_sends_seed_only_when_explicitly_enabled(plugin_package):
|
||||
"""Render ``--seed`` only when the explicit seed toggle is enabled."""
|
||||
prompting_module = sys.modules[f"{plugin_package.__name__}.prompting"]
|
||||
node_class = plugin_package.NODE_CLASS_MAPPINGS["MidjourneyV7Request"]
|
||||
|
||||
build_result = prompting_module.build_prompt(
|
||||
node_class.NODE_DEFINITION,
|
||||
{
|
||||
"prompt": "cat",
|
||||
"seed": 42,
|
||||
"send_explicit_seed": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert build_result.prompt_text == "cat --seed 42"
|
||||
|
||||
|
||||
def test_v7_prompt_builder_rejects_conflicting_personalization_controls(
|
||||
plugin_package,
|
||||
):
|
||||
@@ -231,7 +249,7 @@ def test_niji7_prompt_builder_appends_niji7_supported_flags(plugin_package):
|
||||
|
||||
assert build_result.prompt_text == (
|
||||
"cat --no dog --chaos 5 --weird 20 --ar 2:1"
|
||||
" --repeat 2 --tile --seed 8 --raw --chaos 9 --sw 0 --sv 4"
|
||||
" --repeat 2 --tile --raw --chaos 9 --sw 0 --sv 4"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"images",
|
||||
"style_references",
|
||||
"character_references",
|
||||
@@ -144,6 +145,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"images",
|
||||
"translate_weights",
|
||||
"custom_args",
|
||||
@@ -165,6 +167,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"images",
|
||||
"translate_weights",
|
||||
@@ -190,6 +193,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"images",
|
||||
"translate_weights",
|
||||
@@ -218,6 +222,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"custom_args",
|
||||
],
|
||||
@@ -234,6 +239,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"aspect_ratio",
|
||||
"batch",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"custom_args",
|
||||
],
|
||||
"return_types": ("IMAGE",),
|
||||
@@ -253,6 +259,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"images",
|
||||
"translate_weights",
|
||||
"custom_args",
|
||||
@@ -275,6 +282,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"images",
|
||||
"translate_weights",
|
||||
@@ -300,6 +308,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"images",
|
||||
"translate_weights",
|
||||
@@ -322,6 +331,7 @@ EXPECTED_NODE_METADATA = {
|
||||
"batch",
|
||||
"tile",
|
||||
"seed",
|
||||
"send_explicit_seed",
|
||||
"use_raw",
|
||||
"images",
|
||||
"custom_args",
|
||||
|
||||
Reference in New Issue
Block a user