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())

View file

@ -164,3 +164,18 @@ Wat ik deed:
max_tokens en kon de gestructureerde output afkappen.
- Per unresolved kandidaat wordt titel, artiest en status gelogd, zodat
zichtbaar is WAT het model verzon in plaats van alleen hoeveel.
### Eerlijke gedeeltelijke resultaten
Wat ik deed:
- Onder de grounding-floor geeft de pipeline nu een warning plus de nummers
die wel geverifieerd zijn, in plaats van een lege foutmelding; alleen een
volledig lege pool is nog een terminal error.
Waarom:
- Vijf goede, geverifieerde nummers zijn een bruikbaar antwoord; een
foutmelding die echte resultaten verbergt is dat niet. Bij "verras me
met iets nieuws" vragen valt een groot deel van de kandidaten af bij de
verificatie, dus juist daar telt dit. Een weg om dit potentieel te voorkomen/verbeteren in de toekomst is het verbeteren van de prompt, of de LLM met behulp van een derde partij API die zonder de Spotify API te overbelasten gebruikt kan worden om echte nummers te vinden.