feat: Ranking Engine V2 — intelligent scoring with shares, authority, decay & velocity\n\n- Add ArtworkRankingService with V2 formula:\n ranking_score = (base × authority × decay) + velocity_boost\n Base: views×0.2 + downloads×1.5 + favourites×2.5 + comments×3.0 + shares×4.0\n Authority: 1 + (log10(1+followers) + fav_received/1000) × 0.05\n Decay: 1 / (1 + hours/48)\n Velocity: 24h signals × velocity_weights × 0.5\n\n- Add nova:recalculate-rankings command (--chunk, --sync-rank-scores, --skip-index)\n- Add migration: ranking_score, engagement_velocity, shares/comments counts to artwork_stats\n- Upgrade RankingService.computeScores() with shares + comments + velocity\n- Update Meilisearch sortableAttributes: ranking_score, shares_count, engagement_velocity, comments_count\n- Update toSearchableArray() to expose V2 fields\n- Schedule every 30 min with overlap protection\n- Verified: 49733 artworks scored successfully"

This commit is contained in:
2026-02-28 16:41:15 +01:00
parent 90f244f264
commit de3ec22ee5
10 changed files with 837 additions and 14 deletions

View File

@@ -11,7 +11,7 @@ declare(strict_types=1);
return [
// ── Model versioning ────────────────────────────────────────────────────
'model_version' => 'rank_v1',
'model_version' => 'rank_v2',
// ── Engagement signal weights (log-scaled) ──────────────────────────────
'weights' => [
@@ -20,6 +20,36 @@ return [
'downloads' => 2.5,
],
// ── V2 ranking formula weights ──────────────────────────────────────────
'v2' => [
// Base engagement weights (linear, applied to raw counts)
'weights' => [
'views' => 0.2,
'downloads' => 1.5,
'favourites' => 2.5,
'comments' => 3.0,
'shares' => 4.0, // highest — viral intent
],
// 24h velocity weights
'velocity_weights' => [
'views' => 1.0,
'favourites' => 3.0,
'comments' => 4.0,
'shares' => 5.0,
],
// Velocity multiplier applied to the 24h velocity sum
'velocity_multiplier' => 0.5,
// Recency decay half-life in hours
'half_life' => 48,
// Author authority: multiplier = 1 + (authority * factor)
'authority_factor' => 0.05,
'authority_fav_divisor' => 1000,
],
// ── Time-decay half-lives (hours) ───────────────────────────────────────
'half_life' => [
'trending' => 72, // Explore / global trending