Run VF ascend+search once on the merged scene, not per key
Per-scene multi-key steering ran the value-function ascend+search inside the per-key loop, then averaged. That injected independent search noise per key and let a poorly-fit fresh key's VF ascend toward a bad optimum, which the averaging baked in — a body-horror path. Now each key contributes only its learned directions (per-prompt conditioning memory, already delta-capped); the merge is formed and magnitude-disciplined, then a single ascend+search runs on the merged result using the always-on project default key (the most-trained, most stable VF). Keyed single-key scenes also now ascend with the default VF rather than that one key's, for the same stability reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
bc0d035125
commit
643ca447c0
+14
-6
@@ -13221,14 +13221,16 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
# default-key path for this scene (per-entry so it matches no-key behaviour)
|
||||
out.append(self._v2_ascend_conditioning([entry], default_key, apply=value_guidance)[0])
|
||||
continue
|
||||
# Each key contributes only its learned DIRECTIONS here (per-prompt
|
||||
# conditioning memory). The value-function ascend+search runs ONCE on the
|
||||
# merged result below — not per key — because per-key search injected
|
||||
# independent noise and a poorly-fit fresh key's VF could ascend toward a
|
||||
# bad optimum, which the averaging then baked in (a body-horror path).
|
||||
steered = []
|
||||
for key in sorted(keys):
|
||||
try:
|
||||
c, _ = self._v2_apply_conditioning_memory(cond.clone(), _key_global(key), profile)
|
||||
if not isinstance(c, torch.Tensor):
|
||||
c = cond.clone()
|
||||
c = self._v2_ascend_conditioning([(c, meta)], key, apply=value_guidance)[0][0]
|
||||
steered.append(c)
|
||||
steered.append(c if isinstance(c, torch.Tensor) else cond.clone())
|
||||
except Exception as error:
|
||||
print(f"[FunPackStudio] Scene key '{key}' steering failed: {error}")
|
||||
if not steered:
|
||||
@@ -13240,8 +13242,7 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
merged = torch.stack(steered, dim=0).mean(dim=0)
|
||||
# Averaging per-key tensors that point different ways shrinks the
|
||||
# per-token magnitude (and collapses it toward zero when keys
|
||||
# disagree), and ascend/search already broke the per-key renorm —
|
||||
# so a raw mean can land far from the scene encode at the wrong
|
||||
# disagree), leaving the merge far from the scene encode at the wrong
|
||||
# magnitude, which free-runs into warping on simple prompts. Re-impose
|
||||
# the single-key discipline: cap the delta vs the raw encode, then
|
||||
# renormalize to its per-token norm (same tail as
|
||||
@@ -13254,6 +13255,13 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
merged = cond + delta * scale
|
||||
merged = torch.clamp(merged, min=-60.0, max=60.0)
|
||||
merged = merged / merged.norm(dim=-1, keepdim=True).clamp_min(1e-8) * original_norm
|
||||
# Single VF ascend+search on the merged conditioning, using the always-on
|
||||
# project default key (the most-trained, most stable VF) rather than any
|
||||
# one scene key.
|
||||
try:
|
||||
merged = self._v2_ascend_conditioning([(merged, meta)], default_key, apply=value_guidance)[0][0]
|
||||
except Exception as error:
|
||||
print(f"[FunPackStudio] Merged scene ascend failed: {error}")
|
||||
merged = protect_audio_channels(merged, cond)
|
||||
out.append((merged, meta))
|
||||
merged_scenes.append((scene_index, sorted(keys)))
|
||||
|
||||
Reference in New Issue
Block a user