File size: 1,909 Bytes
8b4a5e6
c69f346
8b4a5e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from __future__ import annotations
from fastapi import FastAPI, Body
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import pandas as pd
from typing import Dict, Any, List

from data import append_events, read_events, aggregate
from bandit import EmpiricalBayesHierarchicalThompson
from causal import fit_uplift_binary

# Gradio を FastAPI にマウント
from dashboard import build_ui
import gradio as gr

app = FastAPI(title="AdCopy MAB Optimizer Pro", version="0.1.0")
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

ui = build_ui()
app = gr.mount_gradio_app(app, ui, path="/")

BANDIT = EmpiricalBayesHierarchicalThompson(min_explore=0.05, margin=0.0, n_draws=20000)

@app.get("/api/health")
def health():
    return {"status": "ok"}

@app.get("/api/events")
def get_events():
    df = read_events()
    return JSONResponse(content=df.to_dict(orient="records"))

@app.post("/api/ingest")
def ingest(rows: List[Dict[str, Any]] = Body(..., embed=True)):
    """
    rows: [
      {"date":"2025-09-01","medium":"FB","creative":"A1","is_control":1,"impressions":1000,"clicks":30,"conversions":5,"cost":1000.0,"features_json":"{\\"len\\":20}"},
      ...
    ]
    """
    df = pd.DataFrame(rows)
    append_events(df)
    return {"ok": True, "n": len(df)}

@app.get("/api/aggregate")
def get_agg():
    agg = aggregate()
    return JSONResponse(content=agg.to_dict(orient="records"))

@app.post("/api/optimize")
def optimize():
    agg = aggregate()
    if agg.empty:
        return {"message": "no data"}
    rec = BANDIT.recommend(agg)
    return JSONResponse(content=rec)

@app.post("/api/uplift")
def uplift():
    agg = aggregate()
    if agg.empty:
        return {"message": "no data"}
    res = fit_uplift_binary(agg)
    return JSONResponse(content=res)