feat(recommender): Thompson-sampling bandit over candidate sources (M6)
Nightly Beta(α, β) per user and source from wave impressions (reward: complete or like, ×0.99 daily decay) stored in user_profiles_rec.bandit; the wave adds 0.2·(θ − 0.5) per candidate source, sources without data stay neutral. The user's exploration share now follows how well `fresh` does against the other sources. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f7722e28ad
commit
ff0aafdb1e
6 files changed
+130
-2
No files matched your search
@@ -15,6 +15,7 @@ import numpy as np
|
||||
import psycopg
|
||||
|
||||
from pipu_rec.train.als import ALSModel, normalize, train_als
|
||||
from pipu_rec.train.bandit import update_bandits
|
||||
from pipu_rec.train.metrics import evaluate
|
||||
from pipu_rec.train.signals import DISLIKE, LIKE, Interaction, event_weight, implicit_scores
|
||||
|
||||
@@ -157,9 +158,11 @@ def train_all(dsn: str, now: float | None = None) -> dict[str, Any]:
|
||||
if not conn.execute("SELECT pg_try_advisory_lock(%s)", (ADVISORY_LOCK,)).fetchone()[0]: # type: ignore[index]
|
||||
return {"skipped": "another training is running"}
|
||||
try:
|
||||
# Бандит считается всегда — ему хватает и пары сессий волны, в отличие от ALS.
|
||||
bandit_users = update_bandits(conn, now)
|
||||
interactions = load_interactions(conn)
|
||||
if len(interactions) < MIN_INTERACTIONS:
|
||||
return {"skipped": f"only {len(interactions)} interactions"}
|
||||
return {"skipped": f"only {len(interactions)} interactions", "bandit_users": bandit_users}
|
||||
started = time.monotonic()
|
||||
offline = offline_metrics(interactions, now)
|
||||
model = train_als(implicit_scores(interactions, now))
|
||||
@@ -171,6 +174,7 @@ def train_all(dsn: str, now: float | None = None) -> dict[str, Any]:
|
||||
"users": len(model.users),
|
||||
"items": len(model.items),
|
||||
"interactions": len(interactions),
|
||||
"bandit_users": bandit_users,
|
||||
"train_s": round(time.monotonic() - started, 1),
|
||||
}
|
||||
if not should_activate(offline, active_metrics(conn, "als")):
|
||||
|
||||
Reference in new issue
Block a user