Multi-Track Discovery Architecture
This document details the architecture of the Multi-Track Discovery System, introduced to allow parallel exploration of multiple user interests simultaneously, replacing the previous sequential topic processing.
Core Concept
Instead of processing one topic at a time (e.g., "Lego" -> Hypotheses -> Next Topic), the system now parallelizes the discovery process:
- Normalizes the user's input (e.g., "Lego and coffee") into distinct topics (["Lego", "Coffee"]).
- Generates hypotheses for all normalized topics in a single bulk LLM call.
- Fetches product previews for all generated hypotheses in parallel.
- Presents all tracks to the user simultaneously (e.g., as tabs or cards).
System Flow
sequenceDiagram
participant U as User (Frontend)
participant DM as DialogueManager
participant A as AnthropicService (LLM)
participant RS as RecommendationService (DB/Vector)
U->>DM: POST /recommendations/init (Quiz Answers)
rect rgb(200, 220, 240)
Note over DM, A: Step 1: Topic Normalization
DM->>A: normalize_topics("Lego & Coffee, Fishing")
A-->>DM: ["Lego", "Coffee", "Fishing"]
end
rect rgb(220, 240, 200)
Note over DM, A: Step 2: Bulk Hypothesis Generation
DM->>A: generate_hypotheses_bulk(["Lego", "Coffee", "Fishing"], Context)
A-->>DM: { "Lego": [Hyp1, Hyp2], "Coffee": [Hyp3, Hyp4], ... }
end
rect rgb(240, 220, 220)
Note over DM, RS: Step 3: Parallel Product Previews
par For Each Hypothesis
DM->>RS: find_preview_products(Hypothesis Search Queries)
RS-->>DM: [ProductDTO, ProductDTO, ...]
end
end
Note over DM: Construct TopicTrack objects
DM-->>U: Session with tracks[] and state="overview"
Note over U: User sees tabs: [Lego] [Coffee] [Fishing]
U->>DM: POST /interact (action="select_track", value="Lego")
DM->>DM: Set selected_topic="Lego", state="showing_hypotheses"
DM-->>U: Return active track hypotheses
detailed Components
1. Topic Normalizer (AnthropicService.normalize_topics)
Crucial for handling mixed inputs like "Lego and coffee".
- Input:
["Lego and coffee", "Travel"] - LLM Task: Split compound topics, remove noise, translate to session language.
- Output:
["Lego", "Coffee", "Travel"]
2. Bulk Generator (AnthropicService.generate_hypotheses_bulk)
Optimized for performance and Rate Limits. Instead of $N$ calls for $N$ topics, we make 1 call with a JSON prompt asking for hypotheses for all topics at once. This reduces latency from ~2-3 minutes (sequential) to ~10-15 seconds.
3. Track Structure (recommendations.models.TopicTrack)
The session now holds a list of tracks, not just a single active topic.
class TopicTrack(BaseModel):
topic_id: str
topic_name: str # e.g. "Lego"
title: str # User-facing title
preview_text: str # Short description
hypotheses: List[Hypothesis]
4. State Machine Updates
- New State:
DiscoveryState.OVERVIEW— The initial state afterinit, where multiple tracks are available but none is "active" yet. - New Action:
select_track— Transitions fromOVERVIEWtoSHOWING_HYPOTHESESfor a specific topic.
Performance Considerations
- Latency: The bulk generation step dominates latency (~10s).
- Rate Limits: By using a single bulk call, we stay well within Anthropic Tier 1 limits (unlike parallel requests which trigger 429 errors).
- Fallback: If bulk generation fails, the system falls back to processing just the first topic sequentially.