94 lines
6.2 KiB
Markdown
94 lines
6.2 KiB
Markdown
# Spec: Quality & Diversity Baseline
|
|
|
|
## Problem
|
|
|
|
The daily "Today Brief" ranking surface can surface low-quality content (items with near-zero completion rates, spam-level engagement, or negligible scores) and can be dominated by a single prolific creator. Without quality gates and diversity enforcement active by default, the briefing experience degrades for pilot users, undermining the P1 concierge alpha's retention goals.
|
|
|
|
tidalDB already has the primitives — `Gate` (min-threshold filters on signal aggregations), `DiversityConstraints` (max-per-creator, format-mix), and the `DiversitySelector` with greedy multi-stage relaxation. What is missing is a **curated "brief" ranking profile** that wires these primitives into sensible defaults, and **integration tests** that prove the quality floor and diversity invariants hold under realistic conditions.
|
|
|
|
## Goals
|
|
|
|
1. **Quality floor on brief results.** Items in the brief must pass minimum engagement thresholds before they are eligible for ranking. Specifically:
|
|
- A minimum view count gate ensures items have been seen by enough users to have a meaningful signal.
|
|
- A minimum completion rate gate (via `completion` signal) ensures items are not abandoned content.
|
|
- Items failing either gate are excluded before scoring, not after.
|
|
|
|
2. **Creator diversity in top results.** No single creator should dominate the brief. The brief profile must enforce a max-per-creator constraint tight enough that a brief of N items has content from at least `ceil(N / max_per_creator)` distinct creators (when sufficient creator variety exists).
|
|
|
|
3. **Format diversity in top results.** No single content format should dominate the brief beyond a configurable fraction (e.g., no more than 60% video in a 10-item brief).
|
|
|
|
4. **A named "brief" ranking profile** registered as a built-in profile that codifies these quality gates and diversity constraints. The profile is usable via `RETRIEVE items USING PROFILE brief` or `SearchBuilder::profile("brief")`.
|
|
|
|
5. **Integration tests** proving:
|
|
- Items below the quality floor are excluded from brief results.
|
|
- Creator diversity is enforced: multiple creators represented in results.
|
|
- Format diversity is enforced: no format exceeds the `format_mix_max_fraction`.
|
|
- The brief profile is registered and resolvable by name.
|
|
|
|
## Non-Goals
|
|
|
|
- Custom per-user quality thresholds (future personalization work).
|
|
- Dynamic threshold tuning based on catalog size (future operational work).
|
|
- Changing the `DiversitySelector` algorithm itself (already correct and well-tested).
|
|
- Exposing quality gate configuration via an API or schema DSL (profiles are code-defined for now).
|
|
|
|
## Existing Primitives
|
|
|
|
### Gates (`ranking::profile::Gate`)
|
|
Already implemented and enforced in the scoring pipeline. `passes_gates()` in `ranking/executor/helpers.rs` evaluates each gate before a candidate enters the scoring loop. Gates check `agg(signal, window) >= min_threshold`. This is exactly what we need for the quality floor.
|
|
|
|
### DiversityConstraints / DiversitySelector
|
|
Already implemented with greedy multi-stage relaxation in `ranking/diversity/`. Enforces `max_per_creator` and `format_mix_max_fraction`. Applied as Stage 5 of the scoring pipeline. Both the `Retrieve` builder (query-level override) and the `RankingProfile` (profile-level default) can specify diversity constraints.
|
|
|
|
### Built-in Profiles
|
|
25 built-in profiles registered in `ranking/builtins.rs`. The new "brief" profile follows the same pattern.
|
|
|
|
## Design
|
|
|
|
### "brief" Profile Definition
|
|
|
|
```
|
|
Name: brief
|
|
Version: 1
|
|
Sort: Hot { gravity: 1.5 }
|
|
Candidate Strategy: Scan { sort_field: "created_at" }
|
|
Gates:
|
|
- view / Value / AllTime >= 3.0 (min 3 total views)
|
|
- completion / Value / AllTime >= 1.0 (at least 1 completion)
|
|
Boosts:
|
|
- view / DecayScore / AllTime * 1.0
|
|
- like / DecayScore / AllTime * 2.0
|
|
- completion / DecayScore / AllTime * 1.5
|
|
Diversity:
|
|
- max_per_creator: 2
|
|
- format_mix_max_fraction: 0.6
|
|
Exploration: 0.0 (disabled — exploration injects candidates that bypass quality gates)
|
|
```
|
|
|
|
Rationale:
|
|
- **View gate >= 3**: Items with fewer than 3 views have insufficient signal to rank meaningfully. This is a low bar appropriate for an alpha with a small catalog.
|
|
- **Completion gate >= 1**: At least one user must have completed (or substantially engaged with) the item. Filters out abandoned/broken content.
|
|
- **max_per_creator: 2**: In a typical 10-item brief, this ensures at least 5 distinct creators. Tight enough to prevent domination, loose enough to allow a standout creator to appear twice.
|
|
- **format_mix: 0.6**: No single format exceeds 60% of the brief. In a 10-item brief, max 6 of one format.
|
|
- **Exploration: 0.0**: Disabled because `inject_exploration()` runs after gate filtering and can re-introduce candidates that failed quality gates, undermining the curated-brief guarantee. Exploration is appropriate for discovery surfaces (`for_you`) but not for quality-gated surfaces.
|
|
- **Hot sort with gravity 1.5**: Balances recency with engagement, appropriate for a daily brief cadence.
|
|
|
|
### Implementation Notes
|
|
|
|
Two additional fixes were required in the scoring pipeline to make diversity constraints effective:
|
|
|
|
1. **Format enrichment**: `ScoredCandidate.format` was never populated from item metadata, making `format_mix_max_fraction` enforcement impossible. Fixed by extending the metadata enrichment loop in `query/executor/mod.rs` to populate both `creator_id` and `format`.
|
|
|
|
2. **Metadata loading trigger**: The `needs_metadata_for_creator_grouping` flag only checked `max_per_creator`, not `format_mix_max_fraction`. Extended to check both, ensuring metadata is loaded when format diversity is configured.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [x] A `brief` built-in ranking profile exists and is registered at startup.
|
|
- [x] Items with fewer than 3 total views are excluded from brief results.
|
|
- [x] Items with 0 completions are excluded from brief results.
|
|
- [x] Multiple creators represented in brief results (no single creator dominates).
|
|
- [x] No single format exceeds 60% of a brief result set.
|
|
- [x] All existing tests continue to pass (no regressions in the 25 existing profiles).
|
|
- [x] Integration tests demonstrate all scenarios above.
|
|
- [x] `cargo clippy -D warnings` and `cargo fmt` pass cleanly.
|