feat: add key-free demo mode replaying recorded fixtures

This commit is contained in:
Justin Visser 2026-08-11 09:14:22 +02:00
parent 0664cc2d27
commit 401a0ddea7
21 changed files with 1040 additions and 31 deletions

View file

@ -0,0 +1,78 @@
"""Demo-only pipeline decorator for honest fuzzy replay disclosure."""
import time
from collections.abc import AsyncGenerator
from contextlib import aclosing
from app.adapters.demo.catalog import DemoCatalog
from app.adapters.demo.recommender import DemoRecommender, parse_recorded_intent
from app.adapters.demo.scenario import select_replay_scenario
from app.config import Settings
from app.domain.models import ConversationTurn, PreviousRecommendation, Track
from app.pipeline.event import PipelineEvent, PipelineMetadataEvent, PipelineWarningEvent
from app.pipeline.grounding import Grounder
from app.pipeline.orchestrator import RecommendationPipeline
from app.ports.protocols import MusicCatalog
DEMO_REPLAY_CODE = "demo_replay"
class DemoReplayPipeline:
"""Decorate the real pipeline with a fuzzy-replay warning event."""
def __init__(self, settings: Settings) -> None:
"""Create one cache-preserving pipeline with a replay recommender."""
self.settings = settings
self.pipeline = RecommendationPipeline(DemoRecommender(settings), settings)
async def stream(
self,
session_id: str,
request_id: str,
catalog: MusicCatalog,
query: str,
history: tuple[ConversationTurn, ...],
previous_recommendations: tuple[PreviousRecommendation, ...],
) -> AsyncGenerator[PipelineEvent]:
"""Stream the selected fixture and disclose non-exact selection."""
match = select_replay_scenario(query, bool(previous_recommendations))
seeded_pool = await self._prepare_refinement_pool(catalog)
event_stream = self.pipeline.stream(
session_id,
request_id,
catalog,
query,
history,
previous_recommendations,
seeded_pool=seeded_pool,
)
async with aclosing(event_stream) as events:
async for event in events:
yield event
if isinstance(event, PipelineMetadataEvent) and not match.is_exact:
yield PipelineWarningEvent(
code=DEMO_REPLAY_CODE,
message=f'Demo replay is showing the recorded "{match.chip}" scenario.',
)
async def _prepare_refinement_pool(
self,
catalog: MusicCatalog,
) -> tuple[Track, ...] | None:
if not isinstance(catalog, DemoCatalog):
return None
intent_bodies = catalog.cassette.intent_response_bodies
if len(intent_bodies) < 2:
return None
# Refinement cassettes record the parent intent first and refinement intent last.
parent_intent = parse_recorded_intent(intent_bodies[0])
result = await Grounder(self.settings).ground(
catalog,
parent_intent.candidates,
# The recorded parent pool is listener-neutral, so replay has no known-track exclusions.
frozenset(),
parent_intent.familiarity,
self.settings.rerank_count + self.settings.rerank_pool_buffer,
time.monotonic() + self.settings.request_deadline_seconds,
)
return result.tracks