Spaces:
Running
A newer version of the Gradio SDK is available:
6.1.0
title: Tune Duel
emoji: 📊
colorFrom: purple
colorTo: green
sdk: gradio
sdk_version: 5.49.1
app_file: app.py
pinned: false
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
🎶 Tune Duel - Recommender System Competition
A Gradio-based web application for comparing music recommendation models through head-to-head battles using an Elo rating system.
Overview
Tune Duel is a competitive platform where different music recommendation models compete against each other. Users input their favorite songs with ratings (1-5 stars), and the system automatically matches them with Spotify IDs for enhanced recommendation capabilities. The system presents recommendations from two different models side-by-side with embedded Spotify players, allowing users to listen and compare tracks directly in the interface. Users then vote on which model provided better recommendations, and the results are used to update Elo ratings for each model.
Features
- Song Rating System: Users can rate multiple songs (1-5 stars) to provide richer context for recommendations
- Automatic Spotify ID Matching: System automatically finds and includes Spotify IDs for input songs
- Real-time Track Suggestions: As users type song names, the system shows matching tracks from the database
- Random Track Selection: Users can click random buttons to quickly populate fields with valid tracks from the database
- Spotify Web Player Integration: Embedded Spotify players for both input songs and recommendations
- Track Validation: Built-in validation ensures users enter songs that exist in the tracks database
- Enhanced Recommendation Display: Recommendations include embedded Spotify players for immediate preview
- Head-to-Head Model Comparison: Compare recommendations from two different models simultaneously
- Elo Rating System: Models are ranked using the Elo rating system (similar to chess ratings)
- Real-time Leaderboard: Live leaderboard showing current model rankings
- Flexible Model Integration: Support for both HTTP API and Python-based models
- Caching System: Intelligent caching to improve performance and reduce API calls
- Vote Logging: Complete audit trail of all votes and interactions
- Modern Web Interface: Clean, responsive Gradio-based UI
Project Structure
gradio/
├── app.py # Main Gradio application
├── models.yaml # Model configuration file
├── tracks.csv # Track database with Spotify IDs
├── requirements.txt # Python dependencies
├── README.md # This file
├── state/ # Persistent data storage
│ ├── elo.pkl # Elo ratings (pickle)
│ ├── leaderboard.csv # Leaderboard data
│ └── votes.jsonl # Vote history log
├── team_alpha/ # Example team implementation
│ └── src/
│ └── recommender.py
├── team_beta/ # Example team implementation
│ └── src/
│ └── recommender.py
└── team_gamma/ # Example team implementation
└── src/
└── recommender.py
Installation
Clone the repository:
git clone <repository-url> cd gradioInstall dependencies:
pip install -r requirements.txtConfigure models (see Configuration section below)
Run the application:
python app.pyAccess the web interface: Open your browser and navigate to
http://localhost:7860
Configuration
Model Configuration (models.yaml)
Models are configured in the models.yaml file. Each model can be either:
HTTP API Models
models:
- name: "my_api_model"
type: http
endpoint: "https://api.example.com/recommend"
timeout: 8
topk: 10
API Requirements:
- Endpoint must accept POST requests
- Request body:
{"song_ratings": [{"song": "song name", "rating": 5, "spotify_id": "abc123"}, ...]} - Response format:
{"items": ["item1", "item2", ...]}or{"recommendations": [...]}
Python Models
models:
- name: "my_python_model"
type: python
callable: "team_alpha.src.recommender.query"
topk: 10
Python Requirements:
- Must be importable as a module
- Function signature:
query(song_ratings: List[Dict[str, any]]) -> List[Tuple[str, str]] - Should return a list of (spotify_id, track_name) tuples
Example Model Implementation
# team_alpha/src/recommender.py
def query(song_ratings: List[Dict[str, any]]) -> List[Tuple[str, str]]:
"""
Generate music recommendations based on user's song ratings.
Args:
song_ratings: List of dicts with 'song', 'rating', and 'spotify_id' keys
e.g., [{"song": "Taylor Swift - 22", "rating": 5, "spotify_id": "abc123"}, ...]
Returns:
List of (spotify_id, track_name) tuples
"""
# Your recommendation logic here
recommendations = [
("4iV5W9uYEdYUVa79Axb7Rh", "Never Gonna Give You Up"),
("0VjIjW4GlUZAMYd2vXMi3b", "Blinding Lights"),
# ... more recommendations
]
return recommendations
Usage
Basic Workflow
- Enter Songs with Ratings: Input up to 5 songs with ratings (1-5 stars) in the provided fields. Use the "Add More Songs" button to reveal additional input fields for songs 4-5. As you type, matching tracks from the database will appear as suggestions. You can also click the 🎲 Random buttons to quickly fill fields with random tracks, or use "🎲 Fill All Random" to populate all fields at once.
- Preview Input Songs: Click the ▶️ Play button next to any song to start the embedded Spotify player and listen to the track
- Select Models: Choose two different models to compare (or use "Random Pair")
- Get Recommendations: Click "Recommend" to fetch suggestions from both models
- Compare Results: Review the recommendations side-by-side with embedded Spotify players for each recommended track
- Listen and Vote: Listen to recommended tracks using the embedded players, then choose which model provided better recommendations:
- A Wins: Model A had better recommendations
- B Wins: Model B had better recommendations
- Tie: Both models performed equally well
- Skip: Skip this comparison
Elo Rating System
- Starting Rating: 1200 (all models start equal)
- K-Factor: 16 (rating change sensitivity)
- Outcomes:
- Win: +16 points (expected)
- Loss: -16 points (expected)
- Tie: 0 points (expected)
Enhanced Data Format
The system now provides recommenders with rich data including Spotify IDs:
Input Song Ratings Format:
song_ratings = [
{
"song": "Blinding Lights by The Weeknd",
"rating": 5,
"spotify_id": "0VjIjW4GlUZAMYd2vXMi3b"
},
{
"song": "Shape of You by Ed Sheeran",
"rating": 4,
"spotify_id": "4uLU6hMCjMI75M1A2tKUQC"
}
]
Recommendation Output Format:
recommendations = [
("4iV5W9uYEdYUVa79Axb7Rh", "Never Gonna Give You Up"),
("0VjIjW4GlUZAMYd2vXMi3b", "Blinding Lights"),
("4uLU6hMCjMI75M1A2tKUQC", "Shape of You")
]
Benefits for Recommenders:
- Song names: Human-readable context
- Ratings: User preference strength (1-5 stars)
- Spotify IDs: Access to audio features, metadata, popularity, genre, etc.
Leaderboard
The leaderboard shows:
- Model Name: Name of the recommendation model
- Elo Rating: Current Elo rating (higher = better)
Spotify Integration
Track Database
The system includes a comprehensive track database (tracks.csv) with:
- Track names and artist names
- Spotify track IDs for each track
- Automatic matching of user input to Spotify IDs
Spotify Web Players
- Input song preview: Click ▶️ buttons to preview input songs
- Recommendation preview: Each recommended track includes an embedded Spotify player
- Real-time playback: Listen to tracks without leaving the interface
Model Interface
All models must implement the following interface:
def query(song_ratings: List[Dict[str, any]], topk: int = 5) -> List[Tuple[str, str]]:
"""
Generate recommendations for given song ratings with Spotify integration.
Args:
song_ratings: List of dicts with 'song', 'rating', and 'spotify_id' keys
e.g., [
{"song": "Blinding Lights by The Weeknd", "rating": 5, "spotify_id": "0VjIjW4GlUZAMYd2vXMi3b"},
{"song": "Shape of You by Ed Sheeran", "rating": 4, "spotify_id": "4uLU6hMCjMI75M1A2tKUQC"}
]
topk: Maximum number of recommendations to return (default: 5)
Returns:
List of (spotify_id, track_name) tuples
e.g., [
("4iV5W9uYEdYUVa79Axb7Rh", "Never Gonna Give You Up"),
("0VjIjW4GlUZAMYd2vXMi3b", "Blinding Lights")
]
"""
pass
Input Data Structure:
song: Human-readable track name (e.g., "Blinding Lights by The Weeknd")rating: User preference rating (1-5 stars)spotify_id: Spotify track ID for enhanced capabilities (e.g., "0VjIjW4GlUZAMYd2vXMi3b")
Output Data Structure:
spotify_id: Spotify track ID for the recommended tracktrack_name: Human-readable track name for display
Configuration Parameters
name: Unique identifier for the modeltype: Either "http" or "python"endpoint: HTTP URL (for http models) - must accept enhanced song_ratings formatcallable: Python module path (for python models) - must implement enhanced interfacetimeout: Request timeout in seconds (default: 3) - optimized for user experiencetopk: Number of recommendations to return (default: 10)
Timeout Configuration:
- Default: 8 seconds for both HTTP and Python models
- Purpose: Ensures recommendations return quickly for better user experience
- Override: Can be customized per model in
models.yaml - Python Models: Uses signal-based timeout handling
- HTTP Models: Uses requests library timeout
State Management
The application maintains several state files:
state/elo.pkl: Current Elo ratings for all modelsstate/leaderboard.csv: Human-readable leaderboardstate/votes.jsonl: Complete vote historystate/cache.pkl: Recommendation cache for performance
Logging
All votes are logged with:
- Timestamp
- Client IP address
- Song name
- Model A and B names
- Vote outcome
Troubleshooting
Common Issues
- "No models configured": Check that
models.yamlexists and contains valid model definitions - "Failed to get recommendations": Verify model endpoints are accessible or Python modules are importable
- "Duplicate model names": Ensure all model names in
models.yamlare unique - Import errors: Check that Python model paths are correct and modules are accessible
- Spotify Player Issues:
- "No preview available": Ensure tracks exist in
tracks.csvwith valid Spotify IDs - Players not loading: Check internet connection and Spotify embed permissions
- "No preview available": Ensure tracks exist in
- Track Validation Errors:
- "Track not found": Use exact track names from database or click 🎲 Random buttons
- Format issues: Enter tracks as "Song Name by Artist Name"
- Model Format Issues:
- Wrong return format: Ensure models return
List[Tuple[str, str]]format - Missing Spotify IDs: Check that input song ratings include
spotify_idfield
- Wrong return format: Ensure models return
- Timeout Issues:
- Model timeout: Models must return results within 3 seconds
- Slow recommendations: Optimize model code or increase timeout in
models.yaml - Python model timeout: Use efficient algorithms and avoid blocking operations
- HTTP model timeout: Ensure endpoints respond quickly or increase timeout
Debug Mode
For debugging, you can modify the application to run in debug mode:
# In app.py, change the launch call:
demo.queue(default_concurrency_limit=20).launch(
server_name="0.0.0.0",
server_port=7860,
debug=True
)
Contributing
- Fork the repository
- Create a feature branch
- Implement your changes
- Add tests if applicable
- Submit a pull request
License
MIT LICENSE Copyright (c) 2025 bouncmpe343
Acknowledgments
- Built with Gradio
- Uses Elo rating system for fair model comparison
- Inspired by competitive machine learning platforms