File size: 2,873 Bytes
08beb33
 
1e8ae02
 
08beb33
b0b2ee4
 
08beb33
1e8ae02
b0b2ee4
457028c
b0b2ee4
457028c
b0b2ee4
 
 
5082269
08beb33
e126340
b0b2ee4
 
 
e126340
 
 
b0b2ee4
e126340
1e8ae02
b0b2ee4
 
 
 
 
 
1e8ae02
b0b2ee4
 
 
 
46c9a57
b0b2ee4
 
 
 
 
 
 
 
 
 
e126340
b0b2ee4
e126340
b0b2ee4
e126340
 
b0b2ee4
e126340
 
 
457028c
e126340
b0b2ee4
e126340
b0b2ee4
e126340
 
b0b2ee4
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
import streamlit as st
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import NearestNeighbors

st.set_page_config(page_title="DNA Sonoro: Filtro de Elite", page_icon="🧬")
st.title("🧬 DNA Sonoro: Precisão Máxima")

@st.cache_data
def carregar_dados():
    df = pd.read_csv("tracks_features.csv")
    # Mantendo apenas o essencial para não fritar a memória
    df = df[['name', 'artists', 'danceability', 'energy', 'acousticness', 'instrumentalness', 'valence', 'tempo']].dropna()
    # Limpeza de strings para busca não falhar por causa de espaço ou letra maiúscula
    df['name_clean'] = df['name'].str.lower().str.strip()
    df['artists_clean'] = df['artists'].str.lower().str.strip()
    return df

try:
    df = carregar_dados()
    
    # Motor matemático
    features = ['danceability', 'energy', 'acousticness', 'instrumentalness', 'valence', 'tempo']
    scaler = StandardScaler()
    df_scaled = scaler.fit_transform(df[features])
    model = NearestNeighbors(n_neighbors=11, metric='cosine')
    model.fit(df_scaled)

    st.markdown("### 🔎 Busca Refinada")
    col1, col2 = st.columns(2)
    with col1:
        musica_input = st.text_input("Nome da música:", placeholder="Ex: Spring Day")
    with col2:
        artista_input = st.text_input("Nome do artista (Opcional):", placeholder="Ex: BTS")

    if musica_input:
        # Busca exata ou parcial mas rigorosa
        termo_musica = musica_input.lower().strip()
        termo_artista = artista_input.lower().strip() if artista_input else ""
        
        # Filtro direto no DataFrame (mais rápido e preciso que o Fuzzy para 1M de linhas)
        if termo_artista:
            match = df[(df['name_clean'].str.contains(termo_musica)) & (df['artists_clean'].str.contains(termo_artista))]
        else:
            match = df[df['name_clean'] == termo_musica]
            if match.empty:
                match = df[df['name_clean'].str.contains(termo_musica)].head(1)

        if not match.empty:
            idx = match.index[0]
            track = df.iloc[idx]
            st.success(f"🎯 **Identificada:** {track['name']}{track['artists']}")
            
            # Cálculo da vibe
            distances, indices = model.kneighbors([df_scaled[idx]])
            
            st.subheader("💡 Recomendações com DNA idêntico:")
            for i in indices[0]:
                if i != idx:
                    res = df.iloc[i]
                    st.write(f"✨ **{res['name']}** — {res['artists']}")
                    simil = int((1 - distances[0][list(indices[0]).index(i)]) * 100)
                    st.caption(f"Compatibilidade: {simil}%")
        else:
            st.error("Não achei essa combinação na base. Tente apenas uma palavra-chave da música.")

except Exception as e:
    st.error(f"Erro no motor: {e}")