0d0a8f46b1
The recommendation scoring knobs move out of YAML (radio profile) and out of the systemMixWeights hard-code (daily_mix profile) into DB-backed settings with live effect (#1250) — the defaults-discovery lab per decision #1247: the operator turns knobs to find good values, which then get baked back into shipped defaults; end users and other operators should never need the card. - Migration 0040: recommendation_weight_profiles (radio / daily_mix, 8 weight columns), taste_tuning singleton (engagement half-life + completion-curve points), recommendation_tuning_audit (one row per change with a {field, old, new} diff — the trend view's markers, #1251). - internal/recsettings: boot reconcile seeds shipped defaults without clobbering tuned rows (coverart SettingsService pattern), validates patches (bounds, curve ordering), writes audit rows, and pushes daily_mix weights + taste config into package playlists. No-op patches write no audit row. - playlists gains SetSystemMixWeights / SetTasteConfig swap points under a RWMutex — no signature threading through the producers; the scheduler's taste rebuild reads the pushed config. - Radio reads its weight profile from the service per request; the 8 weight fields leave config.RecommendationConfig (YAML keeps only RecentlyPlayedHours / RadioSize / RadioSizeMax). - Admin API: GET/PATCH/reset under /api/admin/recommendation-tuning, echoing current + shipped values. - Web: new admin Tuning tab — two weight profiles side by side, taste card, per-scope save (changed fields only) + reset, deviation dots against shipped defaults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TsF3cNoKrqCYsU78cXC8U6
58 lines
2.5 KiB
SQL
58 lines
2.5 KiB
SQL
-- Recommendation tuning lab (milestone #127, Scribe #1250).
|
|
--
|
|
-- The scoring weights move out of YAML (radio profile) and out of the
|
|
-- systemMixWeights hard-code (daily_mix profile) into DB-backed
|
|
-- settings with live effect — the defaults-discovery lab (decision
|
|
-- #1247): the operator turns knobs here to FIND good values, which
|
|
-- then get baked into shipped defaults; end users and other operators
|
|
-- should never need this card.
|
|
--
|
|
-- Rows are seeded by the recsettings service's boot reconcile (the
|
|
-- coverart SettingsService pattern), not by this migration, so shipped
|
|
-- defaults live in exactly one place (Go).
|
|
|
|
CREATE TABLE recommendation_weight_profiles (
|
|
profile text PRIMARY KEY
|
|
CONSTRAINT recommendation_weight_profiles_profile_check
|
|
CHECK (profile IN ('radio', 'daily_mix')),
|
|
base_weight double precision NOT NULL,
|
|
like_boost double precision NOT NULL,
|
|
recency_weight double precision NOT NULL,
|
|
skip_penalty double precision NOT NULL,
|
|
jitter_magnitude double precision NOT NULL,
|
|
context_weight double precision NOT NULL,
|
|
similarity_weight double precision NOT NULL,
|
|
taste_weight double precision NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Taste-profile build knobs: engagement half-life + the completion→
|
|
-- engagement curve points (taste.Config's tunable subset).
|
|
CREATE TABLE taste_tuning (
|
|
singleton boolean PRIMARY KEY DEFAULT true
|
|
CONSTRAINT taste_tuning_singleton_check CHECK (singleton),
|
|
half_life_days double precision NOT NULL,
|
|
engagement_hard_skip double precision NOT NULL,
|
|
engagement_neutral double precision NOT NULL,
|
|
engagement_full double precision NOT NULL,
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Every knob turn writes one audit row; the metrics trend view
|
|
-- (#1251) annotates these on its timeline so cause→effect is visible
|
|
-- after a change. changes is a jsonb array of {field, old, new}.
|
|
CREATE TABLE recommendation_tuning_audit (
|
|
id bigserial PRIMARY KEY,
|
|
changed_at timestamptz NOT NULL DEFAULT now(),
|
|
scope text NOT NULL
|
|
CONSTRAINT recommendation_tuning_audit_scope_check
|
|
CHECK (scope IN ('radio', 'daily_mix', 'taste')),
|
|
action text NOT NULL
|
|
CONSTRAINT recommendation_tuning_audit_action_check
|
|
CHECK (action IN ('update', 'reset')),
|
|
changes jsonb NOT NULL
|
|
);
|
|
|
|
CREATE INDEX recommendation_tuning_audit_changed_at_idx
|
|
ON recommendation_tuning_audit (changed_at DESC);
|