Add Krea2 variant evidence node
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"purpose": "Structured fixed-seed Krea2 prompt/image evidence for SxCP atlas pose variants.",
|
"purpose": "Structured fixed-seed Krea2 prompt/image evidence for SxCP atlas pose variants.",
|
||||||
|
"artifact_policy": "Image paths are external ComfyUI artifacts and may be cleaned; seed, summaries, observation, decision, and commit are the durable record.",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"id": "doggy-52-climax-target-structural",
|
"id": "doggy-52-climax-target-structural",
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ parsing the JSON directly.
|
|||||||
|
|
||||||
In ComfyUI, use the `SxCP Krea2 Pose Variant` node when you want a workflow to
|
In ComfyUI, use the `SxCP Krea2 Pose Variant` node when you want a workflow to
|
||||||
select one catalog variant and emit a compatible `hardcore_position_config` for
|
select one catalog variant and emit a compatible `hardcore_position_config` for
|
||||||
the existing Position Pool / Action Filter / Insta-OF chain.
|
the existing Position Pool / Action Filter / Insta-OF chain. Pair it with
|
||||||
|
`SxCP Krea2 Variant Evidence` to display the fixed-seed eval entry, image paths,
|
||||||
|
and generator decision behind that variant.
|
||||||
|
|
||||||
## Inventory
|
## Inventory
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ Runtime logs are written under `.sxcp_eval/` and ignored by git.
|
|||||||
Durable fixed-seed findings that justify a guide rule, generator patch, or pose
|
Durable fixed-seed findings that justify a guide rule, generator patch, or pose
|
||||||
variant promotion are recorded in [`krea2-eval-log.json`](krea2-eval-log.json).
|
variant promotion are recorded in [`krea2-eval-log.json`](krea2-eval-log.json).
|
||||||
Use runtime logs for scratch notes; use the JSON log only for evidence that
|
Use runtime logs for scratch notes; use the JSON log only for evidence that
|
||||||
should remain tied to a catalog variant.
|
should remain tied to a catalog variant. Image paths in that log point at
|
||||||
|
external ComfyUI artifacts and may be cleaned; the durable evidence is the fixed
|
||||||
|
seed, prompt summaries, observation, decision, and commit.
|
||||||
|
|
||||||
## Optional Command Hook
|
## Optional Command Hook
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from . import krea2_eval_log
|
||||||
from . import krea2_pose_variant_catalog
|
from . import krea2_pose_variant_catalog
|
||||||
from .hardcore_position_config import (
|
from .hardcore_position_config import (
|
||||||
build_hardcore_action_filter_json,
|
build_hardcore_action_filter_json,
|
||||||
@@ -12,6 +13,7 @@ try:
|
|||||||
hardcore_position_key_choices,
|
hardcore_position_key_choices,
|
||||||
)
|
)
|
||||||
except ImportError: # Allows local smoke tests from the repository root.
|
except ImportError: # Allows local smoke tests from the repository root.
|
||||||
|
import krea2_eval_log
|
||||||
import krea2_pose_variant_catalog
|
import krea2_pose_variant_catalog
|
||||||
from hardcore_position_config import (
|
from hardcore_position_config import (
|
||||||
build_hardcore_action_filter_json,
|
build_hardcore_action_filter_json,
|
||||||
@@ -140,6 +142,59 @@ class SxCPKrea2PoseVariant:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPKrea2VariantEvidence:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
keys = krea2_pose_variant_catalog.variant_keys()
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"variant_key": (keys or ["missing_catalog_variant"], {"default": keys[0] if keys else "missing_catalog_variant"}),
|
||||||
|
"result": (["accepted", "rejected", "inconclusive", "any"], {"default": "accepted"}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"variant_key_in": ("STRING", {"default": ""}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "INT", "STRING")
|
||||||
|
RETURN_NAMES = (
|
||||||
|
"summary",
|
||||||
|
"baseline_image_path",
|
||||||
|
"candidate_image_path",
|
||||||
|
"evidence_json",
|
||||||
|
"seed",
|
||||||
|
"decision",
|
||||||
|
)
|
||||||
|
FUNCTION = "build"
|
||||||
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
|
def build(self, variant_key, result="accepted", variant_key_in=""):
|
||||||
|
key = str(variant_key_in or variant_key or "").strip()
|
||||||
|
result_filter = None if result == "any" else result
|
||||||
|
entries = krea2_eval_log.entries_for_variant(key, result=result_filter)
|
||||||
|
if not entries:
|
||||||
|
empty = {
|
||||||
|
"variant_key": key,
|
||||||
|
"result": result,
|
||||||
|
"summary": "no Krea2 eval evidence found",
|
||||||
|
}
|
||||||
|
return empty["summary"], "", "", json.dumps(empty, ensure_ascii=True, sort_keys=True), -1, ""
|
||||||
|
entry = entries[0]
|
||||||
|
summary = (
|
||||||
|
f"evidence={entry.get('id')}; variant={entry.get('variant_key')}; "
|
||||||
|
f"seed={entry.get('seed')}; result={entry.get('result')}; decision={entry.get('decision')}"
|
||||||
|
)
|
||||||
|
seed = entry.get("seed")
|
||||||
|
return (
|
||||||
|
summary,
|
||||||
|
str(entry.get("baseline_image") or ""),
|
||||||
|
str(entry.get("candidate_image") or ""),
|
||||||
|
json.dumps(entry, ensure_ascii=True, sort_keys=True),
|
||||||
|
int(seed) if isinstance(seed, int) else -1,
|
||||||
|
str(entry.get("decision") or ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SxCPHardcoreActionFilter:
|
class SxCPHardcoreActionFilter:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -203,10 +258,12 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"SxCPHardcorePositionPool": SxCPHardcorePositionPool,
|
"SxCPHardcorePositionPool": SxCPHardcorePositionPool,
|
||||||
"SxCPHardcoreActionFilter": SxCPHardcoreActionFilter,
|
"SxCPHardcoreActionFilter": SxCPHardcoreActionFilter,
|
||||||
"SxCPKrea2PoseVariant": SxCPKrea2PoseVariant,
|
"SxCPKrea2PoseVariant": SxCPKrea2PoseVariant,
|
||||||
|
"SxCPKrea2VariantEvidence": SxCPKrea2VariantEvidence,
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
"SxCPHardcorePositionPool": "SxCP Hardcore Position Pool",
|
"SxCPHardcorePositionPool": "SxCP Hardcore Position Pool",
|
||||||
"SxCPHardcoreActionFilter": "SxCP Hardcore Action Filter",
|
"SxCPHardcoreActionFilter": "SxCP Hardcore Action Filter",
|
||||||
"SxCPKrea2PoseVariant": "SxCP Krea2 Pose Variant",
|
"SxCPKrea2PoseVariant": "SxCP Krea2 Pose Variant",
|
||||||
|
"SxCPKrea2VariantEvidence": "SxCP Krea2 Variant Evidence",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,6 +327,11 @@ NODE_INPUT_TOOLTIPS = {
|
|||||||
"combine_mode": "replace discards incoming position choices; add merges this variant with the incoming position config.",
|
"combine_mode": "replace discards incoming position choices; add merges this variant with the incoming position config.",
|
||||||
"hardcore_position_config": "Optional incoming hardcore position config. Connect this when layering a variant on an existing pool.",
|
"hardcore_position_config": "Optional incoming hardcore position config. Connect this when layering a variant on an existing pool.",
|
||||||
},
|
},
|
||||||
|
"SxCPKrea2VariantEvidence": {
|
||||||
|
"variant_key": "Catalog variant whose fixed-seed eval evidence should be shown.",
|
||||||
|
"result": "Filter eval entries by result. accepted is the evidence used for proven variants.",
|
||||||
|
"variant_key_in": "Optional connected variant key from SxCP Krea2 Pose Variant. When connected, it overrides the selector.",
|
||||||
|
},
|
||||||
"SxCPHardcoreActionFilter": {
|
"SxCPHardcoreActionFilter": {
|
||||||
"focus": "keep_pool preserves/broadens the incoming pool; *_only modes force one action family.",
|
"focus": "keep_pool preserves/broadens the incoming pool; *_only modes force one action family.",
|
||||||
"allow_toys": "Allow toy/strap-on wording in hardcore actions.",
|
"allow_toys": "Allow toy/strap-on wording in hardcore actions.",
|
||||||
|
|||||||
+26
-1
@@ -6807,6 +6807,7 @@ def smoke_krea2_pose_variant_catalog_policy() -> None:
|
|||||||
def smoke_krea2_eval_log_policy() -> None:
|
def smoke_krea2_eval_log_policy() -> None:
|
||||||
log = krea2_eval_log.load_eval_log()
|
log = krea2_eval_log.load_eval_log()
|
||||||
_expect(log.get("version") == 1, "Krea2 eval log version changed unexpectedly")
|
_expect(log.get("version") == 1, "Krea2 eval log version changed unexpectedly")
|
||||||
|
_expect("external ComfyUI artifacts" in str(log.get("artifact_policy") or ""), "Krea2 eval log should document external artifact policy")
|
||||||
entries = krea2_eval_log.entries()
|
entries = krea2_eval_log.entries()
|
||||||
_expect(entries, "Krea2 eval log has no entries")
|
_expect(entries, "Krea2 eval log has no entries")
|
||||||
catalog_keys = set(krea2_pose_variant_catalog.variant_keys())
|
catalog_keys = set(krea2_pose_variant_catalog.variant_keys())
|
||||||
@@ -6833,7 +6834,7 @@ def smoke_krea2_eval_log_policy() -> None:
|
|||||||
image_path = str(entry.get(image_key) or "")
|
image_path = str(entry.get(image_key) or "")
|
||||||
if image_path:
|
if image_path:
|
||||||
_expect(Path(image_path).is_absolute(), f"{entry_id}.{image_key} should be absolute when present")
|
_expect(Path(image_path).is_absolute(), f"{entry_id}.{image_key} should be absolute when present")
|
||||||
_expect(Path(image_path).is_file(), f"{entry_id}.{image_key} is missing: {image_path}")
|
_expect(Path(image_path).suffix.lower() == ".png", f"{entry_id}.{image_key} should reference a PNG artifact")
|
||||||
boobjob_entries = krea2_eval_log.entries_for_variant("pov_boobjob_upright_cleavage", result="accepted")
|
boobjob_entries = krea2_eval_log.entries_for_variant("pov_boobjob_upright_cleavage", result="accepted")
|
||||||
_expect(boobjob_entries and boobjob_entries[0].get("seed") == 7302, "Boobjob accepted eval evidence changed")
|
_expect(boobjob_entries and boobjob_entries[0].get("seed") == 7302, "Boobjob accepted eval evidence changed")
|
||||||
mutation = krea2_eval_log.entries_for_variant("pov_handjob_upright_centered")[0]
|
mutation = krea2_eval_log.entries_for_variant("pov_handjob_upright_centered")[0]
|
||||||
@@ -8870,6 +8871,7 @@ def smoke_node_hardcore_position_registration() -> None:
|
|||||||
"SxCPHardcorePositionPool",
|
"SxCPHardcorePositionPool",
|
||||||
"SxCPHardcoreActionFilter",
|
"SxCPHardcoreActionFilter",
|
||||||
"SxCPKrea2PoseVariant",
|
"SxCPKrea2PoseVariant",
|
||||||
|
"SxCPKrea2VariantEvidence",
|
||||||
]
|
]
|
||||||
for node_name in required_nodes:
|
for node_name in required_nodes:
|
||||||
_expect(node_name in sxcp_nodes.NODE_CLASS_MAPPINGS, f"{node_name} missing from node registry")
|
_expect(node_name in sxcp_nodes.NODE_CLASS_MAPPINGS, f"{node_name} missing from node registry")
|
||||||
@@ -8931,6 +8933,29 @@ def smoke_node_hardcore_position_registration() -> None:
|
|||||||
_expect("torso bent forward" in avoid_cues, "Krea2 Pose Variant lost avoid cues output")
|
_expect("torso bent forward" in avoid_cues, "Krea2 Pose Variant lost avoid cues output")
|
||||||
_expect("variant=pov_boobjob_upright_cleavage" in variant_summary, "Krea2 Pose Variant summary lost key")
|
_expect("variant=pov_boobjob_upright_cleavage" in variant_summary, "Krea2 Pose Variant summary lost key")
|
||||||
|
|
||||||
|
evidence_node = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2VariantEvidence"]
|
||||||
|
evidence_inputs = evidence_node.INPUT_TYPES().get("required") or {}
|
||||||
|
_expect("variant_key" in evidence_inputs, "Krea2 Variant Evidence lost variant selector")
|
||||||
|
_expect("tooltip" in evidence_inputs["variant_key"][1], "Krea2 Variant Evidence tooltip injection missing")
|
||||||
|
(
|
||||||
|
evidence_summary,
|
||||||
|
baseline_image,
|
||||||
|
candidate_image,
|
||||||
|
evidence_json,
|
||||||
|
evidence_seed,
|
||||||
|
evidence_decision,
|
||||||
|
) = evidence_node().build(
|
||||||
|
"pov_boobjob_upright_cleavage",
|
||||||
|
"accepted",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
parsed_evidence = json.loads(evidence_json)
|
||||||
|
_expect(evidence_seed == 7302, "Krea2 Variant Evidence returned wrong fixed seed")
|
||||||
|
_expect(evidence_decision == "generator_patch", "Krea2 Variant Evidence returned wrong decision")
|
||||||
|
_expect("boobjob-7302" in evidence_summary, "Krea2 Variant Evidence summary lost entry id")
|
||||||
|
_expect(baseline_image.endswith(".png") and candidate_image.endswith(".png"), "Krea2 Variant Evidence lost image paths")
|
||||||
|
_expect(parsed_evidence.get("variant_key") == "pov_boobjob_upright_cleavage", "Krea2 Variant Evidence returned wrong JSON")
|
||||||
|
|
||||||
|
|
||||||
def smoke_node_formatter_registration() -> None:
|
def smoke_node_formatter_registration() -> None:
|
||||||
required_nodes = [
|
required_nodes = [
|
||||||
|
|||||||
Reference in New Issue
Block a user