feat(explore): more variance in the related rail (stronger MMR diversification)
CI / lint (push) Successful in 3s
CI / frontend-build (push) Successful in 21s
CI / backend-lint-and-test (push) Successful in 26s
CI / integration (push) Successful in 3m24s

Operator wants the Explore "related" rail to span more — the #1188 diversifier
was tuned conservatively. Push all three knobs so it reaches further across
clusters instead of clumping near the anchor:

- MMR lam 0.55 → 0.40 — weight the diversity penalty harder (the main dial).
- candidate pool min(200, max(limit*5, 60)) → min(400, max(limit*8, 100)) — a
  wider nearest-cosine pool so MMR has genuinely distinct neighbourhoods to pick
  from, not just the near-dupes.
- pHash dup_threshold 6 → 8 — collapse more near-duplicate reposts/clones,
  freeing rail slots for distinct picks.

Still deterministic (same set per image, just more spread) and relevance-anchored
via the lam*sim-to-anchor term. Backend-only; no migration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
This commit is contained in:
2026-07-01 00:46:56 -04:00
parent 7cdce0c474
commit ef3318aac1
+10 -3
View File
@@ -289,7 +289,7 @@ def _gallery_images(rows, artists: dict[int, dict]) -> list[GalleryImage]:
] ]
def _diversify_similar(src, rows, limit, *, dup_threshold=6, lam=0.55): def _diversify_similar(src, rows, limit, *, dup_threshold=8, lam=0.40):
"""Trim a nearest-cosine candidate pool down to `limit` diverse picks. """Trim a nearest-cosine candidate pool down to `limit` diverse picks.
1. pHash collapse: drop any candidate whose perceptual hash is within 1. pHash collapse: drop any candidate whose perceptual hash is within
@@ -300,6 +300,11 @@ def _diversify_similar(src, rows, limit, *, dup_threshold=6, lam=0.55):
the most relevant up top but pushes the selection to SPAN clusters the most relevant up top but pushes the selection to SPAN clusters
instead of returning 40 variations of one image. instead of returning 40 variations of one image.
`lam` is the variance dial: lower = weight the diversity penalty harder, so
the rail reaches further across clusters (operator wanted MORE variance,
2026-07-01 — dropped 0.55→0.40, dup 6→8, paired with a wider pool in
`similar()`).
Falls back to nearest-order (`rows[:limit]`) on any failure or a small pool. Falls back to nearest-order (`rows[:limit]`) on any failure or a small pool.
""" """
if len(rows) <= 1: if len(rows) <= 1:
@@ -658,8 +663,10 @@ class GalleryService:
return [] return []
# Over-fetch so diversification has clusters to spread across — without a # Over-fetch so diversification has clusters to spread across — without a
# wide pool there's nothing but the near-dupes to choose from. # wide pool there's nothing but the near-dupes to choose from. Widened
pool_n = min(200, max(limit * 5, 60)) # (5×→8×, cap 200→400) so the stronger MMR has genuinely distinct
# neighbourhoods to reach into for more variance (operator, 2026-07-01).
pool_n = min(400, max(limit * 8, 100))
distance = ImageRecord.siglip_embedding.cosine_distance(src.siglip_embedding) distance = ImageRecord.siglip_embedding.cosine_distance(src.siglip_embedding)
eff = _effective_date_col() eff = _effective_date_col()
stmt = select(ImageRecord, Post.post_date, eff.label("eff")) stmt = select(ImageRecord, Post.post_date, eff.label("eff"))