Repository navigation
Keep Balanced detours connected and add 5% look-back - #208
Conversation
|
Changes requested at What we saw on our test server. Two seeds: a baking competition and a food-travel documentary. With conservative settings, the lineup filled with one long-running sitcom. That sitcom is not close to either seed. It is missing from the baking seed's 49 Potion neighbours and is 19th on the documentary's. On a fresh draw it has about a 1% chance. Two paths lead from there to a takeover. This PR already closes the first: the preceding title's one-third share, which let sitcoms chain into each other. The second remains, and this PR makes it stronger:
I replayed this with the real
1. Apply support inside each anchor's contribution, not as a second weighted sum.
A Potion tie already counts as full support. So in the interest pool the per-anchor factor is 1 wherever an anchor contributes, and the product's only other effect is the squaring. Ask:
The predecessor gate and the #206 fade rate then both hold. 2. A watched title doesn't outrank its own neighbours. In the watched part of the profile, a title's match with itself should count no more than its best match with any other title:
Seeds keep their self-match, because the seeds are an explicit choice; item 3 bounds them. The aired show stays in play, level with its closest neighbour, and watching it pulls in similar titles rather than more of itself. 3. A rotation cap.
The selection loop is shared, so the cap applies to Metadata and Semantic modes as well. In a model of the metadata scoring, a seed show that matches itself filled 4–5 hours of a 12-hour lineup. The comparable is US internet radio, which runs under the statutory "sound recording performance complement" (17 U.S.C. § 114(j)(13)). In any 3 hours a station may play at most 4 tracks by one artist, and no more than 3 of them in a row. Radio scheduling tools build in the same idea as artist and title separation. It keeps a station sounding like a station, and none of it depends on how the recommender scores titles. Proof in the PR description:
A focused test for the cap is enough. Everything else is approved as written:
Seed voting and the other direction notes are in the next comment. They are for a later PR and are not a condition of this review. Build (exact head |
|
For a later PR, not a condition of this review. The operator asked for direction and prior art alongside the kickback. Which of these get built, and when, is the operator's call. The middle ground isn't a Discovery setting. Today, low Discovery means "the closest neighbours of whichever seed likes a title most". High Discovery means "more weight on broad pools". Neither one describes the lane the seeds share. The proposal: Discovery measures distance from what the seeds agree on. 1. Seeds vote.
2. Keep "more of it" separate from "more like it". 3. Discount momentum, before and after watch time.
Related work: degenerate feedback loops (Jiang, Chiappa, Lattimore, György & Kohli, AIES 2019) and algorithmic confounding (Chaney, Stewart & Engelhardt, RecSys 2018). A recommender that learns from what it showed narrows toward its own output, and recorded starts are what the channel showed. 4. Look-back: "older" should mean "not current". 5. Optional: calibration. 6. The planned watch-time PR. |
|
Approved at Ask 1 (support per anchor): done. Support now multiplies each anchor's own contribution, and the profile isn't multiplied by a second weighted sum. Removing the preceding-title term entirely goes further than the gate I asked for, and it closes the loosened case by construction: an unwatched pick can no longer pull in its sequels. Ask 2 (watched self-match): done. A watched title's semantic and metadata self-match are capped at its best match with any other title. Seeds keep theirs, and look-back uses the same cap. I reran the kickback replay on this head, using the real scorer and the same neighbour ranks. The table compares the aired sitcom with the closest food documentary on interest weight:
Against its own closest neighbour, the aired sitcom now sits at 1.3× after one airing and 1.08× after three. Before the cap it was about 2×. Watching a show now brings in shows like it rather than more of it, and the lead arrives later than on Ask 3 (rotation cap): withdrawn. It was a guard against the self-match snowball, and asks 1 and 2 removed that cause. What remains is drift toward whatever is recorded as watched: every airing while someone is tuned in counts as a start. That's an input question, and it belongs with the watch-time work rather than here. The PR's 10-pick replays (at most two picks from one title, 19–22% airtime for the top title) agree. Checked:
Build (exact head |
What this changes
Balanced recommendations use original seeds and recorded viewing to steer related choices. An unwatched scheduled detour no longer admits or boosts its neighbors: the preceding scheduled title has no Balanced affinity contribution or neighbor retrieval. Metadata and Semantic modes retain their existing behavior.
Connection support applies within each seed/watched relationship before its history coefficient, rather than multiplying the assembled profile by another weighted history sum. A recorded start therefore applies the intended 25% EWMA update once. For non-seed watched anchors, semantic and supported metadata self-matches are capped at their strongest other catalog match. Older watched semantic look-back uses the same cap. Explicit seeds keep self-matches, and the separate Familiarity boost remains.
Connections can be genres, tags, cast, director, studio, exact nonempty content rating or Potion similarity. One broad tie is weaker; multiple ties strengthen metadata without requiring a genre. Connected exploration replaces uniform catalog sampling. These ties can overlap and do not guarantee a tonal match.
A fixed 5% look-back uses original seeds plus up to three distinct older watched sources, sampled by their older start counts. Current interests use the latest 50 available non-filler starts; older counts come from the existing lifetime aggregate minus that window. Independent random streams preserve title/episode draws. Default shares are 85.5% interests / 7.6% metadata / 1.9% connected exploration / 5% look-back. Empty pools redistribute their shares; no supported pool fails visibly.
Saved reasons, dialog and docs describe these contributions. Existing episode selection, availability and repeat rules remain. No migration, setting or runtime dependency is added. Existing Balanced channels use the policy on next generation/growth; saved lineup entries are not rewritten. Reverting this PR restores the previous generator.
Scope after review
The double-weighting correction and watched-self cap are included. The maintainer-directed revision also removes predecessor influence completely. The suggested fixed three-airings-per-twelve-hours rotation cap is not included: airtime allocation, a living candidate shortlist and a continuously advancing EPG belong to a separate scheduling change. This PR corrects recommendation influence; it does not establish whole-lineup balance. Existing playback-driven growth/looping behavior remains. Actual watch-duration capture and weighting remain separate.
Design issue
Not needed — maintainer-directed fork change following isolated trials and review.
AI use
Codex implemented the change, ran focused validation, and prepared the documentation. The earlier clean-context review assessed the original implementation against its trial formulas; it did not establish that those formulas encoded the intended viewing behavior. A separate clean-context reviewer assessed revised checkpoint
5db753080and found no implementation-vs-plan drift. It inspected the validation record and harness without rerunning the test suites.Testing
pnpm exec prettier --check .andgit diff --checkpass.