feat: add key-free demo mode replaying recorded fixtures
This commit is contained in:
parent
0664cc2d27
commit
401a0ddea7
21 changed files with 1040 additions and 31 deletions
|
|
@ -12,6 +12,11 @@ from fastapi import FastAPI
|
|||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from app.adapters.anthropic.llm import AnthropicRecommender
|
||||
from app.adapters.demo.cassette import load_cassette
|
||||
from app.adapters.demo.catalog import DemoCatalog
|
||||
from app.adapters.demo.pipeline import DemoReplayPipeline
|
||||
from app.adapters.demo.playlist import DemoPlaylistWriter
|
||||
from app.adapters.demo.scenario import select_replay_scenario, suggestion_items
|
||||
from app.adapters.spotify.auth import TokenSet, refresh_access_token
|
||||
from app.adapters.spotify.client import SpotifyClient
|
||||
from app.adapters.spotify.errors import SpotifyError
|
||||
|
|
@ -19,6 +24,7 @@ from app.adapters.spotify.session import PendingLogins, SessionStore, SpotifySes
|
|||
from app.api.recommendations import router as recommendations_router
|
||||
from app.api.routes import router
|
||||
from app.config import AppMode, Settings, settings
|
||||
from app.domain.models import PreviousRecommendation
|
||||
from app.observability.logging import configure_logging
|
||||
from app.observability.timing import RequestTimingMiddleware
|
||||
from app.pipeline.orchestrator import RecommendationPipeline
|
||||
|
|
@ -38,17 +44,35 @@ def create_app(
|
|||
@asynccontextmanager
|
||||
async def lifespan(application: FastAPI) -> AsyncIterator[None]:
|
||||
_validate_live_settings(active_settings)
|
||||
application.state.session_store = SessionStore()
|
||||
application.state.pending_logins = PendingLogins()
|
||||
application.state.settings = active_settings
|
||||
application.state.seed_session_id = None
|
||||
application.state.suggestions = suggestion_items()
|
||||
if active_settings.app_mode is AppMode.DEMO:
|
||||
application.state.demo_session = _demo_session()
|
||||
application.state.recommendation_pipeline = DemoReplayPipeline(active_settings)
|
||||
|
||||
def demo_catalog_factory(
|
||||
session: SpotifySession,
|
||||
query: str,
|
||||
previous_recommendations: tuple[PreviousRecommendation, ...],
|
||||
) -> DemoCatalog:
|
||||
match = select_replay_scenario(query, bool(previous_recommendations))
|
||||
return DemoCatalog(load_cassette(match.key))
|
||||
|
||||
application.state.music_catalog_factory = demo_catalog_factory
|
||||
application.state.spotify_client_factory = lambda session: DemoPlaylistWriter()
|
||||
yield
|
||||
return
|
||||
|
||||
async with httpx2.AsyncClient(
|
||||
timeout=active_settings.spotify_timeout_seconds,
|
||||
transport=http_transport,
|
||||
) as http:
|
||||
application.state.http = http
|
||||
application.state.session_store = SessionStore()
|
||||
application.state.pending_logins = PendingLogins()
|
||||
application.state.settings = active_settings
|
||||
application.state.seed_session_id = None
|
||||
anthropic_client = AsyncAnthropic(
|
||||
api_key=active_settings.anthropic_api_key or "unused-demo-key",
|
||||
api_key=active_settings.anthropic_api_key,
|
||||
timeout=active_settings.llm_timeout_seconds,
|
||||
http_client=anthropic_http_client,
|
||||
)
|
||||
|
|
@ -61,7 +85,15 @@ def create_app(
|
|||
def spotify_client_factory(session: SpotifySession) -> SpotifyClient:
|
||||
return SpotifyClient(http, session, active_settings)
|
||||
|
||||
def music_catalog_factory(
|
||||
session: SpotifySession,
|
||||
query: str,
|
||||
previous_recommendations: tuple[PreviousRecommendation, ...],
|
||||
) -> SpotifyClient:
|
||||
return spotify_client_factory(session)
|
||||
|
||||
application.state.spotify_client_factory = spotify_client_factory
|
||||
application.state.music_catalog_factory = music_catalog_factory
|
||||
if (
|
||||
active_settings.app_mode is AppMode.LIVE
|
||||
and active_settings.spotify_seed_refresh_token
|
||||
|
|
@ -141,3 +173,11 @@ async def _install_seed_session(
|
|||
display_name=current_user.display_name,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _demo_session() -> SpotifySession:
|
||||
return SpotifySession(
|
||||
tokens=TokenSet(access_token="demo", refresh_token="demo", expires_at=float("inf")),
|
||||
account_id="demo-listener",
|
||||
display_name="Demo Listener",
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue