File size: 4,217 Bytes
71a92ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import streamlit as st
import pandas as pd
import joblib
import os

# 1. Page Configuration
st.set_page_config(page_title="BgemBox Music Engine", layout="wide", page_icon="🎵")

# Custom CSS to improve font size and table padding
st.markdown("""

    <style>

    .main .block-container {padding-top: 2rem;}

    th {background-color: #f0f2f6 !important; font-size: 16px !important;}

    td {font-size: 15px !important;}

    </style>

    """, unsafe_allow_html=True)

# 2. Load Scaler and Data
@st.cache_resource
def load_assets():
    # 1. Veriyi yükle
    data = pd.read_pickle("final_music_data.pkl")
    
    # 2. Scaler'ı yükle
    scaler = joblib.load("scaler.pkl")
    
    # 3. Kümeleme sütunlarını kontrol et (Return'den ÖNCE olmalı)
    if 'sub_cluster' not in data.columns:
        if 'cluster' in data.columns:
            data['sub_cluster'] = data['cluster']
        else:
            # st.error burada çalışmayabilir, konsola yazdıralım
            print("Critical Error: No clustering columns found!")
            
    # İki nesneyi birden döndür
    return data, scaler

try:
    # Fonksiyon iki değer döndürdüğü için ikisini de ayrı ayrı almalıyız
    df, music_scaler = load_assets()
except Exception as e:
    st.error(f"Asset Loading Error: {e}")
    st.stop()

# 3. Sidebar Configuration
st.sidebar.title("Music Engine Settings")
st.sidebar.markdown("---")
st.sidebar.write("This AI-powered engine clusters music based on technical audio features like BPM, Energy, and Acousticness.")
st.sidebar.info("Developed by Elif | 2026")

# 4. Cluster Labels
cluster_names = {
    8.0: "🌟 Mainstream Pop Hits",
    1.0: "🎸 Classic Rock & Dynamic Rhythms",
    2.0: "🎹 Alternative & Indie Vibes",
    7.0: "📜 Nostalgic Oldies",
    3.0: "🌊 Chill & Low-Fi Moods",
    4.0: "⚡ High-Energy / Gym Motivation",
    0.0: "💎 Unique Rare Finds",
    5.0: "💎 Unique Rare Finds",
    6.0: "💎 Unique Rare Finds"
}

# 5. Main UI
st.title("🎵 BgemBox Music Recommendation System")
st.subheader("Discover music through Data Science")
st.markdown("---")

tab1, tab2 = st.tabs(["Search by Artist", "Discover by Mood"])

# TAB 1: Recommendation by Artist
with tab1:
    st.write("### Find Similar Artists")
    artist_list = sorted(df['Artist'].unique())
    selected_artist = st.selectbox("Select an Artist you like:", artist_list)

    if st.button("Recommend Similar Music"):
        artist_data = df[df['Artist'] == selected_artist].iloc[0]
        cluster_id = artist_data['sub_cluster']
        
        friendly_name = cluster_names.get(cluster_id, "Similar Style Tracks")
        st.success(f"Artist **{selected_artist}** belongs to the **{friendly_name}** segment.")
        
        recommendations = df[(df['sub_cluster'] == cluster_id) & (df['Artist'] != selected_artist)]
        recommendations = recommendations.sort_values(by='Popularity', ascending=False).head(5)
        
        st.write("#### Recommended for you:")
        # Used st.table for better readability and tighter columns
        st.table(recommendations[['Artist', 'Top Genre', 'Popularity']])

# TAB 2: Discover by Mood
with tab2:
    st.write("### How are you feeling today?")
    selected_mood_name = st.selectbox("Select a Mood:", list(cluster_names.values()))
    
    mood_id = [k for k, v in cluster_names.items() if v == selected_mood_name][0]
    
    if st.button("Generate Playlist"):
        mood_list = df[df['sub_cluster'] == mood_id]
        
        if not mood_list.empty:
            # Taking a random sample of 10
            playlist = mood_list.sample(min(len(mood_list), 10))
            st.write(f"#### Your {selected_mood_name} Playlist:")
            
            # Use st.table here instead of dataframe for better font size and compact columns
            st.table(playlist[['Artist', 'Top Genre', 'Popularity', 'Energy', 'Beats Per Minute (BPM)']])
        else:
            st.warning("This specific cluster is currently empty or has only one track.")

# 6. Footer
st.markdown("---")
st.caption("© 2026  Data Science Specialization Project")