Spaces:
Running
Running
deploy app, storage, readme
Browse files
app.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import random
|
| 3 |
import threading
|
|
|
|
| 4 |
import uuid
|
| 5 |
import os
|
| 6 |
import html
|
|
@@ -18,6 +19,8 @@ SUBMIT_KEY = os.getenv("RATINGS_SUBMIT_KEY")
|
|
| 18 |
assert SUBMIT_KEY, "Missing required env var: RATINGS_SUBMIT_KEY"
|
| 19 |
POOL_REPO_ID = "taigasan/e6-visual-ratings"
|
| 20 |
VOTE_STORAGE = VoteStorage(mode="local" if DEBUG_MODE else "hf", local_dir=LOCAL_DATA_DIR, token=RATINGS_APP_TOKEN)
|
|
|
|
|
|
|
| 21 |
|
| 22 |
# -- Pool dataset -----------------------------------------------------------
|
| 23 |
if DEBUG_MODE:
|
|
@@ -32,6 +35,32 @@ else:
|
|
| 32 |
)
|
| 33 |
_pool_df = pd.read_parquet(_pool_path)
|
| 34 |
_pool_group_dfs = {g: gdf for g, gdf in _pool_df.groupby("group")}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
def _pool_fetch_pair(group_name: str) -> tuple:
|
| 37 |
gdf = _pool_group_dfs[group_name]
|
|
@@ -73,10 +102,19 @@ def _commit_oldest_pending(state: dict):
|
|
| 73 |
threading.Thread(target=VOTE_STORAGE.append_vote_row, args=(oldest.copy(), oldest.get("winner")), daemon=True).start()
|
| 74 |
|
| 75 |
def _render_current(state: dict, submit_status: str = "") -> tuple:
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
can_go_back = bool(state.get("can_go_back"))
|
| 81 |
back_md = "[back](#back)" if can_go_back else "<span class='subtle-back-link-disabled'>back</span>"
|
| 82 |
details = f"<span class='subtle-note'>Group: {state['group']}</span>"
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import random
|
| 3 |
import threading
|
| 4 |
+
import time
|
| 5 |
import uuid
|
| 6 |
import os
|
| 7 |
import html
|
|
|
|
| 19 |
assert SUBMIT_KEY, "Missing required env var: RATINGS_SUBMIT_KEY"
|
| 20 |
POOL_REPO_ID = "taigasan/e6-visual-ratings"
|
| 21 |
VOTE_STORAGE = VoteStorage(mode="local" if DEBUG_MODE else "hf", local_dir=LOCAL_DATA_DIR, token=RATINGS_APP_TOKEN)
|
| 22 |
+
STATS_PATH = Path(__file__).resolve().parent.parent / "stats.parquet"
|
| 23 |
+
STATS_RELOAD_S = 30 * 60
|
| 24 |
|
| 25 |
# -- Pool dataset -----------------------------------------------------------
|
| 26 |
if DEBUG_MODE:
|
|
|
|
| 35 |
)
|
| 36 |
_pool_df = pd.read_parquet(_pool_path)
|
| 37 |
_pool_group_dfs = {g: gdf for g, gdf in _pool_df.groupby("group")}
|
| 38 |
+
_stats_lock = threading.Lock()
|
| 39 |
+
_stats_last_loaded_at = 0.0
|
| 40 |
+
_stats_by_key: dict[str, tuple[int, int]] = {}
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def _reload_stats_if_due(force: bool = False):
|
| 44 |
+
global _stats_last_loaded_at, _stats_by_key
|
| 45 |
+
now = time.time()
|
| 46 |
+
if not force and (now - _stats_last_loaded_at) < STATS_RELOAD_S:
|
| 47 |
+
return
|
| 48 |
+
with _stats_lock:
|
| 49 |
+
now = time.time()
|
| 50 |
+
if not force and (now - _stats_last_loaded_at) < STATS_RELOAD_S:
|
| 51 |
+
return
|
| 52 |
+
if STATS_PATH.exists():
|
| 53 |
+
_stats_df = pd.read_parquet(STATS_PATH, columns=["item_key", "wins", "losses"]) # [n, 3]
|
| 54 |
+
_stats_by_key = {
|
| 55 |
+
str(r.item_key): (int(r.wins), int(r.losses))
|
| 56 |
+
for r in _stats_df.itertuples(index=False)
|
| 57 |
+
}
|
| 58 |
+
else:
|
| 59 |
+
_stats_by_key = {}
|
| 60 |
+
_stats_last_loaded_at = now
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
_reload_stats_if_due(force=True)
|
| 64 |
|
| 65 |
def _pool_fetch_pair(group_name: str) -> tuple:
|
| 66 |
gdf = _pool_group_dfs[group_name]
|
|
|
|
| 102 |
threading.Thread(target=VOTE_STORAGE.append_vote_row, args=(oldest.copy(), oldest.get("winner")), daemon=True).start()
|
| 103 |
|
| 104 |
def _render_current(state: dict, submit_status: str = "") -> tuple:
|
| 105 |
+
_reload_stats_if_due()
|
| 106 |
+
wins_a, losses_a = _stats_by_key.get(str(state["key_a"]), (0, 0))
|
| 107 |
+
wins_b, losses_b = _stats_by_key.get(str(state["key_b"]), (0, 0))
|
| 108 |
+
total_a = wins_a + losses_a
|
| 109 |
+
total_b = wins_b + losses_b
|
| 110 |
+
win_pct_a = f"{(100.0 * wins_a / total_a):.1f}%" if total_a > 0 else "-"
|
| 111 |
+
win_pct_b = f"{(100.0 * wins_b / total_b):.1f}%" if total_b > 0 else "-"
|
| 112 |
+
title_a = "Image A"
|
| 113 |
+
title_b = "Image B"
|
| 114 |
+
img_a_html = f"<div class=\"rating-card\"><div class=\"rating-card-title\"><strong>{html.escape(title_a)}</strong></div><div class=\"rating-image-frame\"><img src=\"{html.escape(state['url_a'])}\" class=\"rating-image\" loading=\"eager\" referrerpolicy=\"no-referrer\"></div></div>"
|
| 115 |
+
img_b_html = f"<div class=\"rating-card\"><div class=\"rating-card-title\"><strong>{html.escape(title_b)}</strong></div><div class=\"rating-image-frame\"><img src=\"{html.escape(state['url_b'])}\" class=\"rating-image\" loading=\"eager\" referrerpolicy=\"no-referrer\"></div></div>"
|
| 116 |
+
link_a = f"Image A: https://e621.net/posts/{state['id_a']} | Wins: {wins_a} | Losses: {losses_a} | Win percentage: {win_pct_a}"
|
| 117 |
+
link_b = f"Image B: https://e621.net/posts/{state['id_b']} | Wins: {wins_b} | Losses: {losses_b} | Win percentage: {win_pct_b}"
|
| 118 |
can_go_back = bool(state.get("can_go_back"))
|
| 119 |
back_md = "[back](#back)" if can_go_back else "<span class='subtle-back-link-disabled'>back</span>"
|
| 120 |
details = f"<span class='subtle-note'>Group: {state['group']}</span>"
|