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}") |