fix: degrade to partial results below the grounding floor

This commit is contained in:
Justin Visser 2026-08-10 14:16:59 +02:00
parent 0ccc9a5d4e
commit 47cbeac87a
3 changed files with 68 additions and 3 deletions

View file

@ -130,12 +130,19 @@ class RecommendationPipeline:
)
pool = await self._grounded_pool(session_id, catalog, intent, taste)
if len(pool) < self.settings.grounding_floor:
if not pool:
yield PipelineErrorEvent(
code="insufficient_grounding",
message="Not enough requested tracks could be verified safely.",
code="no_grounded_results",
message="None of the proposed tracks could be verified on Spotify.",
)
return
if len(pool) < self.settings.grounding_floor:
# Fewer verified tracks than promised is still an answer; an
# empty error in its place would hide real results.
yield PipelineWarningEvent(
code="partial_results",
message="Fewer tracks than usual could be verified; showing what held up.",
)
selection = _TrackSelection(pool, self.settings.rerank_count)
async for event in self._ranked_events(intent, taste.text, history, selection):

View file

@ -243,3 +243,46 @@ def _track(track_id: str, title: str) -> Track:
album_art_url=None,
external_url=None,
)
def test_below_floor_pool_streams_partial_results_after_warning() -> None:
async def run() -> None:
found = _track("found", "Found Song")
missing = _track("missing", "Missing Song")
catalog = FakeCatalog((found,))
recommender = FakeRecommender([_intent(found, missing)])
pipeline = RecommendationPipeline(
recommender,
Settings(
rerank_count=2,
rerank_pool_buffer=0,
grounding_floor=2,
grounding_concurrency=2,
request_deadline_seconds=1.0,
),
)
events = await _collect(pipeline, catalog, "query")
assert [event.type for event in events] == ["metadata", "warning", "track", "done"]
warning = events[1]
assert warning.type == "warning"
assert warning.code == "partial_results"
asyncio.run(run())
def test_empty_pool_is_a_terminal_error() -> None:
async def run() -> None:
missing = _track("missing", "Missing Song")
catalog = FakeCatalog(())
recommender = FakeRecommender([_intent(missing)])
events = await _run_pipeline(catalog, recommender)
assert [event.type for event in events] == ["metadata", "error"]
error = events[-1]
assert error.type == "error"
assert error.code == "no_grounded_results"
asyncio.run(run())