Spaces:
Sleeping
Sleeping
import streamlit as st | |
import numpy as np | |
import pandas as pd | |
import tensorflow as tf | |
from transformers import RobertaTokenizer, TFRobertaForSequenceClassification | |
from sentence_transformers import SentenceTransformer, util | |
import spotipy | |
from spotipy.oauth2 import SpotifyClientCredentials | |
import os | |
sim_model = SentenceTransformer("sentence-transformers/all-mpnet-base-v2") | |
# Function to analyze sentiment of the user's input | |
def analyze_user_input(user_input, tokenizer, model): | |
encoded_input = tokenizer(user_input, return_tensors="tf", truncation=True, padding=True, max_length=512) | |
outputs = model(encoded_input) | |
scores = tf.nn.softmax(outputs.logits, axis=-1).numpy()[0] | |
predicted_class_idx = tf.argmax(outputs.logits, axis=-1).numpy()[0] | |
sentiment_label = model.config.id2label[predicted_class_idx] | |
sentiment_score = scores[predicted_class_idx] | |
return sentiment_label, sentiment_score | |
# Function to match songs from the dataset with the user's sentiment | |
def match_songs_with_sentiment(user_sentiment_label, user_sentiment_score,inputVector, score_range,songs_df): | |
# Filter songs with the same sentiment label | |
matched_songs = songs_df[songs_df['sentiment'] == user_sentiment_label] | |
# Calculate the score range | |
score_min = max(0, user_sentiment_score - score_range) | |
score_max = min(1, user_sentiment_score + score_range) | |
# Further filter songs whose scores fall within the specified range | |
matched_songs = matched_songs[(matched_songs['score'] >= score_min) & (matched_songs['score'] <= score_max)] | |
# Shuffle the matched songs to get a random order | |
matched_songs = matched_songs.sample(frac=1).reset_index(drop=True) | |
matched_songs['similarity'] = matched_songs['seq'].apply(lambda x: util.pytorch_cos_sim(sim_model.encode(x), inputVector)) | |
top_5 = matched_songs['similarity'].sort_values(ascending=False).head(5) | |
# Sort the songs by how close their score is to the user's sentiment score | |
# matched_songs['score_diff'] = abs(matched_songs['score'] - user_sentiment_score) | |
# matched_songs = matched_songs.sort_values(by='score_diff') | |
# Select the top five songs and return | |
return matched_songs.loc[top_5.index, ['song','artist','seq','similarity','sentiment','score']] | |
client_id = os.getenv('client_id') | |
client_secret = os.getenv('client_secret') | |
client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret) | |
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) | |
def get_track_id(song_name): | |
# Search for the track ID using the song name | |
results = sp.search(q=song_name, type='track', limit=1) | |
if results['tracks']['items']: | |
track_id = results['tracks']['items'][0]['id'] | |
return track_id | |
else: | |
print(f"No results found for {song_name}") | |
return None | |
def get_track_preview_url(track_id): | |
# Get the 30-second preview URL for the track | |
track_info = sp.track(track_id) | |
preview_url = track_info['preview_url'] | |
return preview_url | |
# Initialize the tokenizer and model outside of the functions to speed up repeated calls | |
tokenizer = RobertaTokenizer.from_pretrained('roberta-base') | |
model = TFRobertaForSequenceClassification.from_pretrained('arpanghoshal/EmoRoBERTa') | |
# Streamlit app layout | |
st.set_page_config(page_title="MODUS MUSIC", layout="wide") # New: Setting page title and layout | |
# Custom CSS for background and text color | |
st.markdown(""" | |
<style> | |
.stApp { | |
background: rgb(0,0,0); | |
background-size: cover; | |
color: white; /* Sets global text color to white */ | |
} | |
/* General rule for all labels */ | |
label { | |
color: white !important; | |
} | |
/* Specific color for the main title */ | |
h1 { | |
color: red !important; /* Making the MODUS MUSIC title red */ | |
} | |
/* Additional specific styling */ | |
.stTextInput > label, .stButton > button, .css-10trblm, .css-1yjuwjr, .intro { | |
color: white !important; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
image_path = './MODUSMUSIC.png' # Replace with the actual path to your image | |
st.image(image_path, use_column_width=False, width=250) # Adjust the width as needed | |
# Custom gradient background using CSS | |
st.markdown(""" | |
<style> | |
.stApp { | |
background: rgb(0,0,0); | |
background-size: cover; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Custom HTML for the main title | |
st.markdown("<h1 style='text-align: center; font-weight: bold;'>MODUS MUSIC</h1>", unsafe_allow_html=True) | |
st.title('Music Suggestion Based on Your Feeling') # Existing Title | |
# New: Introduction Section | |
with st.container(): | |
st.markdown(""" | |
<style> | |
.intro { | |
font-size:18px; | |
} | |
</style> | |
<div class='intro'> | |
Welcome to Modus Music! Share your vibe, and let's find the perfect songs to match your mood. | |
Just type in your thoughts, and we'll do the rest. | |
</div> | |
""", unsafe_allow_html=True) | |
# User input text area | |
with st.container(): | |
user_input = st.text_area("What's your vibe? Tell me about it:", key="123", height=150, max_chars=500) | |
m = st.markdown(""" | |
<style> | |
div.stButton > button:first-child { | |
background-color: rgb(204, 49, 49); | |
} | |
</style>""", unsafe_allow_html=True) | |
# Use the custom style for the button | |
submit_button = st.button("Generate music") | |
# Processing and Displaying Results | |
if submit_button and len(user_input.split()) > 5: | |
# New: Define inputVector here | |
inputVector = sim_model.encode(user_input) | |
# Run sentiment analysis on the user input | |
sentiment_label, sentiment_score = analyze_user_input(user_input, tokenizer, model) | |
st.write(f"Sentiment: {sentiment_label}, Score: {sentiment_score:.2f}") | |
# Load songs dataframe | |
songs_df = pd.read_csv('./music_mental_health.csv') | |
# Suggest songs | |
suggested_songs = match_songs_with_sentiment(sentiment_label, sentiment_score, inputVector, 0.0003, songs_df) | |
suggested_songs['similarity'] = suggested_songs['similarity'].apply(lambda x: x.numpy()[0][0]) | |
# Styling for the suggested songs display | |
with st.container(): | |
st.markdown("<div class='song-list'>", unsafe_allow_html=True) | |
st.write("Based on your vibe, you might like these songs:") | |
for index, row in suggested_songs.iterrows(): | |
song = row['song'] | |
artist = row['artist'] | |
track_id = get_track_id(song) | |
if track_id.strip(): | |
preview_url = get_track_preview_url(track_id) | |
#st.write(f"Similarity: {row['similarity']}") | |
st.write(f"{song} by {artist}") | |
with st.expander(f"Show Lyrics for {song} by {artist}", expanded=False): | |
st.write(f"Lyrics: {row['seq']}") | |
if preview_url: | |
st.audio(preview_url) | |
else: | |
st.write("No Preview Available") | |
st.markdown("</div>", unsafe_allow_html=True) | |
st.dataframe(suggested_songs[['song','artist','seq','similarity','sentiment','score']]) | |
elif submit_button and not len(user_input.split()) > 5: | |
st.warning("Please provide a longer response with 5 words or more.") | |
st.rerun() | |