music / app.py
IshmamF's picture
Update app.py
7201617 verified
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()