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>
- newApp (extracted from main) is the exact production wiring; the
`ci / db` job now also runs it on PostgreSQL, Redis and Meilisearch
and walks the main user flows over HTTP: first admin sign-in and
credential change, local source and scan, search, album / artist /
top tracks, signed stream, events and history, likes, fallback wave,
playback state, upload queue up to review.
- ALS on a small library produced fewer than 64 factors and the insert
into vector(64) failed; vectors are now zero-padded to the column size.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Implicit scores from play events and reactions per the signals table
(90-day half-life, weaker skips outside the wave, dislikes override).
- numpy ALS for implicit feedback; time-split evaluation on the last
7 days (NDCG@10, Recall@50) against a popularity baseline; a new model
is activated only if NDCG@10 does not regress by more than 2%.
- Vectors are written to track_embeddings.cf and user_profiles_rec.taste_cf,
versions to model_versions; NightlyTrainer runs at TRAIN_HOUR and on
first start, `pipu-rec train` runs it manually.
- Wave: cf and item_cf candidate sources and a 0.10 cf term in the v1
score; impressions are tagged heuristic-v1+cf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>