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