fix(studio): the wire is the instruction — drop the ownership toggle
A wired positive CONDITIONING means Studio does not encode the prompt. That is not a preference to configure; it is what wiring the input says, and it is what a wired negative CONDITIONING has always done. Wanting CLIP to own the prompt means not wiring one. Removes clip_owns_prompt from the node, both settings panels and the settings JSON.
This commit is contained in:
+4
-2
@@ -22,8 +22,10 @@
|
||||
connected, so Studio re-encoded from text and discarded what the node built — which on an
|
||||
i2v/r2v graph is not the same tensor, because Studio's encode never sees the reference
|
||||
image (nothing wires `h3_references` or `source_image`). CLIP keeps the negative, the
|
||||
references and phrase classification. "Let CLIP re-encode a wired conditioning" restores
|
||||
the old order. Replaces "Skip Studio's positive processing".
|
||||
references and phrase classification. No setting selects between them — wiring the input
|
||||
is the instruction, the same way a wired negative CONDITIONING has always won. "Skip
|
||||
Studio's positive processing" is gone; it was a switch for something the graph already
|
||||
said.
|
||||
- **Rating-driven phrase emphasis is OFF by default.** It changes what the model sees on
|
||||
every rated run; unvalidated work that does that is something to turn on, not to discover.
|
||||
Overlapping spans are also bounded — their biases add, and three overlapping x1.5 spans
|
||||
|
||||
+5
-7
@@ -7092,8 +7092,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
return f"stand-in tokenizer: {source}" if source else "stand-in tokenizer loaded"
|
||||
|
||||
def _v2_conditioning_source(self, clip, prompt_text, positive_conditioning, encode_cache=None,
|
||||
reference_image=None, h3_references=None,
|
||||
clip_owns_prompt=False):
|
||||
reference_image=None, h3_references=None):
|
||||
# A wired positive CONDITIONING OWNS the prompt. CLIP used to win here, on the theory
|
||||
# that a graph with both connected meant CLIP — but wiring a conditioning is an
|
||||
# explicit act, and discarding it in favour of a re-encode is the surprising half.
|
||||
@@ -7106,8 +7105,9 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
# re-encode is a different tensor, and an i2v/r2v sampler gets handed a text-only one.
|
||||
#
|
||||
# CLIP keeps every OTHER job — the negative, the references, phrase classification —
|
||||
# which is why both stay connected. `clip_owns_prompt` restores the old precedence.
|
||||
if positive_conditioning is not None and not clip_owns_prompt:
|
||||
# which is why both stay connected. No setting selects between them: WIRING the input
|
||||
# is the instruction. Wanting CLIP to own the prompt means not wiring a conditioning.
|
||||
if positive_conditioning is not None:
|
||||
clip_note = ("positive CONDITIONING is wired and owns the prompt"
|
||||
+ ("; CLIP still encodes the negative and references"
|
||||
if clip is not None
|
||||
@@ -12051,7 +12051,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
split_by_transitions=False, split_transition_placement="start", reference_injection=False,
|
||||
value_guidance=True, latent=None, seed_output_connected=False,
|
||||
steer_mode="relative", absolute_strength=0.6,
|
||||
clip_owns_prompt=False, h3_phrase_emphasis=False,
|
||||
h3_phrase_emphasis=False,
|
||||
_seed=None, _seed_source="fresh seed", _scene_seeds=None, _velocity_keys=None,
|
||||
batch_variants=1, guess_mode=False, guess_direction="up", guess_range=1.0,
|
||||
guess_freeze_seed=True, movie_editor_scene_ratings=None, scene_segments=None,
|
||||
@@ -12510,7 +12510,6 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
encode_cache=encode_cache,
|
||||
reference_image=source_image,
|
||||
h3_references=_h3_references,
|
||||
clip_owns_prompt=clip_owns_prompt,
|
||||
)
|
||||
fallback_graph = render_refinement_loss_graph(refinement_key, "v2", "clip", 0, 0.0, [])
|
||||
if not isinstance(cond, torch.Tensor):
|
||||
@@ -15130,7 +15129,6 @@ class FunPackStudio:
|
||||
user_intent_prompt=effective_intent,
|
||||
refinement_key_input=refinement_key_input,
|
||||
positive_conditioning=positive_conditioning,
|
||||
clip_owns_prompt=bool(rf.get("clip_owns_prompt", False)),
|
||||
h3_phrase_emphasis=bool(rf.get("h3_phrase_emphasis", False)),
|
||||
clip_vision_output=clip_vision_output,
|
||||
source_image=source_image if vision_conditioning else None,
|
||||
|
||||
@@ -112,8 +112,6 @@
|
||||
{ name: "negative_erase_renorm", label: "Keep prompt strength", kind: "bool", default: true,
|
||||
dependsOn: "negative_erase", dependsVals: [true],
|
||||
hint: "Puts each word back to its original strength after the change, so the result reads as 'less of that thing' rather than 'quieter prompt'. Off is the raw result." },
|
||||
{ name: "clip_owns_prompt", label: "Let CLIP re-encode a wired conditioning", kind: "bool", default: false,
|
||||
hint: "OFF: a wired positive CONDITIONING owns the prompt and Studio steers it — the node that built it may have shown Qwen a reference image, which Studio has no way to reproduce. ON restores the old behaviour, where CLIP re-encodes from text and the wired conditioning is discarded. Text-only scenes lose Studio's per-scene split either way; shortcuts and $variables still apply." },
|
||||
{ name: "h3_phrase_emphasis", label: "Rating-driven phrase emphasis (H3)", kind: "bool", default: false,
|
||||
hint: "EXPERIMENTAL, unvalidated. Boosts the attention paid to phrases the rating said were MISSING, by biasing their attention logits in H3's packed stream. Needs a rated run first. Turn it off if generations drift away from the prompt — and note it forces SLA to run dense." }
|
||||
];
|
||||
|
||||
@@ -168,7 +168,7 @@ class _StubClip:
|
||||
pass
|
||||
|
||||
|
||||
def _source(node, clip, wired, monkeypatch, clip_owns_prompt=False):
|
||||
def _source(node, clip, wired, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
node, "_v2_encode_prompt",
|
||||
lambda *a, **k: (torch.ones(1, 4, 8), {"pooled_output": None}, "encoded"),
|
||||
@@ -177,8 +177,7 @@ def _source(node, clip, wired, monkeypatch, clip_owns_prompt=False):
|
||||
node, "_v2_extract_conditioning",
|
||||
lambda c: (torch.zeros(1, 4, 8), {"pooled_output": None}), raising=False)
|
||||
monkeypatch.setattr(node, "_v2_text_tokenizer_status", lambda: "tokenizer ok", raising=False)
|
||||
return node._v2_conditioning_source(clip, "a prompt", wired,
|
||||
clip_owns_prompt=clip_owns_prompt)
|
||||
return node._v2_conditioning_source(clip, "a prompt", wired)
|
||||
|
||||
|
||||
def test_a_wired_conditioning_owns_the_prompt_even_with_clip_connected(monkeypatch, capsys):
|
||||
@@ -194,16 +193,6 @@ def test_a_wired_conditioning_owns_the_prompt_even_with_clip_connected(monkeypat
|
||||
assert "CLIP still encodes the negative" in status
|
||||
|
||||
|
||||
def test_clip_still_owns_the_prompt_when_asked_to(monkeypatch):
|
||||
"""The old precedence, on request rather than by default."""
|
||||
node = FunPackVideoRefinerV2()
|
||||
wired = [[torch.zeros(1, 4, 8), {}]]
|
||||
cond, _meta, _status, owner = _source(node, _StubClip(), wired, monkeypatch,
|
||||
clip_owns_prompt=True)
|
||||
assert owner == "CLIP-owned"
|
||||
assert torch.equal(cond, torch.ones(1, 4, 8))
|
||||
|
||||
|
||||
def test_the_ownership_note_is_said_once_not_once_per_scene(monkeypatch, capsys):
|
||||
node = FunPackVideoRefinerV2()
|
||||
wired = [[torch.zeros(1, 4, 8), {}]]
|
||||
|
||||
@@ -60,11 +60,13 @@ def test_clip_keeps_every_other_job(studio):
|
||||
assert "CLIP still encodes the negative and references" in note
|
||||
|
||||
|
||||
def test_clip_owns_the_prompt_when_asked(studio):
|
||||
cond, _meta, _note, owner = studio._v2_conditioning_source(
|
||||
object(), "a cat", _wired(), clip_owns_prompt=True)
|
||||
assert owner == "CLIP-owned"
|
||||
assert torch.equal(cond, torch.ones(1, 4, 8))
|
||||
def test_no_setting_selects_between_them(studio):
|
||||
"""The wire IS the instruction. Wanting CLIP to own the prompt means not wiring a
|
||||
conditioning, so there is nothing here to configure."""
|
||||
import inspect
|
||||
params = inspect.signature(studio._v2_conditioning_source).parameters
|
||||
assert "clip_owns_prompt" not in params
|
||||
assert "prefer_wired" not in params
|
||||
|
||||
|
||||
def test_no_conditioning_wired_still_uses_clip(studio):
|
||||
|
||||
+1
-14
@@ -85,7 +85,7 @@ function defaultSettings() {
|
||||
return {
|
||||
refinement_key: "",
|
||||
overrides: { refinement_key: false, feedback_prompt: false, user_intent_prompt: false, negative_prompt: false },
|
||||
refiner: { mode: "Refine", advisor_mode: "Off", advisor_thinking: true, im_feeling_lucky: false, reset_session: false, feedback_prompt: "", user_intent_prompt_override: "", negative_prompt: "", temporal_style: "natural", split_by_transitions: false, split_transition_placement: "start", reference_injection: false, vision_conditioning: true, value_guidance: true, steer_mode: "relative", absolute_strength: 0.6, negative_erase: false, negative_erase_strength: 0.5, negative_erase_mode: "project", negative_erase_renorm: true, clip_owns_prompt: false, h3_phrase_emphasis: false },
|
||||
refiner: { mode: "Refine", advisor_mode: "Off", advisor_thinking: true, im_feeling_lucky: false, reset_session: false, feedback_prompt: "", user_intent_prompt_override: "", negative_prompt: "", temporal_style: "natural", split_by_transitions: false, split_transition_placement: "start", reference_injection: false, vision_conditioning: true, value_guidance: true, steer_mode: "relative", absolute_strength: 0.6, negative_erase: false, negative_erase_strength: 0.5, negative_erase_mode: "project", negative_erase_renorm: true, h3_phrase_emphasis: false },
|
||||
advisor_llm: { enabled: false, model_path: "huihui-ai/Huihui-Qwen3-8B-abliterated-v2", dtype: "bfloat16" },
|
||||
loras: [],
|
||||
loras_config: { mode: "ltx2", per_block: false },
|
||||
@@ -1132,19 +1132,6 @@ function openPanel(node) {
|
||||
body.append(row("Keep prompt strength", negRe));
|
||||
}
|
||||
|
||||
// Who owns the positive when both CLIP and a CONDITIONING are wired.
|
||||
const clipOwns = el("input"); clipOwns.type = "checkbox";
|
||||
clipOwns.checked = !!settings.refiner.clip_owns_prompt;
|
||||
clipOwns.addEventListener("change", () => {
|
||||
settings.refiner.clip_owns_prompt = clipOwns.checked;
|
||||
});
|
||||
body.append(row("Let CLIP re-encode a wired conditioning", clipOwns));
|
||||
body.append(el("div", "funpack-studio-hint",
|
||||
"Off: a wired positive CONDITIONING owns the prompt and Studio steers it — the node "
|
||||
+ "that built it may have shown Qwen a reference image, which Studio cannot reproduce. "
|
||||
+ "On restores the old behaviour, where CLIP re-encodes from text and the wired "
|
||||
+ "conditioning is discarded."));
|
||||
|
||||
const phraseEmph = el("input"); phraseEmph.type = "checkbox";
|
||||
phraseEmph.checked = !!settings.refiner.h3_phrase_emphasis;
|
||||
phraseEmph.addEventListener("change", () => {
|
||||
|
||||
Reference in New Issue
Block a user