thr3shr / backend /scripts /run_realism_debug_eval.py
Dinamush
chore: drop personal default selected-tags lists from tooling
dc624ae
Raw
History Blame Contribute Delete
4.83 kB
"""Thorough remote real-life vs anime eval (multi-model) + optional local video check.
Writes JSON under scripts/out/ and prints a definitive GO/NO_GO conclusion.
"""
from __future__ import annotations
import json
import logging
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REPO = ROOT.parent
sys.path.insert(0, str(ROOT))
from app.realism_eval import predict_real_life, run_realism_eval_multi_model # noqa: E402
from app.schemas import AppSettings # noqa: E402
from app.services import VIDEO_EXTENSIONS, extract_scores_with_experimental_media # noqa: E402
from app.storage import init_db # noqa: E402
from app.taxonomy import reload_taxonomy # noqa: E402
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
)
logger = logging.getLogger("run_realism_debug_eval")
def _settings_from_db() -> AppSettings:
from app.api import _settings_from_db as load
return load()
def _probe_local_videos(settings: AppSettings, model: str, limit: int = 8) -> dict:
"""Score local videos with multi-frame pooling if present."""
roots = []
if settings.root_repo:
roots.append(Path(settings.root_repo).expanduser())
extra = os.environ.get("THR3SHR_VIDEO_PROBE_ROOT", "").strip()
if extra:
roots.append(Path(extra).expanduser())
videos: list[Path] = []
for root in roots:
if root is None or not root.is_dir():
continue
for path in root.iterdir():
if path.suffix.lower() in VIDEO_EXTENSIONS and path.is_file():
videos.append(path)
if videos:
break
videos = sorted(videos)[:limit]
items = []
for path in videos:
try:
scores = extract_scores_with_experimental_media(
path,
experimental_media_enabled=True,
tagger_model=model,
wd_general_threshold=settings.wd_general_threshold,
)
is_rl, folder, score, evidence = predict_real_life(
scores,
selected={"real_life", "photo", *(settings.selected_tags or [])},
)
items.append(
{
"path": str(path),
"predicted_real_life": is_rl,
"folder": folder,
"score": score,
"evidence": evidence,
}
)
except Exception as err:
items.append({"path": str(path), "error": str(err)})
return {
"model": model,
"count": len(items),
"predicted_real_life": sum(1 for i in items if i.get("predicted_real_life")),
"items": items,
}
def main() -> int:
init_db()
reload_taxonomy()
settings = _settings_from_db()
count = int(sys.argv[1]) if len(sys.argv) > 1 else 16
count = max(8, min(count, 40))
logger.info("starting multi-model realism eval count_per_class=%s", count)
multi = run_realism_eval_multi_model(count_per_class=count, settings=settings)
best = multi.get("best_model") or "wd_eva02_large"
logger.info("probing local videos with best_model=%s", best)
video_probe = _probe_local_videos(settings, best, limit=10)
out_dir = Path(__file__).resolve().parent / "out"
out_dir.mkdir(parents=True, exist_ok=True)
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
payload = {
"generated_at": datetime.now(timezone.utc).isoformat(),
"multi_model": multi,
"local_video_probe": video_probe,
}
out_path = out_dir / f"realism_debug_eval_{stamp}.json"
latest = out_dir / "realism_debug_eval_latest.json"
text = json.dumps(payload, indent=2)
out_path.write_text(text, encoding="utf-8")
latest.write_text(text, encoding="utf-8")
overall = multi.get("overall_conclusion") or {}
print("=== REALISM DEBUG EVAL ===")
print("decision:", overall.get("decision"))
print("best_model:", overall.get("best_model"))
print("summary:", overall.get("summary"))
print("video:", overall.get("video_and_gif"))
for report in multi.get("reports") or []:
m = report.get("metrics") or {}
print(
f"- {report.get('tagger_model')}: {report.get('conclusion', {}).get('decision')} "
f"P={m.get('precision')} R={m.get('recall')} F1={m.get('f1')} "
f"animeFP={m.get('anime_false_positive_rate')} n={report.get('count_evaluated')}"
)
print("local_video_predicted_real_life:", video_probe.get("predicted_real_life"), "/", video_probe.get("count"))
print("wrote", out_path)
return 0 if overall.get("decision") == "GO" else 2
if __name__ == "__main__":
raise SystemExit(main())