Streamlit / app.py
Rutson's picture
Update app.py
b0b2ee4 verified
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}")