Upload 3 files
Browse files- .gitattributes +1 -0
- Spotify_Youtube.csv +3 -0
- app.py +144 -0
- requirements.txt +7 -0
.gitattributes
CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
Spotify_Youtube.csv filter=lfs diff=lfs merge=lfs -text
|
Spotify_Youtube.csv
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a08bda951ec1c62a2fbaeb5547141ba23dd7b16347f0e83bd043b1ba9cf168cd
|
3 |
+
size 30782016
|
app.py
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
import datetime
|
4 |
+
|
5 |
+
# --- Load your dataset ---
|
6 |
+
df_clean = pd.read_csv("your_dataset.csv") # Replace with your actual filename
|
7 |
+
audio_feature_cols = ["Valence", "Danceability", "Energy", "Tempo", "Instrumentalness"] # Customize if needed
|
8 |
+
|
9 |
+
# --- Global feedback memory ---
|
10 |
+
feedback_df = pd.DataFrame(columns=["Query", "Title", "Artist", "Feedback"])
|
11 |
+
|
12 |
+
# --- Dummy parsing logic (replace with your LLM function if needed) ---
|
13 |
+
def parse_user_input(user_input):
|
14 |
+
return {
|
15 |
+
"mood": "happy",
|
16 |
+
"context": "",
|
17 |
+
"preference": "Likes",
|
18 |
+
"reference_song": "",
|
19 |
+
"genre": "",
|
20 |
+
"instrumental": "",
|
21 |
+
"tempo": "",
|
22 |
+
"artist": "",
|
23 |
+
"gender": "",
|
24 |
+
"limit": "5"
|
25 |
+
}
|
26 |
+
|
27 |
+
# --- Dummy explanation generator ---
|
28 |
+
def generate_explanation(user_input, row):
|
29 |
+
return f"{row['Title']} by {row['Artist']} fits your input: {user_input}"
|
30 |
+
|
31 |
+
# --- Dummy recommender fallback ---
|
32 |
+
def recommend_by_reference_song(parsed, df, feature_cols, llm, prompt):
|
33 |
+
return df.head(int(parsed["limit"])) # Replace with actual similarity logic
|
34 |
+
|
35 |
+
def recommend_from_dataframe(parsed, df):
|
36 |
+
mood = parsed["mood"].lower()
|
37 |
+
top_n = int(parsed.get("limit", "5"))
|
38 |
+
val_range = (0.3, 0.7)
|
39 |
+
dance_range = (0.3, 0.7)
|
40 |
+
|
41 |
+
if mood == "happy":
|
42 |
+
val_range = (0.6, 1.0)
|
43 |
+
dance_range = (0.6, 1.0)
|
44 |
+
elif mood == "sad":
|
45 |
+
val_range = (0.0, 0.4)
|
46 |
+
dance_range = (0.0, 0.4)
|
47 |
+
|
48 |
+
df_filtered = df[
|
49 |
+
(df["Valence"] >= val_range[0]) & (df["Valence"] <= val_range[1]) &
|
50 |
+
(df["Danceability"] >= dance_range[0]) & (df["Danceability"] <= dance_range[1])
|
51 |
+
]
|
52 |
+
|
53 |
+
sort_col = parsed.get("preference", "Likes")
|
54 |
+
if sort_col not in df.columns:
|
55 |
+
sort_col = "Likes"
|
56 |
+
|
57 |
+
return df_filtered.sort_values(by=sort_col, ascending=False).head(top_n)
|
58 |
+
|
59 |
+
# --- Feedback ---
|
60 |
+
def submit_feedback(query, title, artist, feedback_type):
|
61 |
+
global feedback_df
|
62 |
+
new_feedback = pd.DataFrame([{
|
63 |
+
"Query": query,
|
64 |
+
"Title": title,
|
65 |
+
"Artist": artist,
|
66 |
+
"Feedback": feedback_type
|
67 |
+
}])
|
68 |
+
feedback_df = pd.concat([feedback_df, new_feedback], ignore_index=True)
|
69 |
+
return f"β
Feedback recorded for {title}: {feedback_type}"
|
70 |
+
|
71 |
+
def save_results(results_df):
|
72 |
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
73 |
+
path = f"recommendations_{timestamp}.csv"
|
74 |
+
results_df.to_csv(path, index=False)
|
75 |
+
return path
|
76 |
+
|
77 |
+
def save_feedback():
|
78 |
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
79 |
+
path = f"feedback_log_{timestamp}.csv"
|
80 |
+
feedback_df.to_csv(path, index=False)
|
81 |
+
return path
|
82 |
+
|
83 |
+
# --- Main handler ---
|
84 |
+
def handle_query(input_text):
|
85 |
+
parsed = parse_user_input(input_text)
|
86 |
+
if parsed["reference_song"].strip().lower() not in ["", "...", "none", "n/a"]:
|
87 |
+
results = recommend_by_reference_song(parsed, df_clean, audio_feature_cols, None, None)
|
88 |
+
else:
|
89 |
+
results = recommend_from_dataframe(parsed, df_clean)
|
90 |
+
|
91 |
+
results = results.copy()
|
92 |
+
results["Explanation"] = results.apply(lambda row: generate_explanation(input_text, row), axis=1)
|
93 |
+
return results[["Title", "Artist", "Explanation"]], results
|
94 |
+
|
95 |
+
# --- Gradio Interface ---
|
96 |
+
with gr.Blocks() as demo:
|
97 |
+
gr.Markdown("## π§ Song Recommender with Feedback")
|
98 |
+
|
99 |
+
user_input = gr.Textbox(label="What kind of song are you looking for?")
|
100 |
+
btn_run = gr.Button("π Recommend Songs")
|
101 |
+
|
102 |
+
song_output = gr.Dataframe(label="π΅ Recommended Songs")
|
103 |
+
results_state = gr.State()
|
104 |
+
|
105 |
+
download_btn = gr.Button("β¬οΈ Download Recommendations CSV", visible=False)
|
106 |
+
download_file = gr.File()
|
107 |
+
btn_run.click(fn=handle_query, inputs=user_input, outputs=[song_output, results_state])
|
108 |
+
btn_run.click(lambda: gr.update(visible=True), None, outputs=[download_btn])
|
109 |
+
download_btn.click(fn=save_results, inputs=[results_state], outputs=download_file)
|
110 |
+
|
111 |
+
gr.Markdown("### π§ Optional Feedback")
|
112 |
+
toggle_feedback_btn = gr.Button("βοΈ Give Feedback")
|
113 |
+
feedback_group = gr.Group(visible=False)
|
114 |
+
|
115 |
+
with feedback_group:
|
116 |
+
with gr.Row():
|
117 |
+
feedback_title = gr.Textbox(label="Song Title")
|
118 |
+
feedback_artist = gr.Textbox(label="Artist")
|
119 |
+
|
120 |
+
with gr.Row():
|
121 |
+
btn_like = gr.Button("π Relevant")
|
122 |
+
btn_dislike = gr.Button("π Not Relevant")
|
123 |
+
|
124 |
+
feedback_response = gr.Textbox(label="Feedback Message")
|
125 |
+
|
126 |
+
toggle_feedback_btn.click(lambda: gr.update(visible=True), None, outputs=[feedback_group])
|
127 |
+
|
128 |
+
btn_like.click(
|
129 |
+
fn=submit_feedback,
|
130 |
+
inputs=[user_input, feedback_title, feedback_artist, gr.State("π")],
|
131 |
+
outputs=feedback_response
|
132 |
+
)
|
133 |
+
|
134 |
+
btn_dislike.click(
|
135 |
+
fn=submit_feedback,
|
136 |
+
inputs=[user_input, feedback_title, feedback_artist, gr.State("π")],
|
137 |
+
outputs=feedback_response
|
138 |
+
)
|
139 |
+
|
140 |
+
download_feedback_btn = gr.Button("β¬οΈ Download Feedback Log CSV", visible=True)
|
141 |
+
download_feedback_file = gr.File()
|
142 |
+
download_feedback_btn.click(fn=save_feedback, outputs=download_feedback_file)
|
143 |
+
|
144 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
pandas
|
3 |
+
transformers
|
4 |
+
scikit-learn
|
5 |
+
accelerate
|
6 |
+
torch
|
7 |
+
gender-guesser
|