feat(admin): wave metrics split by model version (M6)
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 51s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m5s
ci / ts / ts (packages + web) (push) Successful in 1m3s
ci / api / api (push) Successful in 29s
ci / db / db (push) Failing after 12s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 51s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m5s
ci / ts / ts (packages + web) (push) Successful in 1m3s
ci / api / api (push) Successful in 29s
ci / db / db (push) Failing after 12s
The library page compares listen-through, early-skip and like rates per impression model version, so v1 and the trained ranker can be compared online. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fbbe5d7528
commit
d91ff89c64
9 files changed
+373
-252
No files matched your search
@@ -624,10 +624,36 @@ func (st *Store) AnalysisCounts(ctx context.Context) (AnalysisCounts, error) {
|
||||
|
||||
// WaveMetrics — метрики волны за 7 дней (docs/recommendations.md#1-цели-и-как-измеряем-успех).
|
||||
type WaveMetrics struct {
|
||||
Served, Sessions int
|
||||
Served, Sessions int
|
||||
WaveRates
|
||||
ByModel []WaveModelMetrics
|
||||
}
|
||||
|
||||
// WaveRates — доли по показам с известным исходом (nil — исходов ещё нет).
|
||||
type WaveRates struct {
|
||||
ListenThrough, EarlySkip, LikeRate *float32
|
||||
}
|
||||
|
||||
// WaveModelMetrics — метрики показов одной версии модели.
|
||||
type WaveModelMetrics struct {
|
||||
ModelVer string
|
||||
Served int
|
||||
WaveRates
|
||||
}
|
||||
|
||||
func rates(judged, through, early, liked int) WaveRates {
|
||||
if judged == 0 {
|
||||
return WaveRates{}
|
||||
}
|
||||
lt, es, lr := float32(through)/float32(judged), float32(early)/float32(judged), float32(liked)*100/float32(judged)
|
||||
return WaveRates{ListenThrough: <, EarlySkip: &es, LikeRate: &lr}
|
||||
}
|
||||
|
||||
const waveOutcomes = `count(outcome),
|
||||
count(*) FILTER (WHERE outcome IN ('complete', 'like')),
|
||||
count(*) FILTER (WHERE outcome IN ('skip_early', 'dislike')),
|
||||
count(*) FILTER (WHERE outcome = 'like')`
|
||||
|
||||
// WaveMetrics считает метрики по показам с известным исходом.
|
||||
func (st *Store) WaveMetrics(ctx context.Context) (WaveMetrics, error) {
|
||||
var (
|
||||
@@ -635,20 +661,32 @@ func (st *Store) WaveMetrics(ctx context.Context) (WaveMetrics, error) {
|
||||
judged, through, early, liked int
|
||||
)
|
||||
err := st.pool.QueryRow(ctx, `
|
||||
SELECT count(*), count(DISTINCT wave_session_id), count(outcome),
|
||||
count(*) FILTER (WHERE outcome IN ('complete', 'like')),
|
||||
count(*) FILTER (WHERE outcome IN ('skip_early', 'dislike')),
|
||||
count(*) FILTER (WHERE outcome = 'like')
|
||||
SELECT count(*), count(DISTINCT wave_session_id), `+waveOutcomes+`
|
||||
FROM wave_impressions WHERE served_at > now() - interval '7 days'`).
|
||||
Scan(&m.Served, &m.Sessions, &judged, &through, &early, &liked)
|
||||
if err != nil {
|
||||
return WaveMetrics{}, fmt.Errorf("library: wave metrics: %w", err)
|
||||
}
|
||||
if judged > 0 {
|
||||
lt, es, lr := float32(through)/float32(judged), float32(early)/float32(judged), float32(liked)*100/float32(judged)
|
||||
m.ListenThrough, m.EarlySkip, m.LikeRate = <, &es, &lr
|
||||
m.WaveRates = rates(judged, through, early, liked)
|
||||
|
||||
rows, err := st.pool.Query(ctx, `
|
||||
SELECT coalesce(model_ver, ''), count(*), `+waveOutcomes+`
|
||||
FROM wave_impressions WHERE served_at > now() - interval '7 days'
|
||||
GROUP BY 1 ORDER BY 2 DESC`)
|
||||
if err != nil {
|
||||
return WaveMetrics{}, fmt.Errorf("library: wave metrics by model: %w", err)
|
||||
}
|
||||
return m, nil
|
||||
defer rows.Close()
|
||||
m.ByModel = []WaveModelMetrics{}
|
||||
for rows.Next() {
|
||||
var mm WaveModelMetrics
|
||||
if err := rows.Scan(&mm.ModelVer, &mm.Served, &judged, &through, &early, &liked); err != nil {
|
||||
return WaveMetrics{}, fmt.Errorf("library: wave metrics by model: %w", err)
|
||||
}
|
||||
mm.WaveRates = rates(judged, through, early, liked)
|
||||
m.ByModel = append(m.ByModel, mm)
|
||||
}
|
||||
return m, rows.Err()
|
||||
}
|
||||
|
||||
// FingerprintTodo — файл, которому нужны отпечатки.
|
||||
|
||||
Reference in new issue
Block a user