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() | |