mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-14 09:43:22 -03:00
fix(metadata): exclude scalar fields from conditioning provenance inputs
This commit is contained in:
@@ -82,11 +82,7 @@ class GenericNodeExtractor(NodeMetadataExtractor):
|
||||
text = val.strip()
|
||||
break
|
||||
|
||||
input_conditionings = [
|
||||
value
|
||||
for input_name, value in inputs.items()
|
||||
if input_name.startswith("conditioning") and value is not None
|
||||
]
|
||||
input_conditionings = _collect_conditioning_inputs(inputs)
|
||||
if text or input_conditionings:
|
||||
prompt_metadata = _ensure_prompt_metadata(metadata, node_id)
|
||||
if text:
|
||||
@@ -434,6 +430,24 @@ def _first_output_tuple(outputs):
|
||||
return None
|
||||
|
||||
|
||||
def _collect_conditioning_inputs(inputs):
|
||||
"""Collect conditioning object inputs (``conditioning*`` keys).
|
||||
|
||||
Primitive values (None, str, int, float, bool) are excluded so scalar
|
||||
fields like ``conditioning_strength`` are not mistaken for conditioning
|
||||
objects during provenance tracking.
|
||||
"""
|
||||
if not inputs:
|
||||
return []
|
||||
return [
|
||||
value
|
||||
for input_name, value in inputs.items()
|
||||
if input_name.startswith("conditioning")
|
||||
and value is not None
|
||||
and not isinstance(value, (str, int, float, bool))
|
||||
]
|
||||
|
||||
|
||||
def _record_conditioning_source(
|
||||
metadata, node_id, output_conditioning, input_conditionings
|
||||
):
|
||||
@@ -525,13 +539,7 @@ class ConditioningCombineExtractor(NodeMetadataExtractor):
|
||||
if not inputs:
|
||||
return
|
||||
|
||||
input_conditionings = []
|
||||
for input_name in inputs:
|
||||
if (
|
||||
input_name.startswith("conditioning")
|
||||
and inputs[input_name] is not None
|
||||
):
|
||||
input_conditionings.append(inputs[input_name])
|
||||
input_conditionings = _collect_conditioning_inputs(inputs)
|
||||
|
||||
if input_conditionings:
|
||||
prompt_metadata = _ensure_prompt_metadata(metadata, node_id)
|
||||
|
||||
@@ -637,6 +637,134 @@ def test_conditioning_provenance_recovers_transformed_switched_prompts(
|
||||
assert params["negative_prompt"] == "expected negative"
|
||||
|
||||
|
||||
def test_conditioning_provenance_identity_switch_between_encoders(
|
||||
metadata_registry, monkeypatch
|
||||
):
|
||||
"""Lock identity-preserving switches placed directly between encoders.
|
||||
|
||||
A switch returns the selected input conditioning verbatim, so provenance
|
||||
must be recovered through object identity without any transform metadata.
|
||||
"""
|
||||
prompt_graph = {
|
||||
"encode_pos": {
|
||||
"class_type": "CLIPTextEncode",
|
||||
"inputs": {"text": "chosen positive", "clip": ["clip", 0]},
|
||||
},
|
||||
"encode_other_pos": {
|
||||
"class_type": "CLIPTextEncode",
|
||||
"inputs": {"text": "unchosen positive", "clip": ["clip", 0]},
|
||||
},
|
||||
"positive_switch": {
|
||||
"class_type": "ComfySwitchNode",
|
||||
"inputs": {
|
||||
"switch": True,
|
||||
"on_false": ["encode_other_pos", 0],
|
||||
"on_true": ["encode_pos", 0],
|
||||
},
|
||||
},
|
||||
"sampler": {
|
||||
"class_type": "ClownsharKSampler_Beta",
|
||||
"inputs": {
|
||||
"seed": 123,
|
||||
"steps": 8,
|
||||
"cfg": 1.0,
|
||||
"sampler_name": "linear/euler",
|
||||
"scheduler": "beta57",
|
||||
"denoise": 1.0,
|
||||
"positive": ["positive_switch", 0],
|
||||
"negative": ["encode_other_pos", 0],
|
||||
"latent_image": {
|
||||
"samples": types.SimpleNamespace(shape=(1, 4, 16, 16))
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
prompt = SimpleNamespace(original_prompt=prompt_graph)
|
||||
|
||||
chosen_conditioning = object()
|
||||
unchosen_conditioning = object()
|
||||
|
||||
monkeypatch.setattr(metadata_processor, "standalone_mode", False)
|
||||
|
||||
metadata_registry.start_collection("prompt-identity-switch")
|
||||
metadata_registry.set_current_prompt(prompt)
|
||||
|
||||
metadata_registry.record_node_execution(
|
||||
"encode_pos", "CLIPTextEncode", {"text": "chosen positive"}, None
|
||||
)
|
||||
metadata_registry.update_node_execution(
|
||||
"encode_pos", "CLIPTextEncode", [(chosen_conditioning,)]
|
||||
)
|
||||
metadata_registry.record_node_execution(
|
||||
"encode_other_pos", "CLIPTextEncode", {"text": "unchosen positive"}, None
|
||||
)
|
||||
metadata_registry.update_node_execution(
|
||||
"encode_other_pos", "CLIPTextEncode", [(unchosen_conditioning,)]
|
||||
)
|
||||
metadata_registry.record_node_execution(
|
||||
"positive_switch",
|
||||
"ComfySwitchNode",
|
||||
{
|
||||
"switch": True,
|
||||
"on_false": unchosen_conditioning,
|
||||
"on_true": chosen_conditioning,
|
||||
},
|
||||
None,
|
||||
)
|
||||
metadata_registry.update_node_execution(
|
||||
"positive_switch", "ComfySwitchNode", [(chosen_conditioning,)]
|
||||
)
|
||||
metadata_registry.record_node_execution(
|
||||
"sampler",
|
||||
"ClownsharKSampler_Beta",
|
||||
{
|
||||
"seed": 123,
|
||||
"steps": 8,
|
||||
"cfg": 1.0,
|
||||
"sampler_name": "linear/euler",
|
||||
"scheduler": "beta57",
|
||||
"denoise": 1.0,
|
||||
"positive": chosen_conditioning,
|
||||
"negative": unchosen_conditioning,
|
||||
"latent_image": {
|
||||
"samples": types.SimpleNamespace(shape=(1, 4, 16, 16))
|
||||
},
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
||||
metadata = metadata_registry.get_metadata("prompt-identity-switch")
|
||||
params = MetadataProcessor.extract_generation_params(metadata)
|
||||
|
||||
assert params["prompt"] == "chosen positive"
|
||||
assert params["negative_prompt"] == "unchosen positive"
|
||||
|
||||
|
||||
def test_conditioning_provenance_ignores_scalar_conditioning_fields(
|
||||
metadata_registry, monkeypatch
|
||||
):
|
||||
"""Scalar fields like ``conditioning_strength`` must not be collected as
|
||||
conditioning objects for unregistered transform nodes."""
|
||||
monkeypatch.setattr(metadata_processor, "standalone_mode", False)
|
||||
|
||||
metadata_registry.start_collection("prompt-scalar-filter")
|
||||
metadata_registry.set_current_prompt(SimpleNamespace(original_prompt={}))
|
||||
|
||||
input_conditioning = object()
|
||||
metadata_registry.record_node_execution(
|
||||
"strength_node",
|
||||
"SomeStrengthTransform",
|
||||
{"conditioning": input_conditioning, "conditioning_strength": 0.8},
|
||||
None,
|
||||
return_types=("CONDITIONING",),
|
||||
)
|
||||
|
||||
metadata = metadata_registry.get_metadata("prompt-scalar-filter")
|
||||
assert metadata[PROMPTS]["strength_node"]["orig_conditionings"] == [
|
||||
input_conditioning
|
||||
]
|
||||
|
||||
|
||||
def test_conditioning_provenance_recovers_kj_set_get_prompts(
|
||||
metadata_registry, monkeypatch
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user