File size: 5,170 Bytes
e803c5d
 
 
 
 
49ba027
 
e803c5d
49ba027
 
 
 
 
 
 
 
 
e803c5d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# Convert the relevant parts of your notebook into a Python script
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
import gradio as gr
import gdown
import os

# Add this at the start of your script
def download_dataset():
    if not os.path.exists('song_dataset.csv'):
        # Replace with your Google Drive file ID
        url = "https://docs.google.com/spreadsheets/d/1MKqJmWQ1PxKHDkpIdbQEeTz_ohpjOsYPyVp6esEZsq4/"
        gdown.download(url, 'song_dataset.csv', quiet=False)

# Add this line before loading the dataset
download_dataset()
# Load the data
df = pd.read_csv('song_dataset.csv')

# Create user-song matrix
interaction_matrix = df.pivot_table(
    index='user',
    columns='song',
    values='play_count',
    fill_value=0
)

def search_songs(query):
    if not query or len(query) < 2:
        return gr.update(choices=[])
    try:
        matches = song_choices[
            song_choices['display'].str.lower().str.contains(query.lower(), regex=False)
        ]['display'].tolist()
        return gr.update(choices=matches[:10])
    except Exception as e:
        print(f"Search error: {e}")
        return gr.update(choices=[])

def add_to_selection(new_song, current_selections):
    if not current_selections:
        current_selections = []
    
    if new_song and new_song not in current_selections and len(current_selections) < 5:
        current_selections.append(new_song)
    
    return gr.update(choices=current_selections, value=current_selections)

def make_recommendations(selected_songs, n_recommendations=5):
    if not selected_songs:
        return "Please select at least one song to get recommendations."
        
    temp_user_profile = pd.Series(0, index=interaction_matrix.columns)
    for song in selected_songs:
        song_id = song_choices[song_choices['display'] == song]['song'].iloc[0]
        temp_user_profile[song_id] = 1
    
    user_sim = cosine_similarity([temp_user_profile], interaction_matrix)[0]
    
    unheard_songs = list(set(interaction_matrix.columns) - 
                        set([song_choices[song_choices['display'] == song]['song'].iloc[0] 
                             for song in selected_songs]))
    
    pred_ratings = []
    for song in unheard_songs:
        pred = np.sum(user_sim * interaction_matrix[song]) / np.sum(np.abs(user_sim))
        pred_ratings.append((song, pred))
    
    ratings = np.array([r[1] for r in pred_ratings])
    if len(ratings) > 0:
        min_rating, max_rating = ratings.min(), ratings.max()
        if max_rating > min_rating:
            normalized_ratings = 1 + 4 * (ratings - min_rating) / (max_rating - min_rating)
        else:
            normalized_ratings = [3.0] * len(ratings)
    else:
        return "No recommendations found for the selected songs."
    
    recommendations = list(zip([r[0] for r in pred_ratings], normalized_ratings))
    recommendations = sorted(recommendations, key=lambda x: x[1], reverse=True)[:n_recommendations]
    
    output = ""
    for song_id, rating in recommendations:
        song_details = df[df['song'] == song_id].iloc[0]
        output += f"Title: {song_details['title']}\n"
        output += f"Artist: {song_details['artist_name']}\n"
        output += f"Year: {song_details['year']}\n"
        output += f"Rating: {rating:.2f}/5.00\n"
        output += "-" * 50 + "\n"
    
    return output

# Create song choices for dropdown
song_choices = df[['song', 'title', 'artist_name']].drop_duplicates()
song_choices['display'] = song_choices['title'] + " - " + song_choices['artist_name']
song_list = song_choices['display'].tolist()

# Create Gradio interface
with gr.Blocks(title="Wanna Be Spotify") as iface:
    gr.Markdown("# 🎵 Wanna Be Spotify")
    gr.Markdown("Search and select up to 5 songs you've enjoyed to get personalized recommendations!")
    
    with gr.Row():
        search_box = gr.Textbox(
            label="Search for songs",
            placeholder="Type song or artist name...",
            show_label=True
        )
    
    with gr.Row():
        search_results = gr.Radio(
            choices=[],
            label="Search Results",
            interactive=True,
            show_label=True
        )
    
    with gr.Row():
        selected_songs = gr.Dropdown(
            choices=[],
            label="Selected Songs",
            interactive=True,
            multiselect=True,
            max_choices=5,
            show_label=True
        )
    
    with gr.Row():
        recommendations = gr.Textbox(
            label="Recommendations",
            interactive=False,
            lines=10,
            show_label=True
        )
    
    submit_btn = gr.Button("Get Recommendations")

    search_box.change(
        fn=search_songs,
        inputs=[search_box],
        outputs=[search_results]
    )
    
    search_results.change(
        fn=add_to_selection,
        inputs=[search_results, selected_songs],
        outputs=[selected_songs]
    )
    
    submit_btn.click(
        fn=make_recommendations,
        inputs=[selected_songs],
        outputs=[recommendations]
    )

# Launch the interface
iface.launch()