iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
AI & Data

從0開始的MLFLOW應用搭建系列 第 23

Day 23 – 建立記錄 API /log-ab-event

  • 分享至 

  • xImage
  •  

🎯 今日目標

  1. 建立一個 /log-ab-event API,用來紀錄使用者行為事件(例如「使用者點擊了推薦的動畫」)。
  2. 資料會寫入 workspace/logs/ab_events.csv
  3. 說明如何將此紀錄作為 AB 測試資料,供之後分析模型效果使用。

🔍 背景

推薦系統只有提供推薦還不夠。
企業級系統必須要 追蹤使用者對推薦的反應
例如:

  • 哪個模型提供的推薦被點擊更多?
  • 哪個推薦清單帶來更高轉換率?

這些資訊會作為後續 AB 測試 的基礎。


🧩 1. 更新 FastAPI 主程式

請修改 src/api/main.py,在 /recommend 之後新增以下內容。
(完整內容如下)

import mlflow
import mlflow.pyfunc
from fastapi import FastAPI
from pydantic import BaseModel
import pandas as pd
import os
import csv
from datetime import datetime

app = FastAPI(
    title="Anime Recommender API",
    description="FastAPI + MLflow 企業級推薦系統",
    version="2.0.0"
)

# === Health Check ===
@app.get("/health")
def health_check():
    return {"status": "ok", "message": "FastAPI is running 🚀"}

# === 輸入格式定義 ===
class RecommendRequest(BaseModel):
    anime_titles: list[str]

class ABEvent(BaseModel):
    user_id: str
    model_version: int
    recommended_title: str
    clicked: bool
    timestamp: datetime = datetime.utcnow()

# === 載入模型 ===
mlflow.set_tracking_uri("http://mlflow:5000")
MODEL_URI = "models:/AnimeRecsysModel/Staging"
print(f"📦 Loading model from {MODEL_URI} ...")
model = mlflow.pyfunc.load_model(MODEL_URI)
print("✅ Model loaded successfully!")

# === 推薦 API ===
@app.post("/recommend")
def recommend(request: RecommendRequest):
    try:
        df_input = pd.DataFrame(request.anime_titles)
        result = model.predict(df_input)
        return {
            "input": request.anime_titles,
            "recommendations": result[0]
        }
    except Exception as e:
        return {"error": str(e)}

# === 記錄 API (/log-ab-event) ===
@app.post("/log-ab-event")
def log_ab_event(event: ABEvent):
    LOG_DIR = "/usr/mlflow/workspace/logs"
    os.makedirs(LOG_DIR, exist_ok=True)
    log_path = os.path.join(LOG_DIR, "ab_events.csv")

    # 檢查檔案是否存在,若不存在就加上標題列
    file_exists = os.path.isfile(log_path)
    with open(log_path, mode="a", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        if not file_exists:
            writer.writerow(["timestamp", "user_id", "model_version", "recommended_title", "clicked"])
        writer.writerow([
            event.timestamp.isoformat(),
            event.user_id,
            event.model_version,
            event.recommended_title,
            event.clicked
        ])
    return {"message": "Event logged successfully", "event": event.dict()}

🧠 程式解說

區塊 功能
ABEvent(BaseModel) 定義使用者行為事件的輸入格式。
timestamp 預設使用 UTC 時間,確保資料可對齊後續分析。
log_ab_event() 將事件資料追加寫入 workspace/logs/ab_events.csv
os.makedirs(LOG_DIR, exist_ok=True) 自動建立日誌資料夾。

🧪 2. 測試 /log-ab-event API

python-dev 容器使用 curl 測試

curl -X POST http://fastapi:8000/log-ab-event \
  -H "Content-Type: application/json" \
  -d '{
        "user_id": "user_123",
        "model_version": 7,
        "recommended_title": "Steins;Gate",
        "clicked": true
      }'

https://ithelp.ithome.com.tw/upload/images/20251007/20178626ZF7lY94mZs.png

資料會寫到:

/usr/mlflow/workspace/logs/ab_events.csv

他會對應到本機環境:

/usr/mlflow-fastapi-zero-to-prod/workspace/logs/ab_events.csv

我們可以用vscode打開來看看

https://ithelp.ithome.com.tw/upload/images/20251007/20178626oIA6kDWvRS.png


🧭 架構概念圖

Client (Streamlit / Web / App)
        │
        ├── POST /recommend   → 取得推薦清單
        │
        └── POST /log-ab-event → 回報使用者點擊行為
                              │
                              ▼
                    workspace/logs/ab_events.csv

💡 延伸應用

之後AB Test 分析時
我們會用這個 ab_events.csv 來計算:

  • 每個模型的點擊率 (CTR)
  • 每個版本推薦被點擊的分佈
  • 哪個模型在真實用戶互動中表現較好

✅ 重點總結

  • 建立了第二支 API:/log-ab-event

  • 所有使用者行為會被紀錄到 workspace/logs/ab_events.csv

  • 這份紀錄將成為後續 AB 測試分析的依據

  • 目前 FastAPI 已形成雙 API 架構:

    /recommend      → 提供推薦
    /log-ab-event   → 收集點擊紀錄
    

上一篇
Day 22 – 建立推薦 API /recommend
系列文
從0開始的MLFLOW應用搭建23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言