From 78dc9252f67bb29899c1cab4736cd7d2a0d3a4bb Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 19:28:00 +0300 Subject: [PATCH 1/8] Release Refiner V2 appearance safety --- CHANGELOG.md | 24 +++ README.md | 11 ++ __init__.py | 7 +- conditioning.py | 213 ++++++++++++++++++-- docs/FunPackVideoRefinerV2.md | 22 +++ docs/FunPackVideoRefinerV2QuickGuide.md | 37 ++++ funpack.py | 7 +- model_management.py | 9 + pyproject.toml | 2 +- templates.py | 188 ++++++++++++++++++ tests/test_v2_category_alignment.py | 157 ++++++++++++++- web/funpack_refinement_key_loader.js | 250 ++++++++++++++++++++++++ 12 files changed, 905 insertions(+), 22 deletions(-) create mode 100644 docs/FunPackVideoRefinerV2QuickGuide.md create mode 100644 web/funpack_refinement_key_loader.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 84bd8da0..bfdf12a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [2.3.0] - 2026-05-08 + +### Added + +Added `Wrong appearance` rating to `FunPack Video Refiner V2` for outputs contaminated by remembered clothing, character, subject, or background concepts. + +Added `FunPack Refinement Key Loader`, with a selectable key dropdown, create-on-load behavior, and browser-side JSON import/export buttons. + +Added a Discord-friendly Refiner V2 quick guide for new users. + +### Changed + +Updated Refiner V2 Prompt Repair so it only auto-adds safe repair concepts such as action, camera, details, quality, and style. Appearance, subject/character, and environment/background concepts are now blocked from Prompt Repair. + +Updated `I'm Feeling Lucky` in Refiner V2 so appearance, subject/character, and environment/background memory is not auto-injected unless the user explicitly includes that phrase in the current prompt. + +Updated legacy Void/Lucky token-bank selection to skip appearance, subject/character, and environment/background tokens. + +Updated Refiner V2 and `FunPack Apply LoRA Weights` so both can accept a linked refinement key from `FunPack Refinement Key Loader`. + +### Fixed + +Fixed appearance bleed-over where highly liked clothing or character tags could reappear in unrelated image-to-video prompts. + ## [2.2.1] - 2026-05-07 ### Fixed diff --git a/README.md b/README.md index bed2b069..fbc2d780 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,16 @@ A set of ComfyUI nodes for experimenting with video generation workflows based on WAN, HunyuanVideo, LTX, and similar models. +## Updates in 2.3.0 + +Refiner V2 now blocks learned appearance, character, subject, and background concepts from Prompt Repair, Lucky auto-injection, and legacy Void memory unless the current prompt explicitly asks for them. + +Added `Wrong appearance` for outputs polluted by remembered clothing or character traits. This suppresses the responsible appearance memory without penalizing unrelated action, camera, detail, or quality learning. + +Added `FunPack Refinement Key Loader` for selecting, creating, importing, and exporting Refiner V2 keys. The loader can feed both Refiner V2 and `FunPack Apply LoRA Weights`. + +Added a paste-friendly [`Refiner V2 quick guide`](docs/FunPackVideoRefinerV2QuickGuide.md) for new users. + ## Updates in 2.2.1 Fixed Refiner V2 prompt phrase categorization so background, appearance, quality, camera, and action phrases stay aligned before the node updates Lucky memory or LoRA suggestions. @@ -68,6 +78,7 @@ Per-node documentation is available in the [`docs`](docs) folder. Start with: - [`docs/FunPackVideoRefinerV2.md`](docs/FunPackVideoRefinerV2.md) for `FunPack Video Refiner V2` +- [`docs/FunPackVideoRefinerV2QuickGuide.md`](docs/FunPackVideoRefinerV2QuickGuide.md) for a short Discord-friendly Refiner V2 guide - [`docs/FunPackLoraWorkflow.md`](docs/FunPackLoraWorkflow.md) for the LoRA/refiner helper workflow Version history is available in [CHANGELOG.md](CHANGELOG.md). diff --git a/__init__.py b/__init__.py index a48eda75..9b7dc80a 100644 --- a/__init__.py +++ b/__init__.py @@ -18,7 +18,7 @@ if __package__: from .model_management import FunPackApplyLoraWeights, FunPackLoraLoader from .samplers import FunPackHybridEuler2SSampler from .context_transition import FunPackContextTransitionWindows - from .templates import FunPackTemplateManager + from .templates import FunPackRefinementKeyLoader, FunPackTemplateManager else: # Standalone tests may not have the full ComfyUI/CUDA runtime loaded. from conditioning import ( @@ -56,8 +56,9 @@ else: except Exception: FunPackContextTransitionWindows = None try: - from templates import FunPackTemplateManager + from templates import FunPackRefinementKeyLoader, FunPackTemplateManager except Exception: + FunPackRefinementKeyLoader = None FunPackTemplateManager = None WEB_DIRECTORY = "./web" @@ -77,6 +78,7 @@ NODE_CLASS_MAPPINGS = { "FunPackContextTransitionWindows": FunPackContextTransitionWindows, "FunPackApplyLoraWeights": FunPackApplyLoraWeights, "FunPackLoraLoader": FunPackLoraLoader, + "FunPackRefinementKeyLoader": FunPackRefinementKeyLoader, "FunPackTemplateManager": FunPackTemplateManager, } NODE_CLASS_MAPPINGS = {name: cls for name, cls in NODE_CLASS_MAPPINGS.items() if cls is not None} @@ -96,6 +98,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "FunPackContextTransitionWindows": "FunPack Context Transition Windows", "FunPackApplyLoraWeights": "FunPack Apply LoRA Weights", "FunPackLoraLoader": "FunPack LoRA Loader", + "FunPackRefinementKeyLoader": "FunPack Refinement Key Loader", "FunPackTemplateManager": "FunPack Template Manager", } diff --git a/conditioning.py b/conditioning.py index be04c176..1d4a3da0 100644 --- a/conditioning.py +++ b/conditioning.py @@ -1457,10 +1457,21 @@ class FunPackVideoRefiner: return None, "" return canvas.clone(), f"{best['label']} ({best['seq_len']} positions)" + def _legacy_auto_inject_token_allowed(self, token): + token = str(token or "").strip().lower() + if not token: + return False + category = self._infer_concept_category([token]) + if category in {"appearance", "subject", "environment", "character"}: + return False + return True + def _eligible_void_bank_items(self, global_adaptive, embedding_dim): bank = self._ensure_void_token_bank(global_adaptive) eligible = [] for token, item in bank.items(): + if not self._legacy_auto_inject_token_allowed(token): + continue if int(item.get("awful_count", 0)) >= 2 and int(item.get("liked_count", 0)) <= 0: continue score = self._void_bank_score(item) @@ -1479,6 +1490,8 @@ class FunPackVideoRefiner: bank = self._ensure_void_token_bank(global_adaptive) candidates = [] for token, item in bank.items(): + if not self._legacy_auto_inject_token_allowed(token): + continue score = self._void_bank_score(item) embedding_shape = self._serialized_tensor_shape(item.get("embedding")) if embedding_shape is None or len(embedding_shape) != 1 or int(embedding_shape[0]) != int(embedding_dim): @@ -1643,6 +1656,8 @@ class FunPackVideoRefiner: bank = self._ensure_void_token_bank(global_adaptive) lucky_pool = [] for token, item in bank.items(): + if not self._legacy_auto_inject_token_allowed(token): + continue embedding_shape = self._serialized_tensor_shape(item.get("embedding")) if embedding_shape is None or len(embedding_shape) != 1 or int(embedding_shape[0]) != int(embedding_dim): continue @@ -1871,6 +1886,8 @@ class FunPackVideoRefiner: token = full_word.strip().lower() if not self._is_valuable_token(token): continue + if not self._legacy_auto_inject_token_allowed(token): + continue if token_mask_list is not None and not all(token_mask_list[start:min(len(token_mask_list), end)]): continue score = float(word_importance.get(token, 1.0)) @@ -5477,6 +5494,7 @@ V2_RATING_LABELS = [ "Wrong details", "Wrong action", "Wrong details + action", + "Wrong appearance", "Missing details + quality", "Missing action + quality", "Awful", @@ -5493,6 +5511,13 @@ V2_RATING_PROFILES = { "Wrong details": {"key": "wrong_details", "reward": 0.20, "level": 5, "missing_axes": ["details"], "wrong_axes": ["details"]}, "Wrong action": {"key": "wrong_action", "reward": 0.10, "level": 4, "missing_axes": ["action"], "wrong_axes": ["action"]}, "Wrong details + action": {"key": "wrong_details_action", "reward": 0.00, "level": 3, "missing_axes": ["details", "action"], "wrong_axes": ["details", "action"]}, + "Wrong appearance": { + "key": "wrong_appearance", + "reward": 0.0, + "level": 4, + "missing_axes": [], + "wrong_categories": ["appearance", "subject", "environment"], + }, "Missing details + quality": {"key": "missing_details_quality", "reward": -0.40, "level": 2, "missing_axes": ["details", "quality"]}, "Missing action + quality": {"key": "missing_action_quality", "reward": -0.55, "level": 1, "missing_axes": ["action", "quality"]}, "Awful": {"key": "awful", "reward": -0.90, "level": 0, "missing_axes": ["details", "action", "quality"]}, @@ -5521,6 +5546,11 @@ V2_RATING_ALIASES = { "Wrong concepts": "Wrong action", "Wrong movement": "Wrong action", "Wrong micro-movements": "Wrong details", + "Wrong character": "Wrong appearance", + "Wrong characters": "Wrong appearance", + "Wrong outfit": "Wrong appearance", + "Wrong clothing": "Wrong appearance", + "Wrong clothes": "Wrong appearance", "Missing everything": "Awful", } @@ -5566,6 +5596,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): V2_STATE_PREFIX = "refine_v2" ACTION_LORA_TYPES = {"action", "concept"} + AUTO_INJECT_BLOCKED_CATEGORIES = {"appearance", "subject", "environment"} + AUTO_INJECT_ALLOWED_CATEGORIES = {"action", "camera", "details", "quality", "style"} CATEGORY_DESCRIPTIONS = { "action": "physical actions, body movement, animation, motion, gestures, moving subjects", "camera": "camera motion, framing, zoom, pan, dolly, close-up, wide shot, focus behavior", @@ -5603,6 +5635,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "hands", "pose", "expression", "beard", "makeup", "body", "anatomy", "wearing", "wears", "dressed", "clothed", "costume", "shirt", "coat", "robe", "boots", "hat", "helmet", "gloves", "mask", "tattoo", "freckles", "scar", "silhouette", + "pants", "skirt", "tights", "stockings", "socks", "shoes", "heels", "uniform", "flowing", "curly", "straight", "long", "short", "blonde", "brunette", }, "environment": { @@ -5650,7 +5683,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): APPEARANCE_CONTEXT_WORDS = { "hair", "eyes", "face", "skin", "dress", "jacket", "armor", "outfit", "clothing", "shirt", "coat", "robe", "boots", "hat", "helmet", "gloves", "mask", "body", - "anatomy", "beard", "makeup", "costume", + "anatomy", "beard", "makeup", "costume", "pants", "skirt", "tights", "stockings", + "socks", "shoes", "heels", "uniform", } ENVIRONMENT_CONTEXT_WORDS = { "background", "setting", "environment", "landscape", "room", "street", "forest", @@ -5675,6 +5709,12 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "label": "Exploration Seed"}), "reset_session": ("BOOLEAN", {"default": False, "label": "Reset V2 Session"}), "lora_stack": ("FUNPACK_LORA_STACK", {"tooltip": "Optional stack from FunPack LoRA Loader. V2 writes prompt-specific suggested weights."}), + "refinement_key_input": ("STRING", { + "default": "", + "multiline": False, + "forceInput": True, + "tooltip": "Optional linked refinement key, for example from FunPack Refinement Key Loader. Overrides the refinement_key widget when connected.", + }), "user_intent_prompt": ("STRING", { "multiline": True, "default": "", @@ -5860,6 +5900,56 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): ) return primary, float(confidence) + def _v2_primary_category_for_text(self, text): + return self._v2_scores_primary(self._v2_heuristic_scores(text))[0] + + def _v2_item_primary_category(self, item): + if not isinstance(item, dict): + return self._v2_primary_category_for_text(item) + scores = ( + item.get("effective_category_scores") or + item.get("category_scores") or + item.get("clip_heuristic_scores") or + self._v2_heuristic_scores(item.get("text", "")) + ) + primary, _ = self._v2_scores_primary(scores) + return str(item.get("primary") or primary or "details").lower() + + def _v2_item_has_blocked_auto_category(self, item): + if isinstance(item, dict): + categories = { + str(item.get("primary", "")).lower(), + str(item.get("machine_primary", "")).lower(), + self._v2_item_primary_category(item), + } + scores = item.get("effective_category_scores", item.get("category_scores", {})) + if isinstance(scores, dict): + primary, confidence = self._v2_scores_primary(scores) + categories.add(primary) + for category, score in scores.items(): + if float(score or 0.0) >= max(0.42, float(confidence) * 0.82): + categories.add(str(category).lower()) + return bool(categories & self.AUTO_INJECT_BLOCKED_CATEGORIES) + return self._v2_primary_category_for_text(item) in self.AUTO_INJECT_BLOCKED_CATEGORIES + + def _v2_prompt_repair_text_allowed(self, text): + if not self._v2_clean_phrase_text(text): + return False + if self._v2_item_has_blocked_auto_category(text): + return False + return self._v2_primary_category_for_text(text) in self.AUTO_INJECT_ALLOWED_CATEGORIES + + def _v2_auto_inject_entry_allowed(self, entry, prompt=""): + text = str(entry.get("text", "") if isinstance(entry, dict) else entry).strip() + if not text: + return False + explicit = self._v2_prompt_contains_text(prompt, text) + if isinstance(entry, dict) and bool(entry.get("auto_inject_suppressed")) and not explicit: + return False + if self._v2_item_has_blocked_auto_category(entry) and not explicit: + return False + return True + def _v2_clip_similarity_scores(self, clip, phrase, category_vectors): phrase_cond, _, _ = self._v2_encode_prompt(clip, phrase) phrase_vector = self._v2_conditioning_vector(phrase_cond) @@ -6118,6 +6208,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "resolved_count": 0, "regressed_count": 0, "wrong_count": 0, + "wrong_appearance_count": 0, + "auto_inject_blocked_count": 0, + "auto_inject_suppressed": False, "bad_count": 0, "wanted_axes": {}, "satisfied_axes": {}, @@ -6148,6 +6241,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): entry.setdefault("resolved_count", 0) entry.setdefault("regressed_count", 0) entry.setdefault("wrong_count", 0) + entry.setdefault("wrong_appearance_count", 0) + entry.setdefault("auto_inject_blocked_count", 0) + entry.setdefault("auto_inject_suppressed", False) entry.setdefault("bad_count", 0) entry.setdefault("wanted_axes", {}) entry.setdefault("satisfied_axes", {}) @@ -6260,13 +6356,31 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): add(" ".join(words[start:start + size]), "ngram", phrase, phrase.get("position", index) + start, phrase_context) prompt = str(last_run.get("prompt", "") or "") - prompt_segments = [ - {"text": segment.strip()} - for segment in re.split(r"[,.;\n]+", prompt) - if segment.strip() - ] - for position, segment in enumerate(prompt_segments): - add(segment.get("text", ""), "prompt_phrase", None, position, self._v2_context_for_phrase(prompt_segments, position, segment.get("text", ""))) + encoded_prompt = str(last_run.get("encoded_prompt", "") or "") + + def add_prompt_segments(source_prompt, kind, offset=0): + prompt_segments = [ + {"text": segment.strip()} + for segment in re.split(r"[,.;\n]+", source_prompt) + if segment.strip() + ] + for position, segment in enumerate(prompt_segments): + add( + segment.get("text", ""), + kind, + None, + offset + position, + self._v2_context_for_phrase(prompt_segments, position, segment.get("text", "")), + ) + + add_prompt_segments(prompt, "prompt_phrase") + if encoded_prompt and encoded_prompt != prompt: + add_prompt_segments(encoded_prompt, "auto_phrase", offset=128) + + for position, candidate in enumerate(last_run.get("repair_candidates", []) or []): + if not isinstance(candidate, dict): + continue + add(candidate.get("text", ""), "repair_candidate", candidate, 256 + position, {}) return units[:96] def _v2_classify_phrases(self, clip, phrases, global_state=None): @@ -6419,6 +6533,11 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "Guidance: '-Just forget it-' skipped learning. Use it for workflow/model/seed failures; " "use a missing-axis rating when the prompt should teach the node." ) + if learning_profile.get("key") == "wrong_appearance": + return ( + "Guidance: wrong-appearance rating suppresses auto-injected character, clothing, " + "subject, and background memory without training unrelated action/detail/quality ratings." + ) if learning_profile.get("wrong_axes"): return ( "Guidance: wrong-intent rating preserved satisfied axes but marked the current " @@ -6504,6 +6623,10 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): def _v2_memory_kind_scale(self, kind): if kind in {"prompt_phrase", "phrase"}: return 1.0 + if kind == "auto_phrase": + return 0.72 + if kind == "repair_candidate": + return 0.64 if kind == "ngram": return 0.62 if kind == "token": @@ -6513,6 +6636,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): def _v2_update_preferred_context_memory(self, global_state, last_run, rating_profile, iter_num, axis_feedback=None): if not isinstance(global_state, dict) or not isinstance(last_run, dict) or rating_profile.get("skip_learning"): return "Preferred context: no update." + if rating_profile.get("key") == "wrong_appearance": + return "Preferred context: skipped for wrong appearance." phrases = [phrase for phrase in last_run.get("phrases", []) or [] if isinstance(phrase, dict)] if not phrases: return "Preferred context: no prompt phrases." @@ -6615,6 +6740,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): regressed_axes = set(axis_feedback.get("regressed_axes", [])) wrong_axes = set(axis_feedback.get("wrong_axes", [])) reward = float(rating_profile.get("reward", 0.0)) + wrong_appearance = rating_profile.get("key") == "wrong_appearance" + original_prompt = str(last_run.get("prompt", "") or "") preferred_context_status = self._v2_update_preferred_context_memory( global_state, last_run, @@ -6625,6 +6752,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): touched = [] trained = [] kind_counts = {} + suppressed = [] for phrase in concepts: text = str(phrase.get("text", "")).strip().lower() if not text: @@ -6664,6 +6792,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): matched_wrong = phrase_axes & wrong_axes rating_evidence = entry.setdefault("rating_evidence", {}) weights_before = dict(weights) + count_category_evidence = rating_profile.get("key") != "discover" def bump_evidence(name, axes): axis_counts = rating_evidence.setdefault(name, {}) @@ -6675,7 +6804,23 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): relation = self._v2_axis_category_weight(axis, category, effective_before if prefer_current else machine_scores) weights[category] = float(weights.get(category, 0.0)) + amount * relation - if rating_profile.get("key") == "like": + if wrong_appearance: + explicit = self._v2_prompt_contains_text(original_prompt, text) + auto_source = phrase.get("kind") in {"auto_phrase", "repair_candidate"} + should_suppress = self._v2_item_has_blocked_auto_category(phrase) and (auto_source or not explicit) + if should_suppress: + delta = -0.95 * kind_scale + entry["wrong_appearance_count"] = int(entry.get("wrong_appearance_count", 0)) + 1 + entry["auto_inject_blocked_count"] = int(entry.get("auto_inject_blocked_count", 0)) + 1 + entry["auto_inject_suppressed"] = True + rating_evidence["wrong_appearance"] = int(rating_evidence.get("wrong_appearance", 0)) + 1 + for category in self.AUTO_INJECT_BLOCKED_CATEGORIES: + weights[category] = float(weights.get(category, 0.0)) - 0.30 * kind_scale + suppressed.append(text) + else: + delta = 0.0 + count_category_evidence = False + elif rating_profile.get("key") == "like": delta = 0.55 * kind_scale entry["liked_count"] = int(entry.get("liked_count", 0)) + 1 rating_evidence["liked"] = int(rating_evidence.get("liked", 0)) + 1 @@ -6769,9 +6914,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): for category, value in weights.items() } entry["category_evidence_count"] = int(entry.get("category_evidence_count", 0)) + ( - 0 if rating_profile.get("key") == "discover" else 1 + 1 if count_category_evidence else 0 ) - if isinstance(context_sense, dict) and rating_profile.get("key") != "discover": + if isinstance(context_sense, dict) and count_category_evidence: sense_weights = self._v2_clean_category_scores(context_sense.get("category_weights", {})) for category, value in entry["category_weights"].items(): sense_weights[category] = float(sense_weights.get(category, 0.0)) + ( @@ -6816,10 +6961,15 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): if not touched: return "Lucky memory: no prompt phrases stored." kind_summary = ", ".join(f"{name}:{count}" for name, count in sorted(kind_counts.items())) or "none" + suppression_summary = ( + f" Appearance auto-injection suppressed: {', '.join(suppressed[:8])}{'...' if len(suppressed) > 8 else ''}." + if suppressed else + "" + ) return ( f"Category memory trained: {len(touched)} concept unit(s) ({kind_summary}). " f"Sample: {', '.join(trained) if trained else ', '.join(touched[:6])}. " - f"{preferred_context_status} " + f"{preferred_context_status}{suppression_summary} " f"{self._v2_axis_feedback_status(axis_feedback)}" ) @@ -6871,6 +7021,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): def _v2_update_conditioning_memory(self, global_state, last_run, rating_profile, axis_feedback=None): if not isinstance(last_run, dict) or rating_profile.get("skip_learning"): return + if rating_profile.get("key") == "wrong_appearance": + return payload = last_run.get("conditioning") if not isinstance(payload, dict): return @@ -7083,19 +7235,27 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): clean = self._v2_clean_phrase_text(text) if not clean: return + if not self._v2_prompt_repair_text_allowed(clean): + return words = self._v2_phrase_words(clean) if len(words) > 16: return axes = set(axes or set()) & missing_axes if not axes or self._v2_prompt_contains_text(prompt, clean): return + safe_cluster = [ + self._v2_clean_phrase_text(item) + for item in (cluster or []) + if self._v2_prompt_repair_text_allowed(item) + ] + safe_cluster = [item for item in safe_cluster if item] existing = candidates.get(clean) payload = { "text": clean, "axes": axes, "score": float(score), "source": source, - "cluster": list(cluster or []), + "cluster": safe_cluster, } if existing is None or payload["score"] > existing["score"]: candidates[clean] = payload @@ -7124,7 +7284,10 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): self._v2_clean_phrase_text(item) for item in entry.get("phrases", []) ] - cluster = [item for item in cluster if item and not self._v2_prompt_contains_text(prompt, item)] + cluster = [ + item for item in cluster + if item and self._v2_prompt_repair_text_allowed(item) and not self._v2_prompt_contains_text(prompt, item) + ] score = ( 2.0 + float(entry.get("score", 0.0)) * 0.34 + @@ -7179,7 +7342,11 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): for item in ranked: cluster = item.get("cluster", []) if item.get("source") == "preferred_context" else [] for cluster_text in cluster: - if cluster_text in selected_texts or self._v2_prompt_contains_text(prompt, cluster_text): + if ( + cluster_text in selected_texts or + self._v2_prompt_contains_text(prompt, cluster_text) or + not self._v2_prompt_repair_text_allowed(cluster_text) + ): continue cluster_item = dict(item) cluster_item["text"] = cluster_text @@ -7238,11 +7405,14 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): for text, entry in memory.items(): if not isinstance(entry, dict): continue + if not self._v2_auto_inject_entry_allowed(entry, prompt): + continue score = float(entry.get("score", 0.0)) score += min(1.0, int(entry.get("liked_count", 0)) * 0.14) score += min(1.2, sum(int(v) for v in entry.get("wanted_axes", {}).values()) * 0.10) score -= min(1.6, int(entry.get("bad_count", 0)) * 0.22) score -= min(1.1, int(entry.get("wrong_count", 0)) * 0.18) + score -= min(1.8, int(entry.get("auto_inject_blocked_count", 0)) * 0.65) if score <= 0.10: continue scored.append((score, entry.get("primary", "details"), str(entry.get("text", text)).strip())) @@ -7389,11 +7559,16 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return "LoRA suggestions: " + " | ".join(parts) def refine_v2(self, positive_prompt, clip, rating, refinement_key, - seed=0, reset_session=False, lora_stack=None, im_feeling_lucky=False, user_intent_prompt=""): + seed=0, reset_session=False, lora_stack=None, im_feeling_lucky=False, user_intent_prompt="", + refinement_key_input=""): if seed != 0: torch.manual_seed(seed) random.seed(seed) + linked_refinement_key = str(refinement_key_input or "").strip() + if linked_refinement_key: + refinement_key = linked_refinement_key + rating_profile = normalize_refiner_v2_rating(rating) rating_label = rating_profile.get("label", str(rating)) state, state_status = self._v2_load_state(refinement_key, reset_session=reset_session) @@ -7558,6 +7733,12 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "phrases": phrases, "intent_prompt": intent_prompt, "repair_candidates": state_repair_candidates, + "encoded_role": encoded_role, + "auto_injected_prompt_additions": [ + item.get("text", "") + for item in state_repair_candidates + if isinstance(item, dict) and str(item.get("text", "")).strip() + ], "rating_label": "Unrated", "iteration": int(global_state["total_iterations"]), } diff --git a/docs/FunPackVideoRefinerV2.md b/docs/FunPackVideoRefinerV2.md index 25ebdc4d..d7f8f7ab 100644 --- a/docs/FunPackVideoRefinerV2.md +++ b/docs/FunPackVideoRefinerV2.md @@ -17,6 +17,10 @@ V2 replaces the old `FunPack Video Refiner` public node in version `2.2.0`. It u - `Missing action` - `Missing quality` - `Missing details + action` +- `Wrong details` +- `Wrong action` +- `Wrong details + action` +- `Wrong appearance` - `Missing details + quality` - `Missing action + quality` - `Awful` @@ -24,8 +28,12 @@ V2 replaces the old `FunPack Video Refiner` public node in version `2.2.0`. It u Older `Missing concept` labels are accepted as aliases for `Missing action`. +Use `Wrong appearance` when the video is polluted by remembered clothing, character traits, subject identity, or background concepts that were not requested for the current image. This suppresses those concepts from future auto-injection without deleting them for explicit prompts. + **refinement_key**: V2 session key. V2 stores separate `refine_v2` state under this key. +**refinement_key_input**: Optional linked key input, usually from `FunPack Refinement Key Loader`. When connected, it overrides the text widget. + **seed**: Optional seed for deterministic exploration paths. **reset_session**: Clears the V2 session state for the selected key. @@ -34,6 +42,20 @@ Older `Missing concept` labels are accepted as aliases for `Missing action`. **im_feeling_lucky**: When enabled, V2 composes a learned prompt from rated phrase memory and encodes it through the connected CLIP. When disabled, V2 may still store Lucky memory from rated runs, but it does not compose or apply a Lucky prompt. +## Appearance Safety + +Refiner V2 treats image-to-video appearance as image-owned by default. Learned appearance, subject/character, and environment/background phrases are not auto-added by Prompt Repair or Lucky unless they are already present in the current prompt. + +Prompt Repair is only for motion, camera work, small non-identity details, quality, and style. It will not add clothing, body traits, character identity, or background phrases from memory. + +Legacy Void memory also skips appearance, subject/character, and environment/background tokens so old token-bank preferences cannot reintroduce those concepts. + +## Refinement Key Loader + +`FunPack Refinement Key Loader` lists existing V2 keys, creates a typed key when none is selected, and exposes `Import`, `Export`, and `Refresh` buttons in the browser UI. + +Connect its `refinement_key` output to Refiner V2's `refinement_key_input` and to `FunPack Apply LoRA Weights`' `refinement_key_input` so both nodes use the same memory key. + ## Outputs **modified_positive**: Refined positive conditioning. diff --git a/docs/FunPackVideoRefinerV2QuickGuide.md b/docs/FunPackVideoRefinerV2QuickGuide.md new file mode 100644 index 00000000..7486bf04 --- /dev/null +++ b/docs/FunPackVideoRefinerV2QuickGuide.md @@ -0,0 +1,37 @@ +# Refiner V2 Quick Guide + +`FunPack Video Refiner V2` is a prompt memory node. It takes your positive prompt, encodes it through the connected CLIP, remembers how you rated the previous output, and slowly learns which actions, camera moves, details, quality cues, and style cues work for your workflows. + +It does not look at the finished video pixels. It does not magically know what is inside your input image. It does not replace clear prompting. In image-to-video, it now treats character appearance, clothing, subject identity, and background as image-owned by default, so it should not inject old remembered outfits or characters into a new image unless you explicitly prompt them. + +## How To Use It + +1. Add `FunPack Video Refiner V2` before your sampler where positive conditioning is encoded. +2. Connect your `CLIP`. +3. Type a `refinement_key`, or use `FunPack Refinement Key Loader` and connect its output into `refinement_key_input`. +4. First run only seeds memory. Generate once, look at the result, then rate that result on the next run with the same key. +5. Use `Perfect` when the output is good and should be remembered. +6. Use `Missing action` when the requested motion did not happen. +7. Use `Missing details` when small non-identity details are weak, like smoke, reflections, particles, hand contact, object interaction, or secondary motion. +8. Use `Missing quality` when the idea is right but the result is messy or ugly. +9. Use `Wrong action`, `Wrong details`, or `Wrong details + action` when the video looks usable but did the wrong thing. +10. Use `Wrong appearance` when Refiner/Lucky brought in unwanted clothing, face, body, character, subject, or background memory. +11. Use `-Just forget it-` for broken runs, bad seeds, workflow mistakes, model failures, or anything you do not want learned. + +## Lucky Mode + +`I'm Feeling Lucky` composes a prompt from learned memory. It is useful when you want the node to suggest motion, camera, detail, quality, or style ideas from previous liked outputs. + +Lucky should not auto-add remembered outfits, character traits, subjects, or backgrounds anymore. If you want an appearance item, write it directly in the prompt. + +## Examples + +If your prompt says `person smoking and exhaling smoke` but the video only shows a puff with no exhale, rate `Missing details` or `Missing action`, depending on what matters most. This teaches the key that smoke/exhale matters in that prompt context, without globally banning smoking. + +If you liked `white tights` in older prompts but your new input image is only a portrait face, and Lucky tries to bring tights into the scene, rate `Wrong appearance`. That tells Refiner to suppress that appearance memory from auto-injection while still allowing `white tights` when you explicitly type it. + +If the camera should push in, orbit, pan, or change framing and it stays static, rate `Missing action` or `Wrong action`. Camera movement belongs to the action/camera side of memory, so it remains safe for repair and Lucky. + +## Key Loader + +Use `FunPack Refinement Key Loader` when you want a reusable key dropdown or want to move keys between workflows/machines. Its `Import` and `Export` buttons save/load the key as JSON. Connect the loader to both Refiner V2 and `FunPack Apply LoRA Weights` so LoRA suggestions and prompt memory use the same key. diff --git a/funpack.py b/funpack.py index c1afca82..4013e4aa 100644 --- a/funpack.py +++ b/funpack.py @@ -19,7 +19,7 @@ try: from .model_management import FunPackApplyLoraWeights, FunPackLoraLoader from .samplers import FunPackHybridEuler2SSampler, sample_funpack_hybrid_euler_2s from .context_transition import FunPackContextTransitionWindows - from .templates import FunPackTemplateManager + from .templates import FunPackRefinementKeyLoader, FunPackTemplateManager except ImportError: from conditioning import ( FunPackLorebookEnhancer, @@ -38,7 +38,7 @@ except ImportError: from model_management import FunPackApplyLoraWeights, FunPackLoraLoader from samplers import FunPackHybridEuler2SSampler, sample_funpack_hybrid_euler_2s from context_transition import FunPackContextTransitionWindows - from templates import FunPackTemplateManager + from templates import FunPackRefinementKeyLoader, FunPackTemplateManager NODE_CLASS_MAPPINGS = { "FunPackPromptCombiner": FunPackPromptCombiner, @@ -55,6 +55,7 @@ except ImportError: "FunPackContextTransitionWindows": FunPackContextTransitionWindows, "FunPackApplyLoraWeights": FunPackApplyLoraWeights, "FunPackLoraLoader": FunPackLoraLoader, + "FunPackRefinementKeyLoader": FunPackRefinementKeyLoader, "FunPackTemplateManager": FunPackTemplateManager, } @@ -73,6 +74,7 @@ except ImportError: "FunPackContextTransitionWindows": "FunPack Context Transition Windows", "FunPackApplyLoraWeights": "FunPack Apply LoRA Weights", "FunPackLoraLoader": "FunPack LoRA Loader", + "FunPackRefinementKeyLoader": "FunPack Refinement Key Loader", "FunPackTemplateManager": "FunPack Template Manager", } @@ -93,6 +95,7 @@ __all__ = [ "FunPackStoryMemLastFrameExtractor", "FunPackApplyLoraWeights", "FunPackLoraLoader", + "FunPackRefinementKeyLoader", "FunPackTemplateManager", "sample_funpack_hybrid_euler_2s", ] diff --git a/model_management.py b/model_management.py index 07038c92..5b63939b 100644 --- a/model_management.py +++ b/model_management.py @@ -189,6 +189,12 @@ class FunPackApplyLoraWeights: any_type, { "lora_list": ("STRING", {"default": "[]", "multiline": False}), + "refinement_key_input": ("STRING", { + "default": "", + "multiline": False, + "forceInput": True, + "tooltip": "Optional linked refinement key, for example from FunPack Refinement Key Loader. Overrides the refinement_key widget when connected.", + }), "lora_0": (loras, {"default": "None"}), "lora_0_type": (LORA_TYPES, {"default": "general"}), "lora_0_base_weight": ( @@ -358,6 +364,9 @@ class FunPackApplyLoraWeights: return abs(float(saved_base) - float(entry["base_model_weight"])) <= 1e-6 def apply_lora_weights(self, positive_prompt, refinement_key, mode, per_block=False, **kwargs): + linked_refinement_key = str(kwargs.pop("refinement_key_input", "") or "").strip() + if linked_refinement_key: + refinement_key = linked_refinement_key mode = (mode or "ltx2").lower() per_block = coerce_bool(per_block) prompt_key = prompt_key_for_mode(positive_prompt, mode) diff --git a/pyproject.toml b/pyproject.toml index 5b279c3a..043b7fce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [project] name = "ComfyUI-FunPack" # Unique identifier for your node. Immutable after creation. description = "A set of nodes for experiments with video generation models, including prompt refinement, adaptive LoRA weight workflows, story tools, video stitching, lorebook enhancement and more." -version = "2.2.1" # Custom Node version. Must be semantically versioned. +version = "2.3.0" # Custom Node version. Must be semantically versioned. license = { text = "GNU GPL v3" } dependencies = [] # Filled in from requirements.txt diff --git a/templates.py b/templates.py index 3d106b03..554b116b 100644 --- a/templates.py +++ b/templates.py @@ -27,6 +27,7 @@ except ImportError: TEMPLATE_NONE = "-None-" +REFINEMENT_KEY_NONE = "-None-" TEMPLATE_DB_VERSION = 1 WILDCARD_RE = re.compile(r"\{([^{}]*\|[^{}]*)\}") @@ -46,6 +47,120 @@ def template_store_path(): return os.path.join(template_store_dir(), "templates.json") +def refinement_store_dir(): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "refinements") + + +def normalize_refinement_key(value): + value = str(value or "").strip() + if not value or value == REFINEMENT_KEY_NONE: + return "" + return value + + +def empty_v2_refinement_state(refinement_key): + return { + "version": 2, + "refinement_key": refinement_key, + "state_namespace": "clip", + "global": { + "total_iterations": 0, + "avg_reward_ema": 0.0, + "good_streak": 0, + "bad_streak": 0, + "last_rating_label": "Initial discovery", + "last_missing_axes": [], + "phrase_memory": {}, + "axis_conditioning_memory": {}, + "lora_weight_memory": {}, + "preferred_context_memory": {}, + "loss_history": [], + }, + "prompt_histories": {}, + "last_run": None, + } + + +def refinement_key_path(refinement_key): + return refinement_state_path(refinement_key, "clip", prefix="refine_v2") + + +def normalize_refinement_state(data, fallback_key=""): + if not isinstance(data, dict): + return None, "" + key = normalize_refinement_key(data.get("refinement_key") or fallback_key) + if not key: + return None, "" + state = dict(data) + state["version"] = 2 + state["refinement_key"] = key + state["state_namespace"] = "clip" + state.setdefault("global", {}) + state["global"].setdefault("phrase_memory", {}) + state["global"].setdefault("axis_conditioning_memory", {}) + state["global"].setdefault("lora_weight_memory", {}) + state["global"].setdefault("preferred_context_memory", {}) + state["global"].setdefault("loss_history", []) + state.setdefault("prompt_histories", {}) + state.setdefault("last_run", None) + return state, key + + +def load_refinement_key_state(refinement_key, create=False): + key = normalize_refinement_key(refinement_key) + if not key: + return None, "", "No refinement key selected." + path = refinement_key_path(key) + if os.path.exists(path): + try: + with open(path, "r", encoding="utf-8") as file: + data = json.load(file) + state, loaded_key = normalize_refinement_state(data, key) + if state is None: + return None, key, f"Refinement key '{key}' is unreadable." + return state, loaded_key, f"Loaded refinement key '{loaded_key}'." + except (json.JSONDecodeError, OSError, ValueError): + return None, key, f"Refinement key '{key}' is unreadable." + if not create: + return None, key, f"Refinement key '{key}' does not exist." + state = empty_v2_refinement_state(key) + save_refinement_key_state(state, key) + return state, key, f"Created refinement key '{key}'." + + +def save_refinement_key_state(state, refinement_key): + key = normalize_refinement_key(refinement_key) + if not key: + return "" + state, key = normalize_refinement_state(state, key) + if state is None: + return "" + path = refinement_key_path(key) + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "w", encoding="utf-8") as file: + json.dump(state, file, indent=2) + return path + + +def refinement_key_names(): + keys = set() + directory = refinement_store_dir() + if os.path.isdir(directory): + for filename in os.listdir(directory): + if not filename.startswith("refine_v2_") or not filename.endswith(".json"): + continue + path = os.path.join(directory, filename) + try: + with open(path, "r", encoding="utf-8") as file: + data = json.load(file) + key = normalize_refinement_key(data.get("refinement_key") if isinstance(data, dict) else "") + if key: + keys.add(key) + except (json.JSONDecodeError, OSError, ValueError): + continue + return [REFINEMENT_KEY_NONE] + sorted(keys) + + def empty_template_db(): return { "version": TEMPLATE_DB_VERSION, @@ -322,6 +437,79 @@ async def funpack_templates_import(request): return web.json_response({"imported": imported, "templates": template_names()}) +@PromptServer.instance.routes.get("/funpack/refinement_keys") +async def funpack_refinement_keys(_): + return web.json_response( + {"keys": refinement_key_names(), "path": refinement_store_dir()}, + headers={"Cache-Control": "no-store, max-age=0"}, + ) + + +@PromptServer.instance.routes.get("/funpack/refinement_keys/export") +async def funpack_refinement_keys_export(request): + key = normalize_refinement_key(request.query.get("key", "")) + state, loaded_key, status = load_refinement_key_state(key, create=False) + if state is None: + return web.json_response({"error": status}, status=404) + return web.json_response( + state, + headers={ + "Cache-Control": "no-store, max-age=0", + "Content-Disposition": f"attachment; filename=funpack_refinement_{loaded_key}.json", + }, + ) + + +@PromptServer.instance.routes.post("/funpack/refinement_keys/import") +async def funpack_refinement_keys_import(request): + incoming = await request.json() + if isinstance(incoming, dict) and isinstance(incoming.get("state"), dict): + incoming = incoming["state"] + state, key = normalize_refinement_state(incoming) + if state is None: + return web.json_response({"error": "Imported file is not a valid V2 refinement key JSON."}, status=400) + path = save_refinement_key_state(state, key) + if not path: + return web.json_response({"error": "Could not save imported refinement key."}, status=400) + return web.json_response({"imported": key, "keys": refinement_key_names()}) + + +class FunPackRefinementKeyLoader: + CATEGORY = "FunPack/Refinement" + RETURN_TYPES = ("STRING", "STRING") + RETURN_NAMES = ("refinement_key", "status") + FUNCTION = "load_refinement_key" + OUTPUT_NODE = True + DESCRIPTION = "Loads, creates, imports, and exports FunPack Video Refiner V2 refinement keys." + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "refinement_key": (refinement_key_names(), {"default": REFINEMENT_KEY_NONE}), + "key_name": ("STRING", {"default": "", "multiline": False}), + "create_if_missing": ("BOOLEAN", {"default": True}), + }, + } + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float("nan") + + @classmethod + def VALIDATE_INPUTS(cls, refinement_key=None, **kwargs): + return True + + def load_refinement_key(self, refinement_key, key_name, create_if_missing=True): + selected = normalize_refinement_key(refinement_key) + typed = normalize_refinement_key(key_name) + target = selected or typed + if not target: + return ("", "No refinement key selected. Pick an existing key or type a new key name.") + _, loaded_key, status = load_refinement_key_state(target, create=bool(create_if_missing)) + return (loaded_key if loaded_key else target, status) + + class FunPackTemplateManager: CATEGORY = "FunPack/Templates" RETURN_TYPES = ("STRING", "STRING", "STRING", "SIGMAS", "CONDITIONING", "FUNPACK_LORA_STACK", "STRING", "STRING") diff --git a/tests/test_v2_category_alignment.py b/tests/test_v2_category_alignment.py index 75a38129..e8191bf4 100644 --- a/tests/test_v2_category_alignment.py +++ b/tests/test_v2_category_alignment.py @@ -201,7 +201,10 @@ def test_awful_lora_feedback_reduces_before_missing_axis_boosts(): def test_category_weights_are_recorded_for_every_learning_rating(): refiner = FunPackVideoRefinerV2() - learning_labels = [label for label in V2_RATING_LABELS if label != "-Just forget it-"] + learning_labels = [ + label for label in V2_RATING_LABELS + if label not in {"-Just forget it-", "Wrong appearance"} + ] for label in learning_labels: entry, _, _ = train_phrase(refiner, f"running test {label}", label) @@ -212,6 +215,158 @@ def test_category_weights_are_recorded_for_every_learning_rating(): assert set(entry["effective_category_scores"]) == set(refiner.CATEGORY_DESCRIPTIONS) +def test_wrong_appearance_rating_is_available(): + profile = normalize_refiner_v2_rating("Wrong appearance") + + assert "Wrong appearance" in V2_RATING_LABELS + assert profile["key"] == "wrong_appearance" + assert profile["wrong_categories"] == ["appearance", "subject", "environment"] + + +def test_prompt_repair_blocks_appearance_subject_and_environment(): + refiner = FunPackVideoRefinerV2() + global_state = { + "phrase_memory": { + "white tights": { + "text": "white tights", + "primary": "appearance", + "effective_category_scores": refiner._v2_heuristic_scores("white tights"), + "wanted_axes": {"details": 3}, + "score": 6.0, + "liked_count": 4, + }, + "detailed background": { + "text": "detailed background", + "primary": "environment", + "effective_category_scores": refiner._v2_heuristic_scores("detailed background"), + "wanted_axes": {"details": 3}, + "score": 6.0, + "liked_count": 4, + }, + "female character": { + "text": "female character", + "primary": "subject", + "effective_category_scores": refiner._v2_heuristic_scores("female character"), + "wanted_axes": {"details": 3}, + "score": 6.0, + "liked_count": 4, + }, + "tiny smoke curls": { + "text": "tiny smoke curls", + "primary": "details", + "effective_category_scores": refiner._v2_heuristic_scores("tiny smoke curls"), + "wanted_axes": {"details": 3}, + "score": 4.0, + "liked_count": 2, + }, + } + } + profile = normalize_refiner_v2_rating("Missing details") + feedback = refiner._v2_axis_feedback(profile, None) + + repaired, _, candidates = refiner._v2_repair_prompt_for_missing_axes( + "person smoking", + refiner._v2_classify_phrases(None, prompt_items(refiner, ["person smoking"]), global_state), + global_state, + None, + feedback, + ) + + assert "tiny smoke curls" in repaired + assert "white tights" not in repaired + assert "detailed background" not in repaired + assert "female character" not in repaired + assert all(candidate["text"] != "white tights" for candidate in candidates) + + +def test_lucky_skips_appearance_memory_unless_prompt_mentions_it(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "preferred_context_memory": {}} + phrases = refiner._v2_classify_phrases( + None, + prompt_items(refiner, ["white tights", "walking"]), + global_state, + ) + profile = normalize_refiner_v2_rating("Perfect") + feedback = refiner._v2_axis_feedback(profile, None) + refiner._v2_update_phrase_memory( + global_state, + {"prompt": "white tights walking", "phrases": phrases}, + profile, + 1, + feedback, + ) + + lucky_prompt, _ = refiner._v2_compose_lucky_prompt("", [], global_state) + explicit_prompt, _ = refiner._v2_compose_lucky_prompt( + "white tights", + refiner._v2_classify_phrases(None, prompt_items(refiner, ["white tights"]), global_state), + global_state, + ) + + assert "walking" in lucky_prompt + assert "white tights" not in lucky_prompt + assert "tights" not in lucky_prompt + assert "white tights" in explicit_prompt + + +def test_wrong_appearance_suppresses_only_auto_inserted_appearance_memory(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "preferred_context_memory": {}} + phrases = refiner._v2_classify_phrases(None, prompt_items(refiner, ["walking"]), global_state) + profile = normalize_refiner_v2_rating("Wrong appearance") + feedback = refiner._v2_axis_feedback(profile, None) + + refiner._v2_update_phrase_memory( + global_state, + { + "prompt": "walking", + "encoded_prompt": "walking, white tights", + "phrases": phrases, + "repair_candidates": [{"text": "white tights", "axes": ["details"], "score": 3.0, "source": "memory"}], + }, + profile, + 1, + feedback, + ) + + appearance = global_state["phrase_memory"]["white tights"] + motion = global_state["phrase_memory"]["walking"] + assert appearance["auto_inject_suppressed"] is True + assert appearance["wrong_appearance_count"] >= 1 + assert motion.get("wrong_appearance_count", 0) == 0 + assert motion["category_evidence_count"] == 0 + + +def test_repeated_wrong_appearance_keeps_entry_out_of_lucky(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "preferred_context_memory": {}} + phrases = refiner._v2_classify_phrases(None, prompt_items(refiner, ["walking"]), global_state) + profile = normalize_refiner_v2_rating("Wrong appearance") + feedback = refiner._v2_axis_feedback(profile, None) + + for iteration in range(2): + refiner._v2_update_phrase_memory( + global_state, + { + "prompt": "walking", + "encoded_prompt": "walking, white tights", + "phrases": phrases, + "repair_candidates": [{"text": "white tights", "axes": ["details"], "score": 3.0, "source": "memory"}], + }, + profile, + iteration + 1, + feedback, + ) + + global_state["phrase_memory"]["white tights"]["score"] = 6.0 + global_state["phrase_memory"]["white tights"]["liked_count"] = 8 + lucky_prompt, _ = refiner._v2_compose_lucky_prompt("", [], global_state) + + assert global_state["phrase_memory"]["white tights"]["auto_inject_blocked_count"] >= 2 + assert "white tights" not in lucky_prompt + + def test_forget_rating_skips_category_weight_learning(): refiner = FunPackVideoRefinerV2() global_state = {"phrase_memory": {}} diff --git a/web/funpack_refinement_key_loader.js b/web/funpack_refinement_key_loader.js new file mode 100644 index 00000000..dd05ffac --- /dev/null +++ b/web/funpack_refinement_key_loader.js @@ -0,0 +1,250 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; + +const NODE_NAME = "FunPackRefinementKeyLoader"; +const NONE_KEY = "-None-"; +const BUTTON_NAMES = new Set([ + "funpack_refinement_key_export", + "funpack_refinement_key_import", + "funpack_refinement_key_refresh", +]); + +let cachedKeys = [NONE_KEY]; +const trackedNodes = new Set(); +let pendingRefresh = null; + +function widgetByName(node, name) { + return (node.widgets || []).find((widget) => widget.name === name); +} + +function keyWidget(node) { + return widgetByName(node, "refinement_key"); +} + +function keyNameWidget(node) { + return widgetByName(node, "key_name"); +} + +function selectedKey(node) { + const selected = String(keyWidget(node)?.value || "").trim(); + if (selected && selected !== NONE_KEY) { + return selected; + } + return String(keyNameWidget(node)?.value || "").trim(); +} + +function fitString(ctx, text, maxWidth) { + text = String(text ?? ""); + if (ctx.measureText(text).width <= maxWidth) { + return text; + } + const ellipsis = "..."; + let low = 0; + let high = text.length; + while (low < high) { + const mid = Math.ceil((low + high) / 2); + if (ctx.measureText(text.slice(0, mid) + ellipsis).width <= maxWidth) { + low = mid; + } else { + high = mid - 1; + } + } + return text.slice(0, low) + ellipsis; +} + +function updateKeyWidget(node, values = cachedKeys) { + const widget = keyWidget(node); + if (!widget) { + return; + } + const current = widget.value; + const nextValues = current && !values.includes(current) ? [...values, current] : values; + if (widget.options) { + widget.options.values = nextValues; + } + if (!widget.value || !nextValues.includes(widget.value)) { + widget.value = nextValues[0] || NONE_KEY; + } +} + +async function fetchKeys() { + try { + const response = await api.fetchApi(`/funpack/refinement_keys?cache_bust=${Date.now()}`, { + cache: "no-store", + }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + const data = await response.json(); + const values = Array.isArray(data.keys) && data.keys.length ? data.keys : [NONE_KEY]; + cachedKeys = values; + return values; + } catch (error) { + console.warn("FunPack: failed to refresh refinement keys", error); + return cachedKeys; + } +} + +async function refreshNode(node) { + const values = await fetchKeys(); + updateKeyWidget(node, values); + node.setDirtyCanvas(true, true); +} + +async function refreshTrackedNodes() { + if (pendingRefresh) { + return pendingRefresh; + } + pendingRefresh = (async () => { + const values = await fetchKeys(); + for (const node of [...trackedNodes]) { + if (!node?.graph) { + trackedNodes.delete(node); + continue; + } + updateKeyWidget(node, values); + node.setDirtyCanvas(true, true); + } + })().finally(() => { + pendingRefresh = null; + }); + return pendingRefresh; +} + +async function exportKey(node) { + const key = selectedKey(node); + if (!key) { + app.canvas?.prompt?.("Refinement key export skipped", "Select or type a refinement key first.", () => {}); + return; + } + const response = await api.fetchApi(`/funpack/refinement_keys/export?key=${encodeURIComponent(key)}&cache_bust=${Date.now()}`, { + cache: "no-store", + }); + if (!response.ok) { + const error = await response.json().catch(() => ({})); + throw new Error(error.error || `Export failed with HTTP ${response.status}`); + } + const blob = await response.blob(); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = `funpack_refinement_${key}.json`; + document.body.appendChild(link); + link.click(); + link.remove(); + URL.revokeObjectURL(url); +} + +function importKey() { + const input = document.createElement("input"); + input.type = "file"; + input.accept = ".json,application/json"; + input.onchange = async () => { + const file = input.files?.[0]; + if (!file) { + return; + } + try { + const data = JSON.parse(await file.text()); + const response = await api.fetchApi("/funpack/refinement_keys/import", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(data), + }); + if (!response.ok) { + const error = await response.json().catch(() => ({})); + throw new Error(error.error || `Import failed with HTTP ${response.status}`); + } + await refreshTrackedNodes(); + } catch (error) { + console.warn("FunPack: refinement key import failed", error); + app.canvas?.prompt?.("Refinement key import failed", error.message || String(error), () => {}); + } + }; + input.click(); +} + +class FunPackRefinementKeyButton { + constructor(name, label, callback) { + this.name = name; + this.type = "custom"; + this.options = { serialize: false }; + this.value = ""; + this.label = label; + this.callback = callback; + } + + computeSize(width) { + return [width, LiteGraph.NODE_WIDGET_HEIGHT + 2]; + } + + draw(ctx, _node, width, y, height) { + const x = 20; + const w = width - 40; + const h = height - 2; + ctx.save(); + ctx.beginPath(); + ctx.roundRect(x, y + 1, w, h, [3]); + ctx.fillStyle = LiteGraph.WIDGET_BGCOLOR; + ctx.strokeStyle = LiteGraph.WIDGET_OUTLINE_COLOR; + ctx.fill(); + ctx.stroke(); + ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(fitString(ctx, this.label, w - 12), width / 2, y + height / 2); + ctx.restore(); + } + + mouse(event, _pos, node) { + if (event.type === "pointerup") { + this.callback(node); + return true; + } + return event.type === "pointerdown"; + } +} + +function removeButtons(node) { + node.widgets = (node.widgets || []).filter((widget) => !BUTTON_NAMES.has(widget.name)); +} + +function addButtons(node) { + removeButtons(node); + const buttons = [ + new FunPackRefinementKeyButton("funpack_refinement_key_export", "Export", (currentNode) => void exportKey(currentNode)), + new FunPackRefinementKeyButton("funpack_refinement_key_import", "Import", () => importKey()), + new FunPackRefinementKeyButton("funpack_refinement_key_refresh", "Refresh", (currentNode) => void refreshNode(currentNode)), + ]; + for (const button of buttons) { + node.addCustomWidget(button); + } +} + +function setupNode(node) { + trackedNodes.add(node); + updateKeyWidget(node); + addButtons(node); + void refreshNode(node); +} + +app.registerExtension({ + name: "funpack.refinementKeyLoader", + beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== NODE_NAME) { + return; + } + + const originalOnNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + originalOnNodeCreated?.apply(this, arguments); + setupNode(this); + }; + + const originalConfigure = nodeType.prototype.configure; + nodeType.prototype.configure = function (info) { + originalConfigure?.apply(this, arguments); + setupNode(this, info); + }; + }, +}); From edb5cc36072cdb030e94a088b5dd1a46a202a802 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 19:32:31 +0300 Subject: [PATCH 2/8] Remove duplicate Refiner key widget --- conditioning.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conditioning.py b/conditioning.py index 1d4a3da0..b2041afd 100644 --- a/conditioning.py +++ b/conditioning.py @@ -5703,7 +5703,6 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "positive_prompt": ("STRING", {"multiline": True, "default": "", "placeholder": "Positive prompt"}), "clip": ("CLIP", {"tooltip": "Connected text encoder used for all V2 prompt encoding and similarity checks."}), "rating": (V2_RATING_LABELS, {"default": "Missing action", "label": "Rating"}), - "refinement_key": ("STRING", {"default": "my_style_v2", "multiline": False}), }, "optional": { "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "label": "Exploration Seed"}), @@ -7558,7 +7557,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): prompt_history["lora_weight_suggestions"] = suggestions return "LoRA suggestions: " + " | ".join(parts) - def refine_v2(self, positive_prompt, clip, rating, refinement_key, + def refine_v2(self, positive_prompt, clip, rating, refinement_key="", seed=0, reset_session=False, lora_stack=None, im_feeling_lucky=False, user_intent_prompt="", refinement_key_input=""): if seed != 0: From 1f224123ba6a5f9ceaf3dea9bdd6a2a8d84f590b Mon Sep 17 00:00:00 2001 From: DigitalGarbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 19:40:03 +0300 Subject: [PATCH 3/8] Add new example workflow for Refiner V2 --- ...FunPackRefinerV2_LTXV_ExampleWorkflow.json | 5507 +++++++++++++++++ 1 file changed, 5507 insertions(+) create mode 100644 example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json diff --git a/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json b/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json new file mode 100644 index 00000000..8bfabe48 --- /dev/null +++ b/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json @@ -0,0 +1,5507 @@ +{ + "id": "5dccf3d1-6e5e-41c1-8320-bbd2abb95ebf", + "revision": 0, + "last_node_id": 5239, + "last_link_id": 14498, + "nodes": [ + { + "id": 5145, + "type": "LTXFloatToInt", + "pos": [ + -3507.5079864668505, + 4000.1459627992567 + ], + "size": [ + 270, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "a", + "type": "FLOAT", + "widget": { + "name": "a" + }, + "link": 14066 + } + ], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 14067 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "937831df0e5e1f707340b7e037a52e9d1196e3f8", + "Node name for S&R": "LTXFloatToInt", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 0 + ] + }, + { + "id": 5167, + "type": "KSamplerSelect", + "pos": [ + -2379.7024494145626, + 4038.4023692469204 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 5168, + "type": "PreviewAny", + "pos": [ + -4385.226512535651, + 3084.645124512045 + ], + "size": [ + 289.4653455216139, + 343.798203293964 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14491 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "LoRA Loader Status", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 4845, + "type": "LTXVSeparateAVLatent", + "pos": [ + -2082.2045030891563, + 3494.440137743163 + ], + "size": [ + 271.2833312988281, + 46 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "av_latent", + "type": "LATENT", + "link": 13890 + } + ], + "outputs": [ + { + "name": "video_latent", + "type": "LATENT", + "links": [ + 14298, + 14480 + ] + }, + { + "name": "audio_latent", + "type": "LATENT", + "links": [ + 13455, + 14302 + ] + } + ], + "title": "Separate Low Resolution AV Latent", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5198, + "type": "LTXVSeparateAVLatent", + "pos": [ + -1221.5407165055633, + 3493.950687198729 + ], + "size": [ + 271.2833312988281, + 46 + ], + "flags": {}, + "order": 37, + "mode": 4, + "inputs": [ + { + "name": "av_latent", + "type": "LATENT", + "link": 14303 + } + ], + "outputs": [ + { + "name": "video_latent", + "type": "LATENT", + "links": [ + 14304 + ] + }, + { + "name": "audio_latent", + "type": "LATENT", + "links": [ + 14306 + ] + } + ], + "title": "Separate Low Resolution AV Latent", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5199, + "type": "LTXVTiledVAEDecode", + "pos": [ + -1221.7380406345537, + 3583.402901335242 + ], + "size": [ + 269.8901736365534, + 198 + ], + "flags": {}, + "order": 38, + "mode": 4, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14309 + }, + { + "name": "latents", + "type": "LATENT", + "link": 14304 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 14305 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVTiledVAEDecode", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 2, + 2, + 6, + true, + "auto", + "auto" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5232, + "type": "PreviewAny", + "pos": [ + -2689.132338933934, + 3099.5656012946883 + ], + "size": [ + 584.4302826165278, + 339.8875564758546 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14476 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Status", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 5147, + "type": "LTXVConditioning", + "pos": [ + -2690.0767793685, + 3603.753930143112 + ], + "size": [ + 296.9524603795917, + 79.1230191824834 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 14473 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14459 + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 14088 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 14278, + 14317 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 14279, + 14318 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "LTXVConditioning" + }, + "widgets_values": [ + 25 + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5200, + "type": "LTXVAudioVAEDecode", + "pos": [ + -1219.95377743797, + 3828.1861660025484 + ], + "size": [ + 269.4217902135765, + 47.123019182483404 + ], + "flags": {}, + "order": 39, + "mode": 4, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 14306 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14308 + } + ], + "outputs": [ + { + "name": "Audio", + "type": "AUDIO", + "links": [ + 14450 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVAudioVAEDecode" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5197, + "type": "VHS_VideoCombine", + "pos": [ + -925.8829794510538, + 3495.653727369115 + ], + "size": [ + 250, + 310 + ], + "flags": {}, + "order": 41, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 14305 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 14451 + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 14331 + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "title": "Result", + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", + "Node name for S&R": "VHS_VideoCombine", + "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "result_%date:MM-dd_hh-mm%", + "format": "video/h265-mp4", + "pix_fmt": "yuv420p", + "crf": 20, + "save_metadata": true, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "result_05-07_21-59_00001-audio.mp4", + "subfolder": "", + "type": "temp", + "format": "video/h265-mp4", + "frame_rate": 30, + "workflow": "result_05-07_21-59_00001.png", + "fullpath": "/workspace/ComfyUI/temp/result_05-07_21-59_00001-audio.mp4" + } + } + }, + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5234, + "type": "NormalizeAudioLoudness", + "pos": [ + -1217.0220967914534, + 3916.996295875656 + ], + "size": [ + 277.5000061035156, + 58 + ], + "flags": {}, + "order": 40, + "mode": 4, + "inputs": [ + { + "name": "audio", + "type": "AUDIO", + "link": 14450 + } + ], + "outputs": [ + { + "name": "audio", + "type": "AUDIO", + "links": [ + 14451 + ] + } + ], + "properties": { + "aux_id": "Kijai/ComfyUI-WanVideoWrapper", + "ver": "d18cdb18597f525ef8d613a0cb447080fbab8fce", + "Node name for S&R": "NormalizeAudioLoudness" + }, + "widgets_values": [ + -22 + ] + }, + { + "id": 5193, + "type": "SamplerCustom", + "pos": [ + -1521.9587592427224, + 3493.3602963822873 + ], + "size": [ + 280, + 644.9638554216867 + ], + "flags": {}, + "order": 36, + "mode": 4, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14422 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 14317 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14318 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 14482 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 14483 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 14297 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 14303 + ] + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": null + } + ], + "title": "Sampler", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.3", + "Node name for S&R": "SamplerCustom" + }, + "widgets_values": [ + true, + 1038396381436726, + "randomize", + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 4989, + "type": "PrimitiveFloat", + "pos": [ + -4047.3468830331485, + 4162.766074101198 + ], + "size": [ + 503.47815868041744, + 77.73054862088065 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 13450, + 14066, + 14070, + 14088, + 14331 + ] + } + ], + "title": "fps", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveFloat" + }, + "widgets_values": [ + 30 + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5177, + "type": "PreviewAny", + "pos": [ + -3504.032993175745, + 3095.0195440692464 + ], + "size": [ + 313.15375440166144, + 337.14574394977444 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14282 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 14274 + ] + } + ], + "title": "Enhanced Prompt Preview", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5020, + "type": "LTXVTiledVAEDecode", + "pos": [ + -2081.4899836490504, + 3582.7175410147156 + ], + "size": [ + 269.8901736365534, + 198 + ], + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14055 + }, + { + "name": "latents", + "type": "LATENT", + "link": 14480 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 14011 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVTiledVAEDecode", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 2, + 2, + 6, + true, + "auto", + "auto" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5021, + "type": "LTXVAudioVAEDecode", + "pos": [ + -2074.5265803528687, + 3824.172664222329 + ], + "size": [ + 269.4217902135765, + 47.123019182483404 + ], + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 13455 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14051 + } + ], + "outputs": [ + { + "name": "Audio", + "type": "AUDIO", + "links": [ + 14285 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVAudioVAEDecode" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 4528, + "type": "LTXVConcatAVLatent", + "pos": [ + -2692.1168150539725, + 3722.796257377105 + ], + "size": [ + 295.20239189803476, + 47.12301918248295 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "name": "video_latent", + "type": "LATENT", + "link": 14460 + }, + { + "name": "audio_latent", + "type": "LATENT", + "link": 14064 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 13963 + ] + } + ], + "title": "Concat Refined Video + Audio Latents", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5192, + "type": "LTXVLatentUpsampler", + "pos": [ + -2076.478741406815, + 3914.429910567344 + ], + "size": [ + 275.48004914142155, + 71.78799059939456 + ], + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 14298 + }, + { + "name": "upscale_model", + "type": "LATENT_UPSCALE_MODEL", + "link": 14301 + }, + { + "name": "vae", + "type": "VAE", + "link": 14300 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 14323 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LTXVLatentUpsampler" + }, + "widgets_values": [], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5195, + "type": "LTXVConcatAVLatent", + "pos": [ + -2072.854396167023, + 4027.514441996872 + ], + "size": [ + 291.79999389648435, + 47.84435512229766 + ], + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "name": "video_latent", + "type": "LATENT", + "link": 14324 + }, + { + "name": "audio_latent", + "type": "LATENT", + "link": 14302 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 14297 + ] + } + ], + "title": "Concat Refined Video + Audio Latents", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5205, + "type": "LTXVImgToVideoInplace", + "pos": [ + -1524.2420723511418, + 4178.461731638713 + ], + "size": [ + 280.36925823128377, + 127.59106100617828 + ], + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14325 + }, + { + "name": "image", + "type": "IMAGE", + "link": 14326 + }, + { + "name": "latent", + "type": "LATENT", + "link": 14323 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 14324 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace", + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.5.2", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1, + false + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 4988, + "type": "PrimitiveInt", + "pos": [ + -4048.390415681659, + 4032.18209467316 + ], + "size": [ + 506.76658345056376, + 85.28842477014678 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 14059 + ] + } + ], + "title": "number of frames", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 465, + "fixed" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5201, + "type": "FunPackHybridEuler2SSampler", + "pos": [ + -2088.410916070577, + 4114.3963480347475 + ], + "size": [ + 297.63680812038353, + 366 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "sigmas", + "shape": 7, + "type": "SIGMAS", + "link": 14315 + } + ], + "outputs": [ + { + "name": "sampler", + "type": "SAMPLER", + "links": [] + }, + { + "name": "sigmas", + "type": "SIGMAS", + "links": [] + } + ], + "properties": { + "cnr_id": "funpack", + "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", + "Node name for S&R": "FunPackHybridEuler2SSampler", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [ + 1, + 1, + 1, + 0.7, + "off", + 0.75, + 6, + 0.2, + 0.85 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5050, + "type": "ManualSigmas", + "pos": [ + -2688.654376071476, + 3492.407535659919 + ], + "size": [ + 297.7618766359765, + 71.64421238507339 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 14469 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5144, + "type": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", + "pos": [ + -4050.509757988798, + 3782.8259458113293 + ], + "size": [ + 508.9639946472771, + 210 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 14059 + }, + { + "name": "vae", + "type": "VAE", + "link": 14060 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14061 + }, + { + "name": "image", + "type": "IMAGE,MASK", + "link": 14062 + }, + { + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 14067 + } + ], + "outputs": [ + { + "label": "video_latent", + "name": "latent", + "type": "LATENT", + "links": [ + 14460 + ] + }, + { + "label": "audio_latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 14064 + ] + }, + { + "name": "output_image", + "type": "IMAGE", + "links": [ + 14326 + ] + }, + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 14348 + ] + }, + { + "label": "plain_black", + "name": "output", + "type": "IMAGE", + "links": [] + } + ], + "properties": { + "proxyWidgets": [ + [ + "3059", + "length" + ], + [ + "3980", + "frame_rate" + ], + [ + "5031", + "target_width" + ], + [ + "5031", + "target_height" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5101, + "type": "SamplerCustom", + "pos": [ + -2376.173833228616, + 3494.807541019537 + ], + "size": [ + 280, + 644.9638554216867 + ], + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14421 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 14278 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14279 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 14486 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 14487 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 13963 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 13890 + ] + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": null + } + ], + "title": "Sampler", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.3", + "Node name for S&R": "SamplerCustom" + }, + "widgets_values": [ + true, + 408211233755525, + "randomize", + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5096, + "type": "FunPackHybridEuler2SSampler", + "pos": [ + -2692.7617900563005, + 3820.895095468243 + ], + "size": [ + 295.06974613407635, + 272.5589436984151 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "sigmas", + "shape": 7, + "type": "SIGMAS", + "link": 14469 + } + ], + "outputs": [ + { + "name": "sampler", + "type": "SAMPLER", + "links": [ + 14486 + ] + }, + { + "name": "sigmas", + "type": "SIGMAS", + "links": [ + 14487 + ] + } + ], + "properties": { + "cnr_id": "funpack", + "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", + "Node name for S&R": "FunPackHybridEuler2SSampler", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [ + 0, + 1.65, + 0.7, + 0.5, + "off", + 0.5, + 3, + 0.2, + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5146, + "type": "953c68b0-c00f-4e16-ab59-39af7ce32097", + "pos": [ + -3501.053962071962, + 3484.3459461593543 + ], + "size": [ + 311.20648872536776, + 475.57454540880417 + ], + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "label": "positive_conditioning", + "name": "positive", + "type": "CONDITIONING", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "link": 14070 + }, + { + "name": "clip", + "type": "CLIP", + "link": 14071 + }, + { + "name": "model", + "type": "MODEL", + "link": 14427 + }, + { + "name": "vae", + "type": "VAE", + "link": 14073 + }, + { + "label": "positive_prompt", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 14274 + }, + { + "name": "latent", + "type": "LATENT", + "link": 14348 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 14459 + ] + }, + { + "name": "model", + "type": "MODEL", + "links": [ + 14421, + 14422 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "2483", + "text" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5229, + "type": "LTX2_NAG", + "pos": [ + -4049.362811312737, + 3096.7926698211413 + ], + "size": [ + 502.1137448018944, + 171.12950727397492 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14426 + }, + { + "name": "nag_cond_video", + "shape": 7, + "type": "CONDITIONING", + "link": null + }, + { + "name": "nag_cond_audio", + "shape": 7, + "type": "CONDITIONING", + "link": null + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 14427 + ] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "9c3255f39cd2ea0ebf94a2016af4bd2e5d6eb91b", + "Node name for S&R": "LTX2_NAG" + }, + "widgets_values": [ + 11, + 0.275, + 2.35, + false + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5202, + "type": "ManualSigmas", + "pos": [ + -2386.3426826100235, + 4403.410245834443 + ], + "size": [ + 286.5405142205909, + 70.24154208314985 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 14315, + 14483 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "0.909375, 0.725, 0.421875, 0.0" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5196, + "type": "LatentUpscaleModelLoader", + "pos": [ + -2385.64321264596, + 4297.699280929902 + ], + "size": [ + 285.1080109057697, + 63.260013632212576 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "LATENT_UPSCALE_MODEL", + "type": "LATENT_UPSCALE_MODEL", + "links": [ + 14301 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LatentUpscaleModelLoader" + }, + "widgets_values": [ + "ltx2_spatial_upscaler.safetensors" + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5170, + "type": "KSamplerSelect", + "pos": [ + -2388.0095897749534, + 4194.947968470283 + ], + "size": [ + 286.83204362307833, + 63.61068120769323 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 14482 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler_ancestral_cfg_pp" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5153, + "type": "PreviewAny", + "pos": [ + -2082.4801016069136, + 3102.538429670107 + ], + "size": [ + 839.175670995261, + 342.8519370213312 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14477 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Training Info", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 5019, + "type": "VHS_VideoCombine", + "pos": [ + -1783.626263907655, + 3493.952642031969 + ], + "size": [ + 250, + 310 + ], + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 14011 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 14285 + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 13450 + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "title": "Result", + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", + "Node name for S&R": "VHS_VideoCombine", + "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "result_%date:MM-dd_hh-mm-ss%", + "format": "video/h265-mp4", + "pix_fmt": "yuv420p", + "crf": 20, + "save_metadata": true, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "result_05-08_19-22-27_00001-audio.mp4", + "subfolder": "", + "type": "temp", + "format": "video/h265-mp4", + "frame_rate": 30, + "workflow": "result_05-08_19-22-27_00001.png", + "fullpath": "/workspace/ComfyUI/temp/result_05-08_19-22-27_00001-audio.mp4" + } + } + }, + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 2004, + "type": "LoadImage", + "pos": [ + -4386.235372913527, + 4036.898594725194 + ], + "size": [ + 280, + 315 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 11002, + 14062, + 14280 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "HHuFYC9bEAAd4f9.jpg", + "image" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5188, + "type": "c758fc63-b71c-43f2-b085-ded32443f756", + "pos": [ + -4049.591349938611, + 3313.186716870688 + ], + "size": [ + 505.0919753788826, + 121.53832647689296 + ], + "flags": { + "collapsed": false + }, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 14280 + }, + { + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 14281 + } + ], + "outputs": [ + { + "name": "generated_text", + "type": "STRING", + "links": [ + 14282, + 14474, + 14492 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "5215", + "prompt" + ], + [ + "5185", + "seed" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.20.1" + }, + "widgets_values": [], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5238, + "type": "FunPackApplyLoraWeights", + "pos": [ + -4862.610875119302, + 3471.8420845911883 + ], + "size": [ + 434.32223485180293, + 474 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "refinement_key_input", + "shape": 7, + "type": "STRING", + "link": null + }, + { + "name": "positive_prompt", + "type": "STRING", + "widget": { + "name": "positive_prompt" + }, + "link": 14492 + }, + { + "name": "refinement_key", + "type": "STRING", + "widget": { + "name": "refinement_key" + }, + "link": 14497 + } + ], + "outputs": [ + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [ + 14489, + 14490 + ] + }, + { + "name": "status", + "type": "STRING", + "links": [ + 14491 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "02e89ebd36208f6f5c0d7780f89f7dcdc040b1f1", + "Node name for S&R": "FunPackApplyLoraWeights" + }, + "widgets_values": [ + "", + "my_style_v1", + "ltx2", + true, + "[]", + {}, + { + "on": true, + "lora": "None", + "type": "general", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "action", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "style", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "quality", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "character", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "general", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "action", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "style", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "quality", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "character", + "strength": 1 + }, + "" + ] + }, + { + "id": 5150, + "type": "MarkdownNote", + "pos": [ + -4874.5803841744955, + 4030.3082654487844 + ], + "size": [ + 457.2957979656867, + 322.28010914237484 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This is an example workflow, finetuned for LTX2.3 video model, using FunPack nodes to enhance and correct the results, tweaking them according to user's preferences.\n\nVideo Refiner V2 node learns from your ratings and feedback to provide the best result much more consistently than a base model does.\n\nThis workflow DOES NOT make model learn concepts it were never aware of. It only finetunes conditioning to match what YOU like as user, however it can't introduce knowledge that was never a part of a model.\n\nThis example workflow is actively using subgraphs to compact the space it takes, providing much more neat and clear workspace.\n\nIf you have any feedback or you found a bug or you have problems with using my nodes, feel free to file an issue on Github:\n\nhttps://github.com/digital-garbage/ComfyUI-FunPack\n\nPlease make sure you are reporting issues while using \"main\" branch of the repo. Issues with \"dev\" branch will not be reviewed unless they are critical bugs, breaking workflow fully." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5149, + "type": "MarkdownNote", + "pos": [ + -3162.082761220368, + 4004.8511204429938 + ], + "size": [ + 442.2702587922827, + 287.96370570528234 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "Refiner V2 Quick Guide\n\nFunPack Video Refiner V2 is a prompt memory node. It takes your positive prompt, encodes it through the connected CLIP, remembers how you rated the previous output, and slowly learns which actions, camera moves, details, quality cues, and style cues work for your workflows.\n\nIt does not look at the finished video pixels. It does not magically know what is inside your input image. It does not replace clear prompting. In image-to-video, it now treats character appearance, clothing, subject identity, and background as image-owned by default, so it should not inject old remembered outfits or characters into a new image unless you explicitly prompt them.\n\nHow To Use It\n\n Add FunPack Video Refiner V2 before your sampler where positive conditioning is encoded.\n Connect your CLIP.\n Type a refinement_key, or use FunPack Refinement Key Loader and connect its output into refinement_key_input.\n First run only seeds memory. Generate once, look at the result, then rate that result on the next run with the same key.\n Use Perfect when the output is good and should be remembered.\n Use Missing action when the requested motion did not happen.\n Use Missing details when small non-identity details are weak, like smoke, reflections, particles, hand contact, object interaction, or secondary motion.\n Use Missing quality when the idea is right but the result is messy or ugly.\n Use Wrong action, Wrong details, or Wrong details + action when the video looks usable but did the wrong thing.\n Use Wrong appearance when Refiner/Lucky brought in unwanted clothing, face, body, character, subject, or background memory.\n Use -Just forget it- for broken runs, bad seeds, workflow mistakes, model failures, or anything you do not want learned.\n\nLucky Mode\n\nI'm Feeling Lucky composes a prompt from learned memory. It is useful when you want the node to suggest motion, camera, detail, quality, or style ideas from previous liked outputs.\n\nLucky should not auto-add remembered outfits, character traits, subjects, or backgrounds anymore. If you want an appearance item, write it directly in the prompt.\nExamples\n\nIf your prompt says person smoking and exhaling smoke but the video only shows a puff with no exhale, rate Missing details or Missing action, depending on what matters most. This teaches the key that smoke/exhale matters in that prompt context, without globally banning smoking.\n\nIf you liked white tights in older prompts but your new input image is only a portrait face, and Lucky tries to bring tights into the scene, rate Wrong appearance. That tells Refiner to suppress that appearance memory from auto-injection while still allowing white tights when you explicitly type it.\n\nIf the camera should push in, orbit, pan, or change framing and it stays static, rate Missing action or Wrong action. Camera movement belongs to the action/camera side of memory, so it remains safe for repair and Lucky.\nKey Loader\n\nUse FunPack Refinement Key Loader when you want a reusable key dropdown or want to move keys between workflows/machines. Its Import and Export buttons save/load the key as JSON. Connect the loader to both Refiner V2 and FunPack Apply LoRA Weights so LoRA suggestions and prompt memory use the same key." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5237, + "type": "FunPackVideoRefinerV2", + "pos": [ + -3163.670871437389, + 3484.6075129967685 + ], + "size": [ + 450.56804065586994, + 475.2209928759157 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 14472 + }, + { + "name": "lora_stack", + "shape": 7, + "type": "FUNPACK_LORA_STACK", + "link": 14490 + }, + { + "name": "refinement_key_input", + "shape": 7, + "type": "STRING", + "link": 14494 + }, + { + "name": "positive_prompt", + "type": "STRING", + "widget": { + "name": "positive_prompt" + }, + "link": 14474 + }, + { + "name": "user_intent_prompt", + "shape": 7, + "type": "STRING", + "widget": { + "name": "user_intent_prompt" + }, + "link": 14496 + } + ], + "outputs": [ + { + "name": "modified_positive", + "type": "CONDITIONING", + "links": [ + 14473 + ] + }, + { + "name": "status", + "type": "STRING", + "links": [ + 14476 + ] + }, + { + "name": "training_info", + "type": "STRING", + "links": [ + 14477 + ] + }, + { + "name": "loss_graph", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "e4c65fc2e2dca771e15e0b0f0c20044212870a05", + "Node name for S&R": "FunPackVideoRefinerV2" + }, + "widgets_values": [ + "", + "Wrong details", + 1, + "randomize", + false, + false, + false + ] + }, + { + "id": 5012, + "type": "PrimitiveStringMultiline", + "pos": [ + -4055.4304375982783, + 3481.1266355613766 + ], + "size": [ + 520, + 260 + ], + "flags": { + "collapsed": false + }, + "order": 10, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 14281, + 14496 + ] + } + ], + "title": "Positive Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "Put your original prompt that will be enhanced with prompt enhancer here, or disable the enhancer and connect this to \"positive_prompt\" input of Refiner." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5239, + "type": "FunPackRefinementKeyLoader", + "pos": [ + -3505.5938785840517, + 4049.7856350297743 + ], + "size": [ + 314.7000030517578, + 204 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "refinement_key", + "type": "STRING", + "links": [ + 14494, + 14497 + ] + }, + { + "name": "status", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "b5a875a2609e21f19c08e5951e72af2db220cb5c", + "Node name for S&R": "FunPackRefinementKeyLoader" + }, + "widgets_values": [ + "ltx23_example", + "", + true, + "", + "", + "" + ] + }, + { + "id": 5143, + "type": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", + "pos": [ + -4387.679665836049, + 3474.1287636541992 + ], + "size": [ + 279.2243457043487, + 513.7727601710899 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "link": 14489 + } + ], + "outputs": [ + { + "label": "audio_vae", + "name": "VAE", + "type": "VAE", + "links": [ + 14051, + 14061, + 14308 + ] + }, + { + "label": "fast_vae", + "name": "VAE_1", + "type": "VAE", + "links": [ + 14073 + ] + }, + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [] + }, + { + "label": "video_vae", + "name": "VAE_2", + "type": "VAE", + "links": [ + 14055, + 14060, + 14300, + 14309, + 14325 + ] + }, + { + "label": "LTXV_model", + "name": "model", + "type": "MODEL", + "links": [ + 14426 + ] + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 14071, + 14472 + ] + }, + { + "name": "latent_downscale_factor", + "type": "FLOAT", + "links": [] + }, + { + "label": "lora_loader_status", + "name": "status", + "type": "STRING", + "links": [] + } + ], + "properties": { + "proxyWidgets": [], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#223", + "bgcolor": "#335" + } + ], + "links": [ + [ + 11002, + 2004, + 0, + 2653, + 0, + "IMAGE" + ], + [ + 13450, + 4989, + 0, + 5019, + 4, + "FLOAT" + ], + [ + 13455, + 4845, + 1, + 5021, + 0, + "LATENT" + ], + [ + 13890, + 5101, + 0, + 4845, + 0, + "LATENT" + ], + [ + 13963, + 4528, + 0, + 5101, + 5, + "LATENT" + ], + [ + 14011, + 5020, + 0, + 5019, + 0, + "IMAGE" + ], + [ + 14051, + 5143, + 0, + 5021, + 1, + "VAE" + ], + [ + 14055, + 5143, + 3, + 5020, + 0, + "VAE" + ], + [ + 14059, + 4988, + 0, + 5144, + 0, + "INT" + ], + [ + 14060, + 5143, + 3, + 5144, + 1, + "VAE" + ], + [ + 14061, + 5143, + 0, + 5144, + 2, + "VAE" + ], + [ + 14062, + 2004, + 0, + 5144, + 3, + "IMAGE" + ], + [ + 14064, + 5144, + 1, + 4528, + 1, + "LATENT" + ], + [ + 14066, + 4989, + 0, + 5145, + 0, + "FLOAT" + ], + [ + 14067, + 5145, + 0, + 5144, + 4, + "INT" + ], + [ + 14070, + 4989, + 0, + 5146, + 1, + "FLOAT" + ], + [ + 14071, + 5143, + 5, + 5146, + 2, + "CLIP" + ], + [ + 14073, + 5143, + 1, + 5146, + 4, + "VAE" + ], + [ + 14088, + 4989, + 0, + 5147, + 2, + "FLOAT" + ], + [ + 14274, + 5177, + 0, + 5146, + 5, + "STRING" + ], + [ + 14278, + 5147, + 0, + 5101, + 1, + "CONDITIONING" + ], + [ + 14279, + 5147, + 1, + 5101, + 2, + "CONDITIONING" + ], + [ + 14280, + 2004, + 0, + 5188, + 0, + "IMAGE" + ], + [ + 14281, + 5012, + 0, + 5188, + 1, + "STRING" + ], + [ + 14282, + 5188, + 0, + 5177, + 0, + "STRING" + ], + [ + 14285, + 5021, + 0, + 5019, + 1, + "AUDIO" + ], + [ + 14297, + 5195, + 0, + 5193, + 5, + "LATENT" + ], + [ + 14298, + 4845, + 0, + 5192, + 0, + "LATENT" + ], + [ + 14300, + 5143, + 3, + 5192, + 2, + "VAE" + ], + [ + 14301, + 5196, + 0, + 5192, + 1, + "LATENT_UPSCALE_MODEL" + ], + [ + 14302, + 4845, + 1, + 5195, + 1, + "LATENT" + ], + [ + 14303, + 5193, + 0, + 5198, + 0, + "LATENT" + ], + [ + 14304, + 5198, + 0, + 5199, + 1, + "LATENT" + ], + [ + 14305, + 5199, + 0, + 5197, + 0, + "IMAGE" + ], + [ + 14306, + 5198, + 1, + 5200, + 0, + "LATENT" + ], + [ + 14308, + 5143, + 0, + 5200, + 1, + "VAE" + ], + [ + 14309, + 5143, + 3, + 5199, + 0, + "VAE" + ], + [ + 14315, + 5202, + 0, + 5201, + 0, + "SIGMAS" + ], + [ + 14317, + 5147, + 0, + 5193, + 1, + "CONDITIONING" + ], + [ + 14318, + 5147, + 1, + 5193, + 2, + "CONDITIONING" + ], + [ + 14323, + 5192, + 0, + 5205, + 2, + "LATENT" + ], + [ + 14324, + 5205, + 0, + 5195, + 0, + "LATENT" + ], + [ + 14325, + 5143, + 3, + 5205, + 0, + "VAE" + ], + [ + 14326, + 5144, + 2, + 5205, + 1, + "IMAGE" + ], + [ + 14331, + 4989, + 0, + 5197, + 4, + "FLOAT" + ], + [ + 14348, + 5144, + 3, + 5146, + 6, + "LATENT" + ], + [ + 14421, + 5146, + 2, + 5101, + 0, + "MODEL" + ], + [ + 14422, + 5146, + 2, + 5193, + 0, + "MODEL" + ], + [ + 14426, + 5143, + 4, + 5229, + 0, + "MODEL" + ], + [ + 14427, + 5229, + 0, + 5146, + 3, + "MODEL" + ], + [ + 14450, + 5200, + 0, + 5234, + 0, + "AUDIO" + ], + [ + 14451, + 5234, + 0, + 5197, + 1, + "AUDIO" + ], + [ + 14459, + 5146, + 1, + 5147, + 1, + "CONDITIONING" + ], + [ + 14460, + 5144, + 0, + 4528, + 0, + "LATENT" + ], + [ + 14469, + 5050, + 0, + 5096, + 0, + "SIGMAS" + ], + [ + 14472, + 5143, + 5, + 5237, + 0, + "CLIP" + ], + [ + 14473, + 5237, + 0, + 5147, + 0, + "CONDITIONING" + ], + [ + 14474, + 5188, + 0, + 5237, + 3, + "STRING" + ], + [ + 14476, + 5237, + 1, + 5232, + 0, + "STRING" + ], + [ + 14477, + 5237, + 2, + 5153, + 0, + "STRING" + ], + [ + 14480, + 4845, + 0, + 5020, + 1, + "LATENT" + ], + [ + 14482, + 5170, + 0, + 5193, + 3, + "SAMPLER" + ], + [ + 14483, + 5202, + 0, + 5193, + 4, + "SIGMAS" + ], + [ + 14486, + 5096, + 0, + 5101, + 3, + "SAMPLER" + ], + [ + 14487, + 5096, + 1, + 5101, + 4, + "SIGMAS" + ], + [ + 14489, + 5238, + 0, + 5143, + 0, + "FUNPACK_LORA_STACK" + ], + [ + 14490, + 5238, + 0, + 5237, + 1, + "FUNPACK_LORA_STACK" + ], + [ + 14491, + 5238, + 1, + 5168, + 0, + "STRING" + ], + [ + 14492, + 5188, + 0, + 5238, + 1, + "STRING" + ], + [ + 14494, + 5239, + 0, + 5237, + 2, + "STRING" + ], + [ + 14496, + 5012, + 0, + 5237, + 4, + "STRING" + ], + [ + 14497, + 5239, + 0, + 5238, + 2, + "STRING" + ] + ], + "groups": [], + "definitions": { + "subgraphs": [ + { + "id": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14498, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Model Loaders", + "inputNode": { + "id": -10, + "bounding": [ + -4325.009559761858, + 4005.266954142581, + 120, + 60 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3434.4839648526677, + 3955.266954142581, + 176.96665954589844, + 200 + ] + }, + "inputs": [ + { + "id": "d0987976-3ded-4b5e-8cbb-bf7a8f81e33a", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "linkIds": [ + 14026 + ], + "localized_name": "lora_stack", + "pos": [ + -4225.009559761858, + 4025.266954142581 + ] + } + ], + "outputs": [ + { + "id": "5698eb50-25b5-43c3-bc6d-5ae6ed37cc69", + "name": "VAE", + "type": "VAE", + "linkIds": [ + 13426, + 13426 + ], + "localized_name": "VAE", + "label": "audio_vae", + "pos": [ + -3414.4839648526677, + 3975.266954142581 + ] + }, + { + "id": "93aec5ab-7fdc-4e97-8030-9b93ccb135f7", + "name": "VAE_1", + "type": "VAE", + "linkIds": [ + 14032 + ], + "localized_name": "VAE_1", + "label": "fast_vae", + "pos": [ + -3414.4839648526677, + 3995.266954142581 + ] + }, + { + "id": "23e2004b-5760-4651-9808-e4759172761e", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "linkIds": [ + 13861 + ], + "localized_name": "lora_stack", + "pos": [ + -3414.4839648526677, + 4015.266954142581 + ] + }, + { + "id": "c70376ed-0ba0-4de8-8c69-d0b2e0f98c94", + "name": "VAE_2", + "type": "VAE", + "linkIds": [ + 13428, + 13428 + ], + "localized_name": "VAE_2", + "label": "video_vae", + "pos": [ + -3414.4839648526677, + 4035.266954142581 + ] + }, + { + "id": "d7031e7e-1171-43c2-9dd4-b1ea12834bbc", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14418 + ], + "localized_name": "model", + "label": "LTXV_model", + "pos": [ + -3414.4839648526677, + 4055.266954142581 + ] + }, + { + "id": "3024b60b-1ea8-474c-91cd-85317f7a67a3", + "name": "CLIP", + "type": "CLIP", + "linkIds": [ + 13435, + 13435 + ], + "localized_name": "CLIP", + "pos": [ + -3414.4839648526677, + 4075.266954142581 + ] + }, + { + "id": "b5fb5099-9092-44f9-bacc-690a2860aa29", + "name": "latent_downscale_factor", + "type": "FLOAT", + "linkIds": [], + "pos": [ + -3414.4839648526677, + 4095.266954142581 + ] + }, + { + "id": "cfe9f2c2-261d-43b8-8591-00161f7bd393", + "name": "status", + "type": "STRING", + "linkIds": [ + 14188 + ], + "label": "lora_loader_status", + "pos": [ + -3414.4839648526677, + 4115.266954142581 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 5104, + "type": "FunPackLoraLoader", + "pos": [ + -3840.6243036178707, + 3669.1897293353245 + ], + "size": [ + 230, + 90 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 13916 + }, + { + "localized_name": "lora_stack", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "link": 14026 + }, + { + "localized_name": "clip", + "name": "clip", + "shape": 7, + "type": "CLIP", + "link": null + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 14320 + ] + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": null + }, + { + "localized_name": "lora_stack", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [ + 13861 + ] + }, + { + "localized_name": "status", + "name": "status", + "type": "STRING", + "links": [ + 14188 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "707e27279e2be733a5d787496742848bc745c258", + "Node name for S&R": "FunPackLoraLoader", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [] + }, + { + "id": 5004, + "type": "VAELoaderKJ", + "pos": [ + -4142.837082457477, + 3661.3251095596834 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 13428 + ] + } + ], + "title": "Load Video VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2_video_vae.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5003, + "type": "VAELoaderKJ", + "pos": [ + -4145.009559761858, + 3815.5795641379827 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 13426 + ] + } + ], + "title": "Load Audio VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2_audio_vae.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5017, + "type": "VAELoaderKJ", + "pos": [ + -4143.886540579375, + 3967.8256025029505 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 14032 + ] + } + ], + "title": "Load Preview VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "taeltx2_3.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5006, + "type": "DualCLIPLoader", + "pos": [ + -3835.5303844223104, + 3814.768391164597 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 13435 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "DualCLIPLoader" + }, + "widgets_values": [ + "gemma.safetensors", + "ltx2_embeddings_connector.safetensors", + "ltxv", + "default" + ] + }, + { + "id": 5002, + "type": "DiffusionModelLoaderKJ", + "pos": [ + -4141.903414758422, + 4121.852190133855 + ], + "size": [ + 312.06666564941406, + 178 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "localized_name": "extra_state_dict", + "name": "extra_state_dict", + "shape": 7, + "type": "STRING", + "link": null + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 13916 + ] + } + ], + "title": "Load LTX-2.3 Diffusion Model", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "DiffusionModelLoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2.safetensors", + "bf16", + "bf16", + false, + "disabled", + false + ] + }, + { + "id": 5204, + "type": "LTX2LoraLoaderAdvanced", + "pos": [ + -3821.7206559166707, + 4361.663434778751 + ], + "size": [ + 293.59999694824216, + 242 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14401 + }, + { + "localized_name": "opt_lora_path", + "name": "opt_lora_path", + "shape": 7, + "type": "STRING", + "link": null + }, + { + "localized_name": "blocks", + "name": "blocks", + "shape": 7, + "type": "SELECTEDDITBLOCKS", + "link": null + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14498 + ] + }, + { + "localized_name": "rank", + "name": "rank", + "type": "STRING", + "links": null + }, + { + "localized_name": "loaded_keys_info", + "name": "loaded_keys_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", + "Node name for S&R": "LTX2LoraLoaderAdvanced" + }, + "widgets_values": [ + "distilled_72.safetensors", + 0.75, + 0, + 1, + 1, + 1, + 1 + ] + }, + { + "id": 5203, + "type": "LTX2LoraLoaderAdvanced", + "pos": [ + -4137.706720274676, + 4359.203995818316 + ], + "size": [ + 293.59999694824216, + 242 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14320 + }, + { + "localized_name": "opt_lora_path", + "name": "opt_lora_path", + "shape": 7, + "type": "STRING", + "link": null + }, + { + "localized_name": "blocks", + "name": "blocks", + "shape": 7, + "type": "SELECTEDDITBLOCKS", + "link": null + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14401 + ] + }, + { + "localized_name": "rank", + "name": "rank", + "type": "STRING", + "links": null + }, + { + "localized_name": "loaded_keys_info", + "name": "loaded_keys_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", + "Node name for S&R": "LTX2LoraLoaderAdvanced" + }, + "widgets_values": [ + "distilled_72.safetensors", + 0.48, + 1, + 0, + 0, + 0, + 1 + ] + }, + { + "id": 5225, + "type": "FunPackContextTransitionWindows", + "pos": [ + -3499.400882804922, + 4203.790940060165 + ], + "size": [ + 346.26666870117185, + 394 + ], + "flags": {}, + "order": 8, + "mode": 4, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14498 + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14418 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "ace940fed3f7f2724f784b8d3165871a4e027281", + "Node name for S&R": "FunPackContextTransitionWindows" + }, + "widgets_values": [ + "balanced", + 241, + 73, + "standard_uniform", + "overlap-linear", + 0, + 0, + 4, + 0.2, + 1, + 1, + false, + true, + "", + false + ] + } + ], + "groups": [], + "links": [ + { + "id": 13916, + "origin_id": 5002, + "origin_slot": 0, + "target_id": 5104, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14026, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5104, + "target_slot": 1, + "type": "FUNPACK_LORA_STACK" + }, + { + "id": 13426, + "origin_id": 5003, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14032, + "origin_id": 5017, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 13861, + "origin_id": 5104, + "origin_slot": 2, + "target_id": -20, + "target_slot": 2, + "type": "FUNPACK_LORA_STACK" + }, + { + "id": 13428, + "origin_id": 5004, + "origin_slot": 0, + "target_id": -20, + "target_slot": 3, + "type": "VAE" + }, + { + "id": 13435, + "origin_id": 5006, + "origin_slot": 0, + "target_id": -20, + "target_slot": 5, + "type": "CLIP" + }, + { + "id": 14188, + "origin_id": 5104, + "origin_slot": 3, + "target_id": -20, + "target_slot": 7, + "type": "STRING" + }, + { + "id": 14320, + "origin_id": 5104, + "origin_slot": 0, + "target_id": 5203, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14401, + "origin_id": 5203, + "origin_slot": 0, + "target_id": 5204, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14418, + "origin_id": 5225, + "origin_slot": 0, + "target_id": -20, + "target_slot": 4, + "type": "MODEL" + }, + { + "id": 14498, + "origin_id": 5204, + "origin_slot": 0, + "target_id": 5225, + "target_slot": 0, + "type": "MODEL" + } + ], + "extra": {} + }, + { + "id": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14498, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Image Processing", + "inputNode": { + "id": -10, + "bounding": [ + -4230.013931822186, + 4280.664648566482, + 120, + 180 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3392.3462803758225, + 4300.664648566482, + 120, + 140 + ] + }, + "inputs": [ + { + "id": "0cd8eafb-4599-4caf-8fc4-30f63acf3cd8", + "name": "length", + "type": "INT", + "linkIds": [ + 13389, + 13390 + ], + "localized_name": "length", + "pos": [ + -4130.013931822186, + 4300.664648566482 + ] + }, + { + "id": "45f7e533-25b2-4795-acd6-5dc96f4e70d5", + "name": "vae", + "type": "VAE", + "linkIds": [ + 14054, + 14327, + 14351 + ], + "localized_name": "vae", + "pos": [ + -4130.013931822186, + 4320.664648566482 + ] + }, + { + "id": "e7b3fa68-1694-4761-a92b-f9cf55c8b0d7", + "name": "audio_vae", + "type": "VAE", + "linkIds": [ + 14050 + ], + "localized_name": "audio_vae", + "pos": [ + -4130.013931822186, + 4340.664648566482 + ] + }, + { + "id": "5a5c6f1b-489a-4eff-95cc-ee5d159310eb", + "name": "image", + "type": "IMAGE,MASK", + "linkIds": [ + 13474 + ], + "localized_name": "image", + "pos": [ + -4130.013931822186, + 4360.664648566482 + ] + }, + { + "id": "9b785d25-1e6c-4255-bb3c-97aaf621afe2", + "name": "frame_rate", + "type": "INT", + "linkIds": [ + 14065 + ], + "pos": [ + -4130.013931822186, + 4380.664648566482 + ] + }, + { + "id": "6db1bac4-138a-4b8b-90bf-3961f84d84a3", + "name": "target_width", + "type": "INT", + "linkIds": [ + 14081, + 14389 + ], + "pos": [ + -4130.013931822186, + 4400.664648566482 + ] + }, + { + "id": "0cd2e965-8222-4162-b16f-d204a10034f4", + "name": "target_height", + "type": "INT", + "linkIds": [ + 14082, + 14390 + ], + "pos": [ + -4130.013931822186, + 4420.664648566482 + ] + } + ], + "outputs": [ + { + "id": "42905067-8a71-4026-b386-cdbcbbf428d6", + "name": "latent", + "type": "LATENT", + "linkIds": [ + 14353 + ], + "localized_name": "latent", + "label": "video_latent", + "pos": [ + -3372.3462803758225, + 4320.664648566482 + ] + }, + { + "id": "832cd750-af0e-4127-b7e0-9e7d87efa173", + "name": "Latent", + "type": "LATENT", + "linkIds": [ + 13696 + ], + "localized_name": "Latent", + "label": "audio_latent", + "pos": [ + -3372.3462803758225, + 4340.664648566482 + ] + }, + { + "id": "70c112e1-3f52-4d3e-bff3-43133fe0f5a9", + "name": "output_image", + "type": "IMAGE", + "linkIds": [ + 14149 + ], + "pos": [ + -3372.3462803758225, + 4360.664648566482 + ] + }, + { + "id": "75faa65c-faad-46bc-bf59-05203952150a", + "name": "LATENT", + "type": "LATENT", + "linkIds": [ + 14349 + ], + "pos": [ + -3372.3462803758225, + 4380.664648566482 + ] + }, + { + "id": "136987d9-e5df-4234-88a8-f34dcf46a64c", + "name": "output", + "type": "IMAGE", + "linkIds": [ + 14391 + ], + "label": "plain_black", + "pos": [ + -3372.3462803758225, + 4400.664648566482 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 3980, + "type": "LTXVEmptyLatentAudio", + "pos": [ + -3752.2385283541353, + 4421.631082925247 + ], + "size": [ + 305.8394470214844, + 106 + ], + "flags": { + "collapsed": false + }, + "order": 4, + "mode": 0, + "inputs": [ + { + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 14050 + }, + { + "localized_name": "frames_number", + "name": "frames_number", + "type": "INT", + "widget": { + "name": "frames_number" + }, + "link": 13390 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 14065 + } + ], + "outputs": [ + { + "localized_name": "Latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 13696 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVEmptyLatentAudio" + }, + "widgets_values": [ + 121, + 25, + 1 + ] + }, + { + "id": 3059, + "type": "EmptyLTXVLatentVideo", + "pos": [ + -4054.604251439193, + 4362.302545732084 + ], + "size": [ + 210, + 194 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 13478 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 13479 + }, + { + "localized_name": "length", + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 13389 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 11401, + 14329 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.43", + "Node name for S&R": "EmptyLTXVLatentVideo" + }, + "widgets_values": [ + 512, + 768, + 121, + 1 + ] + }, + { + "id": 5212, + "type": "VAEEncode", + "pos": [ + -3395.061084351483, + 4221.605231546082 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "pixels", + "name": "pixels", + "type": "IMAGE", + "link": 14350 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14351 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 14349 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "VAEEncode" + }, + "widgets_values": [] + }, + { + "id": 5220, + "type": "LoadImage", + "pos": [ + -4052.9158842937736, + 4610.945426788913 + ], + "size": [ + 282.7333297729492, + 314 + ], + "flags": {}, + "order": 0, + "mode": 4, + "inputs": [], + "outputs": [ + { + "localized_name": "IMAGE", + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 14388 + ] + }, + { + "localized_name": "MASK", + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "plain-black-mobile-background-uya4pitjl3vdmatx-1490018872.jpg", + "image" + ] + }, + { + "id": 5219, + "type": "ImageTransformKJ", + "pos": [ + -3749.590944998398, + 4574.8080683828575 + ], + "size": [ + 462, + 261 + ], + "flags": { + "collapsed": true + }, + "order": 8, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE,MASK", + "link": 14388 + }, + { + "localized_name": "mask", + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "localized_name": "target_width", + "name": "target_width", + "type": "INT", + "widget": { + "name": "target_width" + }, + "link": 14389 + }, + { + "localized_name": "target_height", + "name": "target_height", + "type": "INT", + "widget": { + "name": "target_height" + }, + "link": 14390 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "IMAGE", + "links": [ + 14391 + ] + }, + { + "localized_name": "output_mask", + "name": "output_mask", + "type": "MASK", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox", + "name": "bbox", + "shape": 6, + "type": "BBOX", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox_mask", + "name": "bbox_mask", + "shape": 6, + "type": "MASK", + "links": null + }, + { + "label": "768 width", + "localized_name": "width", + "name": "width", + "type": "INT", + "links": [] + }, + { + "label": "768 height", + "localized_name": "height", + "name": "height", + "type": "INT", + "links": [] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "ImageTransformKJ", + "previewEnabled": true, + "showRotationCross": false, + "canvasSize": [ + 432, + 324 + ], + "aux_id": "kijai/ComfyUI-KJNodes", + "fillColor": "#000000", + "previewFile": "crop_preview_dd29a0.webp" + }, + "widgets_values": [ + 768, + 768, + "lanczos", + "keep_long_edge", + 16, + "disabled", + "disabled", + "{\"fillColor\":\"#000000\"}", + "" + ] + }, + { + "id": 3336, + "type": "LTXVPreprocess", + "pos": [ + -4051.7822649723703, + 4222.285074743058 + ], + "size": [ + 270, + 74 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 13864 + } + ], + "outputs": [ + { + "localized_name": "output_image", + "name": "output_image", + "type": "IMAGE", + "links": [ + 13865, + 14149, + 14328, + 14350 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "LTXVPreprocess" + }, + "widgets_values": [ + 0 + ] + }, + { + "id": 5206, + "type": "LTXVImgToVideoInplace", + "pos": [ + -3747.668725148193, + 4054.017919247807 + ], + "size": [ + 270, + 122 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14327 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 14328 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 14329 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 14353 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LTXVImgToVideoInplace" + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 3159, + "type": "LTXVImgToVideoConditionOnly", + "pos": [ + -3756.874428105229, + 4233.494670882838 + ], + "size": [ + 315.26666870117185, + 142.859507731343 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14054 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 13865 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 11401 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVImgToVideoConditionOnly", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 5031, + "type": "ImageTransformKJ", + "pos": [ + -4044.0432045178136, + 4176.011069650051 + ], + "size": [ + 520, + 261 + ], + "flags": { + "collapsed": true + }, + "order": 5, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE,MASK", + "link": 13474 + }, + { + "localized_name": "mask", + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "localized_name": "target_width", + "name": "target_width", + "type": "INT", + "widget": { + "name": "target_width" + }, + "link": 14081 + }, + { + "localized_name": "target_height", + "name": "target_height", + "type": "INT", + "widget": { + "name": "target_height" + }, + "link": 14082 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "IMAGE,MASK", + "links": [ + 13864 + ] + }, + { + "localized_name": "output_mask", + "name": "output_mask", + "type": "MASK", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox", + "name": "bbox", + "shape": 6, + "type": "BBOX", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox_mask", + "name": "bbox_mask", + "shape": 6, + "type": "MASK", + "links": null + }, + { + "label": "768 width", + "localized_name": "width", + "name": "width", + "type": "INT", + "links": [ + 13478 + ] + }, + { + "label": "768 height", + "localized_name": "height", + "name": "height", + "type": "INT", + "links": [ + 13479 + ] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "ImageTransformKJ", + "previewEnabled": true, + "showRotationCross": false, + "canvasSize": [ + 768, + 768 + ], + "aux_id": "kijai/ComfyUI-KJNodes", + "fillColor": "#000000" + }, + "widgets_values": [ + 768, + 768, + "lanczos", + "keep_long_edge", + 16, + "disabled", + "disabled", + "{\"fillColor\":\"#000000\"}", + "" + ] + } + ], + "groups": [], + "links": [ + { + "id": 13478, + "origin_id": 5031, + "origin_slot": 4, + "target_id": 3059, + "target_slot": 0, + "type": "INT" + }, + { + "id": 13479, + "origin_id": 5031, + "origin_slot": 5, + "target_id": 3059, + "target_slot": 1, + "type": "INT" + }, + { + "id": 13865, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 3159, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 11401, + "origin_id": 3059, + "origin_slot": 0, + "target_id": 3159, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 13864, + "origin_id": 5031, + "origin_slot": 0, + "target_id": 3336, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 13389, + "origin_id": -10, + "origin_slot": 0, + "target_id": 3059, + "target_slot": 2, + "type": "INT" + }, + { + "id": 13390, + "origin_id": -10, + "origin_slot": 0, + "target_id": 3980, + "target_slot": 1, + "type": "INT" + }, + { + "id": 14054, + "origin_id": -10, + "origin_slot": 1, + "target_id": 3159, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14050, + "origin_id": -10, + "origin_slot": 2, + "target_id": 3980, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 13474, + "origin_id": -10, + "origin_slot": 3, + "target_id": 5031, + "target_slot": 0, + "type": "IMAGE,MASK" + }, + { + "id": 13696, + "origin_id": 3980, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 14065, + "origin_id": -10, + "origin_slot": 4, + "target_id": 3980, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14081, + "origin_id": -10, + "origin_slot": 5, + "target_id": 5031, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14082, + "origin_id": -10, + "origin_slot": 6, + "target_id": 5031, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14149, + "origin_id": 3336, + "origin_slot": 0, + "target_id": -20, + "target_slot": 2, + "type": "IMAGE" + }, + { + "id": 14327, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5206, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14328, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 5206, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14329, + "origin_id": 3059, + "origin_slot": 0, + "target_id": 5206, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 14349, + "origin_id": 5212, + "origin_slot": 0, + "target_id": -20, + "target_slot": 3, + "type": "LATENT" + }, + { + "id": 14350, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 5212, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 14351, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5212, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 14353, + "origin_id": 5206, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 14388, + "origin_id": 5220, + "origin_slot": 0, + "target_id": 5219, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 14389, + "origin_id": -10, + "origin_slot": 5, + "target_id": 5219, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14390, + "origin_id": -10, + "origin_slot": 6, + "target_id": 5219, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14391, + "origin_id": 5219, + "origin_slot": 0, + "target_id": -20, + "target_slot": 4, + "type": "IMAGE" + } + ], + "extra": {} + }, + { + "id": "953c68b0-c00f-4e16-ab59-39af7ce32097", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14498, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Conditioning Processing", + "inputNode": { + "id": -10, + "bounding": [ + -3757.4569530860326, + 3786.7967005388414, + 159.46666717529297, + 180 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -2907.4297954820227, + 3784.52193989455, + 120, + 100 + ] + }, + "inputs": [ + { + "id": "738e10fc-b836-4774-9137-3c64dc6fd9b1", + "name": "positive", + "type": "CONDITIONING", + "linkIds": [], + "localized_name": "positive", + "label": "positive_conditioning", + "pos": [ + -3617.9902859107397, + 3806.7967005388414 + ] + }, + { + "id": "1f6995d2-3cab-4be6-bf4e-2289e22f7587", + "name": "frame_rate", + "type": "FLOAT", + "linkIds": [], + "localized_name": "frame_rate", + "pos": [ + -3617.9902859107397, + 3826.7967005388414 + ] + }, + { + "id": "3a835bc3-67a3-4315-9360-b111e3a5b8ff", + "name": "clip", + "type": "CLIP", + "linkIds": [ + 14058, + 14057 + ], + "localized_name": "clip", + "pos": [ + -3617.9902859107397, + 3846.7967005388414 + ] + }, + { + "id": "2e41c3e2-f8e8-4de3-a894-344e8eb5debe", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14056 + ], + "localized_name": "model", + "pos": [ + -3617.9902859107397, + 3866.7967005388414 + ] + }, + { + "id": "915bfda1-7565-4cf7-bd69-90348a3b254c", + "name": "vae", + "type": "VAE", + "linkIds": [ + 14052 + ], + "localized_name": "vae", + "shape": 7, + "pos": [ + -3617.9902859107397, + 3886.7967005388414 + ] + }, + { + "id": "969bf9d4-eb1d-462c-8940-dbbf51b5a2d5", + "name": "text", + "type": "STRING", + "linkIds": [ + 14038 + ], + "localized_name": "text", + "label": "positive_prompt", + "pos": [ + -3617.9902859107397, + 3906.7967005388414 + ] + }, + { + "id": "b0c833ae-af25-43fd-9b03-7b6590ed2249", + "name": "latent", + "type": "LATENT", + "linkIds": [], + "pos": [ + -3617.9902859107397, + 3926.7967005388414 + ] + } + ], + "outputs": [ + { + "id": "8984305c-acc8-4330-bd25-5ed589aed5d9", + "name": "positive", + "type": "CONDITIONING", + "linkIds": [ + 14419 + ], + "localized_name": "positive", + "pos": [ + -2887.4297954820227, + 3804.52193989455 + ] + }, + { + "id": "87bdfca5-a3a4-4115-8cea-2ee314e7c57a", + "name": "negative", + "type": "CONDITIONING", + "linkIds": [ + 14155 + ], + "localized_name": "negative", + "pos": [ + -2887.4297954820227, + 3824.52193989455 + ] + }, + { + "id": "1cfeaf78-5049-4af9-957c-13da423761e3", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14423 + ], + "localized_name": "model", + "pos": [ + -2887.4297954820227, + 3844.52193989455 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 2483, + "type": "CLIPTextEncode", + "pos": [ + -3482.3123142591667, + 3729.764452009041 + ], + "size": [ + 330, + 130 + ], + "flags": { + "collapsed": false + }, + "order": 1, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14057 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 14038 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "slot_index": 0, + "links": [ + 14419 + ] + } + ], + "title": "CLIP Text Encode (Positive Prompt)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.28", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "High quality realistic video. A clean tabletop scene with a small glass sculpture, soft studio lighting, gentle camera movement, subtle reflections, natural shadows, and smooth motion. The camera slowly moves closer, then holds steady for a clear final view." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 2612, + "type": "CLIPTextEncode", + "pos": [ + -3482.2778641371956, + 4061.479555285701 + ], + "size": [ + 330, + 120 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14058 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 13734 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "slot_index": 0, + "links": [ + 14155 + ] + } + ], + "title": "CLIP Text Encode (Negative Prompt)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.28", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "low quality, blurry, distorted shapes, broken reflections, noisy shadows, overexposed highlights, undersaturated colors, bad anatomy, people, text, watermark, logo, subtitles, harsh flicker, still frame, frozen motion, frame blending artifacts, compression artifacts" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5137, + "type": "LTX2SamplingPreviewOverride", + "pos": [ + -3481.404969237368, + 3904.2961431762487 + ], + "size": [ + 316.7000030517578, + 98 + ], + "flags": {}, + "order": 3, + "mode": 4, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14056 + }, + { + "localized_name": "latent_upscale_model", + "name": "latent_upscale_model", + "shape": 7, + "type": "LATENT_UPSCALE_MODEL", + "link": null + }, + { + "localized_name": "vae", + "name": "vae", + "shape": 7, + "type": "VAE", + "link": 14052 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 14423 + ] + } + ], + "title": "Sampling Preview Override", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "89dc2f8485e3fbedd549808b07ec20031cca6bf2", + "Node name for S&R": "LTX2SamplingPreviewOverride", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + 8 + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5081, + "type": "PrimitiveStringMultiline", + "pos": [ + -3487.4297954820227, + 3501.2832456967894 + ], + "size": [ + 520, + 180 + ], + "flags": { + "collapsed": false + }, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [ + 13734 + ] + } + ], + "title": "Negative Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "music, underwater, diving, slow motion, photorealistic, photo, realistic, real life, stickers on nipples, disconnected limbs, disconnected genitals, chest pussy, tongue out, cone penis tip, still image, bad quality, subtitles, text, watermark, overlay, pc game, yelling, console game, childish, ugly, text, blur, logo, wordmark, static, low quality, noise, white noise, bleep, censoring, censor, bleeping, beep, beeping, newscast, interview, podcast, chinese, mutant, horror, 70's, film grain, comedy, stand-up " + ], + "color": "#432", + "bgcolor": "#653" + } + ], + "groups": [], + "links": [ + { + "id": 13734, + "origin_id": 5081, + "origin_slot": 0, + "target_id": 2612, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 14058, + "origin_id": -10, + "origin_slot": 2, + "target_id": 2612, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14057, + "origin_id": -10, + "origin_slot": 2, + "target_id": 2483, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14056, + "origin_id": -10, + "origin_slot": 3, + "target_id": 5137, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14052, + "origin_id": -10, + "origin_slot": 4, + "target_id": 5137, + "target_slot": 2, + "type": "VAE" + }, + { + "id": 14038, + "origin_id": -10, + "origin_slot": 5, + "target_id": 2483, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 14155, + "origin_id": 2612, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 14419, + "origin_id": 2483, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 14423, + "origin_id": 5137, + "origin_slot": 0, + "target_id": -20, + "target_slot": 2, + "type": "MODEL" + } + ], + "extra": {} + }, + { + "id": "c758fc63-b71c-43f2-b085-ded32443f756", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14498, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Enhancer", + "inputNode": { + "id": -10, + "bounding": [ + -4185.975620413162, + 2995.9229766057383, + 120, + 80 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3519.1490771969034, + 3006.5191220105444, + 124.5999984741211, + 60 + ] + }, + "inputs": [ + { + "id": "f3881fd2-d951-4f33-874c-a5cd7f3b1f7d", + "name": "image", + "type": "IMAGE", + "linkIds": [ + 14378, + 14478 + ], + "localized_name": "image", + "shape": 7, + "pos": [ + -4085.975620413162, + 3015.9229766057383 + ] + }, + { + "id": "0357b5d7-3e17-46f2-b7dc-62941f69b495", + "name": "prompt", + "type": "STRING", + "linkIds": [ + 14463 + ], + "localized_name": "prompt", + "pos": [ + -4085.975620413162, + 3035.9229766057383 + ] + } + ], + "outputs": [ + { + "id": "53386daa-e704-4fe0-b148-12f3a8138d5c", + "name": "generated_text", + "type": "STRING", + "linkIds": [ + 14481 + ], + "localized_name": "generated_text", + "pos": [ + -3499.1490771969034, + 3026.5191220105444 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 5185, + "type": "CR Seed", + "pos": [ + -3933.9237459684864, + 2701.3944678867133 + ], + "size": [ + 270, + 102 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "seed", + "name": "seed", + "type": "INT", + "links": [ + 14361, + 14374 + ] + }, + { + "localized_name": "show_help", + "name": "show_help", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI_Comfyroll_CustomNodes", + "ver": "d78b780ae43fcf8c6b7c6505e6ffb4584281ceca", + "Node name for S&R": "CR Seed", + "aux_id": "Suzie1/ComfyUI_Comfyroll_CustomNodes" + }, + "widgets_values": [ + 856247973213084, + "randomize" + ] + }, + { + "id": 5183, + "type": "CLIPLoader", + "pos": [ + -3930.3935175132056, + 2863.217812048324 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 14377, + 14461 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "CLIPLoader" + }, + "widgets_values": [ + "sulphur_enhance.safetensors", + "stable_diffusion", + "default" + ] + }, + { + "id": 5187, + "type": "TextGenerateLTX2Prompt", + "pos": [ + -3974.8004741920977, + 3024.673944128882 + ], + "size": [ + 400, + 372 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14461 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 14478 + }, + { + "localized_name": "seed", + "name": "sampling_mode.seed", + "type": "INT", + "widget": { + "name": "sampling_mode.seed" + }, + "link": 14374 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "TextGenerateLTX2Prompt" + }, + "widgets_values": [ + "", + 2048, + "on", + 0.7, + 80, + 1, + 0.05, + 1.05, + 0, + 0, + false, + true + ] + }, + { + "id": 5215, + "type": "TextGenerate", + "pos": [ + -3975.3630377173627, + 3462.6441576677366 + ], + "size": [ + 400, + 372 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14377 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 14378 + }, + { + "localized_name": "prompt", + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 14463 + }, + { + "localized_name": "seed", + "name": "sampling_mode.seed", + "type": "INT", + "widget": { + "name": "sampling_mode.seed" + }, + "link": 14361 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [ + 14481 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "TextGenerate" + }, + "widgets_values": [ + "", + 2048, + "on", + 0.7, + 75, + 1, + 0.1, + 1.05, + 0, + 0, + false, + true + ] + } + ], + "groups": [], + "links": [ + { + "id": 14361, + "origin_id": 5185, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14374, + "origin_id": 5185, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14377, + "origin_id": 5183, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14378, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14461, + "origin_id": 5183, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14463, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5215, + "target_slot": 2, + "type": "STRING" + }, + { + "id": 14478, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14481, + "origin_id": 5215, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "STRING" + } + ], + "extra": {} + } + ] + }, + "config": {}, + "extra": { + "frontendVersion": "1.42.15", + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true, + "workspace_info": { + "id": "elBQFQknIoLYTEwIloQuw" + }, + "node_versions": { + "comfy-core": "0.3.30", + "comfyui-kjnodes": "1.0.8" + }, + "workflowRendererVersion": "LG", + "reroutes": [ + { + "id": 23, + "pos": [ + -2470.7143821696213, + 3999.039532349397 + ], + "linkIds": [ + 13450 + ] + } + ], + "workflow_name": "LTX-2.3 FunPack Node Set Example", + "ds": { + "scale": 0.6651703961652539, + "offset": [ + 5358.842219457412, + -2858.662916099798 + ] + }, + "linkExtensions": [ + { + "id": 13450, + "parentId": 23 + } + ] + }, + "version": 0.4 +} \ No newline at end of file From 60d3cf4b1de81fb59e2295b65ea006a4a68e9a44 Mon Sep 17 00:00:00 2001 From: DigitalGarbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 19:48:44 +0300 Subject: [PATCH 4/8] Delete example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json --- ...FunPackRefinerV2_LTXV_ExampleWorkflow.json | 5507 ----------------- 1 file changed, 5507 deletions(-) delete mode 100644 example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json diff --git a/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json b/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json deleted file mode 100644 index 8bfabe48..00000000 --- a/example_workflows/FunPackRefinerV2_LTXV_ExampleWorkflow.json +++ /dev/null @@ -1,5507 +0,0 @@ -{ - "id": "5dccf3d1-6e5e-41c1-8320-bbd2abb95ebf", - "revision": 0, - "last_node_id": 5239, - "last_link_id": 14498, - "nodes": [ - { - "id": 5145, - "type": "LTXFloatToInt", - "pos": [ - -3507.5079864668505, - 4000.1459627992567 - ], - "size": [ - 270, - 58 - ], - "flags": { - "collapsed": true - }, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "a", - "type": "FLOAT", - "widget": { - "name": "a" - }, - "link": 14066 - } - ], - "outputs": [ - { - "name": "INT", - "type": "INT", - "links": [ - 14067 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-LTXVideo", - "ver": "937831df0e5e1f707340b7e037a52e9d1196e3f8", - "Node name for S&R": "LTXFloatToInt", - "aux_id": "Lightricks/ComfyUI-LTXVideo" - }, - "widgets_values": [ - 0 - ] - }, - { - "id": 5167, - "type": "KSamplerSelect", - "pos": [ - -2379.7024494145626, - 4038.4023692469204 - ], - "size": [ - 270, - 58 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "SAMPLER", - "type": "SAMPLER", - "links": [] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "KSamplerSelect" - }, - "widgets_values": [ - "euler" - ] - }, - { - "id": 5168, - "type": "PreviewAny", - "pos": [ - -4385.226512535651, - 3084.645124512045 - ], - "size": [ - 289.4653455216139, - 343.798203293964 - ], - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "name": "source", - "type": "*", - "link": 14491 - } - ], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": null - } - ], - "title": "LoRA Loader Status", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.5", - "Node name for S&R": "PreviewAny" - }, - "widgets_values": [ - null, - null, - null - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 4845, - "type": "LTXVSeparateAVLatent", - "pos": [ - -2082.2045030891563, - 3494.440137743163 - ], - "size": [ - 271.2833312988281, - 46 - ], - "flags": {}, - "order": 29, - "mode": 0, - "inputs": [ - { - "name": "av_latent", - "type": "LATENT", - "link": 13890 - } - ], - "outputs": [ - { - "name": "video_latent", - "type": "LATENT", - "links": [ - 14298, - 14480 - ] - }, - { - "name": "audio_latent", - "type": "LATENT", - "links": [ - 13455, - 14302 - ] - } - ], - "title": "Separate Low Resolution AV Latent", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.10.0", - "Node name for S&R": "LTXVSeparateAVLatent" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5198, - "type": "LTXVSeparateAVLatent", - "pos": [ - -1221.5407165055633, - 3493.950687198729 - ], - "size": [ - 271.2833312988281, - 46 - ], - "flags": {}, - "order": 37, - "mode": 4, - "inputs": [ - { - "name": "av_latent", - "type": "LATENT", - "link": 14303 - } - ], - "outputs": [ - { - "name": "video_latent", - "type": "LATENT", - "links": [ - 14304 - ] - }, - { - "name": "audio_latent", - "type": "LATENT", - "links": [ - 14306 - ] - } - ], - "title": "Separate Low Resolution AV Latent", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.10.0", - "Node name for S&R": "LTXVSeparateAVLatent" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5199, - "type": "LTXVTiledVAEDecode", - "pos": [ - -1221.7380406345537, - 3583.402901335242 - ], - "size": [ - 269.8901736365534, - 198 - ], - "flags": {}, - "order": 38, - "mode": 4, - "inputs": [ - { - "name": "vae", - "type": "VAE", - "link": 14309 - }, - { - "name": "latents", - "type": "LATENT", - "link": 14304 - } - ], - "outputs": [ - { - "name": "image", - "type": "IMAGE", - "links": [ - 14305 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-LTXVideo", - "ver": "d43181d5723c1721692baef01d90cd1a825bba91", - "Node name for S&R": "LTXVTiledVAEDecode", - "aux_id": "Lightricks/ComfyUI-LTXVideo" - }, - "widgets_values": [ - 2, - 2, - 6, - true, - "auto", - "auto" - ], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5232, - "type": "PreviewAny", - "pos": [ - -2689.132338933934, - 3099.5656012946883 - ], - "size": [ - 584.4302826165278, - 339.8875564758546 - ], - "flags": {}, - "order": 25, - "mode": 0, - "inputs": [ - { - "name": "source", - "type": "*", - "link": 14476 - } - ], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": null - } - ], - "title": "Status", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.5", - "Node name for S&R": "PreviewAny" - }, - "widgets_values": [ - null, - null, - null - ] - }, - { - "id": 5147, - "type": "LTXVConditioning", - "pos": [ - -2690.0767793685, - 3603.753930143112 - ], - "size": [ - 296.9524603795917, - 79.1230191824834 - ], - "flags": {}, - "order": 27, - "mode": 0, - "inputs": [ - { - "name": "positive", - "type": "CONDITIONING", - "link": 14473 - }, - { - "name": "negative", - "type": "CONDITIONING", - "link": 14459 - }, - { - "name": "frame_rate", - "type": "FLOAT", - "widget": { - "name": "frame_rate" - }, - "link": 14088 - } - ], - "outputs": [ - { - "name": "positive", - "type": "CONDITIONING", - "links": [ - 14278, - 14317 - ] - }, - { - "name": "negative", - "type": "CONDITIONING", - "links": [ - 14279, - 14318 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.5", - "Node name for S&R": "LTXVConditioning" - }, - "widgets_values": [ - 25 - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5200, - "type": "LTXVAudioVAEDecode", - "pos": [ - -1219.95377743797, - 3828.1861660025484 - ], - "size": [ - 269.4217902135765, - 47.123019182483404 - ], - "flags": {}, - "order": 39, - "mode": 4, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 14306 - }, - { - "name": "audio_vae", - "type": "VAE", - "link": 14308 - } - ], - "outputs": [ - { - "name": "Audio", - "type": "AUDIO", - "links": [ - 14450 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.64", - "Node name for S&R": "LTXVAudioVAEDecode" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5197, - "type": "VHS_VideoCombine", - "pos": [ - -925.8829794510538, - 3495.653727369115 - ], - "size": [ - 250, - 310 - ], - "flags": {}, - "order": 41, - "mode": 4, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 14305 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 14451 - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - }, - { - "name": "frame_rate", - "type": "FLOAT", - "widget": { - "name": "frame_rate" - }, - "link": 14331 - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "title": "Result", - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", - "Node name for S&R": "VHS_VideoCombine", - "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" - }, - "widgets_values": { - "frame_rate": 8, - "loop_count": 0, - "filename_prefix": "result_%date:MM-dd_hh-mm%", - "format": "video/h265-mp4", - "pix_fmt": "yuv420p", - "crf": 20, - "save_metadata": true, - "pingpong": false, - "save_output": false, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "result_05-07_21-59_00001-audio.mp4", - "subfolder": "", - "type": "temp", - "format": "video/h265-mp4", - "frame_rate": 30, - "workflow": "result_05-07_21-59_00001.png", - "fullpath": "/workspace/ComfyUI/temp/result_05-07_21-59_00001-audio.mp4" - } - } - }, - "color": "#222", - "bgcolor": "#000" - }, - { - "id": 5234, - "type": "NormalizeAudioLoudness", - "pos": [ - -1217.0220967914534, - 3916.996295875656 - ], - "size": [ - 277.5000061035156, - 58 - ], - "flags": {}, - "order": 40, - "mode": 4, - "inputs": [ - { - "name": "audio", - "type": "AUDIO", - "link": 14450 - } - ], - "outputs": [ - { - "name": "audio", - "type": "AUDIO", - "links": [ - 14451 - ] - } - ], - "properties": { - "aux_id": "Kijai/ComfyUI-WanVideoWrapper", - "ver": "d18cdb18597f525ef8d613a0cb447080fbab8fce", - "Node name for S&R": "NormalizeAudioLoudness" - }, - "widgets_values": [ - -22 - ] - }, - { - "id": 5193, - "type": "SamplerCustom", - "pos": [ - -1521.9587592427224, - 3493.3602963822873 - ], - "size": [ - 280, - 644.9638554216867 - ], - "flags": {}, - "order": 36, - "mode": 4, - "inputs": [ - { - "name": "model", - "type": "MODEL", - "link": 14422 - }, - { - "name": "positive", - "type": "CONDITIONING", - "link": 14317 - }, - { - "name": "negative", - "type": "CONDITIONING", - "link": 14318 - }, - { - "name": "sampler", - "type": "SAMPLER", - "link": 14482 - }, - { - "name": "sigmas", - "type": "SIGMAS", - "link": 14483 - }, - { - "name": "latent_image", - "type": "LATENT", - "link": 14297 - } - ], - "outputs": [ - { - "name": "output", - "type": "LATENT", - "links": [ - 14303 - ] - }, - { - "name": "denoised_output", - "type": "LATENT", - "links": null - } - ], - "title": "Sampler", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.3", - "Node name for S&R": "SamplerCustom" - }, - "widgets_values": [ - true, - 1038396381436726, - "randomize", - 1 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 4989, - "type": "PrimitiveFloat", - "pos": [ - -4047.3468830331485, - 4162.766074101198 - ], - "size": [ - 503.47815868041744, - 77.73054862088065 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "FLOAT", - "type": "FLOAT", - "links": [ - 13450, - 14066, - 14070, - 14088, - 14331 - ] - } - ], - "title": "fps", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.16.0", - "Node name for S&R": "PrimitiveFloat" - }, - "widgets_values": [ - 30 - ], - "color": "#222", - "bgcolor": "#000" - }, - { - "id": 5177, - "type": "PreviewAny", - "pos": [ - -3504.032993175745, - 3095.0195440692464 - ], - "size": [ - 313.15375440166144, - 337.14574394977444 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "source", - "type": "*", - "link": 14282 - } - ], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": [ - 14274 - ] - } - ], - "title": "Enhanced Prompt Preview", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "PreviewAny" - }, - "widgets_values": [ - null, - null, - null - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5020, - "type": "LTXVTiledVAEDecode", - "pos": [ - -2081.4899836490504, - 3582.7175410147156 - ], - "size": [ - 269.8901736365534, - 198 - ], - "flags": {}, - "order": 31, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "VAE", - "link": 14055 - }, - { - "name": "latents", - "type": "LATENT", - "link": 14480 - } - ], - "outputs": [ - { - "name": "image", - "type": "IMAGE", - "links": [ - 14011 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-LTXVideo", - "ver": "d43181d5723c1721692baef01d90cd1a825bba91", - "Node name for S&R": "LTXVTiledVAEDecode", - "aux_id": "Lightricks/ComfyUI-LTXVideo" - }, - "widgets_values": [ - 2, - 2, - 6, - true, - "auto", - "auto" - ], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5021, - "type": "LTXVAudioVAEDecode", - "pos": [ - -2074.5265803528687, - 3824.172664222329 - ], - "size": [ - 269.4217902135765, - 47.123019182483404 - ], - "flags": {}, - "order": 32, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 13455 - }, - { - "name": "audio_vae", - "type": "VAE", - "link": 14051 - } - ], - "outputs": [ - { - "name": "Audio", - "type": "AUDIO", - "links": [ - 14285 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.64", - "Node name for S&R": "LTXVAudioVAEDecode" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 4528, - "type": "LTXVConcatAVLatent", - "pos": [ - -2692.1168150539725, - 3722.796257377105 - ], - "size": [ - 295.20239189803476, - 47.12301918248295 - ], - "flags": {}, - "order": 23, - "mode": 0, - "inputs": [ - { - "name": "video_latent", - "type": "LATENT", - "link": 14460 - }, - { - "name": "audio_latent", - "type": "LATENT", - "link": 14064 - } - ], - "outputs": [ - { - "name": "latent", - "type": "LATENT", - "links": [ - 13963 - ] - } - ], - "title": "Concat Refined Video + Audio Latents", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.10.0", - "Node name for S&R": "LTXVConcatAVLatent" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5192, - "type": "LTXVLatentUpsampler", - "pos": [ - -2076.478741406815, - 3914.429910567344 - ], - "size": [ - 275.48004914142155, - 71.78799059939456 - ], - "flags": {}, - "order": 30, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 14298 - }, - { - "name": "upscale_model", - "type": "LATENT_UPSCALE_MODEL", - "link": 14301 - }, - { - "name": "vae", - "type": "VAE", - "link": 14300 - } - ], - "outputs": [ - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 14323 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "LTXVLatentUpsampler" - }, - "widgets_values": [], - "color": "#232", - "bgcolor": "#353" - }, - { - "id": 5195, - "type": "LTXVConcatAVLatent", - "pos": [ - -2072.854396167023, - 4027.514441996872 - ], - "size": [ - 291.79999389648435, - 47.84435512229766 - ], - "flags": {}, - "order": 35, - "mode": 0, - "inputs": [ - { - "name": "video_latent", - "type": "LATENT", - "link": 14324 - }, - { - "name": "audio_latent", - "type": "LATENT", - "link": 14302 - } - ], - "outputs": [ - { - "name": "latent", - "type": "LATENT", - "links": [ - 14297 - ] - } - ], - "title": "Concat Refined Video + Audio Latents", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.10.0", - "Node name for S&R": "LTXVConcatAVLatent" - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 5205, - "type": "LTXVImgToVideoInplace", - "pos": [ - -1524.2420723511418, - 4178.461731638713 - ], - "size": [ - 280.36925823128377, - 127.59106100617828 - ], - "flags": {}, - "order": 33, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "VAE", - "link": 14325 - }, - { - "name": "image", - "type": "IMAGE", - "link": 14326 - }, - { - "name": "latent", - "type": "LATENT", - "link": 14323 - } - ], - "outputs": [ - { - "name": "latent", - "type": "LATENT", - "links": [ - 14324 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVImgToVideoInplace", - "ue_properties": { - "widget_ue_connectable": {}, - "version": "7.5.2", - "input_ue_unconnectable": {} - } - }, - "widgets_values": [ - 1, - false - ], - "color": "#232", - "bgcolor": "#353" - }, - { - "id": 4988, - "type": "PrimitiveInt", - "pos": [ - -4048.390415681659, - 4032.18209467316 - ], - "size": [ - 506.76658345056376, - 85.28842477014678 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "INT", - "type": "INT", - "links": [ - 14059 - ] - } - ], - "title": "number of frames", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.16.0", - "Node name for S&R": "PrimitiveInt" - }, - "widgets_values": [ - 465, - "fixed" - ], - "color": "#222", - "bgcolor": "#000" - }, - { - "id": 5201, - "type": "FunPackHybridEuler2SSampler", - "pos": [ - -2088.410916070577, - 4114.3963480347475 - ], - "size": [ - 297.63680812038353, - 366 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": 14315 - } - ], - "outputs": [ - { - "name": "sampler", - "type": "SAMPLER", - "links": [] - }, - { - "name": "sigmas", - "type": "SIGMAS", - "links": [] - } - ], - "properties": { - "cnr_id": "funpack", - "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", - "Node name for S&R": "FunPackHybridEuler2SSampler", - "aux_id": "digital-garbage/ComfyUI-FunPack" - }, - "widgets_values": [ - 1, - 1, - 1, - 0.7, - "off", - 0.75, - 6, - 0.2, - 0.85 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5050, - "type": "ManualSigmas", - "pos": [ - -2688.654376071476, - 3492.407535659919 - ], - "size": [ - 297.7618766359765, - 71.64421238507339 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "SIGMAS", - "type": "SIGMAS", - "links": [ - 14469 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.14.1", - "Node name for S&R": "ManualSigmas" - }, - "widgets_values": [ - "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5144, - "type": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", - "pos": [ - -4050.509757988798, - 3782.8259458113293 - ], - "size": [ - 508.9639946472771, - 210 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "length", - "type": "INT", - "widget": { - "name": "length" - }, - "link": 14059 - }, - { - "name": "vae", - "type": "VAE", - "link": 14060 - }, - { - "name": "audio_vae", - "type": "VAE", - "link": 14061 - }, - { - "name": "image", - "type": "IMAGE,MASK", - "link": 14062 - }, - { - "name": "frame_rate", - "type": "INT", - "widget": { - "name": "frame_rate" - }, - "link": 14067 - } - ], - "outputs": [ - { - "label": "video_latent", - "name": "latent", - "type": "LATENT", - "links": [ - 14460 - ] - }, - { - "label": "audio_latent", - "name": "Latent", - "type": "LATENT", - "links": [ - 14064 - ] - }, - { - "name": "output_image", - "type": "IMAGE", - "links": [ - 14326 - ] - }, - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 14348 - ] - }, - { - "label": "plain_black", - "name": "output", - "type": "IMAGE", - "links": [] - } - ], - "properties": { - "proxyWidgets": [ - [ - "3059", - "length" - ], - [ - "3980", - "frame_rate" - ], - [ - "5031", - "target_width" - ], - [ - "5031", - "target_height" - ] - ], - "cnr_id": "comfy-core", - "ver": "0.19.5" - }, - "widgets_values": [], - "color": "#232", - "bgcolor": "#353" - }, - { - "id": 5101, - "type": "SamplerCustom", - "pos": [ - -2376.173833228616, - 3494.807541019537 - ], - "size": [ - 280, - 644.9638554216867 - ], - "flags": {}, - "order": 28, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "MODEL", - "link": 14421 - }, - { - "name": "positive", - "type": "CONDITIONING", - "link": 14278 - }, - { - "name": "negative", - "type": "CONDITIONING", - "link": 14279 - }, - { - "name": "sampler", - "type": "SAMPLER", - "link": 14486 - }, - { - "name": "sigmas", - "type": "SIGMAS", - "link": 14487 - }, - { - "name": "latent_image", - "type": "LATENT", - "link": 13963 - } - ], - "outputs": [ - { - "name": "output", - "type": "LATENT", - "links": [ - 13890 - ] - }, - { - "name": "denoised_output", - "type": "LATENT", - "links": null - } - ], - "title": "Sampler", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.3", - "Node name for S&R": "SamplerCustom" - }, - "widgets_values": [ - true, - 408211233755525, - "randomize", - 1 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5096, - "type": "FunPackHybridEuler2SSampler", - "pos": [ - -2692.7617900563005, - 3820.895095468243 - ], - "size": [ - 295.06974613407635, - 272.5589436984151 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": 14469 - } - ], - "outputs": [ - { - "name": "sampler", - "type": "SAMPLER", - "links": [ - 14486 - ] - }, - { - "name": "sigmas", - "type": "SIGMAS", - "links": [ - 14487 - ] - } - ], - "properties": { - "cnr_id": "funpack", - "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", - "Node name for S&R": "FunPackHybridEuler2SSampler", - "aux_id": "digital-garbage/ComfyUI-FunPack" - }, - "widgets_values": [ - 0, - 1.65, - 0.7, - 0.5, - "off", - 0.5, - 3, - 0.2, - 1 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5146, - "type": "953c68b0-c00f-4e16-ab59-39af7ce32097", - "pos": [ - -3501.053962071962, - 3484.3459461593543 - ], - "size": [ - 311.20648872536776, - 475.57454540880417 - ], - "flags": {}, - "order": 24, - "mode": 0, - "inputs": [ - { - "label": "positive_conditioning", - "name": "positive", - "type": "CONDITIONING", - "link": null - }, - { - "name": "frame_rate", - "type": "FLOAT", - "link": 14070 - }, - { - "name": "clip", - "type": "CLIP", - "link": 14071 - }, - { - "name": "model", - "type": "MODEL", - "link": 14427 - }, - { - "name": "vae", - "type": "VAE", - "link": 14073 - }, - { - "label": "positive_prompt", - "name": "text", - "type": "STRING", - "widget": { - "name": "text" - }, - "link": 14274 - }, - { - "name": "latent", - "type": "LATENT", - "link": 14348 - } - ], - "outputs": [ - { - "name": "positive", - "type": "CONDITIONING", - "links": [] - }, - { - "name": "negative", - "type": "CONDITIONING", - "links": [ - 14459 - ] - }, - { - "name": "model", - "type": "MODEL", - "links": [ - 14421, - 14422 - ] - } - ], - "properties": { - "proxyWidgets": [ - [ - "2483", - "text" - ] - ], - "cnr_id": "comfy-core", - "ver": "0.19.5" - }, - "widgets_values": [], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5229, - "type": "LTX2_NAG", - "pos": [ - -4049.362811312737, - 3096.7926698211413 - ], - "size": [ - 502.1137448018944, - 171.12950727397492 - ], - "flags": {}, - "order": 21, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "MODEL", - "link": 14426 - }, - { - "name": "nag_cond_video", - "shape": 7, - "type": "CONDITIONING", - "link": null - }, - { - "name": "nag_cond_audio", - "shape": 7, - "type": "CONDITIONING", - "link": null - } - ], - "outputs": [ - { - "name": "model", - "type": "MODEL", - "links": [ - 14427 - ] - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "9c3255f39cd2ea0ebf94a2016af4bd2e5d6eb91b", - "Node name for S&R": "LTX2_NAG" - }, - "widgets_values": [ - 11, - 0.275, - 2.35, - false - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5202, - "type": "ManualSigmas", - "pos": [ - -2386.3426826100235, - 4403.410245834443 - ], - "size": [ - 286.5405142205909, - 70.24154208314985 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "SIGMAS", - "type": "SIGMAS", - "links": [ - 14315, - 14483 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.14.1", - "Node name for S&R": "ManualSigmas" - }, - "widgets_values": [ - "0.909375, 0.725, 0.421875, 0.0" - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5196, - "type": "LatentUpscaleModelLoader", - "pos": [ - -2385.64321264596, - 4297.699280929902 - ], - "size": [ - 285.1080109057697, - 63.260013632212576 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "LATENT_UPSCALE_MODEL", - "type": "LATENT_UPSCALE_MODEL", - "links": [ - 14301 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "LatentUpscaleModelLoader" - }, - "widgets_values": [ - "ltx2_spatial_upscaler.safetensors" - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 5170, - "type": "KSamplerSelect", - "pos": [ - -2388.0095897749534, - 4194.947968470283 - ], - "size": [ - 286.83204362307833, - 63.61068120769323 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "SAMPLER", - "type": "SAMPLER", - "links": [ - 14482 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "KSamplerSelect" - }, - "widgets_values": [ - "euler_ancestral_cfg_pp" - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 5153, - "type": "PreviewAny", - "pos": [ - -2082.4801016069136, - 3102.538429670107 - ], - "size": [ - 839.175670995261, - 342.8519370213312 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "name": "source", - "type": "*", - "link": 14477 - } - ], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": null - } - ], - "title": "Training Info", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.19.5", - "Node name for S&R": "PreviewAny" - }, - "widgets_values": [ - null, - null, - null - ] - }, - { - "id": 5019, - "type": "VHS_VideoCombine", - "pos": [ - -1783.626263907655, - 3493.952642031969 - ], - "size": [ - 250, - 310 - ], - "flags": {}, - "order": 34, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 14011 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 14285 - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - }, - { - "name": "frame_rate", - "type": "FLOAT", - "widget": { - "name": "frame_rate" - }, - "link": 13450 - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "title": "Result", - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", - "Node name for S&R": "VHS_VideoCombine", - "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" - }, - "widgets_values": { - "frame_rate": 8, - "loop_count": 0, - "filename_prefix": "result_%date:MM-dd_hh-mm-ss%", - "format": "video/h265-mp4", - "pix_fmt": "yuv420p", - "crf": 20, - "save_metadata": true, - "pingpong": false, - "save_output": false, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "result_05-08_19-22-27_00001-audio.mp4", - "subfolder": "", - "type": "temp", - "format": "video/h265-mp4", - "frame_rate": 30, - "workflow": "result_05-08_19-22-27_00001.png", - "fullpath": "/workspace/ComfyUI/temp/result_05-08_19-22-27_00001-audio.mp4" - } - } - }, - "color": "#222", - "bgcolor": "#000" - }, - { - "id": 2004, - "type": "LoadImage", - "pos": [ - -4386.235372913527, - 4036.898594725194 - ], - "size": [ - 280, - 315 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 11002, - 14062, - 14280 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": [] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "HHuFYC9bEAAd4f9.jpg", - "image" - ], - "color": "#232", - "bgcolor": "#353" - }, - { - "id": 5188, - "type": "c758fc63-b71c-43f2-b085-ded32443f756", - "pos": [ - -4049.591349938611, - 3313.186716870688 - ], - "size": [ - 505.0919753788826, - 121.53832647689296 - ], - "flags": { - "collapsed": false - }, - "order": 15, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 14280 - }, - { - "name": "prompt", - "type": "STRING", - "widget": { - "name": "prompt" - }, - "link": 14281 - } - ], - "outputs": [ - { - "name": "generated_text", - "type": "STRING", - "links": [ - 14282, - 14474, - 14492 - ] - } - ], - "properties": { - "proxyWidgets": [ - [ - "5215", - "prompt" - ], - [ - "5185", - "seed" - ] - ], - "cnr_id": "comfy-core", - "ver": "0.20.1" - }, - "widgets_values": [], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5238, - "type": "FunPackApplyLoraWeights", - "pos": [ - -4862.610875119302, - 3471.8420845911883 - ], - "size": [ - 434.32223485180293, - 474 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "refinement_key_input", - "shape": 7, - "type": "STRING", - "link": null - }, - { - "name": "positive_prompt", - "type": "STRING", - "widget": { - "name": "positive_prompt" - }, - "link": 14492 - }, - { - "name": "refinement_key", - "type": "STRING", - "widget": { - "name": "refinement_key" - }, - "link": 14497 - } - ], - "outputs": [ - { - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "links": [ - 14489, - 14490 - ] - }, - { - "name": "status", - "type": "STRING", - "links": [ - 14491 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-FunPack", - "ver": "02e89ebd36208f6f5c0d7780f89f7dcdc040b1f1", - "Node name for S&R": "FunPackApplyLoraWeights" - }, - "widgets_values": [ - "", - "my_style_v1", - "ltx2", - true, - "[]", - {}, - { - "on": true, - "lora": "None", - "type": "general", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "action", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "style", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "quality", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "character", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "general", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "action", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "style", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "quality", - "strength": 1 - }, - { - "on": true, - "lora": "None", - "type": "character", - "strength": 1 - }, - "" - ] - }, - { - "id": 5150, - "type": "MarkdownNote", - "pos": [ - -4874.5803841744955, - 4030.3082654487844 - ], - "size": [ - 457.2957979656867, - 322.28010914237484 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "This is an example workflow, finetuned for LTX2.3 video model, using FunPack nodes to enhance and correct the results, tweaking them according to user's preferences.\n\nVideo Refiner V2 node learns from your ratings and feedback to provide the best result much more consistently than a base model does.\n\nThis workflow DOES NOT make model learn concepts it were never aware of. It only finetunes conditioning to match what YOU like as user, however it can't introduce knowledge that was never a part of a model.\n\nThis example workflow is actively using subgraphs to compact the space it takes, providing much more neat and clear workspace.\n\nIf you have any feedback or you found a bug or you have problems with using my nodes, feel free to file an issue on Github:\n\nhttps://github.com/digital-garbage/ComfyUI-FunPack\n\nPlease make sure you are reporting issues while using \"main\" branch of the repo. Issues with \"dev\" branch will not be reviewed unless they are critical bugs, breaking workflow fully." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5149, - "type": "MarkdownNote", - "pos": [ - -3162.082761220368, - 4004.8511204429938 - ], - "size": [ - 442.2702587922827, - 287.96370570528234 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Refiner V2 Quick Guide\n\nFunPack Video Refiner V2 is a prompt memory node. It takes your positive prompt, encodes it through the connected CLIP, remembers how you rated the previous output, and slowly learns which actions, camera moves, details, quality cues, and style cues work for your workflows.\n\nIt does not look at the finished video pixels. It does not magically know what is inside your input image. It does not replace clear prompting. In image-to-video, it now treats character appearance, clothing, subject identity, and background as image-owned by default, so it should not inject old remembered outfits or characters into a new image unless you explicitly prompt them.\n\nHow To Use It\n\n Add FunPack Video Refiner V2 before your sampler where positive conditioning is encoded.\n Connect your CLIP.\n Type a refinement_key, or use FunPack Refinement Key Loader and connect its output into refinement_key_input.\n First run only seeds memory. Generate once, look at the result, then rate that result on the next run with the same key.\n Use Perfect when the output is good and should be remembered.\n Use Missing action when the requested motion did not happen.\n Use Missing details when small non-identity details are weak, like smoke, reflections, particles, hand contact, object interaction, or secondary motion.\n Use Missing quality when the idea is right but the result is messy or ugly.\n Use Wrong action, Wrong details, or Wrong details + action when the video looks usable but did the wrong thing.\n Use Wrong appearance when Refiner/Lucky brought in unwanted clothing, face, body, character, subject, or background memory.\n Use -Just forget it- for broken runs, bad seeds, workflow mistakes, model failures, or anything you do not want learned.\n\nLucky Mode\n\nI'm Feeling Lucky composes a prompt from learned memory. It is useful when you want the node to suggest motion, camera, detail, quality, or style ideas from previous liked outputs.\n\nLucky should not auto-add remembered outfits, character traits, subjects, or backgrounds anymore. If you want an appearance item, write it directly in the prompt.\nExamples\n\nIf your prompt says person smoking and exhaling smoke but the video only shows a puff with no exhale, rate Missing details or Missing action, depending on what matters most. This teaches the key that smoke/exhale matters in that prompt context, without globally banning smoking.\n\nIf you liked white tights in older prompts but your new input image is only a portrait face, and Lucky tries to bring tights into the scene, rate Wrong appearance. That tells Refiner to suppress that appearance memory from auto-injection while still allowing white tights when you explicitly type it.\n\nIf the camera should push in, orbit, pan, or change framing and it stays static, rate Missing action or Wrong action. Camera movement belongs to the action/camera side of memory, so it remains safe for repair and Lucky.\nKey Loader\n\nUse FunPack Refinement Key Loader when you want a reusable key dropdown or want to move keys between workflows/machines. Its Import and Export buttons save/load the key as JSON. Connect the loader to both Refiner V2 and FunPack Apply LoRA Weights so LoRA suggestions and prompt memory use the same key." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5237, - "type": "FunPackVideoRefinerV2", - "pos": [ - -3163.670871437389, - 3484.6075129967685 - ], - "size": [ - 450.56804065586994, - 475.2209928759157 - ], - "flags": {}, - "order": 22, - "mode": 0, - "inputs": [ - { - "name": "clip", - "type": "CLIP", - "link": 14472 - }, - { - "name": "lora_stack", - "shape": 7, - "type": "FUNPACK_LORA_STACK", - "link": 14490 - }, - { - "name": "refinement_key_input", - "shape": 7, - "type": "STRING", - "link": 14494 - }, - { - "name": "positive_prompt", - "type": "STRING", - "widget": { - "name": "positive_prompt" - }, - "link": 14474 - }, - { - "name": "user_intent_prompt", - "shape": 7, - "type": "STRING", - "widget": { - "name": "user_intent_prompt" - }, - "link": 14496 - } - ], - "outputs": [ - { - "name": "modified_positive", - "type": "CONDITIONING", - "links": [ - 14473 - ] - }, - { - "name": "status", - "type": "STRING", - "links": [ - 14476 - ] - }, - { - "name": "training_info", - "type": "STRING", - "links": [ - 14477 - ] - }, - { - "name": "loss_graph", - "type": "IMAGE", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-FunPack", - "ver": "e4c65fc2e2dca771e15e0b0f0c20044212870a05", - "Node name for S&R": "FunPackVideoRefinerV2" - }, - "widgets_values": [ - "", - "Wrong details", - 1, - "randomize", - false, - false, - false - ] - }, - { - "id": 5012, - "type": "PrimitiveStringMultiline", - "pos": [ - -4055.4304375982783, - 3481.1266355613766 - ], - "size": [ - 520, - 260 - ], - "flags": { - "collapsed": false - }, - "order": 10, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": [ - 14281, - 14496 - ] - } - ], - "title": "Positive Prompt", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.18.2", - "Node name for S&R": "PrimitiveStringMultiline" - }, - "widgets_values": [ - "Put your original prompt that will be enhanced with prompt enhancer here, or disable the enhancer and connect this to \"positive_prompt\" input of Refiner." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5239, - "type": "FunPackRefinementKeyLoader", - "pos": [ - -3505.5938785840517, - 4049.7856350297743 - ], - "size": [ - 314.7000030517578, - 204 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "refinement_key", - "type": "STRING", - "links": [ - 14494, - 14497 - ] - }, - { - "name": "status", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-FunPack", - "ver": "b5a875a2609e21f19c08e5951e72af2db220cb5c", - "Node name for S&R": "FunPackRefinementKeyLoader" - }, - "widgets_values": [ - "ltx23_example", - "", - true, - "", - "", - "" - ] - }, - { - "id": 5143, - "type": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", - "pos": [ - -4387.679665836049, - 3474.1287636541992 - ], - "size": [ - 279.2243457043487, - 513.7727601710899 - ], - "flags": {}, - "order": 18, - "mode": 0, - "inputs": [ - { - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "link": 14489 - } - ], - "outputs": [ - { - "label": "audio_vae", - "name": "VAE", - "type": "VAE", - "links": [ - 14051, - 14061, - 14308 - ] - }, - { - "label": "fast_vae", - "name": "VAE_1", - "type": "VAE", - "links": [ - 14073 - ] - }, - { - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "links": [] - }, - { - "label": "video_vae", - "name": "VAE_2", - "type": "VAE", - "links": [ - 14055, - 14060, - 14300, - 14309, - 14325 - ] - }, - { - "label": "LTXV_model", - "name": "model", - "type": "MODEL", - "links": [ - 14426 - ] - }, - { - "name": "CLIP", - "type": "CLIP", - "links": [ - 14071, - 14472 - ] - }, - { - "name": "latent_downscale_factor", - "type": "FLOAT", - "links": [] - }, - { - "label": "lora_loader_status", - "name": "status", - "type": "STRING", - "links": [] - } - ], - "properties": { - "proxyWidgets": [], - "cnr_id": "comfy-core", - "ver": "0.19.5" - }, - "widgets_values": [], - "color": "#223", - "bgcolor": "#335" - } - ], - "links": [ - [ - 11002, - 2004, - 0, - 2653, - 0, - "IMAGE" - ], - [ - 13450, - 4989, - 0, - 5019, - 4, - "FLOAT" - ], - [ - 13455, - 4845, - 1, - 5021, - 0, - "LATENT" - ], - [ - 13890, - 5101, - 0, - 4845, - 0, - "LATENT" - ], - [ - 13963, - 4528, - 0, - 5101, - 5, - "LATENT" - ], - [ - 14011, - 5020, - 0, - 5019, - 0, - "IMAGE" - ], - [ - 14051, - 5143, - 0, - 5021, - 1, - "VAE" - ], - [ - 14055, - 5143, - 3, - 5020, - 0, - "VAE" - ], - [ - 14059, - 4988, - 0, - 5144, - 0, - "INT" - ], - [ - 14060, - 5143, - 3, - 5144, - 1, - "VAE" - ], - [ - 14061, - 5143, - 0, - 5144, - 2, - "VAE" - ], - [ - 14062, - 2004, - 0, - 5144, - 3, - "IMAGE" - ], - [ - 14064, - 5144, - 1, - 4528, - 1, - "LATENT" - ], - [ - 14066, - 4989, - 0, - 5145, - 0, - "FLOAT" - ], - [ - 14067, - 5145, - 0, - 5144, - 4, - "INT" - ], - [ - 14070, - 4989, - 0, - 5146, - 1, - "FLOAT" - ], - [ - 14071, - 5143, - 5, - 5146, - 2, - "CLIP" - ], - [ - 14073, - 5143, - 1, - 5146, - 4, - "VAE" - ], - [ - 14088, - 4989, - 0, - 5147, - 2, - "FLOAT" - ], - [ - 14274, - 5177, - 0, - 5146, - 5, - "STRING" - ], - [ - 14278, - 5147, - 0, - 5101, - 1, - "CONDITIONING" - ], - [ - 14279, - 5147, - 1, - 5101, - 2, - "CONDITIONING" - ], - [ - 14280, - 2004, - 0, - 5188, - 0, - "IMAGE" - ], - [ - 14281, - 5012, - 0, - 5188, - 1, - "STRING" - ], - [ - 14282, - 5188, - 0, - 5177, - 0, - "STRING" - ], - [ - 14285, - 5021, - 0, - 5019, - 1, - "AUDIO" - ], - [ - 14297, - 5195, - 0, - 5193, - 5, - "LATENT" - ], - [ - 14298, - 4845, - 0, - 5192, - 0, - "LATENT" - ], - [ - 14300, - 5143, - 3, - 5192, - 2, - "VAE" - ], - [ - 14301, - 5196, - 0, - 5192, - 1, - "LATENT_UPSCALE_MODEL" - ], - [ - 14302, - 4845, - 1, - 5195, - 1, - "LATENT" - ], - [ - 14303, - 5193, - 0, - 5198, - 0, - "LATENT" - ], - [ - 14304, - 5198, - 0, - 5199, - 1, - "LATENT" - ], - [ - 14305, - 5199, - 0, - 5197, - 0, - "IMAGE" - ], - [ - 14306, - 5198, - 1, - 5200, - 0, - "LATENT" - ], - [ - 14308, - 5143, - 0, - 5200, - 1, - "VAE" - ], - [ - 14309, - 5143, - 3, - 5199, - 0, - "VAE" - ], - [ - 14315, - 5202, - 0, - 5201, - 0, - "SIGMAS" - ], - [ - 14317, - 5147, - 0, - 5193, - 1, - "CONDITIONING" - ], - [ - 14318, - 5147, - 1, - 5193, - 2, - "CONDITIONING" - ], - [ - 14323, - 5192, - 0, - 5205, - 2, - "LATENT" - ], - [ - 14324, - 5205, - 0, - 5195, - 0, - "LATENT" - ], - [ - 14325, - 5143, - 3, - 5205, - 0, - "VAE" - ], - [ - 14326, - 5144, - 2, - 5205, - 1, - "IMAGE" - ], - [ - 14331, - 4989, - 0, - 5197, - 4, - "FLOAT" - ], - [ - 14348, - 5144, - 3, - 5146, - 6, - "LATENT" - ], - [ - 14421, - 5146, - 2, - 5101, - 0, - "MODEL" - ], - [ - 14422, - 5146, - 2, - 5193, - 0, - "MODEL" - ], - [ - 14426, - 5143, - 4, - 5229, - 0, - "MODEL" - ], - [ - 14427, - 5229, - 0, - 5146, - 3, - "MODEL" - ], - [ - 14450, - 5200, - 0, - 5234, - 0, - "AUDIO" - ], - [ - 14451, - 5234, - 0, - 5197, - 1, - "AUDIO" - ], - [ - 14459, - 5146, - 1, - 5147, - 1, - "CONDITIONING" - ], - [ - 14460, - 5144, - 0, - 4528, - 0, - "LATENT" - ], - [ - 14469, - 5050, - 0, - 5096, - 0, - "SIGMAS" - ], - [ - 14472, - 5143, - 5, - 5237, - 0, - "CLIP" - ], - [ - 14473, - 5237, - 0, - 5147, - 0, - "CONDITIONING" - ], - [ - 14474, - 5188, - 0, - 5237, - 3, - "STRING" - ], - [ - 14476, - 5237, - 1, - 5232, - 0, - "STRING" - ], - [ - 14477, - 5237, - 2, - 5153, - 0, - "STRING" - ], - [ - 14480, - 4845, - 0, - 5020, - 1, - "LATENT" - ], - [ - 14482, - 5170, - 0, - 5193, - 3, - "SAMPLER" - ], - [ - 14483, - 5202, - 0, - 5193, - 4, - "SIGMAS" - ], - [ - 14486, - 5096, - 0, - 5101, - 3, - "SAMPLER" - ], - [ - 14487, - 5096, - 1, - 5101, - 4, - "SIGMAS" - ], - [ - 14489, - 5238, - 0, - 5143, - 0, - "FUNPACK_LORA_STACK" - ], - [ - 14490, - 5238, - 0, - 5237, - 1, - "FUNPACK_LORA_STACK" - ], - [ - 14491, - 5238, - 1, - 5168, - 0, - "STRING" - ], - [ - 14492, - 5188, - 0, - 5238, - 1, - "STRING" - ], - [ - 14494, - 5239, - 0, - 5237, - 2, - "STRING" - ], - [ - 14496, - 5012, - 0, - 5237, - 4, - "STRING" - ], - [ - 14497, - 5239, - 0, - 5238, - 2, - "STRING" - ] - ], - "groups": [], - "definitions": { - "subgraphs": [ - { - "id": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", - "version": 1, - "state": { - "lastGroupId": 151, - "lastNodeId": 5239, - "lastLinkId": 14498, - "lastRerouteId": 57 - }, - "revision": 0, - "config": {}, - "name": "Model Loaders", - "inputNode": { - "id": -10, - "bounding": [ - -4325.009559761858, - 4005.266954142581, - 120, - 60 - ] - }, - "outputNode": { - "id": -20, - "bounding": [ - -3434.4839648526677, - 3955.266954142581, - 176.96665954589844, - 200 - ] - }, - "inputs": [ - { - "id": "d0987976-3ded-4b5e-8cbb-bf7a8f81e33a", - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "linkIds": [ - 14026 - ], - "localized_name": "lora_stack", - "pos": [ - -4225.009559761858, - 4025.266954142581 - ] - } - ], - "outputs": [ - { - "id": "5698eb50-25b5-43c3-bc6d-5ae6ed37cc69", - "name": "VAE", - "type": "VAE", - "linkIds": [ - 13426, - 13426 - ], - "localized_name": "VAE", - "label": "audio_vae", - "pos": [ - -3414.4839648526677, - 3975.266954142581 - ] - }, - { - "id": "93aec5ab-7fdc-4e97-8030-9b93ccb135f7", - "name": "VAE_1", - "type": "VAE", - "linkIds": [ - 14032 - ], - "localized_name": "VAE_1", - "label": "fast_vae", - "pos": [ - -3414.4839648526677, - 3995.266954142581 - ] - }, - { - "id": "23e2004b-5760-4651-9808-e4759172761e", - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "linkIds": [ - 13861 - ], - "localized_name": "lora_stack", - "pos": [ - -3414.4839648526677, - 4015.266954142581 - ] - }, - { - "id": "c70376ed-0ba0-4de8-8c69-d0b2e0f98c94", - "name": "VAE_2", - "type": "VAE", - "linkIds": [ - 13428, - 13428 - ], - "localized_name": "VAE_2", - "label": "video_vae", - "pos": [ - -3414.4839648526677, - 4035.266954142581 - ] - }, - { - "id": "d7031e7e-1171-43c2-9dd4-b1ea12834bbc", - "name": "model", - "type": "MODEL", - "linkIds": [ - 14418 - ], - "localized_name": "model", - "label": "LTXV_model", - "pos": [ - -3414.4839648526677, - 4055.266954142581 - ] - }, - { - "id": "3024b60b-1ea8-474c-91cd-85317f7a67a3", - "name": "CLIP", - "type": "CLIP", - "linkIds": [ - 13435, - 13435 - ], - "localized_name": "CLIP", - "pos": [ - -3414.4839648526677, - 4075.266954142581 - ] - }, - { - "id": "b5fb5099-9092-44f9-bacc-690a2860aa29", - "name": "latent_downscale_factor", - "type": "FLOAT", - "linkIds": [], - "pos": [ - -3414.4839648526677, - 4095.266954142581 - ] - }, - { - "id": "cfe9f2c2-261d-43b8-8591-00161f7bd393", - "name": "status", - "type": "STRING", - "linkIds": [ - 14188 - ], - "label": "lora_loader_status", - "pos": [ - -3414.4839648526677, - 4115.266954142581 - ] - } - ], - "widgets": [], - "nodes": [ - { - "id": 5104, - "type": "FunPackLoraLoader", - "pos": [ - -3840.6243036178707, - 3669.1897293353245 - ], - "size": [ - 230, - 90 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 13916 - }, - { - "localized_name": "lora_stack", - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "link": 14026 - }, - { - "localized_name": "clip", - "name": "clip", - "shape": 7, - "type": "CLIP", - "link": null - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": [ - 14320 - ] - }, - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": null - }, - { - "localized_name": "lora_stack", - "name": "lora_stack", - "type": "FUNPACK_LORA_STACK", - "links": [ - 13861 - ] - }, - { - "localized_name": "status", - "name": "status", - "type": "STRING", - "links": [ - 14188 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-FunPack", - "ver": "707e27279e2be733a5d787496742848bc745c258", - "Node name for S&R": "FunPackLoraLoader", - "aux_id": "digital-garbage/ComfyUI-FunPack" - }, - "widgets_values": [] - }, - { - "id": 5004, - "type": "VAELoaderKJ", - "pos": [ - -4142.837082457477, - 3661.3251095596834 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "VAE", - "name": "VAE", - "type": "VAE", - "links": [ - 13428 - ] - } - ], - "title": "Load Video VAE", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "VAELoaderKJ", - "aux_id": "kijai/ComfyUI-KJNodes" - }, - "widgets_values": [ - "ltx2_video_vae.safetensors", - "main_device", - "fp32" - ] - }, - { - "id": 5003, - "type": "VAELoaderKJ", - "pos": [ - -4145.009559761858, - 3815.5795641379827 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "VAE", - "name": "VAE", - "type": "VAE", - "links": [ - 13426 - ] - } - ], - "title": "Load Audio VAE", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "VAELoaderKJ", - "aux_id": "kijai/ComfyUI-KJNodes" - }, - "widgets_values": [ - "ltx2_audio_vae.safetensors", - "main_device", - "fp32" - ] - }, - { - "id": 5017, - "type": "VAELoaderKJ", - "pos": [ - -4143.886540579375, - 3967.8256025029505 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "VAE", - "name": "VAE", - "type": "VAE", - "links": [ - 14032 - ] - } - ], - "title": "Load Preview VAE", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "VAELoaderKJ", - "aux_id": "kijai/ComfyUI-KJNodes" - }, - "widgets_values": [ - "taeltx2_3.safetensors", - "main_device", - "fp32" - ] - }, - { - "id": 5006, - "type": "DualCLIPLoader", - "pos": [ - -3835.5303844223104, - 3814.768391164597 - ], - "size": [ - 270, - 130 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": [ - 13435 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.18.2", - "Node name for S&R": "DualCLIPLoader" - }, - "widgets_values": [ - "gemma.safetensors", - "ltx2_embeddings_connector.safetensors", - "ltxv", - "default" - ] - }, - { - "id": 5002, - "type": "DiffusionModelLoaderKJ", - "pos": [ - -4141.903414758422, - 4121.852190133855 - ], - "size": [ - 312.06666564941406, - 178 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [ - { - "localized_name": "extra_state_dict", - "name": "extra_state_dict", - "shape": 7, - "type": "STRING", - "link": null - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": [ - 13916 - ] - } - ], - "title": "Load LTX-2.3 Diffusion Model", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "DiffusionModelLoaderKJ", - "aux_id": "kijai/ComfyUI-KJNodes" - }, - "widgets_values": [ - "ltx2.safetensors", - "bf16", - "bf16", - false, - "disabled", - false - ] - }, - { - "id": 5204, - "type": "LTX2LoraLoaderAdvanced", - "pos": [ - -3821.7206559166707, - 4361.663434778751 - ], - "size": [ - 293.59999694824216, - 242 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 14401 - }, - { - "localized_name": "opt_lora_path", - "name": "opt_lora_path", - "shape": 7, - "type": "STRING", - "link": null - }, - { - "localized_name": "blocks", - "name": "blocks", - "shape": 7, - "type": "SELECTEDDITBLOCKS", - "link": null - } - ], - "outputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "links": [ - 14498 - ] - }, - { - "localized_name": "rank", - "name": "rank", - "type": "STRING", - "links": null - }, - { - "localized_name": "loaded_keys_info", - "name": "loaded_keys_info", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", - "Node name for S&R": "LTX2LoraLoaderAdvanced" - }, - "widgets_values": [ - "distilled_72.safetensors", - 0.75, - 0, - 1, - 1, - 1, - 1 - ] - }, - { - "id": 5203, - "type": "LTX2LoraLoaderAdvanced", - "pos": [ - -4137.706720274676, - 4359.203995818316 - ], - "size": [ - 293.59999694824216, - 242 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 14320 - }, - { - "localized_name": "opt_lora_path", - "name": "opt_lora_path", - "shape": 7, - "type": "STRING", - "link": null - }, - { - "localized_name": "blocks", - "name": "blocks", - "shape": 7, - "type": "SELECTEDDITBLOCKS", - "link": null - } - ], - "outputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "links": [ - 14401 - ] - }, - { - "localized_name": "rank", - "name": "rank", - "type": "STRING", - "links": null - }, - { - "localized_name": "loaded_keys_info", - "name": "loaded_keys_info", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", - "Node name for S&R": "LTX2LoraLoaderAdvanced" - }, - "widgets_values": [ - "distilled_72.safetensors", - 0.48, - 1, - 0, - 0, - 0, - 1 - ] - }, - { - "id": 5225, - "type": "FunPackContextTransitionWindows", - "pos": [ - -3499.400882804922, - 4203.790940060165 - ], - "size": [ - 346.26666870117185, - 394 - ], - "flags": {}, - "order": 8, - "mode": 4, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 14498 - } - ], - "outputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "links": [ - 14418 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-FunPack", - "ver": "ace940fed3f7f2724f784b8d3165871a4e027281", - "Node name for S&R": "FunPackContextTransitionWindows" - }, - "widgets_values": [ - "balanced", - 241, - 73, - "standard_uniform", - "overlap-linear", - 0, - 0, - 4, - 0.2, - 1, - 1, - false, - true, - "", - false - ] - } - ], - "groups": [], - "links": [ - { - "id": 13916, - "origin_id": 5002, - "origin_slot": 0, - "target_id": 5104, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 14026, - "origin_id": -10, - "origin_slot": 0, - "target_id": 5104, - "target_slot": 1, - "type": "FUNPACK_LORA_STACK" - }, - { - "id": 13426, - "origin_id": 5003, - "origin_slot": 0, - "target_id": -20, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 14032, - "origin_id": 5017, - "origin_slot": 0, - "target_id": -20, - "target_slot": 1, - "type": "VAE" - }, - { - "id": 13861, - "origin_id": 5104, - "origin_slot": 2, - "target_id": -20, - "target_slot": 2, - "type": "FUNPACK_LORA_STACK" - }, - { - "id": 13428, - "origin_id": 5004, - "origin_slot": 0, - "target_id": -20, - "target_slot": 3, - "type": "VAE" - }, - { - "id": 13435, - "origin_id": 5006, - "origin_slot": 0, - "target_id": -20, - "target_slot": 5, - "type": "CLIP" - }, - { - "id": 14188, - "origin_id": 5104, - "origin_slot": 3, - "target_id": -20, - "target_slot": 7, - "type": "STRING" - }, - { - "id": 14320, - "origin_id": 5104, - "origin_slot": 0, - "target_id": 5203, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 14401, - "origin_id": 5203, - "origin_slot": 0, - "target_id": 5204, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 14418, - "origin_id": 5225, - "origin_slot": 0, - "target_id": -20, - "target_slot": 4, - "type": "MODEL" - }, - { - "id": 14498, - "origin_id": 5204, - "origin_slot": 0, - "target_id": 5225, - "target_slot": 0, - "type": "MODEL" - } - ], - "extra": {} - }, - { - "id": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", - "version": 1, - "state": { - "lastGroupId": 151, - "lastNodeId": 5239, - "lastLinkId": 14498, - "lastRerouteId": 57 - }, - "revision": 0, - "config": {}, - "name": "Image Processing", - "inputNode": { - "id": -10, - "bounding": [ - -4230.013931822186, - 4280.664648566482, - 120, - 180 - ] - }, - "outputNode": { - "id": -20, - "bounding": [ - -3392.3462803758225, - 4300.664648566482, - 120, - 140 - ] - }, - "inputs": [ - { - "id": "0cd8eafb-4599-4caf-8fc4-30f63acf3cd8", - "name": "length", - "type": "INT", - "linkIds": [ - 13389, - 13390 - ], - "localized_name": "length", - "pos": [ - -4130.013931822186, - 4300.664648566482 - ] - }, - { - "id": "45f7e533-25b2-4795-acd6-5dc96f4e70d5", - "name": "vae", - "type": "VAE", - "linkIds": [ - 14054, - 14327, - 14351 - ], - "localized_name": "vae", - "pos": [ - -4130.013931822186, - 4320.664648566482 - ] - }, - { - "id": "e7b3fa68-1694-4761-a92b-f9cf55c8b0d7", - "name": "audio_vae", - "type": "VAE", - "linkIds": [ - 14050 - ], - "localized_name": "audio_vae", - "pos": [ - -4130.013931822186, - 4340.664648566482 - ] - }, - { - "id": "5a5c6f1b-489a-4eff-95cc-ee5d159310eb", - "name": "image", - "type": "IMAGE,MASK", - "linkIds": [ - 13474 - ], - "localized_name": "image", - "pos": [ - -4130.013931822186, - 4360.664648566482 - ] - }, - { - "id": "9b785d25-1e6c-4255-bb3c-97aaf621afe2", - "name": "frame_rate", - "type": "INT", - "linkIds": [ - 14065 - ], - "pos": [ - -4130.013931822186, - 4380.664648566482 - ] - }, - { - "id": "6db1bac4-138a-4b8b-90bf-3961f84d84a3", - "name": "target_width", - "type": "INT", - "linkIds": [ - 14081, - 14389 - ], - "pos": [ - -4130.013931822186, - 4400.664648566482 - ] - }, - { - "id": "0cd2e965-8222-4162-b16f-d204a10034f4", - "name": "target_height", - "type": "INT", - "linkIds": [ - 14082, - 14390 - ], - "pos": [ - -4130.013931822186, - 4420.664648566482 - ] - } - ], - "outputs": [ - { - "id": "42905067-8a71-4026-b386-cdbcbbf428d6", - "name": "latent", - "type": "LATENT", - "linkIds": [ - 14353 - ], - "localized_name": "latent", - "label": "video_latent", - "pos": [ - -3372.3462803758225, - 4320.664648566482 - ] - }, - { - "id": "832cd750-af0e-4127-b7e0-9e7d87efa173", - "name": "Latent", - "type": "LATENT", - "linkIds": [ - 13696 - ], - "localized_name": "Latent", - "label": "audio_latent", - "pos": [ - -3372.3462803758225, - 4340.664648566482 - ] - }, - { - "id": "70c112e1-3f52-4d3e-bff3-43133fe0f5a9", - "name": "output_image", - "type": "IMAGE", - "linkIds": [ - 14149 - ], - "pos": [ - -3372.3462803758225, - 4360.664648566482 - ] - }, - { - "id": "75faa65c-faad-46bc-bf59-05203952150a", - "name": "LATENT", - "type": "LATENT", - "linkIds": [ - 14349 - ], - "pos": [ - -3372.3462803758225, - 4380.664648566482 - ] - }, - { - "id": "136987d9-e5df-4234-88a8-f34dcf46a64c", - "name": "output", - "type": "IMAGE", - "linkIds": [ - 14391 - ], - "label": "plain_black", - "pos": [ - -3372.3462803758225, - 4400.664648566482 - ] - } - ], - "widgets": [], - "nodes": [ - { - "id": 3980, - "type": "LTXVEmptyLatentAudio", - "pos": [ - -3752.2385283541353, - 4421.631082925247 - ], - "size": [ - 305.8394470214844, - 106 - ], - "flags": { - "collapsed": false - }, - "order": 4, - "mode": 0, - "inputs": [ - { - "localized_name": "audio_vae", - "name": "audio_vae", - "type": "VAE", - "link": 14050 - }, - { - "localized_name": "frames_number", - "name": "frames_number", - "type": "INT", - "widget": { - "name": "frames_number" - }, - "link": 13390 - }, - { - "localized_name": "frame_rate", - "name": "frame_rate", - "type": "INT", - "widget": { - "name": "frame_rate" - }, - "link": 14065 - } - ], - "outputs": [ - { - "localized_name": "Latent", - "name": "Latent", - "type": "LATENT", - "links": [ - 13696 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.64", - "Node name for S&R": "LTXVEmptyLatentAudio" - }, - "widgets_values": [ - 121, - 25, - 1 - ] - }, - { - "id": 3059, - "type": "EmptyLTXVLatentVideo", - "pos": [ - -4054.604251439193, - 4362.302545732084 - ], - "size": [ - 210, - 194 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [ - { - "localized_name": "width", - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 13478 - }, - { - "localized_name": "height", - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 13479 - }, - { - "localized_name": "length", - "name": "length", - "type": "INT", - "widget": { - "name": "length" - }, - "link": 13389 - } - ], - "outputs": [ - { - "localized_name": "LATENT", - "name": "LATENT", - "type": "LATENT", - "links": [ - 11401, - 14329 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.43", - "Node name for S&R": "EmptyLTXVLatentVideo" - }, - "widgets_values": [ - 512, - 768, - 121, - 1 - ] - }, - { - "id": 5212, - "type": "VAEEncode", - "pos": [ - -3395.061084351483, - 4221.605231546082 - ], - "size": [ - 140, - 46 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "localized_name": "pixels", - "name": "pixels", - "type": "IMAGE", - "link": 14350 - }, - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 14351 - } - ], - "outputs": [ - { - "localized_name": "LATENT", - "name": "LATENT", - "type": "LATENT", - "links": [ - 14349 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "VAEEncode" - }, - "widgets_values": [] - }, - { - "id": 5220, - "type": "LoadImage", - "pos": [ - -4052.9158842937736, - 4610.945426788913 - ], - "size": [ - 282.7333297729492, - 314 - ], - "flags": {}, - "order": 0, - "mode": 4, - "inputs": [], - "outputs": [ - { - "localized_name": "IMAGE", - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 14388 - ] - }, - { - "localized_name": "MASK", - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "plain-black-mobile-background-uya4pitjl3vdmatx-1490018872.jpg", - "image" - ] - }, - { - "id": 5219, - "type": "ImageTransformKJ", - "pos": [ - -3749.590944998398, - 4574.8080683828575 - ], - "size": [ - 462, - 261 - ], - "flags": { - "collapsed": true - }, - "order": 8, - "mode": 0, - "inputs": [ - { - "localized_name": "image", - "name": "image", - "type": "IMAGE,MASK", - "link": 14388 - }, - { - "localized_name": "mask", - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "localized_name": "target_width", - "name": "target_width", - "type": "INT", - "widget": { - "name": "target_width" - }, - "link": 14389 - }, - { - "localized_name": "target_height", - "name": "target_height", - "type": "INT", - "widget": { - "name": "target_height" - }, - "link": 14390 - } - ], - "outputs": [ - { - "localized_name": "output", - "name": "output", - "type": "IMAGE", - "links": [ - 14391 - ] - }, - { - "localized_name": "output_mask", - "name": "output_mask", - "type": "MASK", - "links": null - }, - { - "color_off": "transparent", - "color_on": "transparent", - "label": " ", - "localized_name": "bbox", - "name": "bbox", - "shape": 6, - "type": "BBOX", - "links": null - }, - { - "color_off": "transparent", - "color_on": "transparent", - "label": " ", - "localized_name": "bbox_mask", - "name": "bbox_mask", - "shape": 6, - "type": "MASK", - "links": null - }, - { - "label": "768 width", - "localized_name": "width", - "name": "width", - "type": "INT", - "links": [] - }, - { - "label": "768 height", - "localized_name": "height", - "name": "height", - "type": "INT", - "links": [] - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "ImageTransformKJ", - "previewEnabled": true, - "showRotationCross": false, - "canvasSize": [ - 432, - 324 - ], - "aux_id": "kijai/ComfyUI-KJNodes", - "fillColor": "#000000", - "previewFile": "crop_preview_dd29a0.webp" - }, - "widgets_values": [ - 768, - 768, - "lanczos", - "keep_long_edge", - 16, - "disabled", - "disabled", - "{\"fillColor\":\"#000000\"}", - "" - ] - }, - { - "id": 3336, - "type": "LTXVPreprocess", - "pos": [ - -4051.7822649723703, - 4222.285074743058 - ], - "size": [ - 270, - 74 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 13864 - } - ], - "outputs": [ - { - "localized_name": "output_image", - "name": "output_image", - "type": "IMAGE", - "links": [ - 13865, - 14149, - 14328, - 14350 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.60", - "Node name for S&R": "LTXVPreprocess" - }, - "widgets_values": [ - 0 - ] - }, - { - "id": 5206, - "type": "LTXVImgToVideoInplace", - "pos": [ - -3747.668725148193, - 4054.017919247807 - ], - "size": [ - 270, - 122 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 14327 - }, - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 14328 - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "link": 14329 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [ - 14353 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "LTXVImgToVideoInplace" - }, - "widgets_values": [ - 0.7, - false - ] - }, - { - "id": 3159, - "type": "LTXVImgToVideoConditionOnly", - "pos": [ - -3756.874428105229, - 4233.494670882838 - ], - "size": [ - 315.26666870117185, - 142.859507731343 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 14054 - }, - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 13865 - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "link": 11401 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [] - } - ], - "properties": { - "cnr_id": "ComfyUI-LTXVideo", - "ver": "d43181d5723c1721692baef01d90cd1a825bba91", - "Node name for S&R": "LTXVImgToVideoConditionOnly", - "aux_id": "Lightricks/ComfyUI-LTXVideo" - }, - "widgets_values": [ - 0.7, - false - ] - }, - { - "id": 5031, - "type": "ImageTransformKJ", - "pos": [ - -4044.0432045178136, - 4176.011069650051 - ], - "size": [ - 520, - 261 - ], - "flags": { - "collapsed": true - }, - "order": 5, - "mode": 0, - "inputs": [ - { - "localized_name": "image", - "name": "image", - "type": "IMAGE,MASK", - "link": 13474 - }, - { - "localized_name": "mask", - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "localized_name": "target_width", - "name": "target_width", - "type": "INT", - "widget": { - "name": "target_width" - }, - "link": 14081 - }, - { - "localized_name": "target_height", - "name": "target_height", - "type": "INT", - "widget": { - "name": "target_height" - }, - "link": 14082 - } - ], - "outputs": [ - { - "localized_name": "output", - "name": "output", - "type": "IMAGE,MASK", - "links": [ - 13864 - ] - }, - { - "localized_name": "output_mask", - "name": "output_mask", - "type": "MASK", - "links": null - }, - { - "color_off": "transparent", - "color_on": "transparent", - "label": " ", - "localized_name": "bbox", - "name": "bbox", - "shape": 6, - "type": "BBOX", - "links": null - }, - { - "color_off": "transparent", - "color_on": "transparent", - "label": " ", - "localized_name": "bbox_mask", - "name": "bbox_mask", - "shape": 6, - "type": "MASK", - "links": null - }, - { - "label": "768 width", - "localized_name": "width", - "name": "width", - "type": "INT", - "links": [ - 13478 - ] - }, - { - "label": "768 height", - "localized_name": "height", - "name": "height", - "type": "INT", - "links": [ - 13479 - ] - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", - "Node name for S&R": "ImageTransformKJ", - "previewEnabled": true, - "showRotationCross": false, - "canvasSize": [ - 768, - 768 - ], - "aux_id": "kijai/ComfyUI-KJNodes", - "fillColor": "#000000" - }, - "widgets_values": [ - 768, - 768, - "lanczos", - "keep_long_edge", - 16, - "disabled", - "disabled", - "{\"fillColor\":\"#000000\"}", - "" - ] - } - ], - "groups": [], - "links": [ - { - "id": 13478, - "origin_id": 5031, - "origin_slot": 4, - "target_id": 3059, - "target_slot": 0, - "type": "INT" - }, - { - "id": 13479, - "origin_id": 5031, - "origin_slot": 5, - "target_id": 3059, - "target_slot": 1, - "type": "INT" - }, - { - "id": 13865, - "origin_id": 3336, - "origin_slot": 0, - "target_id": 3159, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 11401, - "origin_id": 3059, - "origin_slot": 0, - "target_id": 3159, - "target_slot": 2, - "type": "LATENT" - }, - { - "id": 13864, - "origin_id": 5031, - "origin_slot": 0, - "target_id": 3336, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 13389, - "origin_id": -10, - "origin_slot": 0, - "target_id": 3059, - "target_slot": 2, - "type": "INT" - }, - { - "id": 13390, - "origin_id": -10, - "origin_slot": 0, - "target_id": 3980, - "target_slot": 1, - "type": "INT" - }, - { - "id": 14054, - "origin_id": -10, - "origin_slot": 1, - "target_id": 3159, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 14050, - "origin_id": -10, - "origin_slot": 2, - "target_id": 3980, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 13474, - "origin_id": -10, - "origin_slot": 3, - "target_id": 5031, - "target_slot": 0, - "type": "IMAGE,MASK" - }, - { - "id": 13696, - "origin_id": 3980, - "origin_slot": 0, - "target_id": -20, - "target_slot": 1, - "type": "LATENT" - }, - { - "id": 14065, - "origin_id": -10, - "origin_slot": 4, - "target_id": 3980, - "target_slot": 2, - "type": "INT" - }, - { - "id": 14081, - "origin_id": -10, - "origin_slot": 5, - "target_id": 5031, - "target_slot": 2, - "type": "INT" - }, - { - "id": 14082, - "origin_id": -10, - "origin_slot": 6, - "target_id": 5031, - "target_slot": 3, - "type": "INT" - }, - { - "id": 14149, - "origin_id": 3336, - "origin_slot": 0, - "target_id": -20, - "target_slot": 2, - "type": "IMAGE" - }, - { - "id": 14327, - "origin_id": -10, - "origin_slot": 1, - "target_id": 5206, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 14328, - "origin_id": 3336, - "origin_slot": 0, - "target_id": 5206, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 14329, - "origin_id": 3059, - "origin_slot": 0, - "target_id": 5206, - "target_slot": 2, - "type": "LATENT" - }, - { - "id": 14349, - "origin_id": 5212, - "origin_slot": 0, - "target_id": -20, - "target_slot": 3, - "type": "LATENT" - }, - { - "id": 14350, - "origin_id": 3336, - "origin_slot": 0, - "target_id": 5212, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 14351, - "origin_id": -10, - "origin_slot": 1, - "target_id": 5212, - "target_slot": 1, - "type": "VAE" - }, - { - "id": 14353, - "origin_id": 5206, - "origin_slot": 0, - "target_id": -20, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 14388, - "origin_id": 5220, - "origin_slot": 0, - "target_id": 5219, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 14389, - "origin_id": -10, - "origin_slot": 5, - "target_id": 5219, - "target_slot": 2, - "type": "INT" - }, - { - "id": 14390, - "origin_id": -10, - "origin_slot": 6, - "target_id": 5219, - "target_slot": 3, - "type": "INT" - }, - { - "id": 14391, - "origin_id": 5219, - "origin_slot": 0, - "target_id": -20, - "target_slot": 4, - "type": "IMAGE" - } - ], - "extra": {} - }, - { - "id": "953c68b0-c00f-4e16-ab59-39af7ce32097", - "version": 1, - "state": { - "lastGroupId": 151, - "lastNodeId": 5239, - "lastLinkId": 14498, - "lastRerouteId": 57 - }, - "revision": 0, - "config": {}, - "name": "Conditioning Processing", - "inputNode": { - "id": -10, - "bounding": [ - -3757.4569530860326, - 3786.7967005388414, - 159.46666717529297, - 180 - ] - }, - "outputNode": { - "id": -20, - "bounding": [ - -2907.4297954820227, - 3784.52193989455, - 120, - 100 - ] - }, - "inputs": [ - { - "id": "738e10fc-b836-4774-9137-3c64dc6fd9b1", - "name": "positive", - "type": "CONDITIONING", - "linkIds": [], - "localized_name": "positive", - "label": "positive_conditioning", - "pos": [ - -3617.9902859107397, - 3806.7967005388414 - ] - }, - { - "id": "1f6995d2-3cab-4be6-bf4e-2289e22f7587", - "name": "frame_rate", - "type": "FLOAT", - "linkIds": [], - "localized_name": "frame_rate", - "pos": [ - -3617.9902859107397, - 3826.7967005388414 - ] - }, - { - "id": "3a835bc3-67a3-4315-9360-b111e3a5b8ff", - "name": "clip", - "type": "CLIP", - "linkIds": [ - 14058, - 14057 - ], - "localized_name": "clip", - "pos": [ - -3617.9902859107397, - 3846.7967005388414 - ] - }, - { - "id": "2e41c3e2-f8e8-4de3-a894-344e8eb5debe", - "name": "model", - "type": "MODEL", - "linkIds": [ - 14056 - ], - "localized_name": "model", - "pos": [ - -3617.9902859107397, - 3866.7967005388414 - ] - }, - { - "id": "915bfda1-7565-4cf7-bd69-90348a3b254c", - "name": "vae", - "type": "VAE", - "linkIds": [ - 14052 - ], - "localized_name": "vae", - "shape": 7, - "pos": [ - -3617.9902859107397, - 3886.7967005388414 - ] - }, - { - "id": "969bf9d4-eb1d-462c-8940-dbbf51b5a2d5", - "name": "text", - "type": "STRING", - "linkIds": [ - 14038 - ], - "localized_name": "text", - "label": "positive_prompt", - "pos": [ - -3617.9902859107397, - 3906.7967005388414 - ] - }, - { - "id": "b0c833ae-af25-43fd-9b03-7b6590ed2249", - "name": "latent", - "type": "LATENT", - "linkIds": [], - "pos": [ - -3617.9902859107397, - 3926.7967005388414 - ] - } - ], - "outputs": [ - { - "id": "8984305c-acc8-4330-bd25-5ed589aed5d9", - "name": "positive", - "type": "CONDITIONING", - "linkIds": [ - 14419 - ], - "localized_name": "positive", - "pos": [ - -2887.4297954820227, - 3804.52193989455 - ] - }, - { - "id": "87bdfca5-a3a4-4115-8cea-2ee314e7c57a", - "name": "negative", - "type": "CONDITIONING", - "linkIds": [ - 14155 - ], - "localized_name": "negative", - "pos": [ - -2887.4297954820227, - 3824.52193989455 - ] - }, - { - "id": "1cfeaf78-5049-4af9-957c-13da423761e3", - "name": "model", - "type": "MODEL", - "linkIds": [ - 14423 - ], - "localized_name": "model", - "pos": [ - -2887.4297954820227, - 3844.52193989455 - ] - } - ], - "widgets": [], - "nodes": [ - { - "id": 2483, - "type": "CLIPTextEncode", - "pos": [ - -3482.3123142591667, - 3729.764452009041 - ], - "size": [ - 330, - 130 - ], - "flags": { - "collapsed": false - }, - "order": 1, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 14057 - }, - { - "localized_name": "text", - "name": "text", - "type": "STRING", - "widget": { - "name": "text" - }, - "link": 14038 - } - ], - "outputs": [ - { - "localized_name": "CONDITIONING", - "name": "CONDITIONING", - "type": "CONDITIONING", - "slot_index": 0, - "links": [ - 14419 - ] - } - ], - "title": "CLIP Text Encode (Positive Prompt)", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.28", - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "High quality realistic video. A clean tabletop scene with a small glass sculpture, soft studio lighting, gentle camera movement, subtle reflections, natural shadows, and smooth motion. The camera slowly moves closer, then holds steady for a clear final view." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 2612, - "type": "CLIPTextEncode", - "pos": [ - -3482.2778641371956, - 4061.479555285701 - ], - "size": [ - 330, - 120 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 14058 - }, - { - "localized_name": "text", - "name": "text", - "type": "STRING", - "widget": { - "name": "text" - }, - "link": 13734 - } - ], - "outputs": [ - { - "localized_name": "CONDITIONING", - "name": "CONDITIONING", - "type": "CONDITIONING", - "slot_index": 0, - "links": [ - 14155 - ] - } - ], - "title": "CLIP Text Encode (Negative Prompt)", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.28", - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "low quality, blurry, distorted shapes, broken reflections, noisy shadows, overexposed highlights, undersaturated colors, bad anatomy, people, text, watermark, logo, subtitles, harsh flicker, still frame, frozen motion, frame blending artifacts, compression artifacts" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 5137, - "type": "LTX2SamplingPreviewOverride", - "pos": [ - -3481.404969237368, - 3904.2961431762487 - ], - "size": [ - 316.7000030517578, - 98 - ], - "flags": {}, - "order": 3, - "mode": 4, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 14056 - }, - { - "localized_name": "latent_upscale_model", - "name": "latent_upscale_model", - "shape": 7, - "type": "LATENT_UPSCALE_MODEL", - "link": null - }, - { - "localized_name": "vae", - "name": "vae", - "shape": 7, - "type": "VAE", - "link": 14052 - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": [ - 14423 - ] - } - ], - "title": "Sampling Preview Override", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "89dc2f8485e3fbedd549808b07ec20031cca6bf2", - "Node name for S&R": "LTX2SamplingPreviewOverride", - "aux_id": "kijai/ComfyUI-KJNodes" - }, - "widgets_values": [ - 8 - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 5081, - "type": "PrimitiveStringMultiline", - "pos": [ - -3487.4297954820227, - 3501.2832456967894 - ], - "size": [ - 520, - 180 - ], - "flags": { - "collapsed": false - }, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "STRING", - "name": "STRING", - "type": "STRING", - "links": [ - 13734 - ] - } - ], - "title": "Negative Prompt", - "properties": { - "cnr_id": "comfy-core", - "ver": "0.18.2", - "Node name for S&R": "PrimitiveStringMultiline" - }, - "widgets_values": [ - "music, underwater, diving, slow motion, photorealistic, photo, realistic, real life, stickers on nipples, disconnected limbs, disconnected genitals, chest pussy, tongue out, cone penis tip, still image, bad quality, subtitles, text, watermark, overlay, pc game, yelling, console game, childish, ugly, text, blur, logo, wordmark, static, low quality, noise, white noise, bleep, censoring, censor, bleeping, beep, beeping, newscast, interview, podcast, chinese, mutant, horror, 70's, film grain, comedy, stand-up " - ], - "color": "#432", - "bgcolor": "#653" - } - ], - "groups": [], - "links": [ - { - "id": 13734, - "origin_id": 5081, - "origin_slot": 0, - "target_id": 2612, - "target_slot": 1, - "type": "STRING" - }, - { - "id": 14058, - "origin_id": -10, - "origin_slot": 2, - "target_id": 2612, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 14057, - "origin_id": -10, - "origin_slot": 2, - "target_id": 2483, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 14056, - "origin_id": -10, - "origin_slot": 3, - "target_id": 5137, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 14052, - "origin_id": -10, - "origin_slot": 4, - "target_id": 5137, - "target_slot": 2, - "type": "VAE" - }, - { - "id": 14038, - "origin_id": -10, - "origin_slot": 5, - "target_id": 2483, - "target_slot": 1, - "type": "STRING" - }, - { - "id": 14155, - "origin_id": 2612, - "origin_slot": 0, - "target_id": -20, - "target_slot": 1, - "type": "CONDITIONING" - }, - { - "id": 14419, - "origin_id": 2483, - "origin_slot": 0, - "target_id": -20, - "target_slot": 0, - "type": "CONDITIONING" - }, - { - "id": 14423, - "origin_id": 5137, - "origin_slot": 0, - "target_id": -20, - "target_slot": 2, - "type": "MODEL" - } - ], - "extra": {} - }, - { - "id": "c758fc63-b71c-43f2-b085-ded32443f756", - "version": 1, - "state": { - "lastGroupId": 151, - "lastNodeId": 5239, - "lastLinkId": 14498, - "lastRerouteId": 57 - }, - "revision": 0, - "config": {}, - "name": "Enhancer", - "inputNode": { - "id": -10, - "bounding": [ - -4185.975620413162, - 2995.9229766057383, - 120, - 80 - ] - }, - "outputNode": { - "id": -20, - "bounding": [ - -3519.1490771969034, - 3006.5191220105444, - 124.5999984741211, - 60 - ] - }, - "inputs": [ - { - "id": "f3881fd2-d951-4f33-874c-a5cd7f3b1f7d", - "name": "image", - "type": "IMAGE", - "linkIds": [ - 14378, - 14478 - ], - "localized_name": "image", - "shape": 7, - "pos": [ - -4085.975620413162, - 3015.9229766057383 - ] - }, - { - "id": "0357b5d7-3e17-46f2-b7dc-62941f69b495", - "name": "prompt", - "type": "STRING", - "linkIds": [ - 14463 - ], - "localized_name": "prompt", - "pos": [ - -4085.975620413162, - 3035.9229766057383 - ] - } - ], - "outputs": [ - { - "id": "53386daa-e704-4fe0-b148-12f3a8138d5c", - "name": "generated_text", - "type": "STRING", - "linkIds": [ - 14481 - ], - "localized_name": "generated_text", - "pos": [ - -3499.1490771969034, - 3026.5191220105444 - ] - } - ], - "widgets": [], - "nodes": [ - { - "id": 5185, - "type": "CR Seed", - "pos": [ - -3933.9237459684864, - 2701.3944678867133 - ], - "size": [ - 270, - 102 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "seed", - "name": "seed", - "type": "INT", - "links": [ - 14361, - 14374 - ] - }, - { - "localized_name": "show_help", - "name": "show_help", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI_Comfyroll_CustomNodes", - "ver": "d78b780ae43fcf8c6b7c6505e6ffb4584281ceca", - "Node name for S&R": "CR Seed", - "aux_id": "Suzie1/ComfyUI_Comfyroll_CustomNodes" - }, - "widgets_values": [ - 856247973213084, - "randomize" - ] - }, - { - "id": 5183, - "type": "CLIPLoader", - "pos": [ - -3930.3935175132056, - 2863.217812048324 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": [ - 14377, - 14461 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "CLIPLoader" - }, - "widgets_values": [ - "sulphur_enhance.safetensors", - "stable_diffusion", - "default" - ] - }, - { - "id": 5187, - "type": "TextGenerateLTX2Prompt", - "pos": [ - -3974.8004741920977, - 3024.673944128882 - ], - "size": [ - 400, - 372 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 14461 - }, - { - "localized_name": "image", - "name": "image", - "shape": 7, - "type": "IMAGE", - "link": 14478 - }, - { - "localized_name": "seed", - "name": "sampling_mode.seed", - "type": "INT", - "widget": { - "name": "sampling_mode.seed" - }, - "link": 14374 - } - ], - "outputs": [ - { - "localized_name": "generated_text", - "name": "generated_text", - "type": "STRING", - "links": [] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "TextGenerateLTX2Prompt" - }, - "widgets_values": [ - "", - 2048, - "on", - 0.7, - 80, - 1, - 0.05, - 1.05, - 0, - 0, - false, - true - ] - }, - { - "id": 5215, - "type": "TextGenerate", - "pos": [ - -3975.3630377173627, - 3462.6441576677366 - ], - "size": [ - 400, - 372 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 14377 - }, - { - "localized_name": "image", - "name": "image", - "shape": 7, - "type": "IMAGE", - "link": 14378 - }, - { - "localized_name": "prompt", - "name": "prompt", - "type": "STRING", - "widget": { - "name": "prompt" - }, - "link": 14463 - }, - { - "localized_name": "seed", - "name": "sampling_mode.seed", - "type": "INT", - "widget": { - "name": "sampling_mode.seed" - }, - "link": 14361 - } - ], - "outputs": [ - { - "localized_name": "generated_text", - "name": "generated_text", - "type": "STRING", - "links": [ - 14481 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.20.1", - "Node name for S&R": "TextGenerate" - }, - "widgets_values": [ - "", - 2048, - "on", - 0.7, - 75, - 1, - 0.1, - 1.05, - 0, - 0, - false, - true - ] - } - ], - "groups": [], - "links": [ - { - "id": 14361, - "origin_id": 5185, - "origin_slot": 0, - "target_id": 5215, - "target_slot": 3, - "type": "INT" - }, - { - "id": 14374, - "origin_id": 5185, - "origin_slot": 0, - "target_id": 5187, - "target_slot": 2, - "type": "INT" - }, - { - "id": 14377, - "origin_id": 5183, - "origin_slot": 0, - "target_id": 5215, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 14378, - "origin_id": -10, - "origin_slot": 0, - "target_id": 5215, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 14461, - "origin_id": 5183, - "origin_slot": 0, - "target_id": 5187, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 14463, - "origin_id": -10, - "origin_slot": 1, - "target_id": 5215, - "target_slot": 2, - "type": "STRING" - }, - { - "id": 14478, - "origin_id": -10, - "origin_slot": 0, - "target_id": 5187, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 14481, - "origin_id": 5215, - "origin_slot": 0, - "target_id": -20, - "target_slot": 0, - "type": "STRING" - } - ], - "extra": {} - } - ] - }, - "config": {}, - "extra": { - "frontendVersion": "1.42.15", - "VHS_latentpreview": false, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true, - "workspace_info": { - "id": "elBQFQknIoLYTEwIloQuw" - }, - "node_versions": { - "comfy-core": "0.3.30", - "comfyui-kjnodes": "1.0.8" - }, - "workflowRendererVersion": "LG", - "reroutes": [ - { - "id": 23, - "pos": [ - -2470.7143821696213, - 3999.039532349397 - ], - "linkIds": [ - 13450 - ] - } - ], - "workflow_name": "LTX-2.3 FunPack Node Set Example", - "ds": { - "scale": 0.6651703961652539, - "offset": [ - 5358.842219457412, - -2858.662916099798 - ] - }, - "linkExtensions": [ - { - "id": 13450, - "parentId": 23 - } - ] - }, - "version": 0.4 -} \ No newline at end of file From a1dc431be5f2e70a0f6449b204f7200ef1591de3 Mon Sep 17 00:00:00 2001 From: DigitalGarbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 19:50:59 +0300 Subject: [PATCH 5/8] Add files via upload --- example_workflows/LTXFunPackRefinerV2.json | 5517 ++++++++++++++++++++ 1 file changed, 5517 insertions(+) create mode 100644 example_workflows/LTXFunPackRefinerV2.json diff --git a/example_workflows/LTXFunPackRefinerV2.json b/example_workflows/LTXFunPackRefinerV2.json new file mode 100644 index 00000000..52401337 --- /dev/null +++ b/example_workflows/LTXFunPackRefinerV2.json @@ -0,0 +1,5517 @@ +{ + "id": "5dccf3d1-6e5e-41c1-8320-bbd2abb95ebf", + "revision": 0, + "last_node_id": 5239, + "last_link_id": 14500, + "nodes": [ + { + "id": 5145, + "type": "LTXFloatToInt", + "pos": [ + -3507.5079864668505, + 4000.1459627992567 + ], + "size": [ + 270, + 58 + ], + "flags": { + "collapsed": true + }, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "a", + "type": "FLOAT", + "widget": { + "name": "a" + }, + "link": 14066 + } + ], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 14067 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "937831df0e5e1f707340b7e037a52e9d1196e3f8", + "Node name for S&R": "LTXFloatToInt", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 0 + ] + }, + { + "id": 5167, + "type": "KSamplerSelect", + "pos": [ + -2379.7024494145626, + 4038.4023692469204 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 5168, + "type": "PreviewAny", + "pos": [ + -4385.226512535651, + 3084.645124512045 + ], + "size": [ + 289.4653455216139, + 343.798203293964 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14491 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "LoRA Loader Status", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 4845, + "type": "LTXVSeparateAVLatent", + "pos": [ + -2082.2045030891563, + 3494.440137743163 + ], + "size": [ + 271.2833312988281, + 46 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "av_latent", + "type": "LATENT", + "link": 13890 + } + ], + "outputs": [ + { + "name": "video_latent", + "type": "LATENT", + "links": [ + 14298, + 14480 + ] + }, + { + "name": "audio_latent", + "type": "LATENT", + "links": [ + 13455, + 14302 + ] + } + ], + "title": "Separate Low Resolution AV Latent", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5198, + "type": "LTXVSeparateAVLatent", + "pos": [ + -1221.5407165055633, + 3493.950687198729 + ], + "size": [ + 271.2833312988281, + 46 + ], + "flags": {}, + "order": 37, + "mode": 4, + "inputs": [ + { + "name": "av_latent", + "type": "LATENT", + "link": 14303 + } + ], + "outputs": [ + { + "name": "video_latent", + "type": "LATENT", + "links": [ + 14304 + ] + }, + { + "name": "audio_latent", + "type": "LATENT", + "links": [ + 14306 + ] + } + ], + "title": "Separate Low Resolution AV Latent", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5199, + "type": "LTXVTiledVAEDecode", + "pos": [ + -1221.7380406345537, + 3583.402901335242 + ], + "size": [ + 269.8901736365534, + 198 + ], + "flags": {}, + "order": 38, + "mode": 4, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14309 + }, + { + "name": "latents", + "type": "LATENT", + "link": 14304 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 14305 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVTiledVAEDecode", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 2, + 2, + 6, + true, + "auto", + "auto" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5232, + "type": "PreviewAny", + "pos": [ + -2689.132338933934, + 3099.5656012946883 + ], + "size": [ + 584.4302826165278, + 339.8875564758546 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14476 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Status", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 5147, + "type": "LTXVConditioning", + "pos": [ + -2690.0767793685, + 3603.753930143112 + ], + "size": [ + 296.9524603795917, + 79.1230191824834 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 14473 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14459 + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 14088 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 14278, + 14317 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 14279, + 14318 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "LTXVConditioning" + }, + "widgets_values": [ + 25 + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5200, + "type": "LTXVAudioVAEDecode", + "pos": [ + -1219.95377743797, + 3828.1861660025484 + ], + "size": [ + 269.4217902135765, + 47.123019182483404 + ], + "flags": {}, + "order": 39, + "mode": 4, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 14306 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14308 + } + ], + "outputs": [ + { + "name": "Audio", + "type": "AUDIO", + "links": [ + 14450 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVAudioVAEDecode" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5197, + "type": "VHS_VideoCombine", + "pos": [ + -925.8829794510538, + 3495.653727369115 + ], + "size": [ + 250, + 310 + ], + "flags": {}, + "order": 41, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 14305 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 14451 + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 14331 + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "title": "Result", + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", + "Node name for S&R": "VHS_VideoCombine", + "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "result_%date:MM-dd_hh-mm%", + "format": "video/h265-mp4", + "pix_fmt": "yuv420p", + "crf": 20, + "save_metadata": true, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "result_05-07_21-59_00001-audio.mp4", + "subfolder": "", + "type": "temp", + "format": "video/h265-mp4", + "frame_rate": 30, + "workflow": "result_05-07_21-59_00001.png", + "fullpath": "/workspace/ComfyUI/temp/result_05-07_21-59_00001-audio.mp4" + } + } + }, + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5234, + "type": "NormalizeAudioLoudness", + "pos": [ + -1217.0220967914534, + 3916.996295875656 + ], + "size": [ + 277.5000061035156, + 58 + ], + "flags": {}, + "order": 40, + "mode": 4, + "inputs": [ + { + "name": "audio", + "type": "AUDIO", + "link": 14450 + } + ], + "outputs": [ + { + "name": "audio", + "type": "AUDIO", + "links": [ + 14451 + ] + } + ], + "properties": { + "aux_id": "Kijai/ComfyUI-WanVideoWrapper", + "ver": "d18cdb18597f525ef8d613a0cb447080fbab8fce", + "Node name for S&R": "NormalizeAudioLoudness" + }, + "widgets_values": [ + -22 + ] + }, + { + "id": 5193, + "type": "SamplerCustom", + "pos": [ + -1521.9587592427224, + 3493.3602963822873 + ], + "size": [ + 280, + 644.9638554216867 + ], + "flags": {}, + "order": 36, + "mode": 4, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14422 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 14317 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14318 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 14482 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 14483 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 14297 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 14303 + ] + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": null + } + ], + "title": "Sampler", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.3", + "Node name for S&R": "SamplerCustom" + }, + "widgets_values": [ + true, + 371974590179407, + "randomize", + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 4989, + "type": "PrimitiveFloat", + "pos": [ + -4047.3468830331485, + 4162.766074101198 + ], + "size": [ + 503.47815868041744, + 77.73054862088065 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 13450, + 14066, + 14070, + 14088, + 14331 + ] + } + ], + "title": "fps", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveFloat" + }, + "widgets_values": [ + 30 + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5177, + "type": "PreviewAny", + "pos": [ + -3504.032993175745, + 3095.0195440692464 + ], + "size": [ + 313.15375440166144, + 337.14574394977444 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14282 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 14274 + ] + } + ], + "title": "Enhanced Prompt Preview", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5020, + "type": "LTXVTiledVAEDecode", + "pos": [ + -2081.4899836490504, + 3582.7175410147156 + ], + "size": [ + 269.8901736365534, + 198 + ], + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14055 + }, + { + "name": "latents", + "type": "LATENT", + "link": 14480 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 14011 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVTiledVAEDecode", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 2, + 2, + 6, + true, + "auto", + "auto" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5021, + "type": "LTXVAudioVAEDecode", + "pos": [ + -2074.5265803528687, + 3824.172664222329 + ], + "size": [ + 269.4217902135765, + 47.123019182483404 + ], + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 13455 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14051 + } + ], + "outputs": [ + { + "name": "Audio", + "type": "AUDIO", + "links": [ + 14285 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVAudioVAEDecode" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 4528, + "type": "LTXVConcatAVLatent", + "pos": [ + -2692.1168150539725, + 3722.796257377105 + ], + "size": [ + 295.20239189803476, + 47.12301918248295 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "name": "video_latent", + "type": "LATENT", + "link": 14460 + }, + { + "name": "audio_latent", + "type": "LATENT", + "link": 14064 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 13963 + ] + } + ], + "title": "Concat Refined Video + Audio Latents", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5192, + "type": "LTXVLatentUpsampler", + "pos": [ + -2076.478741406815, + 3914.429910567344 + ], + "size": [ + 275.48004914142155, + 71.78799059939456 + ], + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 14298 + }, + { + "name": "upscale_model", + "type": "LATENT_UPSCALE_MODEL", + "link": 14301 + }, + { + "name": "vae", + "type": "VAE", + "link": 14300 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 14323 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LTXVLatentUpsampler" + }, + "widgets_values": [], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5195, + "type": "LTXVConcatAVLatent", + "pos": [ + -2072.854396167023, + 4027.514441996872 + ], + "size": [ + 291.79999389648435, + 47.84435512229766 + ], + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "name": "video_latent", + "type": "LATENT", + "link": 14324 + }, + { + "name": "audio_latent", + "type": "LATENT", + "link": 14302 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 14297 + ] + } + ], + "title": "Concat Refined Video + Audio Latents", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.10.0", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 5205, + "type": "LTXVImgToVideoInplace", + "pos": [ + -1524.2420723511418, + 4178.461731638713 + ], + "size": [ + 280.36925823128377, + 127.59106100617828 + ], + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "name": "vae", + "type": "VAE", + "link": 14325 + }, + { + "name": "image", + "type": "IMAGE", + "link": 14326 + }, + { + "name": "latent", + "type": "LATENT", + "link": 14323 + } + ], + "outputs": [ + { + "name": "latent", + "type": "LATENT", + "links": [ + 14324 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace", + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.5.2", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1, + false + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 4988, + "type": "PrimitiveInt", + "pos": [ + -4048.390415681659, + 4032.18209467316 + ], + "size": [ + 506.76658345056376, + 85.28842477014678 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 14059 + ] + } + ], + "title": "number of frames", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 465, + "fixed" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 5201, + "type": "FunPackHybridEuler2SSampler", + "pos": [ + -2088.410916070577, + 4114.3963480347475 + ], + "size": [ + 297.63680812038353, + 366 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "sigmas", + "shape": 7, + "type": "SIGMAS", + "link": 14315 + } + ], + "outputs": [ + { + "name": "sampler", + "type": "SAMPLER", + "links": [] + }, + { + "name": "sigmas", + "type": "SIGMAS", + "links": [] + } + ], + "properties": { + "cnr_id": "funpack", + "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", + "Node name for S&R": "FunPackHybridEuler2SSampler", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [ + 1, + 1, + 1, + 0.7, + "off", + 0.75, + 6, + 0.2, + 0.85 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5050, + "type": "ManualSigmas", + "pos": [ + -2688.654376071476, + 3492.407535659919 + ], + "size": [ + 297.7618766359765, + 71.64421238507339 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 14469 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5144, + "type": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", + "pos": [ + -4050.509757988798, + 3782.8259458113293 + ], + "size": [ + 508.9639946472771, + 210 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 14059 + }, + { + "name": "vae", + "type": "VAE", + "link": 14060 + }, + { + "name": "audio_vae", + "type": "VAE", + "link": 14061 + }, + { + "name": "image", + "type": "IMAGE,MASK", + "link": 14062 + }, + { + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 14067 + } + ], + "outputs": [ + { + "label": "video_latent", + "name": "latent", + "type": "LATENT", + "links": [ + 14460 + ] + }, + { + "label": "audio_latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 14064 + ] + }, + { + "name": "output_image", + "type": "IMAGE", + "links": [ + 14326 + ] + }, + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 14348 + ] + }, + { + "label": "plain_black", + "name": "output", + "type": "IMAGE", + "links": [] + } + ], + "properties": { + "proxyWidgets": [ + [ + "3059", + "length" + ], + [ + "3980", + "frame_rate" + ], + [ + "5031", + "target_width" + ], + [ + "5031", + "target_height" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5101, + "type": "SamplerCustom", + "pos": [ + -2376.173833228616, + 3494.807541019537 + ], + "size": [ + 280, + 644.9638554216867 + ], + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14421 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 14278 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14279 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 14486 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 14487 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 13963 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 13890 + ] + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": null + } + ], + "title": "Sampler", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.3", + "Node name for S&R": "SamplerCustom" + }, + "widgets_values": [ + true, + 1011767954176464, + "randomize", + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5096, + "type": "FunPackHybridEuler2SSampler", + "pos": [ + -2692.7617900563005, + 3820.895095468243 + ], + "size": [ + 295.06974613407635, + 272.5589436984151 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "sigmas", + "shape": 7, + "type": "SIGMAS", + "link": 14469 + } + ], + "outputs": [ + { + "name": "sampler", + "type": "SAMPLER", + "links": [ + 14486 + ] + }, + { + "name": "sigmas", + "type": "SIGMAS", + "links": [ + 14487 + ] + } + ], + "properties": { + "cnr_id": "funpack", + "ver": "d4aeeff055572d958f46a4e428f5dfaa4f4f4254", + "Node name for S&R": "FunPackHybridEuler2SSampler", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [ + 0, + 1.65, + 0.7, + 0.5, + "off", + 0.5, + 3, + 0.2, + 1 + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5229, + "type": "LTX2_NAG", + "pos": [ + -4049.362811312737, + 3096.7926698211413 + ], + "size": [ + 502.1137448018944, + 171.12950727397492 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 14426 + }, + { + "name": "nag_cond_video", + "shape": 7, + "type": "CONDITIONING", + "link": null + }, + { + "name": "nag_cond_audio", + "shape": 7, + "type": "CONDITIONING", + "link": null + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 14427 + ] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "9c3255f39cd2ea0ebf94a2016af4bd2e5d6eb91b", + "Node name for S&R": "LTX2_NAG" + }, + "widgets_values": [ + 11, + 0.275, + 2.35, + false + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5202, + "type": "ManualSigmas", + "pos": [ + -2386.3426826100235, + 4403.410245834443 + ], + "size": [ + 286.5405142205909, + 70.24154208314985 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 14315, + 14483 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "0.909375, 0.725, 0.421875, 0.0" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5196, + "type": "LatentUpscaleModelLoader", + "pos": [ + -2385.64321264596, + 4297.699280929902 + ], + "size": [ + 285.1080109057697, + 63.260013632212576 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "LATENT_UPSCALE_MODEL", + "type": "LATENT_UPSCALE_MODEL", + "links": [ + 14301 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LatentUpscaleModelLoader" + }, + "widgets_values": [ + "ltx2_spatial_upscaler.safetensors" + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5170, + "type": "KSamplerSelect", + "pos": [ + -2388.0095897749534, + 4194.947968470283 + ], + "size": [ + 286.83204362307833, + 63.61068120769323 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 14482 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler_ancestral_cfg_pp" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 5153, + "type": "PreviewAny", + "pos": [ + -2082.4801016069136, + 3102.538429670107 + ], + "size": [ + 839.175670995261, + 342.8519370213312 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 14477 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null + } + ], + "title": "Training Info", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.19.5", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 5019, + "type": "VHS_VideoCombine", + "pos": [ + -1783.626263907655, + 3493.952642031969 + ], + "size": [ + 250, + 669 + ], + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 14011 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 14285 + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 13450 + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "title": "Result", + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "2984ec4c4b93292421888f38db74a5e8802a8ff8", + "Node name for S&R": "VHS_VideoCombine", + "aux_id": "Kosinkadink/ComfyUI-VideoHelperSuite" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "result_%date:MM-dd_hh-mm-ss%", + "format": "video/h265-mp4", + "pix_fmt": "yuv420p", + "crf": 20, + "save_metadata": true, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "result_05-08_19-47-49_00001-audio.mp4", + "subfolder": "", + "type": "temp", + "format": "video/h265-mp4", + "frame_rate": 30, + "workflow": "result_05-08_19-47-49_00001.png", + "fullpath": "/workspace/ComfyUI/temp/result_05-08_19-47-49_00001-audio.mp4" + } + } + }, + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 2004, + "type": "LoadImage", + "pos": [ + -4386.235372913527, + 4036.898594725194 + ], + "size": [ + 280, + 315 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 11002, + 14062, + 14280 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "HHuFYC9bEAAd4f9.jpg", + "image" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5150, + "type": "MarkdownNote", + "pos": [ + -4874.5803841744955, + 4030.3082654487844 + ], + "size": [ + 457.2957979656867, + 322.28010914237484 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This is an example workflow, finetuned for LTX2.3 video model, using FunPack nodes to enhance and correct the results, tweaking them according to user's preferences.\n\nVideo Refiner V2 node learns from your ratings and feedback to provide the best result much more consistently than a base model does.\n\nThis workflow DOES NOT make model learn concepts it were never aware of. It only finetunes conditioning to match what YOU like as user, however it can't introduce knowledge that was never a part of a model.\n\nThis example workflow is actively using subgraphs to compact the space it takes, providing much more neat and clear workspace.\n\nIf you have any feedback or you found a bug or you have problems with using my nodes, feel free to file an issue on Github:\n\nhttps://github.com/digital-garbage/ComfyUI-FunPack\n\nPlease make sure you are reporting issues while using \"main\" branch of the repo. Issues with \"dev\" branch will not be reviewed unless they are critical bugs, breaking workflow fully." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5149, + "type": "MarkdownNote", + "pos": [ + -3162.082761220368, + 4004.8511204429938 + ], + "size": [ + 442.2702587922827, + 287.96370570528234 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "Refiner V2 Quick Guide\n\nFunPack Video Refiner V2 is a prompt memory node. It takes your positive prompt, encodes it through the connected CLIP, remembers how you rated the previous output, and slowly learns which actions, camera moves, details, quality cues, and style cues work for your workflows.\n\nIt does not look at the finished video pixels. It does not magically know what is inside your input image. It does not replace clear prompting. In image-to-video, it now treats character appearance, clothing, subject identity, and background as image-owned by default, so it should not inject old remembered outfits or characters into a new image unless you explicitly prompt them.\n\nHow To Use It\n\n Add FunPack Video Refiner V2 before your sampler where positive conditioning is encoded.\n Connect your CLIP.\n Type a refinement_key, or use FunPack Refinement Key Loader and connect its output into refinement_key_input.\n First run only seeds memory. Generate once, look at the result, then rate that result on the next run with the same key.\n Use Perfect when the output is good and should be remembered.\n Use Missing action when the requested motion did not happen.\n Use Missing details when small non-identity details are weak, like smoke, reflections, particles, hand contact, object interaction, or secondary motion.\n Use Missing quality when the idea is right but the result is messy or ugly.\n Use Wrong action, Wrong details, or Wrong details + action when the video looks usable but did the wrong thing.\n Use Wrong appearance when Refiner/Lucky brought in unwanted clothing, face, body, character, subject, or background memory.\n Use -Just forget it- for broken runs, bad seeds, workflow mistakes, model failures, or anything you do not want learned.\n\nLucky Mode\n\nI'm Feeling Lucky composes a prompt from learned memory. It is useful when you want the node to suggest motion, camera, detail, quality, or style ideas from previous liked outputs.\n\nLucky should not auto-add remembered outfits, character traits, subjects, or backgrounds anymore. If you want an appearance item, write it directly in the prompt.\nExamples\n\nIf your prompt says person smoking and exhaling smoke but the video only shows a puff with no exhale, rate Missing details or Missing action, depending on what matters most. This teaches the key that smoke/exhale matters in that prompt context, without globally banning smoking.\n\nIf you liked white tights in older prompts but your new input image is only a portrait face, and Lucky tries to bring tights into the scene, rate Wrong appearance. That tells Refiner to suppress that appearance memory from auto-injection while still allowing white tights when you explicitly type it.\n\nIf the camera should push in, orbit, pan, or change framing and it stays static, rate Missing action or Wrong action. Camera movement belongs to the action/camera side of memory, so it remains safe for repair and Lucky.\nKey Loader\n\nUse FunPack Refinement Key Loader when you want a reusable key dropdown or want to move keys between workflows/machines. Its Import and Export buttons save/load the key as JSON. Connect the loader to both Refiner V2 and FunPack Apply LoRA Weights so LoRA suggestions and prompt memory use the same key." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5143, + "type": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", + "pos": [ + -4387.679665836049, + 3474.1287636541992 + ], + "size": [ + 279.2243457043487, + 513.7727601710899 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "link": 14489 + } + ], + "outputs": [ + { + "label": "audio_vae", + "name": "VAE", + "type": "VAE", + "links": [ + 14051, + 14061, + 14308 + ] + }, + { + "label": "fast_vae", + "name": "VAE_1", + "type": "VAE", + "links": [ + 14073 + ] + }, + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [] + }, + { + "label": "video_vae", + "name": "VAE_2", + "type": "VAE", + "links": [ + 14055, + 14060, + 14300, + 14309, + 14325 + ] + }, + { + "label": "LTXV_model", + "name": "model", + "type": "MODEL", + "links": [ + 14426 + ] + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 14071, + 14472 + ] + }, + { + "name": "latent_downscale_factor", + "type": "FLOAT", + "links": [] + }, + { + "label": "lora_loader_status", + "name": "status", + "type": "STRING", + "links": [] + } + ], + "properties": { + "proxyWidgets": [], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5239, + "type": "FunPackRefinementKeyLoader", + "pos": [ + -3505.5938785840517, + 4049.7856350297743 + ], + "size": [ + 314.7000030517578, + 204 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "refinement_key", + "type": "STRING", + "links": [ + 14494, + 14499, + 14500 + ] + }, + { + "name": "status", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "b5a875a2609e21f19c08e5951e72af2db220cb5c", + "Node name for S&R": "FunPackRefinementKeyLoader" + }, + "widgets_values": [ + "ltx23_example", + "", + true, + "", + "", + "" + ] + }, + { + "id": 5238, + "type": "FunPackApplyLoraWeights", + "pos": [ + -4861.784019319389, + 3484.2449215898914 + ], + "size": [ + 434.32223485180293, + 474 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "refinement_key_input", + "shape": 7, + "type": "STRING", + "link": 14499 + }, + { + "name": "positive_prompt", + "type": "STRING", + "widget": { + "name": "positive_prompt" + }, + "link": 14492 + }, + { + "name": "refinement_key", + "type": "STRING", + "widget": { + "name": "refinement_key" + }, + "link": 14500 + } + ], + "outputs": [ + { + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [ + 14489, + 14490 + ] + }, + { + "name": "status", + "type": "STRING", + "links": [ + 14491 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "02e89ebd36208f6f5c0d7780f89f7dcdc040b1f1", + "Node name for S&R": "FunPackApplyLoraWeights" + }, + "widgets_values": [ + "", + "my_style_v1", + "ltx2", + true, + "[]", + {}, + { + "on": true, + "lora": "None", + "type": "general", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "action", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "style", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "quality", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "character", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "general", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "action", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "style", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "quality", + "strength": 1 + }, + { + "on": true, + "lora": "None", + "type": "character", + "strength": 1 + }, + "" + ] + }, + { + "id": 5237, + "type": "FunPackVideoRefinerV2", + "pos": [ + -3163.670871437389, + 3484.6075129967685 + ], + "size": [ + 450.56804065586994, + 475.2209928759157 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 14472 + }, + { + "name": "lora_stack", + "shape": 7, + "type": "FUNPACK_LORA_STACK", + "link": 14490 + }, + { + "name": "refinement_key_input", + "shape": 7, + "type": "STRING", + "link": 14494 + }, + { + "name": "positive_prompt", + "type": "STRING", + "widget": { + "name": "positive_prompt" + }, + "link": 14474 + }, + { + "name": "user_intent_prompt", + "shape": 7, + "type": "STRING", + "widget": { + "name": "user_intent_prompt" + }, + "link": 14496 + } + ], + "outputs": [ + { + "name": "modified_positive", + "type": "CONDITIONING", + "links": [ + 14473 + ] + }, + { + "name": "status", + "type": "STRING", + "links": [ + 14476 + ] + }, + { + "name": "training_info", + "type": "STRING", + "links": [ + 14477 + ] + }, + { + "name": "loss_graph", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "e4c65fc2e2dca771e15e0b0f0c20044212870a05", + "Node name for S&R": "FunPackVideoRefinerV2" + }, + "widgets_values": [ + "", + "Missing details", + 429474071199278, + "randomize", + false, + false, + false + ] + }, + { + "id": 5012, + "type": "PrimitiveStringMultiline", + "pos": [ + -4055.4304375982783, + 3481.1266355613766 + ], + "size": [ + 520, + 260 + ], + "flags": { + "collapsed": false + }, + "order": 11, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 14281, + 14496 + ] + } + ], + "title": "Positive Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5188, + "type": "c758fc63-b71c-43f2-b085-ded32443f756", + "pos": [ + -4049.591349938611, + 3313.186716870688 + ], + "size": [ + 505.0919753788826, + 121.53832647689296 + ], + "flags": { + "collapsed": false + }, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 14280 + }, + { + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 14281 + } + ], + "outputs": [ + { + "name": "generated_text", + "type": "STRING", + "links": [ + 14282, + 14474, + 14492 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "5215", + "prompt" + ], + [ + "5185", + "seed" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.20.1" + }, + "widgets_values": [], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5146, + "type": "953c68b0-c00f-4e16-ab59-39af7ce32097", + "pos": [ + -3501.053962071962, + 3484.3459461593543 + ], + "size": [ + 311.20648872536776, + 475.57454540880417 + ], + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "label": "positive_conditioning", + "name": "positive", + "type": "CONDITIONING", + "link": null + }, + { + "name": "frame_rate", + "type": "FLOAT", + "link": 14070 + }, + { + "name": "clip", + "type": "CLIP", + "link": 14071 + }, + { + "name": "model", + "type": "MODEL", + "link": 14427 + }, + { + "name": "vae", + "type": "VAE", + "link": 14073 + }, + { + "label": "positive_prompt", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 14274 + }, + { + "name": "latent", + "type": "LATENT", + "link": 14348 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 14459 + ] + }, + { + "name": "model", + "type": "MODEL", + "links": [ + 14421, + 14422 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "2483", + "text" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.19.5" + }, + "widgets_values": [], + "color": "#432", + "bgcolor": "#653" + } + ], + "links": [ + [ + 11002, + 2004, + 0, + 2653, + 0, + "IMAGE" + ], + [ + 13450, + 4989, + 0, + 5019, + 4, + "FLOAT" + ], + [ + 13455, + 4845, + 1, + 5021, + 0, + "LATENT" + ], + [ + 13890, + 5101, + 0, + 4845, + 0, + "LATENT" + ], + [ + 13963, + 4528, + 0, + 5101, + 5, + "LATENT" + ], + [ + 14011, + 5020, + 0, + 5019, + 0, + "IMAGE" + ], + [ + 14051, + 5143, + 0, + 5021, + 1, + "VAE" + ], + [ + 14055, + 5143, + 3, + 5020, + 0, + "VAE" + ], + [ + 14059, + 4988, + 0, + 5144, + 0, + "INT" + ], + [ + 14060, + 5143, + 3, + 5144, + 1, + "VAE" + ], + [ + 14061, + 5143, + 0, + 5144, + 2, + "VAE" + ], + [ + 14062, + 2004, + 0, + 5144, + 3, + "IMAGE" + ], + [ + 14064, + 5144, + 1, + 4528, + 1, + "LATENT" + ], + [ + 14066, + 4989, + 0, + 5145, + 0, + "FLOAT" + ], + [ + 14067, + 5145, + 0, + 5144, + 4, + "INT" + ], + [ + 14070, + 4989, + 0, + 5146, + 1, + "FLOAT" + ], + [ + 14071, + 5143, + 5, + 5146, + 2, + "CLIP" + ], + [ + 14073, + 5143, + 1, + 5146, + 4, + "VAE" + ], + [ + 14088, + 4989, + 0, + 5147, + 2, + "FLOAT" + ], + [ + 14274, + 5177, + 0, + 5146, + 5, + "STRING" + ], + [ + 14278, + 5147, + 0, + 5101, + 1, + "CONDITIONING" + ], + [ + 14279, + 5147, + 1, + 5101, + 2, + "CONDITIONING" + ], + [ + 14280, + 2004, + 0, + 5188, + 0, + "IMAGE" + ], + [ + 14281, + 5012, + 0, + 5188, + 1, + "STRING" + ], + [ + 14282, + 5188, + 0, + 5177, + 0, + "STRING" + ], + [ + 14285, + 5021, + 0, + 5019, + 1, + "AUDIO" + ], + [ + 14297, + 5195, + 0, + 5193, + 5, + "LATENT" + ], + [ + 14298, + 4845, + 0, + 5192, + 0, + "LATENT" + ], + [ + 14300, + 5143, + 3, + 5192, + 2, + "VAE" + ], + [ + 14301, + 5196, + 0, + 5192, + 1, + "LATENT_UPSCALE_MODEL" + ], + [ + 14302, + 4845, + 1, + 5195, + 1, + "LATENT" + ], + [ + 14303, + 5193, + 0, + 5198, + 0, + "LATENT" + ], + [ + 14304, + 5198, + 0, + 5199, + 1, + "LATENT" + ], + [ + 14305, + 5199, + 0, + 5197, + 0, + "IMAGE" + ], + [ + 14306, + 5198, + 1, + 5200, + 0, + "LATENT" + ], + [ + 14308, + 5143, + 0, + 5200, + 1, + "VAE" + ], + [ + 14309, + 5143, + 3, + 5199, + 0, + "VAE" + ], + [ + 14315, + 5202, + 0, + 5201, + 0, + "SIGMAS" + ], + [ + 14317, + 5147, + 0, + 5193, + 1, + "CONDITIONING" + ], + [ + 14318, + 5147, + 1, + 5193, + 2, + "CONDITIONING" + ], + [ + 14323, + 5192, + 0, + 5205, + 2, + "LATENT" + ], + [ + 14324, + 5205, + 0, + 5195, + 0, + "LATENT" + ], + [ + 14325, + 5143, + 3, + 5205, + 0, + "VAE" + ], + [ + 14326, + 5144, + 2, + 5205, + 1, + "IMAGE" + ], + [ + 14331, + 4989, + 0, + 5197, + 4, + "FLOAT" + ], + [ + 14348, + 5144, + 3, + 5146, + 6, + "LATENT" + ], + [ + 14421, + 5146, + 2, + 5101, + 0, + "MODEL" + ], + [ + 14422, + 5146, + 2, + 5193, + 0, + "MODEL" + ], + [ + 14426, + 5143, + 4, + 5229, + 0, + "MODEL" + ], + [ + 14427, + 5229, + 0, + 5146, + 3, + "MODEL" + ], + [ + 14450, + 5200, + 0, + 5234, + 0, + "AUDIO" + ], + [ + 14451, + 5234, + 0, + 5197, + 1, + "AUDIO" + ], + [ + 14459, + 5146, + 1, + 5147, + 1, + "CONDITIONING" + ], + [ + 14460, + 5144, + 0, + 4528, + 0, + "LATENT" + ], + [ + 14469, + 5050, + 0, + 5096, + 0, + "SIGMAS" + ], + [ + 14472, + 5143, + 5, + 5237, + 0, + "CLIP" + ], + [ + 14473, + 5237, + 0, + 5147, + 0, + "CONDITIONING" + ], + [ + 14474, + 5188, + 0, + 5237, + 3, + "STRING" + ], + [ + 14476, + 5237, + 1, + 5232, + 0, + "STRING" + ], + [ + 14477, + 5237, + 2, + 5153, + 0, + "STRING" + ], + [ + 14480, + 4845, + 0, + 5020, + 1, + "LATENT" + ], + [ + 14482, + 5170, + 0, + 5193, + 3, + "SAMPLER" + ], + [ + 14483, + 5202, + 0, + 5193, + 4, + "SIGMAS" + ], + [ + 14486, + 5096, + 0, + 5101, + 3, + "SAMPLER" + ], + [ + 14487, + 5096, + 1, + 5101, + 4, + "SIGMAS" + ], + [ + 14489, + 5238, + 0, + 5143, + 0, + "FUNPACK_LORA_STACK" + ], + [ + 14490, + 5238, + 0, + 5237, + 1, + "FUNPACK_LORA_STACK" + ], + [ + 14491, + 5238, + 1, + 5168, + 0, + "STRING" + ], + [ + 14492, + 5188, + 0, + 5238, + 1, + "STRING" + ], + [ + 14494, + 5239, + 0, + 5237, + 2, + "STRING" + ], + [ + 14496, + 5012, + 0, + 5237, + 4, + "STRING" + ], + [ + 14499, + 5239, + 0, + 5238, + 0, + "STRING" + ], + [ + 14500, + 5239, + 0, + 5238, + 2, + "STRING" + ] + ], + "groups": [], + "definitions": { + "subgraphs": [ + { + "id": "4a0d1ad0-44c5-466f-8153-4ad264f785ab", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14500, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Model Loaders", + "inputNode": { + "id": -10, + "bounding": [ + -4325.009559761858, + 4005.266954142581, + 120, + 60 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3434.4839648526677, + 3955.266954142581, + 176.96665954589844, + 200 + ] + }, + "inputs": [ + { + "id": "d0987976-3ded-4b5e-8cbb-bf7a8f81e33a", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "linkIds": [ + 14026 + ], + "localized_name": "lora_stack", + "pos": [ + -4225.009559761858, + 4025.266954142581 + ] + } + ], + "outputs": [ + { + "id": "5698eb50-25b5-43c3-bc6d-5ae6ed37cc69", + "name": "VAE", + "type": "VAE", + "linkIds": [ + 13426, + 13426 + ], + "localized_name": "VAE", + "label": "audio_vae", + "pos": [ + -3414.4839648526677, + 3975.266954142581 + ] + }, + { + "id": "93aec5ab-7fdc-4e97-8030-9b93ccb135f7", + "name": "VAE_1", + "type": "VAE", + "linkIds": [ + 14032 + ], + "localized_name": "VAE_1", + "label": "fast_vae", + "pos": [ + -3414.4839648526677, + 3995.266954142581 + ] + }, + { + "id": "23e2004b-5760-4651-9808-e4759172761e", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "linkIds": [ + 13861 + ], + "localized_name": "lora_stack", + "pos": [ + -3414.4839648526677, + 4015.266954142581 + ] + }, + { + "id": "c70376ed-0ba0-4de8-8c69-d0b2e0f98c94", + "name": "VAE_2", + "type": "VAE", + "linkIds": [ + 13428, + 13428 + ], + "localized_name": "VAE_2", + "label": "video_vae", + "pos": [ + -3414.4839648526677, + 4035.266954142581 + ] + }, + { + "id": "d7031e7e-1171-43c2-9dd4-b1ea12834bbc", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14418 + ], + "localized_name": "model", + "label": "LTXV_model", + "pos": [ + -3414.4839648526677, + 4055.266954142581 + ] + }, + { + "id": "3024b60b-1ea8-474c-91cd-85317f7a67a3", + "name": "CLIP", + "type": "CLIP", + "linkIds": [ + 13435, + 13435 + ], + "localized_name": "CLIP", + "pos": [ + -3414.4839648526677, + 4075.266954142581 + ] + }, + { + "id": "b5fb5099-9092-44f9-bacc-690a2860aa29", + "name": "latent_downscale_factor", + "type": "FLOAT", + "linkIds": [], + "pos": [ + -3414.4839648526677, + 4095.266954142581 + ] + }, + { + "id": "cfe9f2c2-261d-43b8-8591-00161f7bd393", + "name": "status", + "type": "STRING", + "linkIds": [ + 14188 + ], + "label": "lora_loader_status", + "pos": [ + -3414.4839648526677, + 4115.266954142581 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 5104, + "type": "FunPackLoraLoader", + "pos": [ + -3840.6243036178707, + 3669.1897293353245 + ], + "size": [ + 230, + 90 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 13916 + }, + { + "localized_name": "lora_stack", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "link": 14026 + }, + { + "localized_name": "clip", + "name": "clip", + "shape": 7, + "type": "CLIP", + "link": null + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 14320 + ] + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": null + }, + { + "localized_name": "lora_stack", + "name": "lora_stack", + "type": "FUNPACK_LORA_STACK", + "links": [ + 13861 + ] + }, + { + "localized_name": "status", + "name": "status", + "type": "STRING", + "links": [ + 14188 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "707e27279e2be733a5d787496742848bc745c258", + "Node name for S&R": "FunPackLoraLoader", + "aux_id": "digital-garbage/ComfyUI-FunPack" + }, + "widgets_values": [] + }, + { + "id": 5004, + "type": "VAELoaderKJ", + "pos": [ + -4142.837082457477, + 3661.3251095596834 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 13428 + ] + } + ], + "title": "Load Video VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2_video_vae.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5003, + "type": "VAELoaderKJ", + "pos": [ + -4145.009559761858, + 3815.5795641379827 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 13426 + ] + } + ], + "title": "Load Audio VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2_audio_vae.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5017, + "type": "VAELoaderKJ", + "pos": [ + -4143.886540579375, + 3967.8256025029505 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 14032 + ] + } + ], + "title": "Load Preview VAE", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "VAELoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "taeltx2_3.safetensors", + "main_device", + "fp32" + ] + }, + { + "id": 5006, + "type": "DualCLIPLoader", + "pos": [ + -3835.5303844223104, + 3814.768391164597 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 13435 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "DualCLIPLoader" + }, + "widgets_values": [ + "gemma.safetensors", + "ltx2_embeddings_connector.safetensors", + "ltxv", + "default" + ] + }, + { + "id": 5002, + "type": "DiffusionModelLoaderKJ", + "pos": [ + -4141.903414758422, + 4121.852190133855 + ], + "size": [ + 312.06666564941406, + 178 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "localized_name": "extra_state_dict", + "name": "extra_state_dict", + "shape": 7, + "type": "STRING", + "link": null + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 13916 + ] + } + ], + "title": "Load LTX-2.3 Diffusion Model", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "DiffusionModelLoaderKJ", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + "ltx2.safetensors", + "bf16", + "bf16", + false, + "disabled", + false + ] + }, + { + "id": 5204, + "type": "LTX2LoraLoaderAdvanced", + "pos": [ + -3821.7206559166707, + 4361.663434778751 + ], + "size": [ + 293.59999694824216, + 242 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14401 + }, + { + "localized_name": "opt_lora_path", + "name": "opt_lora_path", + "shape": 7, + "type": "STRING", + "link": null + }, + { + "localized_name": "blocks", + "name": "blocks", + "shape": 7, + "type": "SELECTEDDITBLOCKS", + "link": null + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14498 + ] + }, + { + "localized_name": "rank", + "name": "rank", + "type": "STRING", + "links": null + }, + { + "localized_name": "loaded_keys_info", + "name": "loaded_keys_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", + "Node name for S&R": "LTX2LoraLoaderAdvanced" + }, + "widgets_values": [ + "distilled_72.safetensors", + 0.75, + 0, + 1, + 1, + 1, + 1 + ] + }, + { + "id": 5203, + "type": "LTX2LoraLoaderAdvanced", + "pos": [ + -4137.706720274676, + 4359.203995818316 + ], + "size": [ + 293.59999694824216, + 242 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14320 + }, + { + "localized_name": "opt_lora_path", + "name": "opt_lora_path", + "shape": 7, + "type": "STRING", + "link": null + }, + { + "localized_name": "blocks", + "name": "blocks", + "shape": 7, + "type": "SELECTEDDITBLOCKS", + "link": null + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14401 + ] + }, + { + "localized_name": "rank", + "name": "rank", + "type": "STRING", + "links": null + }, + { + "localized_name": "loaded_keys_info", + "name": "loaded_keys_info", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "eeb2ae222c1bddce91506f22a6a5110964a42ce4", + "Node name for S&R": "LTX2LoraLoaderAdvanced" + }, + "widgets_values": [ + "distilled_72.safetensors", + 0.48, + 1, + 0, + 0, + 0, + 1 + ] + }, + { + "id": 5225, + "type": "FunPackContextTransitionWindows", + "pos": [ + -3499.400882804922, + 4203.790940060165 + ], + "size": [ + 346.26666870117185, + 394 + ], + "flags": {}, + "order": 8, + "mode": 4, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14498 + } + ], + "outputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "links": [ + 14418 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-FunPack", + "ver": "ace940fed3f7f2724f784b8d3165871a4e027281", + "Node name for S&R": "FunPackContextTransitionWindows" + }, + "widgets_values": [ + "balanced", + 241, + 73, + "standard_uniform", + "overlap-linear", + 0, + 0, + 4, + 0.2, + 1, + 1, + false, + true, + "", + false + ] + } + ], + "groups": [], + "links": [ + { + "id": 13916, + "origin_id": 5002, + "origin_slot": 0, + "target_id": 5104, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14026, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5104, + "target_slot": 1, + "type": "FUNPACK_LORA_STACK" + }, + { + "id": 13426, + "origin_id": 5003, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14032, + "origin_id": 5017, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 13861, + "origin_id": 5104, + "origin_slot": 2, + "target_id": -20, + "target_slot": 2, + "type": "FUNPACK_LORA_STACK" + }, + { + "id": 13428, + "origin_id": 5004, + "origin_slot": 0, + "target_id": -20, + "target_slot": 3, + "type": "VAE" + }, + { + "id": 13435, + "origin_id": 5006, + "origin_slot": 0, + "target_id": -20, + "target_slot": 5, + "type": "CLIP" + }, + { + "id": 14188, + "origin_id": 5104, + "origin_slot": 3, + "target_id": -20, + "target_slot": 7, + "type": "STRING" + }, + { + "id": 14320, + "origin_id": 5104, + "origin_slot": 0, + "target_id": 5203, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14401, + "origin_id": 5203, + "origin_slot": 0, + "target_id": 5204, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14418, + "origin_id": 5225, + "origin_slot": 0, + "target_id": -20, + "target_slot": 4, + "type": "MODEL" + }, + { + "id": 14498, + "origin_id": 5204, + "origin_slot": 0, + "target_id": 5225, + "target_slot": 0, + "type": "MODEL" + } + ], + "extra": {} + }, + { + "id": "2d968b7e-61e9-49f7-a0a5-bb17386fa820", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14500, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Image Processing", + "inputNode": { + "id": -10, + "bounding": [ + -4230.013931822186, + 4280.664648566482, + 120, + 180 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3392.3462803758225, + 4300.664648566482, + 120, + 140 + ] + }, + "inputs": [ + { + "id": "0cd8eafb-4599-4caf-8fc4-30f63acf3cd8", + "name": "length", + "type": "INT", + "linkIds": [ + 13389, + 13390 + ], + "localized_name": "length", + "pos": [ + -4130.013931822186, + 4300.664648566482 + ] + }, + { + "id": "45f7e533-25b2-4795-acd6-5dc96f4e70d5", + "name": "vae", + "type": "VAE", + "linkIds": [ + 14054, + 14327, + 14351 + ], + "localized_name": "vae", + "pos": [ + -4130.013931822186, + 4320.664648566482 + ] + }, + { + "id": "e7b3fa68-1694-4761-a92b-f9cf55c8b0d7", + "name": "audio_vae", + "type": "VAE", + "linkIds": [ + 14050 + ], + "localized_name": "audio_vae", + "pos": [ + -4130.013931822186, + 4340.664648566482 + ] + }, + { + "id": "5a5c6f1b-489a-4eff-95cc-ee5d159310eb", + "name": "image", + "type": "IMAGE,MASK", + "linkIds": [ + 13474 + ], + "localized_name": "image", + "pos": [ + -4130.013931822186, + 4360.664648566482 + ] + }, + { + "id": "9b785d25-1e6c-4255-bb3c-97aaf621afe2", + "name": "frame_rate", + "type": "INT", + "linkIds": [ + 14065 + ], + "pos": [ + -4130.013931822186, + 4380.664648566482 + ] + }, + { + "id": "6db1bac4-138a-4b8b-90bf-3961f84d84a3", + "name": "target_width", + "type": "INT", + "linkIds": [ + 14081, + 14389 + ], + "pos": [ + -4130.013931822186, + 4400.664648566482 + ] + }, + { + "id": "0cd2e965-8222-4162-b16f-d204a10034f4", + "name": "target_height", + "type": "INT", + "linkIds": [ + 14082, + 14390 + ], + "pos": [ + -4130.013931822186, + 4420.664648566482 + ] + } + ], + "outputs": [ + { + "id": "42905067-8a71-4026-b386-cdbcbbf428d6", + "name": "latent", + "type": "LATENT", + "linkIds": [ + 14353 + ], + "localized_name": "latent", + "label": "video_latent", + "pos": [ + -3372.3462803758225, + 4320.664648566482 + ] + }, + { + "id": "832cd750-af0e-4127-b7e0-9e7d87efa173", + "name": "Latent", + "type": "LATENT", + "linkIds": [ + 13696 + ], + "localized_name": "Latent", + "label": "audio_latent", + "pos": [ + -3372.3462803758225, + 4340.664648566482 + ] + }, + { + "id": "70c112e1-3f52-4d3e-bff3-43133fe0f5a9", + "name": "output_image", + "type": "IMAGE", + "linkIds": [ + 14149 + ], + "pos": [ + -3372.3462803758225, + 4360.664648566482 + ] + }, + { + "id": "75faa65c-faad-46bc-bf59-05203952150a", + "name": "LATENT", + "type": "LATENT", + "linkIds": [ + 14349 + ], + "pos": [ + -3372.3462803758225, + 4380.664648566482 + ] + }, + { + "id": "136987d9-e5df-4234-88a8-f34dcf46a64c", + "name": "output", + "type": "IMAGE", + "linkIds": [ + 14391 + ], + "label": "plain_black", + "pos": [ + -3372.3462803758225, + 4400.664648566482 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 3980, + "type": "LTXVEmptyLatentAudio", + "pos": [ + -3752.2385283541353, + 4421.631082925247 + ], + "size": [ + 305.8394470214844, + 106 + ], + "flags": { + "collapsed": false + }, + "order": 4, + "mode": 0, + "inputs": [ + { + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 14050 + }, + { + "localized_name": "frames_number", + "name": "frames_number", + "type": "INT", + "widget": { + "name": "frames_number" + }, + "link": 13390 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 14065 + } + ], + "outputs": [ + { + "localized_name": "Latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 13696 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "LTXVEmptyLatentAudio" + }, + "widgets_values": [ + 121, + 25, + 1 + ] + }, + { + "id": 3059, + "type": "EmptyLTXVLatentVideo", + "pos": [ + -4054.604251439193, + 4362.302545732084 + ], + "size": [ + 210, + 194 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 13478 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 13479 + }, + { + "localized_name": "length", + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 13389 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 11401, + 14329 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.43", + "Node name for S&R": "EmptyLTXVLatentVideo" + }, + "widgets_values": [ + 512, + 768, + 121, + 1 + ] + }, + { + "id": 5212, + "type": "VAEEncode", + "pos": [ + -3395.061084351483, + 4221.605231546082 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "pixels", + "name": "pixels", + "type": "IMAGE", + "link": 14350 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14351 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 14349 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "VAEEncode" + }, + "widgets_values": [] + }, + { + "id": 5220, + "type": "LoadImage", + "pos": [ + -4052.9158842937736, + 4610.945426788913 + ], + "size": [ + 282.7333297729492, + 314 + ], + "flags": {}, + "order": 0, + "mode": 4, + "inputs": [], + "outputs": [ + { + "localized_name": "IMAGE", + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 14388 + ] + }, + { + "localized_name": "MASK", + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "plain-black-mobile-background-uya4pitjl3vdmatx-1490018872.jpg", + "image" + ] + }, + { + "id": 5219, + "type": "ImageTransformKJ", + "pos": [ + -3749.590944998398, + 4574.8080683828575 + ], + "size": [ + 462, + 261 + ], + "flags": { + "collapsed": true + }, + "order": 8, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE,MASK", + "link": 14388 + }, + { + "localized_name": "mask", + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "localized_name": "target_width", + "name": "target_width", + "type": "INT", + "widget": { + "name": "target_width" + }, + "link": 14389 + }, + { + "localized_name": "target_height", + "name": "target_height", + "type": "INT", + "widget": { + "name": "target_height" + }, + "link": 14390 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "IMAGE", + "links": [ + 14391 + ] + }, + { + "localized_name": "output_mask", + "name": "output_mask", + "type": "MASK", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox", + "name": "bbox", + "shape": 6, + "type": "BBOX", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox_mask", + "name": "bbox_mask", + "shape": 6, + "type": "MASK", + "links": null + }, + { + "label": "768 width", + "localized_name": "width", + "name": "width", + "type": "INT", + "links": [] + }, + { + "label": "768 height", + "localized_name": "height", + "name": "height", + "type": "INT", + "links": [] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "ImageTransformKJ", + "previewEnabled": true, + "showRotationCross": false, + "canvasSize": [ + 432, + 324 + ], + "aux_id": "kijai/ComfyUI-KJNodes", + "fillColor": "#000000", + "previewFile": "crop_preview_dd29a0.webp" + }, + "widgets_values": [ + 768, + 768, + "lanczos", + "keep_long_edge", + 16, + "disabled", + "disabled", + "{\"fillColor\":\"#000000\"}", + "" + ] + }, + { + "id": 3336, + "type": "LTXVPreprocess", + "pos": [ + -4051.7822649723703, + 4222.285074743058 + ], + "size": [ + 270, + 74 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 13864 + } + ], + "outputs": [ + { + "localized_name": "output_image", + "name": "output_image", + "type": "IMAGE", + "links": [ + 13865, + 14149, + 14328, + 14350 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "LTXVPreprocess" + }, + "widgets_values": [ + 0 + ] + }, + { + "id": 5206, + "type": "LTXVImgToVideoInplace", + "pos": [ + -3747.668725148193, + 4054.017919247807 + ], + "size": [ + 270, + 122 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14327 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 14328 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 14329 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 14353 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "LTXVImgToVideoInplace" + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 3159, + "type": "LTXVImgToVideoConditionOnly", + "pos": [ + -3756.874428105229, + 4233.494670882838 + ], + "size": [ + 315.26666870117185, + 142.859507731343 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 14054 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 13865 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 11401 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "cnr_id": "ComfyUI-LTXVideo", + "ver": "d43181d5723c1721692baef01d90cd1a825bba91", + "Node name for S&R": "LTXVImgToVideoConditionOnly", + "aux_id": "Lightricks/ComfyUI-LTXVideo" + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 5031, + "type": "ImageTransformKJ", + "pos": [ + -4044.0432045178136, + 4176.011069650051 + ], + "size": [ + 520, + 1151 + ], + "flags": { + "collapsed": true + }, + "order": 5, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE,MASK", + "link": 13474 + }, + { + "localized_name": "mask", + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "localized_name": "target_width", + "name": "target_width", + "type": "INT", + "widget": { + "name": "target_width" + }, + "link": 14081 + }, + { + "localized_name": "target_height", + "name": "target_height", + "type": "INT", + "widget": { + "name": "target_height" + }, + "link": 14082 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "IMAGE,MASK", + "links": [ + 13864 + ] + }, + { + "localized_name": "output_mask", + "name": "output_mask", + "type": "MASK", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox", + "name": "bbox", + "shape": 6, + "type": "BBOX", + "links": null + }, + { + "color_off": "transparent", + "color_on": "transparent", + "label": " ", + "localized_name": "bbox_mask", + "name": "bbox_mask", + "shape": 6, + "type": "MASK", + "links": null + }, + { + "label": "512 width", + "localized_name": "width", + "name": "width", + "type": "INT", + "links": [ + 13478 + ] + }, + { + "label": "768 height", + "localized_name": "height", + "name": "height", + "type": "INT", + "links": [ + 13479 + ] + } + ], + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "52807058a17532dd3d03f2143fb4c52beab5f936", + "Node name for S&R": "ImageTransformKJ", + "previewEnabled": true, + "showRotationCross": false, + "canvasSize": [ + 512, + 768 + ], + "aux_id": "kijai/ComfyUI-KJNodes", + "fillColor": "#000000", + "previewFile": "crop_preview_44cb63.webp" + }, + "widgets_values": [ + 768, + 768, + "lanczos", + "keep_long_edge", + 16, + "disabled", + "disabled", + "{\"fillColor\":\"#000000\"}", + "" + ] + } + ], + "groups": [], + "links": [ + { + "id": 13478, + "origin_id": 5031, + "origin_slot": 4, + "target_id": 3059, + "target_slot": 0, + "type": "INT" + }, + { + "id": 13479, + "origin_id": 5031, + "origin_slot": 5, + "target_id": 3059, + "target_slot": 1, + "type": "INT" + }, + { + "id": 13865, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 3159, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 11401, + "origin_id": 3059, + "origin_slot": 0, + "target_id": 3159, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 13864, + "origin_id": 5031, + "origin_slot": 0, + "target_id": 3336, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 13389, + "origin_id": -10, + "origin_slot": 0, + "target_id": 3059, + "target_slot": 2, + "type": "INT" + }, + { + "id": 13390, + "origin_id": -10, + "origin_slot": 0, + "target_id": 3980, + "target_slot": 1, + "type": "INT" + }, + { + "id": 14054, + "origin_id": -10, + "origin_slot": 1, + "target_id": 3159, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14050, + "origin_id": -10, + "origin_slot": 2, + "target_id": 3980, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 13474, + "origin_id": -10, + "origin_slot": 3, + "target_id": 5031, + "target_slot": 0, + "type": "IMAGE,MASK" + }, + { + "id": 13696, + "origin_id": 3980, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 14065, + "origin_id": -10, + "origin_slot": 4, + "target_id": 3980, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14081, + "origin_id": -10, + "origin_slot": 5, + "target_id": 5031, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14082, + "origin_id": -10, + "origin_slot": 6, + "target_id": 5031, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14149, + "origin_id": 3336, + "origin_slot": 0, + "target_id": -20, + "target_slot": 2, + "type": "IMAGE" + }, + { + "id": 14327, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5206, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 14328, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 5206, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14329, + "origin_id": 3059, + "origin_slot": 0, + "target_id": 5206, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 14349, + "origin_id": 5212, + "origin_slot": 0, + "target_id": -20, + "target_slot": 3, + "type": "LATENT" + }, + { + "id": 14350, + "origin_id": 3336, + "origin_slot": 0, + "target_id": 5212, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 14351, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5212, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 14353, + "origin_id": 5206, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 14388, + "origin_id": 5220, + "origin_slot": 0, + "target_id": 5219, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 14389, + "origin_id": -10, + "origin_slot": 5, + "target_id": 5219, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14390, + "origin_id": -10, + "origin_slot": 6, + "target_id": 5219, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14391, + "origin_id": 5219, + "origin_slot": 0, + "target_id": -20, + "target_slot": 4, + "type": "IMAGE" + } + ], + "extra": {} + }, + { + "id": "953c68b0-c00f-4e16-ab59-39af7ce32097", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14500, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Conditioning Processing", + "inputNode": { + "id": -10, + "bounding": [ + -3757.4569530860326, + 3786.7967005388414, + 159.46666717529297, + 180 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -2907.4297954820227, + 3784.52193989455, + 120, + 100 + ] + }, + "inputs": [ + { + "id": "738e10fc-b836-4774-9137-3c64dc6fd9b1", + "name": "positive", + "type": "CONDITIONING", + "linkIds": [], + "localized_name": "positive", + "label": "positive_conditioning", + "pos": [ + -3617.9902859107397, + 3806.7967005388414 + ] + }, + { + "id": "1f6995d2-3cab-4be6-bf4e-2289e22f7587", + "name": "frame_rate", + "type": "FLOAT", + "linkIds": [], + "localized_name": "frame_rate", + "pos": [ + -3617.9902859107397, + 3826.7967005388414 + ] + }, + { + "id": "3a835bc3-67a3-4315-9360-b111e3a5b8ff", + "name": "clip", + "type": "CLIP", + "linkIds": [ + 14058, + 14057 + ], + "localized_name": "clip", + "pos": [ + -3617.9902859107397, + 3846.7967005388414 + ] + }, + { + "id": "2e41c3e2-f8e8-4de3-a894-344e8eb5debe", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14056 + ], + "localized_name": "model", + "pos": [ + -3617.9902859107397, + 3866.7967005388414 + ] + }, + { + "id": "915bfda1-7565-4cf7-bd69-90348a3b254c", + "name": "vae", + "type": "VAE", + "linkIds": [ + 14052 + ], + "localized_name": "vae", + "shape": 7, + "pos": [ + -3617.9902859107397, + 3886.7967005388414 + ] + }, + { + "id": "969bf9d4-eb1d-462c-8940-dbbf51b5a2d5", + "name": "text", + "type": "STRING", + "linkIds": [ + 14038 + ], + "localized_name": "text", + "label": "positive_prompt", + "pos": [ + -3617.9902859107397, + 3906.7967005388414 + ] + }, + { + "id": "b0c833ae-af25-43fd-9b03-7b6590ed2249", + "name": "latent", + "type": "LATENT", + "linkIds": [], + "pos": [ + -3617.9902859107397, + 3926.7967005388414 + ] + } + ], + "outputs": [ + { + "id": "8984305c-acc8-4330-bd25-5ed589aed5d9", + "name": "positive", + "type": "CONDITIONING", + "linkIds": [ + 14419 + ], + "localized_name": "positive", + "pos": [ + -2887.4297954820227, + 3804.52193989455 + ] + }, + { + "id": "87bdfca5-a3a4-4115-8cea-2ee314e7c57a", + "name": "negative", + "type": "CONDITIONING", + "linkIds": [ + 14155 + ], + "localized_name": "negative", + "pos": [ + -2887.4297954820227, + 3824.52193989455 + ] + }, + { + "id": "1cfeaf78-5049-4af9-957c-13da423761e3", + "name": "model", + "type": "MODEL", + "linkIds": [ + 14423 + ], + "localized_name": "model", + "pos": [ + -2887.4297954820227, + 3844.52193989455 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 2483, + "type": "CLIPTextEncode", + "pos": [ + -3482.3123142591667, + 3729.764452009041 + ], + "size": [ + 330, + 130 + ], + "flags": { + "collapsed": false + }, + "order": 1, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14057 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 14038 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "slot_index": 0, + "links": [ + 14419 + ] + } + ], + "title": "CLIP Text Encode (Positive Prompt)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.28", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "High quality realistic video. A clean tabletop scene with a small glass sculpture, soft studio lighting, gentle camera movement, subtle reflections, natural shadows, and smooth motion. The camera slowly moves closer, then holds steady for a clear final view." + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 2612, + "type": "CLIPTextEncode", + "pos": [ + -3482.2778641371956, + 4061.479555285701 + ], + "size": [ + 330, + 120 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14058 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 13734 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "slot_index": 0, + "links": [ + 14155 + ] + } + ], + "title": "CLIP Text Encode (Negative Prompt)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.28", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "low quality, blurry, distorted shapes, broken reflections, noisy shadows, overexposed highlights, undersaturated colors, bad anatomy, people, text, watermark, logo, subtitles, harsh flicker, still frame, frozen motion, frame blending artifacts, compression artifacts" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 5137, + "type": "LTX2SamplingPreviewOverride", + "pos": [ + -3481.404969237368, + 3904.2961431762487 + ], + "size": [ + 316.7000030517578, + 98 + ], + "flags": {}, + "order": 3, + "mode": 4, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 14056 + }, + { + "localized_name": "latent_upscale_model", + "name": "latent_upscale_model", + "shape": 7, + "type": "LATENT_UPSCALE_MODEL", + "link": null + }, + { + "localized_name": "vae", + "name": "vae", + "shape": 7, + "type": "VAE", + "link": 14052 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 14423 + ] + } + ], + "title": "Sampling Preview Override", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "89dc2f8485e3fbedd549808b07ec20031cca6bf2", + "Node name for S&R": "LTX2SamplingPreviewOverride", + "aux_id": "kijai/ComfyUI-KJNodes" + }, + "widgets_values": [ + 8 + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5081, + "type": "PrimitiveStringMultiline", + "pos": [ + -3487.4297954820227, + 3501.2832456967894 + ], + "size": [ + 520, + 180 + ], + "flags": { + "collapsed": false + }, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [ + 13734 + ] + } + ], + "title": "Negative Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.2", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "music, underwater, diving, slow motion, still image, bad quality, subtitles, text, watermark, overlay, pc game, yelling, console game, childish, ugly, text, blur, logo, wordmark, static, low quality, noise, white noise, bleep, censoring, censor, bleeping, beep, beeping, newscast, interview, podcast, chinese, mutant, horror, 70's, film grain, comedy, stand-up " + ], + "color": "#432", + "bgcolor": "#653" + } + ], + "groups": [], + "links": [ + { + "id": 13734, + "origin_id": 5081, + "origin_slot": 0, + "target_id": 2612, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 14058, + "origin_id": -10, + "origin_slot": 2, + "target_id": 2612, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14057, + "origin_id": -10, + "origin_slot": 2, + "target_id": 2483, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14056, + "origin_id": -10, + "origin_slot": 3, + "target_id": 5137, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 14052, + "origin_id": -10, + "origin_slot": 4, + "target_id": 5137, + "target_slot": 2, + "type": "VAE" + }, + { + "id": 14038, + "origin_id": -10, + "origin_slot": 5, + "target_id": 2483, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 14155, + "origin_id": 2612, + "origin_slot": 0, + "target_id": -20, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 14419, + "origin_id": 2483, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 14423, + "origin_id": 5137, + "origin_slot": 0, + "target_id": -20, + "target_slot": 2, + "type": "MODEL" + } + ], + "extra": {} + }, + { + "id": "c758fc63-b71c-43f2-b085-ded32443f756", + "version": 1, + "state": { + "lastGroupId": 151, + "lastNodeId": 5239, + "lastLinkId": 14500, + "lastRerouteId": 57 + }, + "revision": 0, + "config": {}, + "name": "Enhancer", + "inputNode": { + "id": -10, + "bounding": [ + -4185.975620413162, + 2995.9229766057383, + 120, + 80 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + -3519.1490771969034, + 3006.5191220105444, + 124.5999984741211, + 60 + ] + }, + "inputs": [ + { + "id": "f3881fd2-d951-4f33-874c-a5cd7f3b1f7d", + "name": "image", + "type": "IMAGE", + "linkIds": [ + 14378, + 14478 + ], + "localized_name": "image", + "shape": 7, + "pos": [ + -4085.975620413162, + 3015.9229766057383 + ] + }, + { + "id": "0357b5d7-3e17-46f2-b7dc-62941f69b495", + "name": "prompt", + "type": "STRING", + "linkIds": [ + 14463 + ], + "localized_name": "prompt", + "pos": [ + -4085.975620413162, + 3035.9229766057383 + ] + } + ], + "outputs": [ + { + "id": "53386daa-e704-4fe0-b148-12f3a8138d5c", + "name": "generated_text", + "type": "STRING", + "linkIds": [ + 14481 + ], + "localized_name": "generated_text", + "pos": [ + -3499.1490771969034, + 3026.5191220105444 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 5185, + "type": "CR Seed", + "pos": [ + -3933.9237459684864, + 2701.3944678867133 + ], + "size": [ + 270, + 102 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "seed", + "name": "seed", + "type": "INT", + "links": [ + 14361, + 14374 + ] + }, + { + "localized_name": "show_help", + "name": "show_help", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI_Comfyroll_CustomNodes", + "ver": "d78b780ae43fcf8c6b7c6505e6ffb4584281ceca", + "Node name for S&R": "CR Seed", + "aux_id": "Suzie1/ComfyUI_Comfyroll_CustomNodes" + }, + "widgets_values": [ + 1090005161630364, + "randomize" + ] + }, + { + "id": 5183, + "type": "CLIPLoader", + "pos": [ + -3930.3935175132056, + 2863.217812048324 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 14377, + 14461 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "CLIPLoader" + }, + "widgets_values": [ + "sulphur_enhance.safetensors", + "stable_diffusion", + "default" + ] + }, + { + "id": 5187, + "type": "TextGenerateLTX2Prompt", + "pos": [ + -3974.8004741920977, + 3024.673944128882 + ], + "size": [ + 400, + 372 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14461 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 14478 + }, + { + "localized_name": "seed", + "name": "sampling_mode.seed", + "type": "INT", + "widget": { + "name": "sampling_mode.seed" + }, + "link": 14374 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "TextGenerateLTX2Prompt" + }, + "widgets_values": [ + "", + 2048, + "on", + 0.7, + 80, + 1, + 0.05, + 1.05, + 0, + 0, + false, + true + ] + }, + { + "id": 5215, + "type": "TextGenerate", + "pos": [ + -3975.3630377173627, + 3462.6441576677366 + ], + "size": [ + 400, + 372 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 14377 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 14378 + }, + { + "localized_name": "prompt", + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 14463 + }, + { + "localized_name": "seed", + "name": "sampling_mode.seed", + "type": "INT", + "widget": { + "name": "sampling_mode.seed" + }, + "link": 14361 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [ + 14481 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.20.1", + "Node name for S&R": "TextGenerate" + }, + "widgets_values": [ + "", + 2048, + "on", + 0.7, + 75, + 1, + 0.1, + 1.05, + 0, + 0, + false, + true + ] + } + ], + "groups": [], + "links": [ + { + "id": 14361, + "origin_id": 5185, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 3, + "type": "INT" + }, + { + "id": 14374, + "origin_id": 5185, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 2, + "type": "INT" + }, + { + "id": 14377, + "origin_id": 5183, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14378, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5215, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14461, + "origin_id": 5183, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 14463, + "origin_id": -10, + "origin_slot": 1, + "target_id": 5215, + "target_slot": 2, + "type": "STRING" + }, + { + "id": 14478, + "origin_id": -10, + "origin_slot": 0, + "target_id": 5187, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 14481, + "origin_id": 5215, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "STRING" + } + ], + "extra": {} + } + ] + }, + "config": {}, + "extra": { + "frontendVersion": "1.42.15", + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true, + "workspace_info": { + "id": "elBQFQknIoLYTEwIloQuw" + }, + "node_versions": { + "comfy-core": "0.3.30", + "comfyui-kjnodes": "1.0.8" + }, + "workflowRendererVersion": "LG", + "reroutes": [ + { + "id": 23, + "pos": [ + -2470.7143821696213, + 3999.039532349397 + ], + "linkIds": [ + 13450 + ] + } + ], + "workflow_name": "LTX-2.3 FunPack Node Set Example", + "ds": { + "scale": 0.8048561793599587, + "offset": [ + 4518.384184524278, + -2916.116634589938 + ] + }, + "linkExtensions": [ + { + "id": 13450, + "parentId": 23 + } + ] + }, + "version": 0.4 +} \ No newline at end of file From 35eae9931809481d0bf435c5f2cfd099b27173b1 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 21:13:51 +0300 Subject: [PATCH 6/8] Tighten Refiner V2 prompt repair intent matching --- CHANGELOG.md | 10 ++ README.md | 8 + conditioning.py | 119 +++++++++++++-- pyproject.toml | 2 +- tests/test_v2_category_alignment.py | 224 ++++++++++++++++++++++++++-- 5 files changed, 343 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfdf12a0..950ed6ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.3.1] - 2026-05-08 + +### Fixed + +Fixed Refiner V2 Prompt Repair so missing/wrong ratings only repair from the current prompt or explicit user intent, instead of pulling unrelated learned favorite actions, details, quality cues, camera moves, or styles from memory. + +Fixed Prompt Repair memory matching so the same word with different neighboring prompt context is treated as different evidence. + +Fixed vague raw user intent handling so prompts like `Figure it out` let the enhanced `positive_prompt` drive repair matching when available. + ## [2.3.0] - 2026-05-08 ### Added diff --git a/README.md b/README.md index fbc2d780..09e3f536 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,14 @@ A set of ComfyUI nodes for experimenting with video generation workflows based on WAN, HunyuanVideo, LTX, and similar models. +## Updates in 2.3.1 + +Refiner V2 Prompt Repair now keeps all missing/wrong ratings tied to the current prompt or explicit user intent. Learned favorite actions, details, quality cues, camera moves, and styles are not repaired into unrelated requests just because they scored well before. + +Prompt Repair now treats the same word in different neighbor contexts as separate evidence, so a liked phrase does not automatically transfer to a different request that happens to share one word. + +When the optional raw user intent is vague, such as `Figure it out`, Refiner V2 now treats the enhanced `positive_prompt` as the stronger repair anchor. + ## Updates in 2.3.0 Refiner V2 now blocks learned appearance, character, subject, and background concepts from Prompt Repair, Lucky auto-injection, and legacy Void memory unless the current prompt explicitly asks for them. diff --git a/conditioning.py b/conditioning.py index b2041afd..73828691 100644 --- a/conditioning.py +++ b/conditioning.py @@ -7202,6 +7202,85 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): text_words = set(self._v2_phrase_words(text_key)) return bool(text_words) and text_words <= prompt_words + def _v2_repair_intent_roots(self, text): + roots = set() + for word in self._v2_phrase_words(text): + roots.add(word) + if len(word) > 4 and word.endswith("ing"): + stem = word[:-3] + roots.add(stem) + if len(stem) > 2 and stem[-1] == stem[-2]: + roots.add(stem[:-1]) + roots.add(stem + "e") + elif len(word) > 3 and word.endswith("ed"): + stem = word[:-2] + roots.add(stem) + roots.add(stem + "e") + elif len(word) > 3 and word.endswith("s"): + roots.add(word[:-1]) + return {root for root in roots if len(root) >= 3} + + def _v2_repair_candidate_matches_intent(self, text, intent_roots): + if not intent_roots: + return False + candidate_roots = self._v2_repair_intent_roots(text) + return bool(candidate_roots & intent_roots) + + def _v2_user_intent_prompt_is_vague(self, prompt): + text = re.sub(r"\s+", " ", str(prompt or "").strip().lower()) + if not text: + return True + words = set(self._v2_phrase_words(text)) + if not words: + return True + vague_words = { + "figure", "out", "something", "anything", "whatever", "surprise", "random", + "choice", "choose", "decide", "good", "nice", "cool", "best", "you", "your", + "it", "make", "do", + } + if len(words) <= 5 and words <= vague_words: + return True + if re.fullmatch(r"(figure it out|surprise me|anything|whatever|your choice|you decide|do something|make it good|make it cool)", text): + return True + scores = self._v2_heuristic_scores(text) + return len(words) <= 3 and not self._v2_axes_for_scores(scores) + + def _v2_repair_reference_context(self, text, reference_phrases): + candidate_roots = self._v2_repair_intent_roots(text) + if not candidate_roots: + return {} + best_phrase = None + best_overlap = 0 + for phrase in reference_phrases or []: + if not isinstance(phrase, dict): + continue + overlap = len(candidate_roots & self._v2_repair_intent_roots(phrase.get("text", ""))) + if overlap > best_overlap: + best_phrase = phrase + best_overlap = overlap + if not isinstance(best_phrase, dict): + return {} + return best_phrase.get("context", {}) if isinstance(best_phrase.get("context", {}), dict) else {} + + def _v2_repair_context_matches_memory(self, text, entry, reference_phrases): + if not isinstance(entry, dict): + return True + context = self._v2_repair_reference_context(text, reference_phrases) + context_words = context.get("context_words", []) if isinstance(context, dict) else [] + senses = entry.get("context_senses", {}) + if isinstance(senses, dict) and senses: + sense, similarity = self._v2_best_context_sense(entry, context) + if isinstance(sense, dict) and similarity >= 0.30: + return True + return len(self._v2_phrase_words(text)) > 1 and not context_words + learned_context = entry.get("context", {}) + learned_words = learned_context.get("context_words", []) if isinstance(learned_context, dict) else [] + if learned_words and context_words: + return self._v2_context_similarity(learned_context, context) >= 0.30 + if learned_words and len(self._v2_phrase_words(text)) <= 1: + return False + return True + def _v2_repair_prompt_for_missing_axes( self, prompt, @@ -7217,6 +7296,14 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return prompt, "Prompt repair: none.", [] candidates = {} + intent_roots = self._v2_repair_intent_roots(prompt) + reference_phrases = [ + phrase + for phrase in list(current_phrases or []) + list(intent_phrases or []) + if isinstance(phrase, dict) + ] + for item in intent_phrases or []: + intent_roots |= self._v2_repair_intent_roots(item.get("text", "")) def candidate_axes(item): if not isinstance(item, dict): @@ -7230,7 +7317,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): axes |= {axis for axis, count in axis_counts.items() if int(count or 0) > 0} return axes - def add_candidate(text, axes, score, source, cluster=None): + def add_candidate(text, axes, score, source, cluster=None, memory_entry=None): clean = self._v2_clean_phrase_text(text) if not clean: return @@ -7242,10 +7329,18 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): axes = set(axes or set()) & missing_axes if not axes or self._v2_prompt_contains_text(prompt, clean): return + if source != "intent" and not self._v2_repair_candidate_matches_intent(clean, intent_roots): + return + if source != "intent" and not self._v2_repair_context_matches_memory(clean, memory_entry, reference_phrases): + return safe_cluster = [ self._v2_clean_phrase_text(item) for item in (cluster or []) - if self._v2_prompt_repair_text_allowed(item) + if ( + self._v2_prompt_repair_text_allowed(item) and + self._v2_repair_candidate_matches_intent(item, intent_roots) and + self._v2_repair_context_matches_memory(item, memory_entry, reference_phrases) + ) ] safe_cluster = [item for item in safe_cluster if item] existing = candidates.get(clean) @@ -7270,7 +7365,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): continue axes = candidate_axes(item) if axes & missing_axes: - add_candidate(item.get("text", ""), axes, 1.75, "previous") + add_candidate(item.get("text", ""), axes, 1.75, "previous", memory_entry=item) preferred_memory = global_state.get("preferred_context_memory", {}) if isinstance(global_state, dict) else {} for entry in preferred_memory.values() if isinstance(preferred_memory, dict) else []: @@ -7295,9 +7390,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): ) if cluster: for offset, item_text in enumerate(cluster[:8]): - add_candidate(item_text, axes, score - offset * 0.03, "preferred_context", cluster=cluster[:8]) + add_candidate(item_text, axes, score - offset * 0.03, "preferred_context", cluster=cluster[:8], memory_entry=entry) else: - add_candidate(entry.get("anchor", ""), axes, score, "preferred_context") + add_candidate(entry.get("anchor", ""), axes, score, "preferred_context", memory_entry=entry) memory = global_state.get("phrase_memory", {}) if isinstance(global_state, dict) else {} for text, entry in memory.items(): @@ -7317,19 +7412,24 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): min(0.9, int(entry.get("wrong_count", 0) or 0) * 0.16) ) if axes & missing_axes and score > 0.60: - add_candidate(entry.get("text", text), axes, score, "memory") + add_candidate(entry.get("text", text), axes, score, "memory", memory_entry=entry) current_axes = set() for phrase in current_phrases or []: current_axes |= candidate_axes(phrase) missing_not_represented = missing_axes - current_axes + source_priority = { + "intent": 4, + "previous": 3, + "preferred_context": 2, + "memory": 1, + } ranked = sorted( candidates.values(), key=lambda item: ( bool(item["axes"] & missing_not_represented), - item["source"] == "preferred_context", - item["source"] == "intent", + source_priority.get(item["source"], 0), item["score"], len(item["text"]), ), @@ -7607,10 +7707,11 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): analysis_prompt = self._v2_prompt_key(positive_prompt) intent_prompt = self._v2_prompt_key(user_intent_prompt) + intent_prompt_is_vague = self._v2_user_intent_prompt_is_vague(intent_prompt) current_prompt_refusal = self._prompt_looks_like_refusal(analysis_prompt) phrases = [] if current_prompt_refusal else self._v2_classify_phrases(clip, self._ordered_prompt_phrases(analysis_prompt), global_state) intent_phrases = [] - if intent_prompt and not current_prompt_refusal: + if intent_prompt and not intent_prompt_is_vague and not current_prompt_refusal: intent_phrases = self._v2_classify_phrases( clip, self._ordered_prompt_phrases(intent_prompt), diff --git a/pyproject.toml b/pyproject.toml index 043b7fce..4745f631 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [project] name = "ComfyUI-FunPack" # Unique identifier for your node. Immutable after creation. description = "A set of nodes for experiments with video generation models, including prompt refinement, adaptive LoRA weight workflows, story tools, video stitching, lorebook enhancement and more." -version = "2.3.0" # Custom Node version. Must be semantically versioned. +version = "2.3.1" # Custom Node version. Must be semantically versioned. license = { text = "GNU GPL v3" } dependencies = [] # Filled in from requirements.txt diff --git a/tests/test_v2_category_alignment.py b/tests/test_v2_category_alignment.py index e8191bf4..95b8b534 100644 --- a/tests/test_v2_category_alignment.py +++ b/tests/test_v2_category_alignment.py @@ -640,6 +640,7 @@ def test_normal_previous_run_can_train_before_current_refusal_is_discarded(tmp_p def test_liked_action_detail_context_clusters_repair_missing_axes(): refiner = FunPackVideoRefinerV2() global_state = {"phrase_memory": {}, "preferred_context_memory": {}} + rich_prompt = "woman walking reaching hand tiny particles rain reflections" liked_phrases = refiner._v2_classify_phrases( None, prompt_items(refiner, [ @@ -656,11 +657,18 @@ def test_liked_action_detail_context_clusters_repair_missing_axes(): refiner._v2_update_phrase_memory( global_state, - {"prompt": "woman walking reaching hand tiny particles rain reflections", "phrases": liked_phrases}, + {"prompt": rich_prompt, "phrases": liked_phrases}, profile, 1, feedback, ) + assert "Preferred context stored" in refiner._v2_update_preferred_context_memory( + global_state, + {"phrases": liked_phrases}, + profile, + 2, + feedback, + ) missing_profile = normalize_refiner_v2_rating("Missing details + action") missing_feedback = refiner._v2_axis_feedback(missing_profile, None) @@ -669,6 +677,11 @@ def test_liked_action_detail_context_clusters_repair_missing_axes(): prompt_items(refiner, ["woman", "rain"]), global_state, ) + intent_phrases = refiner._v2_classify_phrases( + None, + refiner._ordered_prompt_phrases(rich_prompt), + global_state, + ) repaired, status, candidates = refiner._v2_repair_prompt_for_missing_axes( "woman, rain", @@ -676,21 +689,206 @@ def test_liked_action_detail_context_clusters_repair_missing_axes(): global_state, None, missing_feedback, + intent_phrases=intent_phrases, ) - assert "Preferred context stored" in refiner._v2_update_preferred_context_memory( - global_state, - {"phrases": liked_phrases}, - profile, - 2, - feedback, - ) assert "walking" in repaired assert "tiny particles" in repaired - assert "preferred_context" in status + assert "intent" in status or "preferred_context" in status assert len(candidates) >= 2 +def test_prompt_repair_does_not_pull_unrequested_memory_for_any_missing_axis(): + refiner = FunPackVideoRefinerV2() + global_state = { + "phrase_memory": { + "walking": { + "text": "walking", + "primary": "action", + "effective_category_scores": refiner._v2_heuristic_scores("walking"), + "wanted_axes": {"action": 5}, + "score": 5.0, + "liked_count": 5, + }, + "tiny particles": { + "text": "tiny particles", + "primary": "details", + "effective_category_scores": refiner._v2_heuristic_scores("tiny particles"), + "wanted_axes": {"details": 5}, + "score": 5.0, + "liked_count": 5, + }, + "cinematic lighting": { + "text": "cinematic lighting", + "primary": "style", + "effective_category_scores": refiner._v2_heuristic_scores("cinematic lighting"), + "wanted_axes": {"quality": 5}, + "score": 5.0, + "liked_count": 5, + }, + "glass reflections": { + "text": "glass reflections", + "primary": "details", + "effective_category_scores": refiner._v2_heuristic_scores("glass reflections"), + "wanted_axes": {"details": 2}, + "score": 2.0, + "liked_count": 1, + }, + }, + } + profile = normalize_refiner_v2_rating("Awful") + feedback = refiner._v2_axis_feedback(profile, None) + current_phrases = refiner._v2_classify_phrases( + None, + prompt_items(refiner, ["woman", "glass"]), + global_state, + ) + + repaired, _, candidates = refiner._v2_repair_prompt_for_missing_axes( + "woman, glass", + current_phrases, + global_state, + None, + feedback, + ) + + candidate_texts = {candidate["text"] for candidate in candidates} + assert "glass reflections" in repaired + assert "walking" not in repaired + assert "tiny particles" not in repaired + assert "cinematic lighting" not in repaired + assert "walking" not in candidate_texts + assert "tiny particles" not in candidate_texts + assert "cinematic lighting" not in candidate_texts + + +def test_prompt_repair_treats_same_word_with_different_neighbours_as_different(): + refiner = FunPackVideoRefinerV2() + global_state = { + "phrase_memory": { + "turning head": { + "text": "turning head", + "primary": "action", + "effective_category_scores": refiner._v2_heuristic_scores("turning head"), + "wanted_axes": {"action": 4}, + "score": 4.0, + "liked_count": 4, + "context_senses": { + "mid|eyes,portrait": { + "context": { + "anchor_words": ["head", "turning"], + "context_words": ["portrait", "eyes"], + "position_bucket": "mid", + "window": 3, + }, + "category_weights": refiner._v2_category_template(0.0), + "effective_category_scores": refiner._v2_heuristic_scores("turning head"), + "category_evidence_count": 4, + "occurrence_count": 4, + }, + }, + }, + }, + } + profile = normalize_refiner_v2_rating("Missing action") + feedback = refiner._v2_axis_feedback(profile, None) + current_phrases = refiner._v2_classify_phrases( + None, + prompt_items(refiner, ["car", "turning wheel", "street"]), + global_state, + ) + + repaired, _, candidates = refiner._v2_repair_prompt_for_missing_axes( + "car, turning wheel, street", + current_phrases, + global_state, + None, + feedback, + ) + + assert "turning head" not in repaired + assert all(candidate["text"] != "turning head" for candidate in candidates) + + +def test_vague_user_intent_lets_enhanced_positive_prompt_anchor_repair(): + refiner = FunPackVideoRefinerV2() + global_state = { + "phrase_memory": { + "walking slowly": { + "text": "walking slowly", + "primary": "action", + "effective_category_scores": refiner._v2_heuristic_scores("walking slowly"), + "wanted_axes": {"action": 3}, + "score": 3.0, + "liked_count": 3, + }, + }, + } + assert refiner._v2_user_intent_prompt_is_vague("Figure it out") + assert not refiner._v2_user_intent_prompt_is_vague("person walking") + + profile = normalize_refiner_v2_rating("Missing action") + feedback = refiner._v2_axis_feedback(profile, None) + current_phrases = refiner._v2_classify_phrases( + None, + prompt_items(refiner, ["woman", "walking through glass hallway"]), + global_state, + ) + + repaired, _, candidates = refiner._v2_repair_prompt_for_missing_axes( + "woman, walking through glass hallway", + current_phrases, + global_state, + None, + feedback, + intent_phrases=[], + ) + + assert "walking slowly" in repaired + assert any(candidate["text"] == "walking slowly" for candidate in candidates) + + +def test_complex_user_intent_ranks_before_matching_preferred_memory(): + refiner = FunPackVideoRefinerV2() + global_state = { + "phrase_memory": {}, + "preferred_context_memory": { + "reach-memory": { + "anchor": "reaching hand slowly", + "axes": {"action": 4}, + "context": {}, + "phrases": ["reaching hand slowly"], + "score": 10.0, + "liked_count": 8, + }, + }, + } + profile = normalize_refiner_v2_rating("Missing action") + feedback = refiner._v2_axis_feedback(profile, None) + current_phrases = refiner._v2_classify_phrases( + None, + prompt_items(refiner, ["woman"]), + global_state, + ) + intent_phrases = refiner._v2_classify_phrases( + None, + refiner._ordered_prompt_phrases("woman reaching hand toward glass"), + global_state, + ) + + repaired, _, candidates = refiner._v2_repair_prompt_for_missing_axes( + "woman", + current_phrases, + global_state, + None, + feedback, + intent_phrases=intent_phrases, + ) + + assert "reaching hand toward glass" in repaired + assert candidates[0]["source"] == "intent" + + def test_phrase_clusters_train_more_strongly_than_ngrams_and_tokens(): refiner = FunPackVideoRefinerV2() global_state = {"phrase_memory": {}, "preferred_context_memory": {}} @@ -725,7 +923,13 @@ def test_repair_candidates_saved_as_json_lists(tmp_path): refiner.refine_v2(rich_prompt, FakeClip(), "Perfect", "json-repair-test") refiner.refine_v2(rich_prompt, FakeClip(), "Perfect", "json-repair-test") - refiner.refine_v2("woman, rain", FakeClip(), "Missing details + action", "json-repair-test") + refiner.refine_v2( + "woman, rain", + FakeClip(), + "Missing details + action", + "json-repair-test", + user_intent_prompt=rich_prompt, + ) state = json.loads(state_path.read_text(encoding="utf-8")) candidates = state["last_run"]["repair_candidates"] From 10d6a496038927d16f623b0e62257a1852d66b39 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 21:35:42 +0300 Subject: [PATCH 7/8] Release 2.3.2 intent alignment memory --- CHANGELOG.md | 10 + README.md | 6 + conditioning.py | 449 +++++++++++++++++++++++++++- docs/FunPackVideoRefinerV2.md | 2 + pyproject.toml | 2 +- tests/test_v2_category_alignment.py | 176 +++++++++++ 6 files changed, 643 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950ed6ec..c1eb1806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.3.2] - 2026-05-08 + +### Added + +Added Refiner V2 original-intent alignment memory. When `user_intent_prompt` stays the same but an enhancer produces different `positive_prompt` variants, the refiner now remembers intent-enhance pairs, which variants rated well, which original-intent phrases were omitted, and which enhancer-only phrases were rejected. + +### Fixed + +Fixed Refiner V2 so learned original-intent omissions can be restored on later runs, while repeatedly rejected enhancer-only additions can be removed before encoding. Rejected enhancer-only full words and adjacent word pairs are stored as omit evidence for that original intent. + ## [2.3.1] - 2026-05-08 ### Fixed diff --git a/README.md b/README.md index 09e3f536..6622a29f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ A set of ComfyUI nodes for experimenting with video generation workflows based on WAN, HunyuanVideo, LTX, and similar models. +## Updates in 2.3.2 + +Refiner V2 now learns original-intent alignment when `user_intent_prompt` stays the same but an enhancer gives different `positive_prompt` variants. Ratings teach it which intent-enhance pairs represented the original request, which original phrases were missing, and which enhancer-only additions were rejected. + +Learned original-intent omissions can now be restored on later runs, while repeatedly rejected enhancer-only full words and adjacent word pairs can be omitted before encoding. + ## Updates in 2.3.1 Refiner V2 Prompt Repair now keeps all missing/wrong ratings tied to the current prompt or explicit user intent. Learned favorite actions, details, quality cues, camera moves, and styles are not repaired into unrelated requests just because they scored well before. diff --git a/conditioning.py b/conditioning.py index 73828691..1d2a09d7 100644 --- a/conditioning.py +++ b/conditioning.py @@ -5750,6 +5750,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "axis_conditioning_memory": {}, "lora_weight_memory": {}, "preferred_context_memory": {}, + "intent_alignment_memory": {}, "loss_history": [], }, "prompt_histories": {}, @@ -5772,6 +5773,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): data["global"].setdefault("phrase_memory", {}) data["global"].setdefault("lora_weight_memory", {}) data["global"].setdefault("preferred_context_memory", {}) + data["global"].setdefault("intent_alignment_memory", {}) data["global"].setdefault("loss_history", []) return data, "loaded" except (json.JSONDecodeError, OSError, ValueError): @@ -6614,6 +6616,418 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return "" return text + def _v2_phrase_root_set(self, text): + return self._v2_repair_intent_roots(text) + + def _v2_phrase_texts_match(self, left, right): + left_clean = self._v2_clean_phrase_text(left) + right_clean = self._v2_clean_phrase_text(right) + if not left_clean or not right_clean: + return False + if self._v2_prompt_contains_text(left_clean, right_clean) or self._v2_prompt_contains_text(right_clean, left_clean): + return True + left_roots = self._v2_phrase_root_set(left_clean) + right_roots = self._v2_phrase_root_set(right_clean) + if not left_roots or not right_roots: + return False + overlap = left_roots & right_roots + if not overlap: + return False + needed = min(2, len(left_roots)) + return len(overlap) >= needed or (len(overlap) / max(1, len(left_roots))) >= 0.58 + + def _v2_phrase_represented_by(self, text, phrases): + return any( + self._v2_phrase_texts_match(text, phrase.get("text", "") if isinstance(phrase, dict) else phrase) + for phrase in phrases or [] + ) + + def _v2_alignment_token_units(self, text): + words = self._v2_phrase_words(text) + units = [{"token": word, "kind": "word", "words": [word]} for word in words] + for index in range(0, max(0, len(words) - 1)): + pair = " ".join(words[index:index + 2]) + units.append({"token": pair, "kind": "pair", "words": words[index:index + 2]}) + return units + + def _v2_intent_alignment_key(self, intent_prompt): + clean = self._v2_prompt_key(intent_prompt).lower() + return md5(clean.encode("utf-8")).hexdigest() + + def _v2_intent_alignment_phrase_payload(self, phrase): + text = self._v2_clean_phrase_text(phrase.get("text", "") if isinstance(phrase, dict) else phrase) + if not text: + return None + source = phrase if isinstance(phrase, dict) else {} + scores = source.get("effective_category_scores", source.get("category_scores", self._v2_heuristic_scores(text))) + axes = self._v2_order_axes(self._v2_axes_for_scores(scores)) + return { + "text": text, + "axes": axes, + "primary": source.get("primary", self._v2_primary_category_for_text(text)), + "effective_category_scores": self._v2_clean_category_scores(scores), + } + + def _v2_update_intent_alignment_memory(self, global_state, last_run, rating_profile, iter_num, axis_feedback=None): + if not isinstance(global_state, dict) or not isinstance(last_run, dict) or rating_profile.get("skip_learning"): + return "Intent alignment: no learning update." + intent_prompt = self._v2_prompt_key(last_run.get("intent_prompt", "")) + if not intent_prompt or last_run.get("intent_prompt_is_vague") or self._v2_user_intent_prompt_is_vague(intent_prompt): + return "Intent alignment: no explicit original intent." + + positive_prompt = self._v2_prompt_key(last_run.get("prompt", "")) + positive_phrases = [phrase for phrase in last_run.get("phrases", []) or [] if isinstance(phrase, dict)] + intent_phrases = [phrase for phrase in last_run.get("intent_phrases", []) or [] if isinstance(phrase, dict)] + if not intent_phrases: + intent_phrases = self._v2_classify_phrases(None, self._ordered_prompt_phrases(intent_prompt), global_state) + if not positive_phrases or not intent_phrases: + return "Intent alignment: no comparable prompt phrases." + + missing_intent = [ + phrase for phrase in intent_phrases + if not self._v2_phrase_represented_by(phrase.get("text", ""), positive_phrases) + ] + extra_positive = [ + phrase for phrase in positive_phrases + if ( + not self._v2_phrase_represented_by(phrase.get("text", ""), intent_phrases) and + not self._v2_prompt_contains_text(intent_prompt, phrase.get("text", "")) + ) + ] + + memory = global_state.setdefault("intent_alignment_memory", {}) + intent_key = self._v2_intent_alignment_key(intent_prompt) + slot = memory.setdefault(intent_key, { + "intent_prompt": intent_prompt, + "variants": {}, + "intent_enhance_pairs": {}, + "intent_tokens": {}, + "provided_tokens": {}, + "bad_tokens": {}, + "missing_intent_phrases": {}, + "extra_positive_phrases": {}, + "last_seen_iter": 0, + }) + slot["intent_prompt"] = intent_prompt + slot["last_seen_iter"] = int(iter_num) + + reward = float(rating_profile.get("reward", 0.0)) + rating_key = rating_profile.get("key", "") + axis_feedback = axis_feedback or self._v2_axis_feedback( + rating_profile, + global_state.get("last_missing_axes", []), + ) + missing_axes = set(axis_feedback.get("missing_axes", [])) + wrong_axes = set(axis_feedback.get("wrong_axes", [])) + + variant_key = md5(positive_prompt.encode("utf-8")).hexdigest() + variants = slot.setdefault("variants", {}) + variant = variants.setdefault(variant_key, { + "positive_prompt": positive_prompt, + "rating_count": 0, + "avg_reward": 0.0, + "missing_intent_count": 0, + "extra_positive_count": 0, + "last_rating_label": "", + "last_seen_iter": 0, + }) + count = int(variant.get("rating_count", 0)) + variant["avg_reward"] = round((float(variant.get("avg_reward", 0.0)) * count + reward) / float(count + 1), 6) + variant["rating_count"] = count + 1 + variant["missing_intent_count"] = len(missing_intent) + variant["extra_positive_count"] = len(extra_positive) + variant["last_rating_label"] = rating_profile.get("label", "") + variant["last_seen_iter"] = int(iter_num) + pairs = slot.setdefault("intent_enhance_pairs", {}) + pairs[variant_key] = { + "intent_prompt": intent_prompt, + "positive_prompt": positive_prompt, + "rating_count": int(variant["rating_count"]), + "avg_reward": float(variant["avg_reward"]), + "missing_intent_count": int(variant["missing_intent_count"]), + "extra_positive_count": int(variant["extra_positive_count"]), + "last_rating_label": variant["last_rating_label"], + "last_seen_iter": int(iter_num), + } + + intent_token_memory = slot.setdefault("intent_tokens", {}) + intent_token_set = set() + for unit in self._v2_alignment_token_units(intent_prompt): + token = unit["token"] + intent_token_set.add(token) + entry = intent_token_memory.setdefault(token, { + "token": token, + "kind": unit["kind"], + "words": list(unit["words"]), + "seen_count": 0, + "last_seen_iter": 0, + }) + entry["kind"] = unit["kind"] + entry["words"] = list(unit["words"]) + entry["seen_count"] = int(entry.get("seen_count", 0)) + 1 + entry["last_seen_iter"] = int(iter_num) + + provided_token_memory = slot.setdefault("provided_tokens", {}) + bad_token_memory = slot.setdefault("bad_tokens", {}) + token_updates = 0 + for phrase in positive_phrases: + text = self._v2_clean_phrase_text(phrase.get("text", "")) + if not text: + continue + phrase_axes = self._v2_phrase_axes(phrase) + phrase_is_blocked_extra = ( + not self._v2_phrase_represented_by(text, intent_phrases) and + not self._v2_prompt_contains_text(intent_prompt, text) + ) + phrase_is_bad_extra = ( + rating_key == "awful" or + (rating_key == "wrong_appearance" and self._v2_item_has_blocked_auto_category(phrase)) or + bool(wrong_axes & phrase_axes) or + (float(reward) < -0.35 and phrase_is_blocked_extra) + ) + for unit in self._v2_alignment_token_units(text): + token = unit["token"] + entry = provided_token_memory.setdefault(token, { + "token": token, + "kind": unit["kind"], + "words": list(unit["words"]), + "score": 0.0, + "seen_count": 0, + "accepted_count": 0, + "rejected_count": 0, + "intent_count": 0, + "enhancer_only_count": 0, + "phrases": [], + "variants": {}, + "omit": False, + "last_seen_iter": 0, + }) + entry["kind"] = unit["kind"] + entry["words"] = list(unit["words"]) + entry["seen_count"] = int(entry.get("seen_count", 0)) + 1 + entry["last_seen_iter"] = int(iter_num) + entry.setdefault("variants", {})[variant_key] = int(entry.setdefault("variants", {}).get(variant_key, 0)) + 1 + phrases_for_token = list(entry.get("phrases", [])) + if text not in phrases_for_token: + phrases_for_token.append(text) + entry["phrases"] = phrases_for_token[-12:] + if token in intent_token_set: + entry["intent_count"] = int(entry.get("intent_count", 0)) + 1 + delta = 0.06 if rating_key == "like" else 0.0 + else: + entry["enhancer_only_count"] = int(entry.get("enhancer_only_count", 0)) + 1 + if rating_key == "like": + delta = 0.12 + entry["accepted_count"] = int(entry.get("accepted_count", 0)) + 1 + elif phrase_is_bad_extra: + delta = -0.60 if rating_key == "wrong_appearance" else -0.36 + entry["rejected_count"] = int(entry.get("rejected_count", 0)) + 1 + else: + delta = max(-0.06, min(0.08, reward * 0.06)) + entry["score"] = round(max(-6.0, min(6.0, float(entry.get("score", 0.0)) + delta)), 4) + entry["omit"] = ( + token not in intent_token_set and + float(entry.get("score", 0.0)) <= -0.50 and + int(entry.get("rejected_count", 0)) > int(entry.get("accepted_count", 0)) + ) + if entry["omit"]: + bad_token_memory[token] = { + "token": token, + "kind": unit["kind"], + "words": list(unit["words"]), + "score": float(entry.get("score", 0.0)), + "rejected_count": int(entry.get("rejected_count", 0)), + "accepted_count": int(entry.get("accepted_count", 0)), + "phrases": list(entry.get("phrases", []))[-8:], + "last_seen_iter": int(iter_num), + } + else: + bad_token_memory.pop(token, None) + token_updates += 1 + + missing_updates = 0 + for phrase in missing_intent: + payload = self._v2_intent_alignment_phrase_payload(phrase) + if not payload: + continue + axes = set(payload.get("axes", [])) + entry = slot.setdefault("missing_intent_phrases", {}).setdefault(payload["text"], { + **payload, + "score": 0.0, + "missing_count": 0, + "forgiven_count": 0, + "last_seen_iter": 0, + }) + if rating_key == "like": + delta = -0.18 + entry["forgiven_count"] = int(entry.get("forgiven_count", 0)) + 1 + elif rating_key == "awful": + delta = 0.70 + entry["missing_count"] = int(entry.get("missing_count", 0)) + 1 + elif missing_axes: + delta = 0.95 if axes & missing_axes else 0.28 + entry["missing_count"] = int(entry.get("missing_count", 0)) + 1 + elif wrong_axes: + delta = 0.42 if axes & wrong_axes else 0.16 + entry["missing_count"] = int(entry.get("missing_count", 0)) + 1 + else: + delta = -0.10 if reward > 0.35 else 0.18 if reward < -0.20 else 0.0 + entry.update(payload) + entry["score"] = round(max(-2.0, min(6.0, float(entry.get("score", 0.0)) + delta)), 4) + entry["last_seen_iter"] = int(iter_num) + missing_updates += 1 + + extra_updates = 0 + for phrase in extra_positive: + payload = self._v2_intent_alignment_phrase_payload(phrase) + if not payload: + continue + axes = set(payload.get("axes", [])) + entry = slot.setdefault("extra_positive_phrases", {}).setdefault(payload["text"], { + **payload, + "score": 0.0, + "accepted_count": 0, + "rejected_count": 0, + "last_seen_iter": 0, + }) + if rating_key == "like": + delta = 0.42 + entry["accepted_count"] = int(entry.get("accepted_count", 0)) + 1 + elif rating_key == "wrong_appearance" and self._v2_item_has_blocked_auto_category(payload): + delta = -0.95 + entry["rejected_count"] = int(entry.get("rejected_count", 0)) + 1 + elif rating_key == "awful": + delta = -0.78 + entry["rejected_count"] = int(entry.get("rejected_count", 0)) + 1 + elif wrong_axes: + delta = -0.70 if axes & wrong_axes else -0.25 + entry["rejected_count"] = int(entry.get("rejected_count", 0)) + 1 + elif reward < -0.35: + delta = -0.46 + entry["rejected_count"] = int(entry.get("rejected_count", 0)) + 1 + else: + delta = max(-0.08, min(0.12, reward * 0.10)) + entry.update(payload) + entry["score"] = round(max(-6.0, min(6.0, float(entry.get("score", 0.0)) + delta)), 4) + entry["last_seen_iter"] = int(iter_num) + extra_updates += 1 + + if len(variants) > 40: + slot["variants"] = dict(sorted( + variants.items(), + key=lambda item: ( + float(item[1].get("avg_reward", 0.0)) if isinstance(item[1], dict) else -99.0, + int(item[1].get("rating_count", 0)) if isinstance(item[1], dict) else 0, + int(item[1].get("last_seen_iter", 0)) if isinstance(item[1], dict) else 0, + ), + reverse=True, + )[:40]) + + if memory and len(memory) > 80: + global_state["intent_alignment_memory"] = dict(sorted( + memory.items(), + key=lambda item: int(item[1].get("last_seen_iter", 0)) if isinstance(item[1], dict) else 0, + reverse=True, + )[:80]) + + return ( + "Intent alignment learned: " + f"{missing_updates} omitted original phrase(s), {extra_updates} enhancer-only phrase(s), " + f"{token_updates} provided token(s), {len(bad_token_memory)} omit token(s), " + f"variant reward {variant['avg_reward']:+.2f}." + ) + + def _v2_apply_intent_alignment_memory(self, prompt, current_phrases, intent_prompt, intent_phrases, global_state): + intent_prompt = self._v2_prompt_key(intent_prompt) + if not intent_prompt or self._v2_user_intent_prompt_is_vague(intent_prompt): + return prompt, "Intent alignment: no explicit original intent.", [] + memory = global_state.get("intent_alignment_memory", {}) if isinstance(global_state, dict) else {} + slot = memory.get(self._v2_intent_alignment_key(intent_prompt)) if isinstance(memory, dict) else None + if not isinstance(slot, dict): + return prompt, "Intent alignment: no learned enhancer variants for this original prompt.", [] + + intent_phrases = [phrase for phrase in intent_phrases or [] if isinstance(phrase, dict)] + current_phrases = [phrase for phrase in current_phrases or [] if isinstance(phrase, dict)] + additions = [] + for entry in sorted( + slot.get("missing_intent_phrases", {}).values(), + key=lambda item: ( + float(item.get("score", 0.0)) if isinstance(item, dict) else -99.0, + int(item.get("missing_count", 0)) if isinstance(item, dict) else 0, + ), + reverse=True, + ): + if not isinstance(entry, dict): + continue + text = self._v2_clean_phrase_text(entry.get("text", "")) + if ( + not text or + float(entry.get("score", 0.0)) < 0.55 or + self._v2_prompt_contains_text(prompt, text) or + self._v2_phrase_represented_by(text, current_phrases) or + not self._v2_phrase_represented_by(text, intent_phrases) + ): + continue + additions.append(text) + if len(additions) >= 4: + break + + bad_extra_texts = [] + for entry in slot.get("extra_positive_phrases", {}).values(): + if not isinstance(entry, dict): + continue + text = self._v2_clean_phrase_text(entry.get("text", "")) + if ( + text and + float(entry.get("score", 0.0)) <= -0.55 and + int(entry.get("rejected_count", 0)) > int(entry.get("accepted_count", 0)) and + not self._v2_phrase_represented_by(text, intent_phrases) + ): + bad_extra_texts.append(text) + bad_extra_tokens = { + str(token) + for token, entry in slot.get("bad_tokens", {}).items() + if isinstance(entry, dict) and bool(entry.get("token")) + } + intent_token_set = {unit["token"] for unit in self._v2_alignment_token_units(intent_prompt)} + + removed = [] + segments = [segment.strip() for segment in re.split(r"[,;\n]+", str(prompt or "")) if segment.strip()] + if segments and (bad_extra_texts or bad_extra_tokens): + kept = [] + for segment in segments: + segment_is_intent = self._v2_phrase_represented_by(segment, intent_phrases) + segment_is_bad_extra = any( + self._v2_phrase_texts_match(segment, extra_text) or self._v2_prompt_contains_text(segment, extra_text) + for extra_text in bad_extra_texts + ) + segment_tokens = {unit["token"] for unit in self._v2_alignment_token_units(segment)} + segment_has_bad_token = bool((segment_tokens - intent_token_set) & bad_extra_tokens) + if (segment_is_bad_extra or segment_has_bad_token) and not segment_is_intent: + removed.append(segment) + continue + kept.append(segment) + prompt = ", ".join(kept) if kept else str(prompt or "").strip() + + if additions: + prompt = f"{prompt}, {', '.join(additions)}" if str(prompt or "").strip() else ", ".join(additions) + + if not additions and not removed: + return prompt, "Intent alignment: learned variants present, no prompt changes needed.", [] + + adjustments = [ + {"text": text, "source": "intent_missing", "action": "added"} + for text in additions + ] + [ + {"text": text, "source": "enhancer_extra", "action": "removed"} + for text in removed + ] + return ( + prompt, + f"Intent alignment: restored {len(additions)} original phrase(s), removed {len(removed)} rejected enhancer-only phrase(s).", + adjustments, + ) + def _v2_context_cluster_key(self, text, context): signature = self._v2_context_signature(context) key = f"{text}|{signature}" if signature else text @@ -7676,6 +8090,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): global_state.setdefault("axis_conditioning_memory", {}) global_state.setdefault("lora_weight_memory", {}) global_state.setdefault("preferred_context_memory", {}) + global_state.setdefault("intent_alignment_memory", {}) global_state.setdefault("loss_history", []) previous_run = state.get("last_run") previous_run_refusal = self._v2_run_looks_like_refusal(previous_run) @@ -7701,6 +8116,14 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): int(global_state.get("total_iterations", 0)) + 1, axis_feedback, ) + intent_learning_status = self._v2_update_intent_alignment_memory( + global_state, + previous_run, + learning_profile, + int(global_state.get("total_iterations", 0)) + 1, + axis_feedback, + ) + memory_status = f"{memory_status}\n{intent_learning_status}" self._v2_update_conditioning_memory(global_state, previous_run, learning_profile, axis_feedback) if has_previous_run and not learning_profile.get("skip_learning"): self._v2_update_streaks(global_state, learning_profile) @@ -7720,6 +8143,8 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): refusal_status = "" repair_status = "Prompt repair: none." repair_candidates = [] + intent_alignment_status = "Intent alignment: no explicit original intent." + intent_alignment_adjustments = [] if current_prompt_refusal: prompt_to_encode = analysis_prompt lucky_status = "Prompt refusal filter: enhancer refusal detected; current prompt will not be stored or learned." @@ -7729,7 +8154,14 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): prompt_to_encode, lucky_status = self._v2_compose_lucky_prompt(analysis_prompt, phrases, global_state) encoded_role = "lucky prompt" else: - prompt_to_encode, emphasis_status = self._v2_emphasized_prompt(analysis_prompt, phrases, global_state, learning_profile) + aligned_prompt, intent_alignment_status, intent_alignment_adjustments = self._v2_apply_intent_alignment_memory( + analysis_prompt, + phrases, + intent_prompt, + intent_phrases, + global_state, + ) + prompt_to_encode, emphasis_status = self._v2_emphasized_prompt(aligned_prompt, phrases, global_state, learning_profile) prompt_to_encode, repair_status, repair_candidates = self._v2_repair_prompt_for_missing_axes( prompt_to_encode, phrases, @@ -7809,6 +8241,15 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): if len(prompt_preview) > 240: prompt_preview = prompt_preview[:237].rstrip() + "..." state_repair_candidates = self._v2_serializable_repair_candidates(repair_candidates) + state_intent_alignment_adjustments = [ + { + "text": str(item.get("text", "")), + "source": str(item.get("source", "")), + "action": str(item.get("action", "")), + } + for item in intent_alignment_adjustments + if isinstance(item, dict) and str(item.get("text", "")).strip() + ] if prompt_history is not None: prompt_history["canonical_prompt"] = analysis_prompt @@ -7821,6 +8262,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "prompt": prompt_to_encode, "phrases": phrases, "repair_candidates": state_repair_candidates, + "intent_alignment_adjustments": state_intent_alignment_adjustments, }) if current_prompt_refusal: @@ -7832,6 +8274,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "conditioning": tensor_to_serializable(refined.detach().cpu()), "phrases": phrases, "intent_prompt": intent_prompt, + "intent_phrases": intent_phrases, + "intent_prompt_is_vague": bool(intent_prompt_is_vague), + "intent_alignment_adjustments": state_intent_alignment_adjustments, "repair_candidates": state_repair_candidates, "encoded_role": encoded_role, "auto_injected_prompt_additions": [ @@ -7860,6 +8305,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): f"{adaptation_status}\n" f"{training_guidance}\n" f"{lucky_status}" + f"\n{intent_alignment_status}" f"\n{repair_status}" f"{refusal_status_line}" ) @@ -7896,6 +8342,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): "Adaptation\n" f"{adaptation_status}\n" f"{lucky_status}\n" + f"{intent_alignment_status}\n" f"{repair_status}" f"{refusal_status_line}" ), diff --git a/docs/FunPackVideoRefinerV2.md b/docs/FunPackVideoRefinerV2.md index d7f8f7ab..e124eae3 100644 --- a/docs/FunPackVideoRefinerV2.md +++ b/docs/FunPackVideoRefinerV2.md @@ -40,6 +40,8 @@ Use `Wrong appearance` when the video is polluted by remembered clothing, charac **lora_stack**: Optional stack from `FunPack Apply LoRA Weights` / `FunPack LoRA Loader`. V2 writes prompt-specific suggested model weights. +**user_intent_prompt**: Optional raw/original request. When connected, V2 compares it with the enhanced `positive_prompt`, stores intent-enhance pairs, remembers all provided full-word and adjacent word-pair tokens for that intent, and can omit enhancer-only tokens that repeatedly led to bad ratings. + **im_feeling_lucky**: When enabled, V2 composes a learned prompt from rated phrase memory and encodes it through the connected CLIP. When disabled, V2 may still store Lucky memory from rated runs, but it does not compose or apply a Lucky prompt. ## Appearance Safety diff --git a/pyproject.toml b/pyproject.toml index 4745f631..281314e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [project] name = "ComfyUI-FunPack" # Unique identifier for your node. Immutable after creation. description = "A set of nodes for experiments with video generation models, including prompt refinement, adaptive LoRA weight workflows, story tools, video stitching, lorebook enhancement and more." -version = "2.3.1" # Custom Node version. Must be semantically versioned. +version = "2.3.2" # Custom Node version. Must be semantically versioned. license = { text = "GNU GPL v3" } dependencies = [] # Filled in from requirements.txt diff --git a/tests/test_v2_category_alignment.py b/tests/test_v2_category_alignment.py index 95b8b534..8f9d2fe0 100644 --- a/tests/test_v2_category_alignment.py +++ b/tests/test_v2_category_alignment.py @@ -59,6 +59,14 @@ def prompt_items(refiner, words): ] +def prompt_phrases(refiner, prompt, global_state=None): + return refiner._v2_classify_phrases( + None, + refiner._ordered_prompt_phrases(prompt), + global_state or {"phrase_memory": {}}, + ) + + def train_prompt_context(refiner, words, rating_label, global_state=None, iterations=1): global_state = global_state or {"phrase_memory": {}} phrases = refiner._v2_classify_phrases(None, prompt_items(refiner, words), global_state) @@ -279,6 +287,174 @@ def test_prompt_repair_blocks_appearance_subject_and_environment(): assert all(candidate["text"] != "white tights" for candidate in candidates) +def test_intent_alignment_learns_missing_original_intent_from_enhancer_variant(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "intent_alignment_memory": {}} + intent_prompt = "woman walking through neon rain" + enhanced_prompt = "woman smiling, cinematic studio portrait" + profile = normalize_refiner_v2_rating("Missing action") + feedback = refiner._v2_axis_feedback(profile, None) + + status = refiner._v2_update_intent_alignment_memory( + global_state, + { + "prompt": enhanced_prompt, + "phrases": prompt_phrases(refiner, enhanced_prompt, global_state), + "intent_prompt": intent_prompt, + "intent_phrases": prompt_phrases(refiner, intent_prompt, global_state), + }, + profile, + 1, + feedback, + ) + + slot = next(iter(global_state["intent_alignment_memory"].values())) + missing = slot["missing_intent_phrases"]["woman walking through neon rain"] + variant = next(iter(slot["variants"].values())) + assert "Intent alignment learned" in status + assert missing["score"] > 0.5 + assert missing["missing_count"] == 1 + assert variant["missing_intent_count"] == 1 + + +def test_intent_alignment_restores_learned_missing_original_phrase(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "intent_alignment_memory": {}} + intent_prompt = "woman walking through neon rain" + profile = normalize_refiner_v2_rating("Missing action") + feedback = refiner._v2_axis_feedback(profile, None) + refiner._v2_update_intent_alignment_memory( + global_state, + { + "prompt": "woman smiling, cinematic studio portrait", + "phrases": prompt_phrases(refiner, "woman smiling, cinematic studio portrait", global_state), + "intent_prompt": intent_prompt, + "intent_phrases": prompt_phrases(refiner, intent_prompt, global_state), + }, + profile, + 1, + feedback, + ) + + aligned, status, adjustments = refiner._v2_apply_intent_alignment_memory( + "woman smiling, moody closeup", + prompt_phrases(refiner, "woman smiling, moody closeup", global_state), + intent_prompt, + prompt_phrases(refiner, intent_prompt, global_state), + global_state, + ) + + assert "woman walking through neon rain" in aligned + assert "restored 1 original phrase" in status + assert adjustments == [ + {"text": "woman walking through neon rain", "source": "intent_missing", "action": "added"} + ] + + +def test_intent_alignment_removes_rejected_enhancer_only_extra(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "intent_alignment_memory": {}} + intent_prompt = "woman walking through neon rain" + enhanced_prompt = "woman walking through neon rain, white tights" + profile = normalize_refiner_v2_rating("Wrong appearance") + feedback = refiner._v2_axis_feedback(profile, None) + refiner._v2_update_intent_alignment_memory( + global_state, + { + "prompt": enhanced_prompt, + "phrases": prompt_phrases(refiner, enhanced_prompt, global_state), + "intent_prompt": intent_prompt, + "intent_phrases": prompt_phrases(refiner, intent_prompt, global_state), + }, + profile, + 1, + feedback, + ) + + aligned, status, adjustments = refiner._v2_apply_intent_alignment_memory( + enhanced_prompt, + prompt_phrases(refiner, enhanced_prompt, global_state), + intent_prompt, + prompt_phrases(refiner, intent_prompt, global_state), + global_state, + ) + + assert "white tights" not in aligned + assert "woman walking through neon rain" in aligned + assert "removed 1 rejected enhancer-only phrase" in status + assert adjustments == [ + {"text": "white tights", "source": "enhancer_extra", "action": "removed"} + ] + + +def test_intent_alignment_stores_pairs_and_bad_tokens_to_omit(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "intent_alignment_memory": {}} + intent_prompt = "woman walking through neon rain" + enhanced_prompt = "woman walking through neon rain, white tights" + profile = normalize_refiner_v2_rating("Wrong appearance") + feedback = refiner._v2_axis_feedback(profile, None) + + refiner._v2_update_intent_alignment_memory( + global_state, + { + "prompt": enhanced_prompt, + "phrases": prompt_phrases(refiner, enhanced_prompt, global_state), + "intent_prompt": intent_prompt, + "intent_phrases": prompt_phrases(refiner, intent_prompt, global_state), + }, + profile, + 1, + feedback, + ) + + slot = next(iter(global_state["intent_alignment_memory"].values())) + pair = next(iter(slot["intent_enhance_pairs"].values())) + assert pair["intent_prompt"] == intent_prompt + assert pair["positive_prompt"] == enhanced_prompt + assert "woman" in slot["provided_tokens"] + assert slot["provided_tokens"]["woman"]["omit"] is False + assert slot["provided_tokens"]["white"]["omit"] is True + assert slot["provided_tokens"]["tights"]["omit"] is True + assert slot["provided_tokens"]["white tights"]["kind"] == "pair" + assert slot["provided_tokens"]["white tights"]["omit"] is True + assert set(slot["bad_tokens"]) >= {"white", "tights", "white tights"} + + +def test_intent_alignment_omits_bad_token_in_new_enhancer_phrase(): + refiner = FunPackVideoRefinerV2() + global_state = {"phrase_memory": {}, "intent_alignment_memory": {}} + intent_prompt = "woman walking through neon rain" + profile = normalize_refiner_v2_rating("Wrong appearance") + feedback = refiner._v2_axis_feedback(profile, None) + refiner._v2_update_intent_alignment_memory( + global_state, + { + "prompt": "woman walking through neon rain, white tights", + "phrases": prompt_phrases(refiner, "woman walking through neon rain, white tights", global_state), + "intent_prompt": intent_prompt, + "intent_phrases": prompt_phrases(refiner, intent_prompt, global_state), + }, + profile, + 1, + feedback, + ) + + aligned, _, adjustments = refiner._v2_apply_intent_alignment_memory( + "woman walking through neon rain, red tights", + prompt_phrases(refiner, "woman walking through neon rain, red tights", global_state), + intent_prompt, + prompt_phrases(refiner, intent_prompt, global_state), + global_state, + ) + + assert "red tights" not in aligned + assert "woman walking through neon rain" in aligned + assert adjustments == [ + {"text": "red tights", "source": "enhancer_extra", "action": "removed"} + ] + + def test_lucky_skips_appearance_memory_unless_prompt_mentions_it(): refiner = FunPackVideoRefinerV2() global_state = {"phrase_memory": {}, "preferred_context_memory": {}} From 82ceea6c9ab05f21bd2f5c78d8b34d3012c74ba8 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 8 May 2026 22:27:34 +0300 Subject: [PATCH 8/8] Fix Refiner V2 conditioning fallback 2.3.3 --- CHANGELOG.md | 6 +++ README.md | 4 ++ conditioning.py | 64 +++++++++++++++++++++--- pyproject.toml | 2 +- tests/test_v2_category_alignment.py | 76 +++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1eb1806..c4c23d00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [2.3.3] - 2026-05-08 + +### Fixed + +Fixed Refiner V2 so `CLIP` and pre-encoded `positive_conditioning` can both be optional inputs. When `CLIP` is connected, V2 keeps owning prompt encoding as before. When `CLIP` is not connected but `positive_conditioning` is connected, V2 accepts the finished Gemma3/LTX2 conditioning, uses the prompt for analysis, and loads only the Gemma3 tokenizer. + ## [2.3.2] - 2026-05-08 ### Added diff --git a/README.md b/README.md index 6622a29f..9134e0dc 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ A set of ComfyUI nodes for experimenting with video generation workflows based on WAN, HunyuanVideo, LTX, and similar models. +## Updates in 2.3.3 + +Refiner V2 now supports the restored pre-encoded conditioning workflow: connect `positive_conditioning` without `CLIP` and it accepts the finished Gemma3/LTX2 conditioning while loading only the Gemma3 tokenizer. If `CLIP` is connected, V2 still encodes the prompt itself and ignores the fallback conditioning path. + ## Updates in 2.3.2 Refiner V2 now learns original-intent alignment when `user_intent_prompt` stays the same but an enhancer gives different `positive_prompt` variants. Ratings teach it which intent-enhance pairs represented the original request, which original phrases were missing, and which enhancer-only additions were rejected. diff --git a/conditioning.py b/conditioning.py index 1d2a09d7..35e8c1b9 100644 --- a/conditioning.py +++ b/conditioning.py @@ -5701,10 +5701,13 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return { "required": { "positive_prompt": ("STRING", {"multiline": True, "default": "", "placeholder": "Positive prompt"}), - "clip": ("CLIP", {"tooltip": "Connected text encoder used for all V2 prompt encoding and similarity checks."}), "rating": (V2_RATING_LABELS, {"default": "Missing action", "label": "Rating"}), }, "optional": { + "clip": ("CLIP", {"tooltip": "Optional text encoder. When connected, V2 encodes the prompt itself."}), + "positive_conditioning": ("CONDITIONING", { + "tooltip": "Optional pre-encoded Gemma3/LTX2 conditioning. Used only when CLIP is not connected.", + }), "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "label": "Exploration Seed"}), "reset_session": ("BOOLEAN", {"default": False, "label": "Reset V2 Session"}), "lora_stack": ("FUNPACK_LORA_STACK", {"tooltip": "Optional stack from FunPack LoRA Loader. V2 writes prompt-specific suggested weights."}), @@ -5824,6 +5827,44 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return None, {"pooled_output": None}, "encode returned invalid conditioning" return cond, meta, f"encoded {self._get_conditioning_seq_len(cond)} positions" + def _v2_gemma3_tokenizer_status(self): + tokenizer = self._get_tokenizer("ltx2") + if tokenizer is None: + return "Gemma3 tokenizer unavailable" + source = str(getattr(tokenizer, "name_or_path", "") or "").strip() + if source: + return f"Gemma3 tokenizer loaded: {source}" + return "Gemma3 tokenizer loaded" + + def _v2_conditioning_source(self, clip, prompt_text, positive_conditioning): + if clip is not None: + cond, meta, encode_status = self._v2_encode_prompt(clip, prompt_text) + return cond, meta, encode_status, "CLIP-owned" + + if positive_conditioning is None: + return ( + None, + {"pooled_output": None}, + "CLIP missing and no positive CONDITIONING connected", + "CONDITIONING-owned", + ) + + cond, meta = self._v2_extract_conditioning(positive_conditioning) + if not isinstance(cond, torch.Tensor): + return ( + None, + {"pooled_output": None}, + "connected positive CONDITIONING is invalid", + "CONDITIONING-owned", + ) + + tokenizer_status = self._v2_gemma3_tokenizer_status() + encode_status = ( + f"accepted connected positive CONDITIONING " + f"({self._get_conditioning_seq_len(cond)} positions); {tokenizer_status}" + ) + return cond, meta, encode_status, "CONDITIONING-owned" + def _v2_conditioning_vector(self, conditioning): if not isinstance(conditioning, torch.Tensor) or conditioning.dim() <= 1: return None @@ -8071,9 +8112,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): prompt_history["lora_weight_suggestions"] = suggestions return "LoRA suggestions: " + " | ".join(parts) - def refine_v2(self, positive_prompt, clip, rating, refinement_key="", + def refine_v2(self, positive_prompt, clip=None, rating="Missing action", refinement_key="", seed=0, reset_session=False, lora_stack=None, im_feeling_lucky=False, user_intent_prompt="", - refinement_key_input=""): + refinement_key_input="", positive_conditioning=None): if seed != 0: torch.manual_seed(seed) random.seed(seed) @@ -8150,7 +8191,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): lucky_status = "Prompt refusal filter: enhancer refusal detected; current prompt will not be stored or learned." encoded_role = "refusal passthrough" refusal_status = "Current prompt refused by enhancer; storage skipped." - elif im_feeling_lucky: + elif im_feeling_lucky and clip is not None: prompt_to_encode, lucky_status = self._v2_compose_lucky_prompt(analysis_prompt, phrases, global_state) encoded_role = "lucky prompt" else: @@ -8170,13 +8211,20 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): axis_feedback, intent_phrases=intent_phrases, ) - lucky_status = f"Lucky: off | trained memory only. {emphasis_status}" + if im_feeling_lucky and clip is None: + lucky_status = f"Lucky: unavailable without CLIP | connected CONDITIONING accepted. {emphasis_status}" + else: + lucky_status = f"Lucky: off | trained memory only. {emphasis_status}" encoded_role = "current prompt" - cond, meta, encode_status = self._v2_encode_prompt(clip, prompt_to_encode) + cond, meta, encode_status, conditioning_owner = self._v2_conditioning_source( + clip, + prompt_to_encode, + positive_conditioning, + ) fallback_graph = render_refinement_loss_graph(refinement_key, "v2", "clip", 0, 0.0, []) if not isinstance(cond, torch.Tensor): - status = f"ERROR: V2 could not encode prompt | {encode_status}" + status = f"ERROR: V2 could not prepare conditioning | {encode_status}" training_info = f"Rating: {rating_label}\n{memory_status}\n{lucky_status}\n{encode_status}" return ([], status, training_info, fallback_graph) @@ -8300,7 +8348,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): ) refusal_status_line = f"\n{refusal_status}" if refusal_status else "" status = ( - f"V2 {state_status} | CLIP-owned | Rating {rating_label} | Iter {global_state['total_iterations']} | " + f"V2 {state_status} | {conditioning_owner} | Rating {rating_label} | Iter {global_state['total_iterations']} | " f"Learning {'trained previous run' if has_previous_run and not learning_profile.get('skip_learning') else 'not applied'}\n" f"{adaptation_status}\n" f"{training_guidance}\n" diff --git a/pyproject.toml b/pyproject.toml index 281314e9..17b7aac7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [project] name = "ComfyUI-FunPack" # Unique identifier for your node. Immutable after creation. description = "A set of nodes for experiments with video generation models, including prompt refinement, adaptive LoRA weight workflows, story tools, video stitching, lorebook enhancement and more." -version = "2.3.2" # Custom Node version. Must be semantically versioned. +version = "2.3.3" # Custom Node version. Must be semantically versioned. license = { text = "GNU GPL v3" } dependencies = [] # Filled in from requirements.txt diff --git a/tests/test_v2_category_alignment.py b/tests/test_v2_category_alignment.py index 8f9d2fe0..6ac26816 100644 --- a/tests/test_v2_category_alignment.py +++ b/tests/test_v2_category_alignment.py @@ -737,6 +737,82 @@ def test_refiner_training_info_uses_readable_sections(tmp_path): assert "Category compact view:\n-" in training_info +def test_refiner_v2_exposes_clip_and_conditioning_as_optional_inputs(): + inputs = FunPackVideoRefinerV2.INPUT_TYPES() + + assert "clip" not in inputs["required"] + assert "positive_conditioning" not in inputs["required"] + assert "clip" in inputs["optional"] + assert "positive_conditioning" in inputs["optional"] + + +def test_refiner_v2_accepts_conditioning_without_clip_and_loads_gemma3_tokenizer(tmp_path, monkeypatch): + refiner = FunPackVideoRefinerV2() + state_path = tmp_path / "state.json" + refiner._v2_state_path = lambda refinement_key: str(state_path) + tokenizer_modes = [] + + class FakeTokenizer: + name_or_path = "DreamFast/gemma-3-12b-it-heretic-v2" + + def fake_get_tokenizer(mode="ltx2"): + tokenizer_modes.append(mode) + return FakeTokenizer() + + monkeypatch.setattr(refiner, "_get_tokenizer", fake_get_tokenizer) + positive_conditioning = [(torch.full((1, 4, 3), 2.0), {"pooled_output": torch.ones(1, 3)})] + + modified, status, training_info, _ = refiner.refine_v2( + "woman walking through neon rain", + None, + "Perfect", + "conditioning-input-test", + positive_conditioning=positive_conditioning, + ) + + assert tokenizer_modes == ["ltx2"] + assert "CONDITIONING-owned" in status + assert "Gemma3 tokenizer loaded: DreamFast/gemma-3-12b-it-heretic-v2" in training_info + assert modified[0][0].shape == positive_conditioning[0][0].shape + + +def test_refiner_v2_prefers_clip_when_both_clip_and_conditioning_are_connected(tmp_path, monkeypatch): + refiner = FunPackVideoRefinerV2() + state_path = tmp_path / "state.json" + refiner._v2_state_path = lambda refinement_key: str(state_path) + monkeypatch.setattr(refiner, "_get_tokenizer", lambda mode="ltx2": (_ for _ in ()).throw(AssertionError("unexpected tokenizer load"))) + positive_conditioning = [(torch.full((1, 4, 3), 9.0), {"pooled_output": torch.ones(1, 3)})] + + modified, status, training_info, _ = refiner.refine_v2( + "woman walking through neon rain", + FakeClip(), + "Perfect", + "clip-priority-test", + positive_conditioning=positive_conditioning, + ) + + assert "CLIP-owned" in status + assert "accepted connected positive CONDITIONING" not in training_info + assert torch.allclose(modified[0][0], torch.ones(1, 4, 3)) + + +def test_refiner_v2_errors_without_clip_or_conditioning(tmp_path): + refiner = FunPackVideoRefinerV2() + state_path = tmp_path / "state.json" + refiner._v2_state_path = lambda refinement_key: str(state_path) + + modified, status, training_info, _ = refiner.refine_v2( + "woman walking through neon rain", + None, + "Perfect", + "missing-conditioning-test", + ) + + assert modified == [] + assert "ERROR: V2 could not prepare conditioning" in status + assert "CLIP missing and no positive CONDITIONING connected" in training_info + + def test_prompt_enhancer_refusal_is_not_stored_as_last_run(tmp_path): refiner = FunPackVideoRefinerV2() state_path = tmp_path / "state.json"