Method & data
This dashboard shows saved results from the Spotify review-analysis pipeline. The pipeline is in the GitHub repository.
- Ingest (code): every row is hashed, empty texts are quarantined, and identical texts are classified once. The final run classifies a seeded random sample of 100,000 of the 660,622 rows; the other rows are counted as out of scope (they are not stored here, so looking one up by ID finds nothing).
- Enrich: Jev (
jev-1.13.0) picks topic, intent, severity and sentiment. Texts where Jev is unsure (confidence below 0.5) are re-labelled blind by Claude under a declared 20% cap:claude-haiku-4-5through the Batch API in the final run (17.2% of texts),claude-sonnet-5in the development runs. Evidence quotes are exact substrings checked by code. - Verify:
claude-sonnet-5blind-labels a declared random sample (1,000 reviews in the final run), and code compares the results. - Group: Claude proposes subtopics from a sample of complaint quotes, and Jev assigns each complaint to one issue.
- Rank (code): priority = complaint count × mean severity = severity sum.
- Recommend: Claude writes the memo from the aggregates only. Code checks every number, ID and quote.
Architecture of this site: the pipeline publishes a finished run into Neon Postgres (python -m pipeline publish). This app's API routes (/api/*) read it with a SELECT-only role and serve JSON to these pages. Viewing the dashboard never calls a model.
Limits: these are self-selected, historical Play Store reviews. There is no revenue, plan or confirmed-churn data, and cancellation intent is not churn. Verifier agreement is between two models, not accuracy; it is lower on the hard texts the fallback re-labelled (49% all-three agreement) than on texts Jev labelled alone (75%).