Update app.py
Browse files
app.py
CHANGED
|
@@ -4,59 +4,57 @@ from sklearn.preprocessing import StandardScaler
|
|
| 4 |
from sklearn.neighbors import NearestNeighbors
|
| 5 |
from thefuzz import process
|
| 6 |
|
| 7 |
-
|
| 8 |
-
st.
|
| 9 |
-
st.title("🧬 DNA Sonoro: Deep Search")
|
| 10 |
-
st.markdown("Recomendação técnica por vibe. Sem anúncios, focado em sonoridade real.")
|
| 11 |
|
|
|
|
| 12 |
@st.cache_data
|
| 13 |
-
def
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
df =
|
| 18 |
-
df = df.drop_duplicates(subset=['
|
| 19 |
-
df['search_info'] = df['
|
| 20 |
return df
|
| 21 |
|
| 22 |
try:
|
| 23 |
-
with st.spinner("
|
| 24 |
-
df =
|
| 25 |
|
| 26 |
-
#
|
| 27 |
features = ['danceability', 'energy', 'acousticness', 'instrumentalness', 'valence', 'tempo']
|
| 28 |
scaler = StandardScaler()
|
| 29 |
df_scaled = scaler.fit_transform(df[features])
|
| 30 |
|
| 31 |
-
# Modelo de vizinhos com métrica de 'cosine' para precisão máxima
|
| 32 |
model = NearestNeighbors(n_neighbors=7, metric='cosine')
|
| 33 |
model.fit(df_scaled)
|
| 34 |
|
| 35 |
-
query = st.text_input("
|
| 36 |
|
| 37 |
if query:
|
| 38 |
-
# Busca
|
| 39 |
choices = df['search_info'].tolist()
|
|
|
|
| 40 |
best_match = process.extractOne(query, choices)
|
| 41 |
|
| 42 |
-
if best_match and best_match[1] >
|
| 43 |
idx = df[df['search_info'] == best_match[0]].index[0]
|
| 44 |
track = df.iloc[idx]
|
| 45 |
|
| 46 |
-
st.success(f"
|
| 47 |
|
| 48 |
-
# Cálculo de proximidade
|
| 49 |
distances, indices = model.kneighbors([df_scaled[idx]])
|
| 50 |
|
| 51 |
-
st.subheader("💡 Recomendações
|
| 52 |
for i in indices[0]:
|
| 53 |
if i != idx:
|
| 54 |
res = df.iloc[i]
|
| 55 |
-
st.write(f"✨ **{res['
|
| 56 |
simil = int((1 - distances[0][list(indices[0]).index(i)]) * 100)
|
| 57 |
st.caption(f"DNA compatível em {simil}%")
|
| 58 |
else:
|
| 59 |
-
st.warning("Ainda não
|
| 60 |
|
| 61 |
except Exception as e:
|
| 62 |
-
st.error(f"Erro ao
|
|
|
|
| 4 |
from sklearn.neighbors import NearestNeighbors
|
| 5 |
from thefuzz import process
|
| 6 |
|
| 7 |
+
st.set_page_config(page_title="DNA Sonoro: Database Real", page_icon="🧬")
|
| 8 |
+
st.title("🧬 DNA Sonoro: Modo Offline")
|
|
|
|
|
|
|
| 9 |
|
| 10 |
+
# Função para carregar o arquivo que você subiu
|
| 11 |
@st.cache_data
|
| 12 |
+
def carregar_dados_locais():
|
| 13 |
+
# Lendo o arquivo de 346MB que você acabou de subir
|
| 14 |
+
df = pd.read_csv("tracks_features.csv")
|
| 15 |
+
# Limpeza básica para não pesar na memória
|
| 16 |
+
df = df[['name', 'artists', 'danceability', 'energy', 'acousticness', 'instrumentalness', 'valence', 'tempo']].dropna()
|
| 17 |
+
df = df.drop_duplicates(subset=['name', 'artists'])
|
| 18 |
+
df['search_info'] = df['name'].astype(str) + " " + df['artists'].astype(str)
|
| 19 |
return df
|
| 20 |
|
| 21 |
try:
|
| 22 |
+
with st.spinner("Analisando 1.2M de faixas... Isso pode levar um minuto na primeira vez."):
|
| 23 |
+
df = carregar_dados_locais()
|
| 24 |
|
| 25 |
+
# Preparando o motor matemático
|
| 26 |
features = ['danceability', 'energy', 'acousticness', 'instrumentalness', 'valence', 'tempo']
|
| 27 |
scaler = StandardScaler()
|
| 28 |
df_scaled = scaler.fit_transform(df[features])
|
| 29 |
|
|
|
|
| 30 |
model = NearestNeighbors(n_neighbors=7, metric='cosine')
|
| 31 |
model.fit(df_scaled)
|
| 32 |
|
| 33 |
+
query = st.text_input("Busque sua B-side ou Artista:", placeholder="Ex: Spring Day, STAYC, Enhypen...")
|
| 34 |
|
| 35 |
if query:
|
| 36 |
+
# Busca aproximada na sua base gigante
|
| 37 |
choices = df['search_info'].tolist()
|
| 38 |
+
# Pegamos os top matches para ser mais preciso
|
| 39 |
best_match = process.extractOne(query, choices)
|
| 40 |
|
| 41 |
+
if best_match and best_match[1] > 65:
|
| 42 |
idx = df[df['search_info'] == best_match[0]].index[0]
|
| 43 |
track = df.iloc[idx]
|
| 44 |
|
| 45 |
+
st.success(f"🎯 **Encontrei na Base:** {track['name']} — {track['artists']}")
|
| 46 |
|
|
|
|
| 47 |
distances, indices = model.kneighbors([df_scaled[idx]])
|
| 48 |
|
| 49 |
+
st.subheader("💡 Recomendações Técnicas:")
|
| 50 |
for i in indices[0]:
|
| 51 |
if i != idx:
|
| 52 |
res = df.iloc[i]
|
| 53 |
+
st.write(f"✨ **{res['name']}** — {res['artists']}")
|
| 54 |
simil = int((1 - distances[0][list(indices[0]).index(i)]) * 100)
|
| 55 |
st.caption(f"DNA compatível em {simil}%")
|
| 56 |
else:
|
| 57 |
+
st.warning("Ainda não encontrei. Tente o nome exato da música.")
|
| 58 |
|
| 59 |
except Exception as e:
|
| 60 |
+
st.error(f"Erro ao ler o arquivo: {e}")
|