Spaces:
Sleeping
Sleeping
Update dashboard.py
Browse files- dashboard.py +31 -18
dashboard.py
CHANGED
|
@@ -13,18 +13,19 @@ REQUIRED_COLS = [
|
|
| 13 |
"impressions","clicks","conversions","cost","features_json"
|
| 14 |
]
|
| 15 |
|
| 16 |
-
#
|
| 17 |
-
def _ok(msg: str):
|
| 18 |
-
return
|
| 19 |
-
def _warn(msg: str):
|
| 20 |
-
return
|
| 21 |
-
def _err(msg: str):
|
| 22 |
-
return
|
| 23 |
-
|
| 24 |
-
#
|
| 25 |
def ui_refresh_tables():
|
| 26 |
df = read_events()
|
| 27 |
agg = aggregate()
|
|
|
|
| 28 |
return df, agg, _ok("Refreshed.")
|
| 29 |
|
| 30 |
def ui_load_sample():
|
|
@@ -45,30 +46,42 @@ def ui_load_sample():
|
|
| 45 |
return df, agg, _ok("Sample data loaded.")
|
| 46 |
|
| 47 |
def ui_upload_csv(file: gr.File):
|
|
|
|
| 48 |
if file is None:
|
|
|
|
| 49 |
return gr.update(), gr.update(), _warn("CSVファイルを選択してください。")
|
| 50 |
try:
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
except Exception as e:
|
| 53 |
return gr.update(), gr.update(), _err(f"CSV読み込みに失敗: {e}")
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
missing = [c for c in REQUIRED_COLS if c not in df.columns]
|
| 56 |
if missing:
|
| 57 |
return gr.update(), gr.update(), _err(f"必須列が不足: {missing}")
|
| 58 |
|
| 59 |
-
#
|
| 60 |
for c in ["is_control","impressions","clicks","conversions"]:
|
| 61 |
df[c] = df[c].fillna(0).astype(int)
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
df["features_json"] = df["features_json"].fillna("{}").astype(str)
|
| 66 |
|
| 67 |
append_events(df)
|
| 68 |
df2, agg2 = read_events(), aggregate()
|
| 69 |
return df2, agg2, _ok(f"取り込み完了({len(df)}行)。")
|
| 70 |
|
| 71 |
-
#
|
| 72 |
def ui_recommend():
|
| 73 |
agg = aggregate()
|
| 74 |
if agg.empty:
|
|
@@ -93,13 +106,13 @@ def ui_fit_uplift():
|
|
| 93 |
return {"message": "No data"}
|
| 94 |
return fit_uplift_binary(agg)
|
| 95 |
|
| 96 |
-
#
|
| 97 |
def build_ui():
|
| 98 |
with gr.Blocks(title="AdCopy MAB Optimizer Pro") as demo:
|
| 99 |
gr.Markdown("# AdCopy MAB Optimizer Pro — Hierarchical TS + Uplift")
|
| 100 |
|
| 101 |
with gr.Tab("Data"):
|
| 102 |
-
status = gr.Markdown() #
|
| 103 |
with gr.Row():
|
| 104 |
btn_refresh = gr.Button("Refresh")
|
| 105 |
btn_seed = gr.Button("Load Sample Data")
|
|
|
|
| 13 |
"impressions","clicks","conversions","cost","features_json"
|
| 14 |
]
|
| 15 |
|
| 16 |
+
# ---------- helpers ----------
|
| 17 |
+
def _ok(msg: str) -> str:
|
| 18 |
+
return f"✅ {msg}"
|
| 19 |
+
def _warn(msg: str) -> str:
|
| 20 |
+
return f"⚠️ {msg}"
|
| 21 |
+
def _err(msg: str) -> str:
|
| 22 |
+
return f"❌ {msg}"
|
| 23 |
+
|
| 24 |
+
# ---------- data ops ----------
|
| 25 |
def ui_refresh_tables():
|
| 26 |
df = read_events()
|
| 27 |
agg = aggregate()
|
| 28 |
+
# 3つ目の出力(status)は Markdown なので、単なる文字列でOK
|
| 29 |
return df, agg, _ok("Refreshed.")
|
| 30 |
|
| 31 |
def ui_load_sample():
|
|
|
|
| 46 |
return df, agg, _ok("Sample data loaded.")
|
| 47 |
|
| 48 |
def ui_upload_csv(file: gr.File):
|
| 49 |
+
# アウトプットは [grid, grid_agg, status]
|
| 50 |
if file is None:
|
| 51 |
+
# 表は変更しない → gr.update() で“no change”、statusだけ文字列更新
|
| 52 |
return gr.update(), gr.update(), _warn("CSVファイルを選択してください。")
|
| 53 |
try:
|
| 54 |
+
# 文字コードの揺れに対処
|
| 55 |
+
try:
|
| 56 |
+
df = pd.read_csv(file.name)
|
| 57 |
+
except Exception:
|
| 58 |
+
df = pd.read_csv(file.name, encoding="utf-8-sig")
|
| 59 |
except Exception as e:
|
| 60 |
return gr.update(), gr.update(), _err(f"CSV読み込みに失敗: {e}")
|
| 61 |
|
| 62 |
+
# 区切り子の誤検知(TSV等)を簡易補正
|
| 63 |
+
if df.shape[1] == 1 and "," in str(df.columns[0]):
|
| 64 |
+
try:
|
| 65 |
+
df = pd.read_csv(file.name, sep=",", engine="python")
|
| 66 |
+
except Exception:
|
| 67 |
+
pass
|
| 68 |
+
|
| 69 |
missing = [c for c in REQUIRED_COLS if c not in df.columns]
|
| 70 |
if missing:
|
| 71 |
return gr.update(), gr.update(), _err(f"必須列が不足: {missing}")
|
| 72 |
|
| 73 |
+
# 軽いサニタイズ
|
| 74 |
for c in ["is_control","impressions","clicks","conversions"]:
|
| 75 |
df[c] = df[c].fillna(0).astype(int)
|
| 76 |
+
df["cost"] = df.get("cost", 0.0)
|
| 77 |
+
df["cost"] = df["cost"].fillna(0.0).astype(float)
|
| 78 |
+
df["features_json"] = df.get("features_json", "{}").fillna("{}").astype(str)
|
|
|
|
| 79 |
|
| 80 |
append_events(df)
|
| 81 |
df2, agg2 = read_events(), aggregate()
|
| 82 |
return df2, agg2, _ok(f"取り込み完了({len(df)}行)。")
|
| 83 |
|
| 84 |
+
# ---------- bandit / causal ----------
|
| 85 |
def ui_recommend():
|
| 86 |
agg = aggregate()
|
| 87 |
if agg.empty:
|
|
|
|
| 106 |
return {"message": "No data"}
|
| 107 |
return fit_uplift_binary(agg)
|
| 108 |
|
| 109 |
+
# ---------- UI ----------
|
| 110 |
def build_ui():
|
| 111 |
with gr.Blocks(title="AdCopy MAB Optimizer Pro") as demo:
|
| 112 |
gr.Markdown("# AdCopy MAB Optimizer Pro — Hierarchical TS + Uplift")
|
| 113 |
|
| 114 |
with gr.Tab("Data"):
|
| 115 |
+
status = gr.Markdown("") # ← ここは“文字列”を受け取れる
|
| 116 |
with gr.Row():
|
| 117 |
btn_refresh = gr.Button("Refresh")
|
| 118 |
btn_seed = gr.Button("Load Sample Data")
|