Music_Sonar_X / app.py
Manuel Zafra
Update app.py
412755c verified
raw
history blame
10.5 kB
from smolagents import CodeAgent, HfApiModel, tool
import datetime
import requests
import pytz
import yaml
import os
import pickle
import time
import gradio as gr
from tools.final_answer import FinalAnswerTool
# Herramienta para obtener la hora actual en una zona horaria
@tool
def get_current_time_in_timezone(timezone: str) -> str:
"""A tool that fetches the current local time in a specified timezone.
Args:
timezone: A string representing a valid timezone (e.g., 'America/New_York').
"""
try:
# Create timezone object
tz = pytz.timezone(timezone)
# Get current time in that timezone
local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
return f"The current local time in {timezone} is: {local_time}"
except Exception as e:
return f"Error fetching time for timezone '{timezone}': {str(e)}"
# Herramienta para reconocer canciones usando AudD
@tool
def recognize_song(audio_path: str) -> dict:
"""Reconoce una canción a partir de un archivo de audio
Args:
audio_path: ruta al archivo de audio a reconocer
"""
AUDD_API_TOKEN = os.getenv("AUDD_API_TOKEN")
if not os.path.exists(audio_path):
return {"error": "El archivo de audio no existe"}
try:
with open(audio_path, 'rb') as file:
data = {
'api_token': AUDD_API_TOKEN,
'return': 'spotify,apple_music'
}
files = {
'file': file
}
response = requests.post('https://api.audd.io/', data=data, files=files)
if response.status_code != 200:
return {"error": f"Error en la API: {response.status_code}"}
result = response.json()
if result['status'] == 'error':
return {"error": result['error']['error_message']}
if not result.get('result'):
return {"error": "No se pudo reconocer la canción"}
song_info = result['result']
return {
"🎶 Canción": song_info.get('title', 'Desconocido'),
"🎤 Artista": song_info.get('artist', 'Desconocido'),
"📀 Álbum": song_info.get('album', 'Desconocido'),
"🎧 Spotify": song_info.get('spotify', {}).get('external_urls', {}).get('spotify', 'No disponible'),
"🍏 Apple Music": song_info.get('apple_music', {}).get('url', 'No disponible')
}
except Exception as e:
return {"error": f"Error al procesar el audio: {str(e)}"}
# Herramienta para iniciar sesión en Soundeo
@tool
def login_soundeo() -> str:
"""Inicia sesión en Soundeo usando las credenciales almacenadas en secrets"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Obtener credenciales de los secrets
username = os.getenv("SOUNDEO_USERNAME")
password = os.getenv("SOUNDEO_PASSWORD")
if not username or not password:
return "❌ No se encontraron las credenciales en los secrets"
# Configurar opciones de Chrome
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
try:
# Inicializar el driver
driver = webdriver.Chrome(options=chrome_options)
# Navegar a Soundeo
driver.get("https://soundeo.com/login")
time.sleep(3) # Esperar a que cargue la página
# Capturar screenshot para debug
driver.save_screenshot("pre_login.png")
# Completar formulario de login
username_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
)
username_field.send_keys(username)
password_field = driver.find_element(By.ID, "password")
password_field.send_keys(password)
# Hacer clic en el botón de login
login_button = driver.find_element(By.XPATH, "//button[@type='submit']")
login_button.click()
# Esperar a que se complete el login
time.sleep(5)
# Capturar screenshot para verificar
driver.save_screenshot("post_login.png")
# Guardar cookies para uso futuro
pickle.dump(driver.get_cookies(), open("soundeo_cookies.pkl", "wb"))
# Verificar si el login fue exitoso
if "dashboard" in driver.current_url or "account" in driver.current_url:
result = "✅ Login exitoso en Soundeo"
else:
result = "❌ Error al iniciar sesión. Verifica tus credenciales."
driver.quit()
return result
except Exception as e:
return f"❌ Error con Selenium: {str(e)}"
# Herramienta para buscar y añadir una canción a la lista de descarga
@tool
def add_song_to_download_list(song_title: str, artist: str) -> str:
"""Busca una canción en Soundeo y la añade a la lista de descarga
Args:
song_title: título de la canción
artist: nombre del artista
"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
try:
driver = webdriver.Chrome(options=chrome_options)
# Cargar cookies si existen
cookies_file = "soundeo_cookies.pkl"
if os.path.exists(cookies_file):
driver.get("https://soundeo.com")
cookies = pickle.load(open(cookies_file, "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
else:
driver.quit()
return "❌ No hay cookies de sesión. Primero debes iniciar sesión."
# Navegar a la búsqueda
search_query = f"{song_title} {artist}"
search_query = search_query.replace(" ", "+")
driver.get(f"https://soundeo.com/search?q={search_query}")
time.sleep(5)
# Capturar screenshot para debug
driver.save_screenshot("search_results.png")
# Buscar el primer resultado
try:
first_result = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".track-item"))
)
# Hacer clic en "Add to Download List"
download_button = first_result.find_element(By.CSS_SELECTOR, ".download-button")
download_button.click()
time.sleep(3)
driver.save_screenshot("added_to_list.png")
# Obtener información del track añadido
track_info = first_result.find_element(By.CSS_SELECTOR, ".track-title").text
artist_info = first_result.find_element(By.CSS_SELECTOR, ".track-artist").text
driver.quit()
return f"✅ Añadida a la lista de descarga: {track_info} - {artist_info}"
except Exception as e:
driver.quit()
return f"❌ No se encontraron resultados o no se pudo añadir: {str(e)}"
except Exception as e:
return f"❌ Error con Selenium: {str(e)}"
# Configuración del agente
final_answer = FinalAnswerTool()
model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
custom_role_conversions=None,
)
with open("prompts.yaml", 'r') as stream:
prompt_templates = yaml.safe_load(stream)
agent = CodeAgent(
model=model,
tools=[
final_answer,
recognize_song,
login_soundeo,
add_song_to_download_list,
get_current_time_in_timezone
],
max_steps=8,
verbosity_level=1,
grammar=None,
planning_interval=None,
name=None,
description=None,
prompt_templates=prompt_templates
)
# Interfaz de usuario con Gradio
with gr.Blocks() as demo:
gr.Markdown("# 🎵 Asistente Musical - Reconocimiento y Descarga")
with gr.Tab("Reconocimiento de Música"):
with gr.Row():
audio_input = gr.Audio(type="filepath", label="Sube o graba un fragmento de audio")
query_input = gr.Textbox(
label="Consulta (opcional)",
placeholder="Reconoce esta canción y agrégala a mi lista de descarga"
)
submit_btn = gr.Button("Procesar")
output = gr.Markdown()
def process_with_agent(audio=None, text_query=""):
context = {}
if audio:
context["audio_path"] = audio
if not text_query:
text_query = "Reconoce esta canción y dame información detallada sobre ella."
if not text_query:
return "❌ Por favor ingresa una consulta o sube un archivo de audio."
try:
result = agent.run(text_query, context=context)
return result
except Exception as e:
return f"❌ Error al procesar la solicitud: {str(e)}"
submit_btn.click(
fn=process_with_agent,
inputs=[audio_input, query_input],
outputs=output
)
with gr.Tab("Login a Soundeo"):
info_text = gr.Markdown("Las credenciales se cargarán automáticamente desde los secrets")
login_btn = gr.Button("Iniciar Sesión en Soundeo")
login_output = gr.Markdown()
def login_process():
query = "Inicia sesión en Soundeo usando las credenciales almacenadas"
return agent.run(query)
login_btn.click(
fn=login_process,
inputs=[],
outputs=login_output
)
demo.launch()