fac5ae6ce5
The Explore walk got stuck in dense signatures — neighbours all too similar, so forward-arrow couldn't escape and Random was the only exit. Root cause: MMR only diversifies WITHIN the nearest ~400 pool; in a dense cluster that whole pool is near-identical, so there's no escape route in it. - gallery_service.similar(reach=0.0, exclude_ids=None): reach>0 widens the pool (cap 400→1000) and _reach_sample strides across an outward-growing distance span so the set handed to MMR spans near→mid-far (guaranteed escape routes), not just the tight cluster. exclude_ids drops already-walked images. Gallery 'more like this' (reach=0) is unchanged. - api/gallery similar: parse reach + exclude_ids. - explore store: default reach 0.4 (auto-diversifies without touching the dial), pass the breadcrumb as exclude_ids, setReach action. - ExploreView: a Near↔Far reach slider in the trail. - tests: _reach_sample math (deeper ranks with higher reach, near kept); similar exclude_ids drops walked + reach path runs clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.3 KiB
Python
33 lines
1.3 KiB
Python
"""Explore reach sampler (#1476) — pure unit tests for `_reach_sample`, which picks
|
|
a distance-rank spread so the neighbour pool handed to MMR spans near→mid-far and
|
|
the walk can escape a dense cluster. No DB. `_reach_sample` only indexes rows, so
|
|
plain ints stand in for the (ImageRecord, ...) tuples."""
|
|
from backend.app.services.gallery_service import _reach_sample
|
|
|
|
|
|
def test_reach_zero_or_negative_passes_through():
|
|
rows = list(range(1000))
|
|
assert _reach_sample(rows, 40, 0.0) is rows
|
|
assert _reach_sample(rows, 40, -1.0) is rows
|
|
|
|
|
|
def test_small_pool_passes_through():
|
|
# n <= want (limit*8 = 320) → nothing to reach into.
|
|
rows = list(range(50))
|
|
assert _reach_sample(rows, 40, 1.0) is rows
|
|
|
|
|
|
def test_higher_reach_reaches_deeper_ranks():
|
|
rows = list(range(1000))
|
|
near = _reach_sample(rows, 40, 0.2)
|
|
far = _reach_sample(rows, 40, 1.0)
|
|
# Both keep the nearest rank (stride starts at 0) so you can still tag the cluster.
|
|
assert near[0] == 0
|
|
assert far[0] == 0
|
|
# But higher reach samples genuinely farther ranks.
|
|
assert max(far) > max(near)
|
|
assert max(far) >= 900 # reach=1 spans (almost) the whole pool
|
|
assert max(near) <= 550 # reach=0.2 stays in the near half
|
|
# Never runs past the pool.
|
|
assert max(far) <= len(rows) - 1
|