maint: remove the v1 LoRA relevance scorer and suggestion writer

291 lines: _lora_words, _ensure_lora_memory, _score_lora_prompt_relation and
_update_lora_weight_suggestions. The scorer matched prompt words against each
LoRA's filename; the writer was the v1 half of the suggestion pair, superseded
by _v2_update_lora_suggestions, and unreachable since the v1 refiner entry
point was removed on this branch.

_lora_state_id stays — the live v2 writer still uses it.

Checked: no refs anywhere (grep -a, all file types, node_modules excluded),
not a route handler, not in NODE_CLASS_MAPPINGS, not an INPUT_TYPES widget,
no getattr dispatch. Tests: 1379 passed, baseline plus this branch's two new
ones.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-08-25 13:05:37 +03:00
co-authored by Claude Opus 5
parent e9ba41f62a
commit 8739fa8d2e
-291
View File
@@ -3399,297 +3399,6 @@ class FunPackVideoRefiner:
def _lora_state_id(self, lora_name: str, lora_type: str):
return md5(f"{lora_name}::{lora_type}".encode("utf-8")).hexdigest()[:16]
def _lora_words(self, text: str):
return {
word.strip().lower()
for word in re.split(r"[\s,;:_\\/\-().\[\]{}]+", text or "")
if self._is_valuable_token(word.strip())
}
def _ensure_lora_memory(self, memory: dict, lora_entry: dict):
lora_type = lora_entry.get("type", "general")
lora_id = lora_entry.get("id") or self._lora_state_id(lora_entry.get("name", ""), lora_type)
state = memory.setdefault(
lora_id,
{
"name": lora_entry.get("name", ""),
"type": lora_type,
"offset_ratio": 0.0,
"stable_offset_ratio": None,
"reward_ema": 0.0,
"culprit_score": 0.0,
"good_streak": 0,
"bad_streak": 0,
"culprit_hits": 0,
"iterations": 0,
},
)
state["name"] = lora_entry.get("name", "")
state["type"] = lora_type
state.setdefault("offset_ratio", 0.0)
state.setdefault("stable_offset_ratio", None)
state.setdefault("reward_ema", 0.0)
state.setdefault("culprit_score", 0.0)
state.setdefault("good_streak", 0)
state.setdefault("bad_streak", 0)
state.setdefault("culprit_hits", 0)
state.setdefault("iterations", 0)
return lora_id, state
def _score_lora_prompt_relation(self, lora_entry, ordered_concept_ids, concept_clusters, current_concept_labels):
lora_type = lora_entry.get("type", "general")
lora_words = self._lora_words(lora_entry.get("name", ""))
best_score = 0.35 if lora_type == "general" else 0.0
best_labels = []
best_importance = 1.0
for cid in ordered_concept_ids:
cluster = concept_clusters.get(cid)
if not cluster:
continue
cluster = self._ensure_concept_cluster_defaults(cluster)
label = current_concept_labels.get(cid, cluster.get("label", cid))
label_words = self._lora_words(label)
anchor_words = set(cluster.get("anchor_words", []))
prompt_words = label_words | anchor_words
category = cluster.get("category", "general")
overlap = len(lora_words & prompt_words) / max(1, len(lora_words)) if lora_words else 0.0
category_score = 0.62 if lora_type == category else 0.0
if lora_type in {"action", "concept"} and category in {"concept", "details", "subject", "appearance", "action", "environment"}:
category_score = max(category_score, 0.58)
if lora_type == "character" and category in {"character", "subject", "appearance"}:
category_score = max(category_score, 0.72)
if lora_type == "quality" and category == "quality":
category_score = 0.78
if lora_type == "style" and category in {"style", "camera"}:
category_score = max(category_score, 0.58)
score = max(category_score, overlap)
if score > best_score:
best_score = score
best_labels = [label]
best_importance = self._get_concept_mean_importance(cluster)
elif score > 0 and abs(score - best_score) < 1e-6:
best_labels.append(label)
return min(1.0, best_score), best_labels[:4], best_importance
def _update_lora_weight_suggestions(self, lora_stack, active, global_adaptive, ordered_concept_ids,
concept_clusters, current_concept_labels, rating, reward,
rating_profile: Optional[dict] = None):
if not isinstance(lora_stack, dict) or not lora_stack.get("loras"):
return "LoRA suggestions: no FunPack LoRA stack connected."
rating_profile = rating_profile or normalize_refiner_rating(rating)
rating_key = rating_profile.get("key", "")
missing_axes = set(rating_profile.get("missing_axes", []))
missing_count = len(missing_axes)
memory = global_adaptive.setdefault("lora_weight_memory", {})
suggestions = {}
status_parts = []
relation_cache = {}
top_concept_relation = 0.0
concept_lora_count = 0
for entry in lora_stack.get("loras", []):
lora_type = entry.get("type", "general")
lora_id = entry.get("id") or self._lora_state_id(entry.get("name", ""), lora_type)
relation, matched_labels, concept_importance = self._score_lora_prompt_relation(
entry,
ordered_concept_ids,
concept_clusters,
current_concept_labels,
)
relation_cache[lora_id] = (relation, matched_labels, concept_importance)
if lora_type in {"action", "concept", "character"}:
concept_lora_count += 1
top_concept_relation = max(top_concept_relation, relation)
for entry in lora_stack.get("loras", []):
lora_type = entry.get("type", "general")
profile = LORA_REFINER_TYPE_PROFILES.get(lora_type, LORA_REFINER_TYPE_PROFILES["general"])
lora_id, state = self._ensure_lora_memory(memory, entry)
relation, matched_labels, concept_importance = relation_cache.get(lora_id, (0.0, [], 1.0))
state["reward_ema"] = 0.84 * float(state.get("reward_ema", 0.0)) + 0.16 * reward
if rating_key == "like":
state["good_streak"] = int(state.get("good_streak", 0)) + 1
state["bad_streak"] = 0
elif rating_key == "dislike" or {"concept", "quality"}.issubset(missing_axes):
state["bad_streak"] = int(state.get("bad_streak", 0)) + 1
state["good_streak"] = 0
else:
state["good_streak"] = 0
state["bad_streak"] = 0
offset = float(state.get("offset_ratio", 0.0))
stable_offset = state.get("stable_offset_ratio")
culprit_score = float(state.get("culprit_score", 0.0))
culprit_hits = int(state.get("culprit_hits", 0))
if stable_offset is not None and (rating_key == "like" or missing_axes == {"details"}):
offset = 0.72 * offset + 0.28 * float(stable_offset)
step = profile["step"] * max(0.15, relation)
max_offset = profile["max_offset"]
min_offset = profile["min_offset"]
effective_relation = max(relation, profile.get("culprit_bias", 0.0))
base_model = float(entry.get("base_model_weight", entry.get("model_weight", 1.0)))
base_abs = abs(base_model)
is_concept_lora = lora_type in {"action", "concept"}
concept_match_strength = 1.0
if is_concept_lora:
concept_match_strength += 0.30 if matched_labels else 0.0
concept_match_strength += max(0.0, relation - 0.30) * 1.35
is_primary_concept_lora = (
lora_type in {"action", "concept", "character"} and
(
concept_lora_count == 1 or
(top_concept_relation > 0.0 and relation >= max(0.30, top_concept_relation - 1e-6))
)
)
if rating_key == "like":
value_mult = 0.75 + min(1.4, max(0.5, concept_importance)) * 0.25
offset += step * (0.45 + max(0.0, reward)) * value_mult
culprit_score *= 0.72
if state["good_streak"] >= 3:
if stable_offset is None:
stable_offset = offset
else:
stable_offset = 0.78 * float(stable_offset) + 0.22 * offset
state["stable_offset_ratio"] = _clamp(stable_offset, min_offset, max_offset)
offset = state["stable_offset_ratio"]
elif missing_axes:
if "concept" in missing_axes or "quality" in missing_axes:
state["stable_offset_ratio"] = None
culprit_score *= 0.74 if rating_key == "awful" else 0.82
culprit_hits = max(0, culprit_hits - 1)
axis_boost = 0.0
if "details" in missing_axes:
if relation >= 0.12 and lora_type in {"action", "concept", "character", "general", "style"}:
value_mult = 0.85 + min(1.2, max(0.5, concept_importance)) * 0.20
axis_boost += (0.26 + relation * 0.34) * value_mult
elif lora_type == "quality":
axis_boost += 0.06
if "concept" in missing_axes:
if lora_type in {"action", "concept", "character"}:
if is_primary_concept_lora:
axis_boost += (0.95 + abs(reward) * 0.45) * concept_match_strength
elif relation > 0.08:
axis_boost += 0.34 + relation * 0.40
elif lora_type == "general" and relation >= 0.25:
axis_boost += 0.25 + relation * 0.25
if "quality" in missing_axes:
if lora_type == "quality":
axis_boost += 0.90 + abs(reward) * 0.35
elif lora_type == "style" and relation >= 0.25:
axis_boost += 0.20 + relation * 0.20
elif lora_type == "general" and relation >= 0.20:
axis_boost += 0.16 + relation * 0.15
if axis_boost > 0.0:
if rating_key == "awful":
axis_boost *= 1.25
max_offset = max(max_offset, profile["bad_max_offset"] * (0.62 + 0.10 * missing_count))
relation_floor = 0.35 if missing_count >= 2 else 0.22
boost_step = profile["step"] * max(relation_floor, effective_relation)
offset += boost_step * axis_boost
elif relation <= 0.05:
offset *= 0.97
else:
offset *= 0.94
elif rating_key == "dislike":
severity = _clamp((5.0 - float(rating)) / 4.0, 0.0, 1.0)
culprit_signal = max(0.20, effective_relation) * (0.70 + base_abs * 0.30)
if is_concept_lora:
culprit_signal *= concept_match_strength
culprit_score = _clamp(culprit_score * 0.72 + severity * culprit_signal, 0.0, 2.5)
culprit_hits = culprit_hits + 1 if culprit_score >= 0.45 else max(0, culprit_hits - 1)
max_offset = profile["bad_max_offset"] if rating <= 2 else max(max_offset, profile["bad_max_offset"] * 0.72)
bad_floor_strength = min(1.0, 0.45 + 0.35 * culprit_score + 0.14 * state["bad_streak"])
if is_concept_lora:
bad_floor_strength = min(1.0, bad_floor_strength + 0.18 * concept_match_strength)
min_offset = min(min_offset, profile["bad_min_offset"] * bad_floor_strength)
offset -= step * (1.0 + severity * 3.0) * max(0.4, effective_relation) * max(0.8, 0.85 + culprit_score)
if state["bad_streak"] >= 2:
offset -= step * (0.65 + severity * 1.8) * max(0.25, effective_relation)
if is_concept_lora and state["bad_streak"] >= 2:
offset -= step * (0.85 + severity * 2.4) * max(0.50, effective_relation) * concept_match_strength
if state["bad_streak"] >= 2:
state["stable_offset_ratio"] = None
if is_concept_lora and matched_labels and state["bad_streak"] >= 2 and culprit_score >= 0.70:
offset = min(offset, -1.0)
if state["bad_streak"] >= 3 and culprit_score >= 0.85 and abs(1.0 + offset) < 0.08:
offset = -1.0
else:
culprit_score *= 0.92
culprit_hits = max(0, culprit_hits - 1)
if relation <= 0.05:
offset *= 0.94
elif stable_offset is not None:
offset = 0.65 * offset + 0.35 * float(stable_offset)
else:
offset *= 0.90
offset = _clamp(offset, min_offset, max_offset)
state["offset_ratio"] = offset
state["culprit_score"] = culprit_score
state["culprit_hits"] = culprit_hits
state["iterations"] = int(state.get("iterations", 0)) + 1
model_weight = base_model * (1.0 + offset)
suspect = culprit_score >= 0.65 or model_weight <= 0.0 or culprit_hits >= 2
action = (
"invert" if model_weight < 0.0 else
"mute" if model_weight == 0.0 else
"hold" if abs(model_weight - base_model) < 1e-6 else
"reduce" if abs(model_weight) < abs(base_model) else
"boost"
)
suggestions[lora_id] = {
"name": entry.get("name", ""),
"type": lora_type,
"model_weight": model_weight,
"base_model_weight": base_model,
"offset_ratio": offset,
"culprit_score": culprit_score,
"culprit_hits": culprit_hits,
"suspect": suspect,
"action": action,
"relation": relation,
"matched_concepts": matched_labels,
"rating": int(rating),
"rating_label": rating_profile.get("label", str(rating)),
"rating_range": rating_profile.get("legacy_range", ""),
"good_streak": state.get("good_streak", 0),
"bad_streak": state.get("bad_streak", 0),
"stable": state.get("stable_offset_ratio") is not None,
}
match_text = ",".join(matched_labels) if matched_labels else "none"
status_parts.append(
f"{entry.get('name', '?')}[{lora_type}] rel={relation:.2f} "
f"offset={offset:+.3f} next={model_weight:+.3f} "
f"sus={culprit_score:.2f}{' !' if suspect else ''} "
f"match={match_text}"
)
active["lora_weight_suggestions"] = suggestions
active["last_lora_stack"] = lora_stack
if not status_parts:
return "LoRA suggestions: stack empty."
return f"LoRA suggestions ({rating_profile.get('label', str(rating))}): " + " | ".join(status_parts)
# =========================================================================
# MAIN REFINE
# =========================================================================