Update flux2_klein_enhancer.py

This commit is contained in:
capitan01R
2026-01-26 09:21:25 -05:00
committed by GitHub
parent c75dc9d7c6
commit 678891c1cd
+126 -26
View File
@@ -1,15 +1,14 @@
"""
FLUX.2 Klein Conditioning Enhancer - Fixed Version
FLUX.2 Klein Conditioning Enhancer - v1.1 + Multiple Preserve Modes
Built from empirical diagnostic data:
- Conditioning shape: [batch, 512, 12288]
- Active text region: Dynamic (check attention_mask), typically ~77 tokens
- Padding region: Remaining positions (std ~2.3)
- Metadata: pooled_output, attention_mask, reference_latents (for edit)
- Text encoder: Qwen3 8B (4096 hidden → 12288 projected)
Added features:
- preserve_mode: Choose between different preservation behaviors
* linear: Original blend-back method (default, backward compatible)
* dampen: Reduce modification strength before applying
* blend_after: Same as linear (legacy naming)
* hybrid: Dampen first, then blend
CRITICAL FIX: Previous version had mean-recentering that undid the scaling.
This version uses direct operations with no reversion loops.
Main v1 logic: COMPLETELY UNCHANGED
"""
import torch
@@ -30,6 +29,7 @@ class Flux2KleinEnhancer:
- magnitude: Direct scaling of active region embeddings
- contrast: Amplify differences between tokens
- normalize: Equalize token magnitudes
- preserve_original: Blend back original embeddings with multiple modes
All operations modify the active text region only (padding untouched).
"""
@@ -47,14 +47,14 @@ class Flux2KleinEnhancer:
"magnitude": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Scale active region embeddings. >1 = stronger prompt, <1 = weaker."
}),
"contrast": ("FLOAT", {
"default": 0.0,
"min": -1.0,
"max": 2.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Amplify differences between tokens. >0 = sharper concepts."
}),
@@ -67,10 +67,21 @@ class Flux2KleinEnhancer:
}),
},
"optional": {
"preserve_original": ("FLOAT", {
"default": 0.0,
"min": -2.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Blend back original embeddings. 0=full enhancement, 1=no change. For image edit: higher=keep original structure."
}),
"preserve_mode": (["linear", "dampen", "blend_after", "hybrid"], {
"default": "linear",
"tooltip": "linear: direct blend (original) | dampen: reduce modifications first | blend_after: same as linear | hybrid: dampen then blend"
}),
"edit_text_weight": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.05,
"tooltip": "[IMAGE EDIT] Additional scaling for edit mode. <1 = preserve original, >1 = follow prompt."
}),
@@ -109,8 +120,8 @@ class Flux2KleinEnhancer:
return min(77, cond_shape[1])
def enhance(self, conditioning, magnitude=1.0, contrast=0.0, normalize_strength=0.0,
edit_text_weight=1.0, active_end_override=0, low_vram=False,
device="auto", debug=False):
preserve_original=0.0, preserve_mode="linear", edit_text_weight=1.0,
active_end_override=0, low_vram=False, device="auto", debug=False):
if not conditioning:
return (conditioning,)
@@ -120,6 +131,7 @@ class Flux2KleinEnhancer:
magnitude == 1.0 and
contrast == 0.0 and
normalize_strength == 0.0 and
preserve_original == 0.0 and
edit_text_weight == 1.0
)
if no_op:
@@ -163,18 +175,46 @@ class Flux2KleinEnhancer:
print(f"Shape: {cond.shape}")
print(f"Active region: 0 to {active_end}")
print(f"Edit mode: {is_edit_mode}")
print(f"Preserve mode: {preserve_mode}")
if active_end < seq_len:
print(f"Active std: {cond[:, :active_end, :].std().item():.4f}")
print(f"Padding std: {cond[:, active_end:, :].std().item():.4f}")
# Extract active region only
active = cond[:, :active_end, :].clone()
original_active = active.clone() # Store for preserve_original
if debug:
orig_norm = active.norm(dim=-1).mean().item()
print(f"\nBefore modifications:")
print(f" Active region mean norm: {orig_norm:.4f}")
# ============================================================
# DAMPEN MODE: Apply preservation BEFORE modifications
# ============================================================
if preserve_mode == "dampen" and preserve_original != 0.0:
# Calculate dampening factors for all operations
damping = 1.0 - preserve_original
# Dampen the modification parameters
dampened_magnitude = 1.0 + (magnitude - 1.0) * damping
dampened_contrast = contrast * damping
dampened_normalize = normalize_strength * damping
dampened_edit_weight = 1.0 + (edit_text_weight - 1.0) * damping
if debug:
print(f"\nDampen mode ({preserve_original:.2f}):")
print(f" magnitude: {magnitude:.2f} -> {dampened_magnitude:.3f}")
print(f" contrast: {contrast:.2f} -> {dampened_contrast:.3f}")
print(f" normalize: {normalize_strength:.2f} -> {dampened_normalize:.3f}")
print(f" edit_weight: {edit_text_weight:.2f} -> {dampened_edit_weight:.3f}")
# Use dampened values
magnitude = dampened_magnitude
contrast = dampened_contrast
normalize_strength = dampened_normalize
edit_text_weight = dampened_edit_weight
# ============================================================
# OPERATION 1: Contrast (amplify token differences)
# ============================================================
@@ -216,6 +256,21 @@ class Flux2KleinEnhancer:
if debug:
print(f"\nEdit text weight ({edit_text_weight:.2f}): applied for image edit mode")
# ============================================================
# OPERATION 5: Preserve Original (blend back)
# ============================================================
if preserve_original != 0.0 and preserve_mode in ["linear", "blend_after", "hybrid"]:
# Linear interpolation: result = enhanced * (1-p) + original * p
# p=0: fully enhanced
# p=1: original unchanged
# p>1: over-preserve (can create interesting effects)
active = active * (1.0 - preserve_original) + original_active * preserve_original
if debug:
blend_pct = min(preserve_original * 100, 100)
mode_name = "Hybrid blend" if preserve_mode == "hybrid" else "Linear blend"
print(f"\n{mode_name} ({preserve_original:.2f}): {blend_pct:.0f}% original blended back")
# Write back to full tensor
result = cond.clone()
result[:, :active_end, :] = active
@@ -229,7 +284,7 @@ class Flux2KleinEnhancer:
output.append((result.to("cpu", dtype=original_dtype), meta))
del cond, active, result
del cond, active, original_active, result
if device.type == "cuda":
torch.cuda.empty_cache()
@@ -263,21 +318,21 @@ class Flux2KleinDetailController:
"front_mult": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.05,
"tooltip": "First 25% of active tokens"
}),
"mid_mult": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Middle 50% of active tokens"
}),
"end_mult": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Last 25% of active tokens"
}),
@@ -298,10 +353,21 @@ class Flux2KleinDetailController:
"emphasis_mult": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 3.0,
"max": 10.0,
"step": 0.1,
"tooltip": "Multiplier for emphasis region"
}),
"preserve_original": ("FLOAT", {
"default": 0.0,
"min": -2.0,
"max": 10.0,
"step": 0.05,
"tooltip": "Blend back original embeddings. 0=full enhancement, 1=no change. For image edit: higher=keep original structure."
}),
"preserve_mode": (["linear", "dampen", "blend_after", "hybrid"], {
"default": "linear",
"tooltip": "linear: direct blend (original) | dampen: reduce modifications first | blend_after: same as linear | hybrid: dampen then blend"
}),
"low_vram": ("BOOLEAN", {"default": False}),
"device": (devices, {"default": "auto"}),
"debug": ("BOOLEAN", {"default": False}),
@@ -314,7 +380,8 @@ class Flux2KleinDetailController:
def control(self, conditioning, front_mult=1.0, mid_mult=1.0, end_mult=1.0,
emphasis_start=0, emphasis_end=0, emphasis_mult=1.0,
low_vram=False, device="auto", debug=False):
preserve_original=0.0, preserve_mode="linear", low_vram=False,
device="auto", debug=False):
if not conditioning:
return (conditioning,)
@@ -324,7 +391,8 @@ class Flux2KleinDetailController:
front_mult == 1.0 and
mid_mult == 1.0 and
end_mult == 1.0 and
(emphasis_end == 0 or emphasis_mult == 1.0)
(emphasis_end == 0 or emphasis_mult == 1.0) and
preserve_original == 0.0
)
if no_op:
if debug:
@@ -363,6 +431,7 @@ class Flux2KleinDetailController:
active_end = min(77, seq_len)
active = cond[:, :active_end, :].clone()
original_active = active.clone() # Store for preserve_original
num_tokens = active.shape[1]
if debug:
@@ -370,6 +439,26 @@ class Flux2KleinDetailController:
print(f"Flux2KleinDetailController Item {idx}")
print(f"{'='*50}")
print(f"Active tokens: {num_tokens}")
print(f"Preserve mode: {preserve_mode}")
# ============================================================
# DAMPEN MODE: Apply preservation BEFORE regional operations
# ============================================================
if preserve_mode == "dampen" and preserve_original != 0.0:
# Dampen the regional multipliers based on preserve_original
damping = 1.0 - preserve_original
front_mult = 1.0 + (front_mult - 1.0) * damping
mid_mult = 1.0 + (mid_mult - 1.0) * damping
end_mult = 1.0 + (end_mult - 1.0) * damping
emphasis_mult = 1.0 + (emphasis_mult - 1.0) * damping
if debug:
print(f"\nDampen mode ({preserve_original:.2f}):")
print(f" front_mult: -> {front_mult:.3f}")
print(f" mid_mult: -> {mid_mult:.3f}")
print(f" end_mult: -> {end_mult:.3f}")
print(f" emphasis_mult: -> {emphasis_mult:.3f}")
# Calculate region boundaries
front_end = int(num_tokens * 0.25)
@@ -382,17 +471,17 @@ class Flux2KleinDetailController:
if front_mult != 1.0 and front_end > 0:
active[:, :front_end, :] *= front_mult
if debug:
print(f" Front: x{front_mult}")
print(f" Front: x{front_mult:.3f}")
if mid_mult != 1.0 and mid_end > front_end:
active[:, front_end:mid_end, :] *= mid_mult
if debug:
print(f" Mid: x{mid_mult}")
print(f" Mid: x{mid_mult:.3f}")
if end_mult != 1.0 and num_tokens > mid_end:
active[:, mid_end:, :] *= end_mult
if debug:
print(f" End: x{end_mult}")
print(f" End: x{end_mult:.3f}")
# Custom emphasis region
if emphasis_end > 0 and emphasis_mult != 1.0:
@@ -400,7 +489,18 @@ class Flux2KleinDetailController:
emp_end = max(emp_start + 1, min(emphasis_end, num_tokens))
active[:, emp_start:emp_end, :] *= emphasis_mult
if debug:
print(f" Emphasis [{emp_start}:{emp_end}]: x{emphasis_mult}")
print(f" Emphasis [{emp_start}:{emp_end}]: x{emphasis_mult:.3f}")
# ============================================================
# Preserve Original (blend back)
# ============================================================
if preserve_original != 0.0 and preserve_mode in ["linear", "blend_after", "hybrid"]:
active = active * (1.0 - preserve_original) + original_active * preserve_original
if debug:
blend_pct = min(preserve_original * 100, 100)
mode_name = "Hybrid blend" if preserve_mode == "hybrid" else "Linear blend"
print(f"\n{mode_name} ({preserve_original:.2f}): {blend_pct:.0f}% original blended back")
# Write back
result = cond.clone()
@@ -412,7 +512,7 @@ class Flux2KleinDetailController:
output.append((result.to("cpu", dtype=original_dtype), meta))
del cond, active, result
del cond, active, original_active, result
if device.type == "cuda":
torch.cuda.empty_cache()