Clonkz commited on
Commit
849c3a4
·
1 Parent(s): 956d233

creating app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -0
app.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ from sklearn.metrics.pairwise import cosine_similarity
5
+ from sklearn.preprocessing import StandardScaler, MinMaxScaler
6
+ from scipy.sparse import csr_matrix
7
+ from rapidfuzz import process, fuzz
8
+ import spotipy
9
+ from spotipy.oauth2 import SpotifyClientCredentials
10
+ import os
11
+
12
+
13
+ # Spotify API setup
14
+ sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials(
15
+ client_id=os.environ['sp_client_id'],
16
+ client_secret=os.environ['sp_client_secret']))
17
+
18
+ # Define features for scaling and calculations
19
+ features = ['popularity', 'danceability', 'energy', 'loudness', 'speechiness',
20
+ 'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo']
21
+ default_weights = [1/len(features)] * len(features)
22
+
23
+ # Read and preprocess the data
24
+ tracks_data = pd.read_csv('filtered_songs.csv')
25
+ tracks_data = tracks_data[(tracks_data['popularity'] > 40) & (tracks_data['instrumentalness'] <= 0.85)]
26
+
27
+ # Function to fetch a song from Spotify
28
+ def get_song_from_spotify(song_name, artist_name=None):
29
+ try:
30
+ search_query = song_name if not artist_name else f"{song_name} artist:{artist_name}"
31
+ results = sp.search(q=search_query, limit=1, type='track')
32
+ if results['tracks']['items']:
33
+ track = results['tracks']['items'][0]
34
+ audio_features = sp.audio_features(track['id'])[0]
35
+ song_details = {
36
+ 'id': track['id'],
37
+ 'name': track['name'],
38
+ 'popularity': track['popularity'],
39
+ 'duration_ms': track['duration_ms'],
40
+ 'explicit': int(track['explicit']),
41
+ 'artists': ', '.join([artist['name'] for artist in track['artists']]),
42
+ 'danceability': audio_features['danceability'],
43
+ 'energy': audio_features['energy'],
44
+ 'key': audio_features['key'],
45
+ 'loudness': audio_features['loudness'],
46
+ 'mode': audio_features['mode'],
47
+ 'speechiness': audio_features['speechiness'],
48
+ 'acousticness': audio_features['acousticness'],
49
+ 'instrumentalness': audio_features['instrumentalness'],
50
+ 'liveness': audio_features['liveness'],
51
+ 'valence': audio_features['valence'],
52
+ 'tempo': audio_features['tempo'],
53
+ 'time_signature': audio_features['time_signature'],
54
+ }
55
+ return song_details
56
+ else:
57
+ return None
58
+ except Exception as e:
59
+ print(f"Error fetching song from Spotify: {e}")
60
+ return None
61
+
62
+ # Enhanced Fuzzy Matching Function
63
+ def enhanced_fuzzy_matching(song_name, artist_name, df):
64
+ combined_query = f"{song_name} {artist_name}".strip()
65
+ df['combined'] = df['name'] + ' ' + df['artists']
66
+ matches = process.extractOne(combined_query, df['combined'], scorer=fuzz.token_sort_ratio)
67
+ return df.index[df['combined'] == matches[0]].tolist()[0] if matches else None
68
+
69
+ # Function to apply the selected scaler and calculate weighted cosine similarity
70
+ def calculate_weighted_cosine_similarity(input_song_index, weights, num_songs_to_output, tracks_data, scaler_choice):
71
+ # Apply the selected scaler
72
+ if scaler_choice == 'Standard Scaler':
73
+ scaler = StandardScaler()
74
+ else: # MinMaxScaler
75
+ scaler = MinMaxScaler()
76
+ scaled_features = scaler.fit_transform(tracks_data[features]) * weights
77
+ tracks_sparse = csr_matrix(scaled_features)
78
+
79
+ # Calculate cosine similarities
80
+ cosine_similarities = cosine_similarity(tracks_sparse[input_song_index], tracks_sparse).flatten()
81
+ similar_song_indices = np.argsort(-cosine_similarities)[1:num_songs_to_output+1]
82
+ return similar_song_indices
83
+
84
+
85
+ # Function to recommend songs
86
+ def recommend_songs_interface(song_name, artist_name, num_songs_to_output, scaler_choice, tracks_data, *input_weights):
87
+ num_songs_to_output = int(num_songs_to_output)
88
+ weights = np.array([float(weight) for weight in input_weights]) if input_weights else default_weights
89
+ weights /= np.sum(weights) # Normalize weights
90
+
91
+ song_index = enhanced_fuzzy_matching(song_name, artist_name, tracks_data)
92
+ if song_index is not None:
93
+ similar_indices = calculate_weighted_cosine_similarity(song_index, weights, num_songs_to_output, tracks_data, scaler_choice)
94
+ similar_songs = tracks_data.iloc[similar_indices][['name', 'artists']]
95
+ return similar_songs
96
+ else:
97
+ return pd.DataFrame(columns=['name', 'artists'])
98
+
99
+ # Gradio interface setup
100
+ description = "Enter a song name and artist name (optional) to get song recommendations. Adjust the feature weights using the sliders. The system will automatically normalize the weights."
101
+
102
+ inputs = [
103
+ gr.components.Textbox(label="Song Name", placeholder="Enter a song name..."),
104
+ gr.components.Textbox(label="Artist Name (optional)", placeholder="Enter artist name (if known)..."),
105
+ gr.components.Number(label="Number of Songs to Output", value=5),
106
+ gr.components.Dropdown(choices=["Standard Scaler", "MinMax Scaler"], label="Select Scaler", value="Standard Scaler")
107
+ ]
108
+
109
+ # Add sliders for each feature weight
110
+ for feature in features:
111
+ inputs.append(gr.components.Slider(minimum=0, maximum=1, value=1/len(features), label=f"Weight for {feature}"))
112
+
113
+ # Gradio interface setup
114
+ iface = gr.Interface(
115
+ fn=lambda song_name, artist_name, num_songs_to_output, scaler_choice, *input_weights: recommend_songs_interface(song_name, artist_name, num_songs_to_output, scaler_choice, tracks_data, *input_weights),
116
+ inputs=inputs,
117
+ outputs=gr.components.Dataframe(),
118
+ title="Song Recommender",
119
+ description=description
120
+ )
121
+
122
+ # Run the Gradio app
123
+ if __name__ == "__main__":
124
+ iface.launch()