Manuel Zafra commited on
Commit
1f43783
·
verified ·
1 Parent(s): 42d0179

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +292 -262
app.py CHANGED
@@ -6,112 +6,54 @@ import os
6
  import json
7
  import gradio as gr
8
  from tools.final_answer import FinalAnswerTool
9
- import tempfile
10
- import shutil
11
 
12
- # Constantes
13
  HISTORY_FILE = "song_history.json"
14
 
 
15
  LANGUAGES = {
16
  "English": "en",
17
  "Español": "es",
18
  "Français": "fr"
19
  }
20
 
21
- MESSAGES = {
22
- "en": {
23
- "title": "# 🎵 Music Recognition & Fun Facts",
24
- "subtitle": "Identify songs, learn interesting facts about artists, and chat about music",
25
- "language_label": "Choose your language",
26
- "rec_button": "REC FOR 10 SECONDS",
27
- "recognize_button": "RECOGNIZE SONG",
28
- "no_audio": "Please record an audio clip",
29
- "loading": "Recording... Click Stop when done (10 seconds max)",
30
- "audio_loaded": "✅ Audio loaded! Ready to recognize",
31
- "uploading": "Please wait while the audio is being uploaded...",
32
- "searching": "Searching your song in the sonic multiverse, please wait to discover amazing facts about your artist. This is a beta version, it might be a bit slow, please be patient...",
33
- "recognized": "✅ Song successfully recognized!",
34
- "error": "❌ Error recognizing the song: {error}",
35
- "artist_info_title": "### 🌟 About the Artist",
36
- "history_title": "### History of recognized songs",
37
- "history_button": "View History",
38
- "history_limit_label": "Number of songs to show",
39
- "no_history": "📋 No song recognition history yet",
40
- "empty_history": "📋 Song history is empty",
41
- "history_error": "❌ Error getting history: {error}",
42
- "chat_title": "### Ask me more about this artist or music in general",
43
- "chat_placeholder": "Ask about the artist, song, or anything music related...",
44
- "chat_button": "Send"
45
- },
46
- "es": {
47
- "title": "# 🎵 Reconocimiento Musical y Datos Curiosos",
48
- "subtitle": "Identifica canciones, aprende datos interesantes sobre artistas y chatea sobre música",
49
- "language_label": "Elige tu idioma",
50
- "rec_button": "GRABAR POR 10 SEGUNDOS",
51
- "recognize_button": "RECONOCER CANCIÓN",
52
- "no_audio": "Por favor graba un clip de audio",
53
- "loading": "Grabando... Haz clic en Detener cuando termines (máximo 10 segundos)",
54
- "audio_loaded": "✅ ¡Audio cargado! Listo para reconocer",
55
- "uploading": "Por favor espera mientras se carga el audio...",
56
- "searching": "Buscando tu canción en el multiverso sónico, por favor espera para descubrir datos increíbles sobre tu artista. Esta es una versión beta, puede ser un poco lenta, por favor ten paciencia...",
57
- "recognized": "✅ ¡Canción reconocida con éxito!",
58
- "error": "❌ Error al reconocer la canción: {error}",
59
- "artist_info_title": "### 🌟 Sobre el Artista",
60
- "history_title": "### Historial de canciones reconocidas",
61
- "history_button": "Ver Historial",
62
- "history_limit_label": "Número de canciones a mostrar",
63
- "no_history": "📋 No hay historial de canciones reconocidas todavía",
64
- "empty_history": "📋 El historial de canciones está vacío",
65
- "history_error": "❌ Error al obtener el historial: {error}",
66
- "chat_title": "### Pregúntame más sobre este artista o música en general",
67
- "chat_placeholder": "Pregunta sobre el artista, la canción o cualquier tema musical...",
68
- "chat_button": "Enviar"
69
- },
70
- "fr": {
71
- "title": "# 🎵 Reconnaissance Musicale et Anecdotes",
72
- "subtitle": "Identifiez des chansons, découvrez des faits intéressants sur les artistes et discutez de musique",
73
- "language_label": "Choisissez votre langue",
74
- "rec_button": "ENREGISTRER PENDANT 10 SECONDES",
75
- "recognize_button": "RECONNAÎTRE LA CHANSON",
76
- "no_audio": "Veuillez enregistrer un clip audio",
77
- "loading": "Enregistrement... Cliquez sur Arrêter quand c'est fini (10 secondes maximum)",
78
- "audio_loaded": "✅ Audio chargé ! Prêt à reconnaître",
79
- "uploading": "Veuillez patienter pendant le chargement de l'audio...",
80
- "searching": "Recherche de votre chanson dans le multivers sonore, veuillez patienter pour découvrir des faits incroyables sur votre artiste. Ceci est une version bêta, cela peut être un peu lent, soyez patient...",
81
- "recognized": "✅ Chanson reconnue avec succès !",
82
- "error": "❌ Erreur lors de la reconnaissance de la chanson : {error}",
83
- "artist_info_title": "### 🌟 À propos de l'Artiste",
84
- "history_title": "### Historique des chansons reconnues",
85
- "history_button": "Voir l'Historique",
86
- "history_limit_label": "Nombre de chansons à afficher",
87
- "no_history": "📋 Aucun historique de reconnaissance de chansons pour l'instant",
88
- "empty_history": "📋 L'historique des chansons est vide",
89
- "history_error": "❌ Erreur lors de l'obtention de l'historique : {error}",
90
- "chat_title": "### Posez-moi des questions sur cet artiste ou la musique en général",
91
- "chat_placeholder": "Posez des questions sur l'artiste, la chanson ou tout sujet musical...",
92
- "chat_button": "Envoyer"
93
- }
94
- }
95
-
96
- # Herramientas
97
  @tool
98
  def recognize_song(audio_path: str) -> dict:
 
 
 
 
99
  AUDD_API_TOKEN = os.getenv("AUDD_API_TOKEN")
 
100
  if not os.path.exists(audio_path):
101
  return {"error": "The audio file does not exist"}
 
102
  try:
103
  with open(audio_path, 'rb') as file:
104
- data = {'api_token': AUDD_API_TOKEN, 'return': 'spotify,apple_music'}
105
- files = {'file': file}
 
 
 
 
 
106
  response = requests.post('https://api.audd.io/', data=data, files=files)
 
107
  if response.status_code != 200:
108
  return {"error": f"API Error: {response.status_code}"}
 
109
  result = response.json()
 
110
  if result['status'] == 'error':
111
  return {"error": result['error']['error_message']}
 
112
  if not result.get('result'):
113
  return {"error": "Could not recognize the song"}
 
114
  song_info = result['result']
 
 
115
  song_data = {
116
  "Song": song_info.get('title', 'Unknown'),
117
  "Artist": song_info.get('artist', 'Unknown'),
@@ -120,92 +62,156 @@ def recognize_song(audio_path: str) -> dict:
120
  "Apple Music": song_info.get('apple_music', {}).get('url', 'Not available'),
121
  "Recognition Date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
122
  }
 
 
123
  save_to_history(song_data)
 
124
  return song_data
 
125
  except Exception as e:
126
  return {"error": f"Error processing audio: {str(e)}"}
127
 
 
128
  def save_to_history(song_data):
 
129
  try:
 
130
  if os.path.exists(HISTORY_FILE):
131
  with open(HISTORY_FILE, 'r') as f:
132
- history = json.load(f) if f.read().strip() else []
 
 
 
133
  else:
134
  history = []
 
 
135
  history.insert(0, song_data)
 
 
136
  if len(history) > 50:
137
  history = history[:50]
 
 
138
  with open(HISTORY_FILE, 'w') as f:
139
  json.dump(history, f, indent=2)
 
140
  except Exception as e:
141
  print(f"Error saving to history: {str(e)}")
142
 
 
143
  @tool
144
- def view_song_history(limit: int = 10, language: str = "en") -> str:
145
- lang = LANGUAGES.get(language, "en")
 
 
 
146
  try:
147
  if not os.path.exists(HISTORY_FILE):
148
- return f"📋 {MESSAGES[lang]['no_history']}"
 
149
  with open(HISTORY_FILE, 'r') as f:
150
- history = json.load(f)
 
 
 
 
151
  if not history:
152
- return f"📋 {MESSAGES[lang]['empty_history']}"
 
 
153
  history = history[:min(limit, len(history))]
154
- result = f"📋 **{MESSAGES[lang]['history_title']}:**\n\n"
 
 
 
155
  for i, song in enumerate(history, 1):
156
  result += f"{i}. **{song.get('Song', 'Unknown')}** - *{song.get('Artist', 'Unknown')}*\n"
157
  result += f" 📀 Album: {song.get('Album', 'Unknown')}\n"
 
158
  if song.get('Spotify', 'Not available') != 'Not available':
159
  result += f" 🎧 [Spotify]({song.get('Spotify')})\n"
 
160
  if song.get('Apple Music', 'Not available') != 'Not available':
161
  result += f" 🍏 [Apple Music]({song.get('Apple Music')})\n"
 
162
  result += f" 🕒 Recognized on: {song.get('Recognition Date', 'Unknown date')}\n\n"
 
163
  return result
 
164
  except Exception as e:
165
- return f"❌ {MESSAGES[lang]['history_error'].format(error=str(e))}"
166
 
 
167
  @tool
168
- def get_artist_info(artist_name: str, song_title: str, language: str = "en") -> dict:
 
 
 
 
 
 
169
  prompts = {
170
- "en": f"Provide interesting and fun facts about the music artist '{artist_name}' that fans would love to know. Include stories about their career, personal anecdotes, how their song '{song_title}' was created if known, or surprising facts about their life. Include an image URL if possible. Focus on highlighting their contributions to music and anything that makes them unique as an artist. Keep it engaging and positive.",
171
- "es": f"Proporciona datos interesantes y curiosos sobre el artista musical '{artist_name}' que a los fans les encantaría conocer. Incluye historias sobre su carrera, anécdotas personales, cómo se creó su canción '{song_title}' si se sabe, o datos sorprendentes sobre su vida. Incluye una URL de imagen si es posible. Céntrate en destacar sus contribuciones a la música y cualquier cosa que les haga únicos como artistas. Mantenlo atractivo y positivo.",
172
- "fr": f"Fournissez des faits intéressants et amusants sur l'artiste musical '{artist_name}' que les fans aimeraient connaître. Incluez des histoires sur leur carrière, des anecdotes personnelles, comment leur chanson '{song_title}' a été créée si connu, ou des faits surprenants sur leur vie. Incluez une URL d'image si possible. Concentrez-vous sur la mise en valeur de leurs contributions à la musique et tout ce qui les rend uniques en tant qu'artiste. Gardez-le engageant et positif.",
173
  }
174
- language = language if language in prompts else "en"
175
- messages = [{"role": "user", "content": prompts[language]}]
 
 
 
 
 
 
 
 
176
  try:
 
177
  response = model(messages)
178
- content = response.content
179
- image_url = None
180
- if "[Image:" in content:
181
- start = content.find("[Image:") + 7
182
- end = content.find("]", start)
183
- image_url = content[start:end].strip()
184
- content = content[:start-7] + content[end+1:]
185
- return {"text": content.strip(), "image": image_url}
186
  except Exception as e:
187
- return {"text": f"Could not retrieve information about {artist_name}: {str(e)}", "image": None}
188
 
 
189
  @tool
190
  def chat_with_assistant(query: str, artist_info: str = "", language: str = "en") -> str:
 
 
 
 
 
 
 
191
  system_messages = {
192
  "en": "You are a music expert assistant who specializes in providing engaging information about artists, songs, and music history. Focus on sharing interesting, fun facts that highlight the artist's unique contributions and stories.",
193
  "es": "Eres un asistente experto en música que se especializa en proporcionar información interesante sobre artistas, canciones e historia musical. Céntrate en compartir datos curiosos e interesantes que destaquen las contribuciones únicas y las historias del artista.",
194
- "fr": "Vous êtes un assistant expert en musique qui se spécialise dans la fourniture d'informations intéressantes sur les artistes, les chansons et l'histoire de la musique. Concentrez-vous sur le partage de faits intéressants et amusants qui mettent en évidence les contributions uniques et les histoires de l'artiste.",
195
  }
196
- language = language if language in system_messages else "en"
197
- context = f"Previous context about the artist: {artist_info}\n\n" if artist_info else ""
 
 
 
 
 
 
 
 
 
198
  messages = [
199
  {"role": "system", "content": system_messages[language]},
200
  {"role": "user", "content": context + query}
201
  ]
 
202
  try:
 
203
  response = model(messages)
204
  return response.content
205
  except Exception as e:
206
  return f"Sorry, I couldn't process your request: {str(e)}"
207
 
208
- # Configuración del agente
209
  final_answer = FinalAnswerTool()
210
  model = HfApiModel(
211
  max_tokens=2096,
@@ -217,9 +223,16 @@ model = HfApiModel(
217
  with open("prompts.yaml", 'r') as stream:
218
  prompt_templates = yaml.safe_load(stream)
219
 
 
220
  agent = CodeAgent(
221
  model=model,
222
- tools=[final_answer, recognize_song, view_song_history, get_artist_info, chat_with_assistant],
 
 
 
 
 
 
223
  max_steps=8,
224
  verbosity_level=1,
225
  grammar=None,
@@ -229,177 +242,194 @@ agent = CodeAgent(
229
  prompt_templates=prompt_templates
230
  )
231
 
232
- # Descargar imagen (función auxiliar)
233
- def download_image(image_url):
234
- if not image_url:
235
- return ""
236
- try:
237
- response = requests.get(image_url, stream=True)
238
- if response.status_code == 200:
239
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
240
- shutil.copyfileobj(response.raw, temp_file)
241
- temp_file.close()
242
- return temp_file.name
243
- return ""
244
- except Exception:
245
- return ""
246
-
247
- # Interfaz de usuario con Gradio
248
- with gr.Blocks(title="Music Recognition & Fun Facts", css=".large-text {font-size: 1.5em !important;} .big-button {font-size: 1.2em; padding: 15px 30px;}") as demo:
249
  selected_language = gr.State("en")
250
  song_info_state = gr.State(None)
251
  artist_info_state = gr.State("")
252
- audio_status = gr.State("no_audio")
253
-
254
- title = gr.Markdown(value=MESSAGES["en"]["title"], elem_id="title")
255
- subtitle = gr.Markdown(value=MESSAGES["en"]["subtitle"], elem_id="subtitle")
256
-
 
 
257
  with gr.Row():
258
  language_dropdown = gr.Dropdown(
259
- choices=[("English", "en"), ("Español", "es"), ("Français", "fr")],
260
- value="en",
261
- label=MESSAGES["en"]["language_label"]
262
  )
263
-
 
264
  with gr.Tab("Song Recognition & Chat"):
265
- audio_status_msg = gr.Markdown(value=MESSAGES["en"]["no_audio"], elem_id="audio_status_msg")
 
 
 
266
  with gr.Row():
267
  with gr.Column(scale=1):
268
- audio_input = gr.Audio(type="filepath", visible=False)
269
- record_btn = gr.Button(value=MESSAGES["en"]["rec_button"], elem_classes="big-button", variant="primary", elem_id="record_btn")
270
- audio_loaded_msg = gr.Markdown("", elem_classes="large-text")
271
- recognize_btn = gr.Button(value=MESSAGES["en"]["recognize_button"], variant="secondary", elem_id="recognize_btn")
272
-
 
273
  with gr.Row():
274
  recognition_results = gr.Markdown("")
275
-
 
276
  with gr.Row():
277
- artist_info_text = gr.Markdown("")
278
- artist_info_image = gr.Image(type="filepath")
279
-
280
- chat_title = gr.Markdown(value=MESSAGES["en"]["chat_title"], elem_id="chat_title")
281
- chat_history = gr.Chatbot(label="Music Chat", type="messages")
282
-
283
  with gr.Row():
284
  chat_input = gr.Textbox(
285
- placeholder=MESSAGES["en"]["chat_placeholder"],
286
- label="Your question",
287
- elem_id="chat_input"
288
  )
289
- chat_btn = gr.Button(value=MESSAGES["en"]["chat_button"], variant="primary", elem_id="chat_btn")
290
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  with gr.Tab("Song History"):
292
- gr.Markdown(value=MESSAGES["en"]["history_title"])
 
293
  with gr.Row():
294
- history_limit = gr.Slider(minimum=5, maximum=50, value=10, step=5, label=MESSAGES["en"]["history_limit_label"], elem_id="history_limit")
295
- view_history_btn = gr.Button(value=MESSAGES["en"]["history_button"], elem_id="view_history_btn")
 
296
  history_output = gr.Markdown()
297
-
298
- def update_ui(language_name):
299
- lang = LANGUAGES.get(language_name, "en")
300
- return (
301
- MESSAGES[lang]["title"],
302
- MESSAGES[lang]["subtitle"],
303
- MESSAGES[lang]["no_audio"],
304
- MESSAGES[lang]["rec_button"],
305
- MESSAGES[lang]["recognize_button"],
306
- MESSAGES[lang]["chat_title"],
307
- MESSAGES[lang]["chat_placeholder"],
308
- MESSAGES[lang]["chat_button"],
309
- MESSAGES[lang]["history_limit_label"],
310
- MESSAGES[lang]["history_button"]
311
  )
312
 
313
- language_dropdown.change(
314
- fn=update_ui,
315
- inputs=[language_dropdown],
316
- outputs=[title, subtitle, audio_status_msg, record_btn, recognize_btn, chat_title, chat_input, chat_btn, history_limit, view_history_btn]
317
- )
318
-
319
- def toggle_audio_widget(language_name):
320
- lang = LANGUAGES.get(language_name, "en")
321
- return gr.update(visible=True), "loading", MESSAGES[lang]["loading"]
322
-
323
- record_btn.click(
324
- fn=toggle_audio_widget,
325
- inputs=[language_dropdown],
326
- outputs=[audio_input, audio_status, audio_status_msg]
327
- )
328
-
329
- def update_audio_status(audio_path, language_name):
330
- lang = LANGUAGES.get(language_name, "en")
331
- if audio_path:
332
- return "ready", MESSAGES[lang]["audio_loaded"]
333
- else:
334
- return "no_audio", MESSAGES[lang]["no_audio"]
335
-
336
- audio_input.change(
337
- fn=update_audio_status,
338
- inputs=[audio_input, language_dropdown],
339
- outputs=[audio_status, audio_loaded_msg]
340
- )
341
-
342
- def process_audio(audio_path, language_name, status):
343
- lang = LANGUAGES.get(language_name, "en")
344
- if not audio_path or status != "ready":
345
- return None, "", "", MESSAGES[lang]["no_audio"], ""
346
- yield None, "", "", MESSAGES[lang]["uploading"], ""
347
- yield None, "", "", MESSAGES[lang]["searching"], ""
348
- try:
349
- result = recognize_song(audio_path)
350
- if "error" in result:
351
- return None, "", "", MESSAGES[lang]["error"].format(error=result['error']), ""
352
- artist_info = get_artist_info(result['Artist'], result['Song'], lang)
353
- recognition_msg = f"### 🎵 Recognized Song: {result['Song']}\n\n**🎤 Artist:** {result['Artist']}\n**📀 Album:** {result['Album']}\n\n"
354
- if result['Spotify'] != "Not available":
355
- recognition_msg += f"**🎧 [Listen on Spotify]({result['Spotify']})**\n"
356
- if result['Apple Music'] != "Not available":
357
- recognition_msg += f"**🍏 [Listen on Apple Music]({result['Apple Music']})**\n"
358
- artist_facts_content = f"{MESSAGES[lang]['artist_info_title']}\n\n{artist_info['text']}"
359
- image_filepath = download_image(artist_info['image']) if artist_info['image'] else ""
360
- status_msg = MESSAGES[lang]["recognized"]
361
- return result, recognition_msg, artist_facts_content, status_msg, image_filepath
362
- except Exception as e:
363
- return None, "", "", MESSAGES[lang]["error"].format(error=str(e)), ""
364
-
365
- recognize_btn.click(
366
- fn=process_audio,
367
- inputs=[audio_input, language_dropdown, audio_status],
368
- outputs=[song_info_state, recognition_results, artist_info_text, audio_status_msg, artist_info_image]
369
- ).then(
370
- fn=lambda a: a,
371
- inputs=[artist_info_text],
372
- outputs=[artist_info_state]
373
- )
374
-
375
- def process_chat(query, language_name, song_info, artist_info):
376
- lang = LANGUAGES.get(language_name, "en")
377
- if not query:
378
- return []
379
- try:
380
- response = chat_with_assistant(query, artist_info, lang)
381
- return [(query, response)]
382
- except Exception as e:
383
- return [(query, f"Sorry, I couldn't process your request: {str(e)}")]
384
-
385
- chat_btn.click(
386
- fn=process_chat,
387
- inputs=[chat_input, language_dropdown, song_info_state, artist_info_state],
388
- outputs=[chat_history]
389
- ).then(
390
- fn=lambda: "",
391
- inputs=[],
392
- outputs=[chat_input]
393
- )
394
-
395
- def view_history_process(limit, language_name):
396
- lang = LANGUAGES.get(language_name, "en")
397
- return view_song_history(int(limit), lang)
398
-
399
- view_history_btn.click(
400
- fn=view_history_process,
401
- inputs=[history_limit, language_dropdown],
402
- outputs=[history_output]
403
- )
404
-
405
  demo.launch()
 
6
  import json
7
  import gradio as gr
8
  from tools.final_answer import FinalAnswerTool
 
 
9
 
10
+ # File to save the history of recognized songs
11
  HISTORY_FILE = "song_history.json"
12
 
13
+ # Supported languages (sin alemán)
14
  LANGUAGES = {
15
  "English": "en",
16
  "Español": "es",
17
  "Français": "fr"
18
  }
19
 
20
+ # Tool to recognize songs using AudD
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  @tool
22
  def recognize_song(audio_path: str) -> dict:
23
+ """Recognizes a song from an audio file
24
+ Args:
25
+ audio_path: path to the audio file to recognize
26
+ """
27
  AUDD_API_TOKEN = os.getenv("AUDD_API_TOKEN")
28
+
29
  if not os.path.exists(audio_path):
30
  return {"error": "The audio file does not exist"}
31
+
32
  try:
33
  with open(audio_path, 'rb') as file:
34
+ data = {
35
+ 'api_token': AUDD_API_TOKEN,
36
+ 'return': 'spotify,apple_music'
37
+ }
38
+ files = {
39
+ 'file': file
40
+ }
41
  response = requests.post('https://api.audd.io/', data=data, files=files)
42
+
43
  if response.status_code != 200:
44
  return {"error": f"API Error: {response.status_code}"}
45
+
46
  result = response.json()
47
+
48
  if result['status'] == 'error':
49
  return {"error": result['error']['error_message']}
50
+
51
  if not result.get('result'):
52
  return {"error": "Could not recognize the song"}
53
+
54
  song_info = result['result']
55
+
56
+ # Create object with song information
57
  song_data = {
58
  "Song": song_info.get('title', 'Unknown'),
59
  "Artist": song_info.get('artist', 'Unknown'),
 
62
  "Apple Music": song_info.get('apple_music', {}).get('url', 'Not available'),
63
  "Recognition Date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
64
  }
65
+
66
+ # Save to history
67
  save_to_history(song_data)
68
+
69
  return song_data
70
+
71
  except Exception as e:
72
  return {"error": f"Error processing audio: {str(e)}"}
73
 
74
+ # Function to save song to history
75
  def save_to_history(song_data):
76
+ """Saves a song to the history"""
77
  try:
78
+ # Load existing history or create new
79
  if os.path.exists(HISTORY_FILE):
80
  with open(HISTORY_FILE, 'r') as f:
81
+ try:
82
+ history = json.load(f)
83
+ except json.JSONDecodeError:
84
+ history = []
85
  else:
86
  history = []
87
+
88
+ # Add song to the beginning of history (most recent first)
89
  history.insert(0, song_data)
90
+
91
+ # Limit history to the 50 most recent songs
92
  if len(history) > 50:
93
  history = history[:50]
94
+
95
+ # Save updated history
96
  with open(HISTORY_FILE, 'w') as f:
97
  json.dump(history, f, indent=2)
98
+
99
  except Exception as e:
100
  print(f"Error saving to history: {str(e)}")
101
 
102
+ # Tool to view song history
103
  @tool
104
+ def view_song_history(limit: int = 10) -> str:
105
+ """Shows the history of recognized songs
106
+ Args:
107
+ limit: maximum number of songs to display (default 10)
108
+ """
109
  try:
110
  if not os.path.exists(HISTORY_FILE):
111
+ return "📋 No song recognition history yet."
112
+
113
  with open(HISTORY_FILE, 'r') as f:
114
+ try:
115
+ history = json.load(f)
116
+ except json.JSONDecodeError:
117
+ return "📋 Error loading song history."
118
+
119
  if not history:
120
+ return "📋 Song history is empty."
121
+
122
+ # Limit the number of songs to display
123
  history = history[:min(limit, len(history))]
124
+
125
+ # Format output
126
+ result = "📋 **Song Recognition History:**\n\n"
127
+
128
  for i, song in enumerate(history, 1):
129
  result += f"{i}. **{song.get('Song', 'Unknown')}** - *{song.get('Artist', 'Unknown')}*\n"
130
  result += f" 📀 Album: {song.get('Album', 'Unknown')}\n"
131
+
132
  if song.get('Spotify', 'Not available') != 'Not available':
133
  result += f" 🎧 [Spotify]({song.get('Spotify')})\n"
134
+
135
  if song.get('Apple Music', 'Not available') != 'Not available':
136
  result += f" 🍏 [Apple Music]({song.get('Apple Music')})\n"
137
+
138
  result += f" 🕒 Recognized on: {song.get('Recognition Date', 'Unknown date')}\n\n"
139
+
140
  return result
141
+
142
  except Exception as e:
143
+ return f"❌ Error getting history: {str(e)}"
144
 
145
+ # Tool to get artist information in selected language (sin alemán)
146
  @tool
147
+ def get_artist_info(artist_name: str, language: str = "en") -> str:
148
+ """Gets background information and fun facts about a music artist in the specified language
149
+ Args:
150
+ artist_name: name of the artist to get information about
151
+ language: language code (en, es, fr)
152
+ """
153
+ # Language-specific prompts (sin alemán)
154
  prompts = {
155
+ "en": f"Provide interesting and fun facts about the music artist '{artist_name}' that fans would love to know. Include stories about their career, personal anecdotes, how their most famous songs were created, or surprising facts about their life. Focus on highlighting their contributions to music and anything that makes them unique as an artist. Keep it engaging and positive.",
156
+ "es": f"Proporciona datos interesantes y curiosos sobre el artista musical '{artist_name}' que a los fans les encantaría conocer. Incluye historias sobre su carrera, anécdotas personales, cómo se crearon sus canciones más famosas o datos sorprendentes sobre su vida. Céntrate en destacar sus contribuciones a la música y cualquier cosa que les haga únicos como artistas. Mantenlo atractivo y positivo.",
157
+ "fr": f"Fournissez des faits intéressants et amusants sur l'artiste musical '{artist_name}' que les fans aimeraient connaître. Incluez des histoires sur leur carrière, des anecdotes personnelles, comment leurs chansons les plus célèbres ont été créées, ou des faits surprenants sur leur vie. Concentrez-vous sur la mise en valeur de leurs contributions à la musique et tout ce qui les rend uniques en tant qu'artiste. Gardez-le engageant et positif."
158
  }
159
+
160
+ # Default to English if language not supported
161
+ if language not in prompts:
162
+ language = "en"
163
+
164
+ # Create messages for the model
165
+ messages = [
166
+ {"role": "user", "content": prompts[language]}
167
+ ]
168
+
169
  try:
170
+ # Using the same model that powers our agent
171
  response = model(messages)
172
+ return response.content
 
 
 
 
 
 
 
173
  except Exception as e:
174
+ return f"Could not retrieve information about {artist_name}: {str(e)}"
175
 
176
+ # Chat with LLM tool (sin alemán)
177
  @tool
178
  def chat_with_assistant(query: str, artist_info: str = "", language: str = "en") -> str:
179
+ """Chat with the AI assistant about any music related topic in the specified language
180
+ Args:
181
+ query: user's question or request
182
+ artist_info: previous artist info to provide context
183
+ language: language code (en, es, fr)
184
+ """
185
+ # Language-specific system messages (sin alemán)
186
  system_messages = {
187
  "en": "You are a music expert assistant who specializes in providing engaging information about artists, songs, and music history. Focus on sharing interesting, fun facts that highlight the artist's unique contributions and stories.",
188
  "es": "Eres un asistente experto en música que se especializa en proporcionar información interesante sobre artistas, canciones e historia musical. Céntrate en compartir datos curiosos e interesantes que destaquen las contribuciones únicas y las historias del artista.",
189
+ "fr": "Vous êtes un assistant expert en musique qui se spécialise dans la fourniture d'informations intéressantes sur les artistes, les chansons et l'histoire de la musique. Concentrez-vous sur le partage de faits intéressants et amusants qui mettent en évidence les contributions uniques et les histoires de l'artiste."
190
  }
191
+
192
+ # Default to English if language not supported
193
+ if language not in system_messages:
194
+ language = "en"
195
+
196
+ # Create context
197
+ context = ""
198
+ if artist_info:
199
+ context = f"Previous context about the artist: {artist_info}\n\n"
200
+
201
+ # Create messages for the model
202
  messages = [
203
  {"role": "system", "content": system_messages[language]},
204
  {"role": "user", "content": context + query}
205
  ]
206
+
207
  try:
208
+ # Using the model to generate a response
209
  response = model(messages)
210
  return response.content
211
  except Exception as e:
212
  return f"Sorry, I couldn't process your request: {str(e)}"
213
 
214
+ # Agent configuration
215
  final_answer = FinalAnswerTool()
216
  model = HfApiModel(
217
  max_tokens=2096,
 
223
  with open("prompts.yaml", 'r') as stream:
224
  prompt_templates = yaml.safe_load(stream)
225
 
226
+ # Agent definition
227
  agent = CodeAgent(
228
  model=model,
229
+ tools=[
230
+ final_answer,
231
+ recognize_song,
232
+ view_song_history,
233
+ get_artist_info,
234
+ chat_with_assistant
235
+ ],
236
  max_steps=8,
237
  verbosity_level=1,
238
  grammar=None,
 
242
  prompt_templates=prompt_templates
243
  )
244
 
245
+ # Gradio user interface
246
+ with gr.Blocks(title="Music Recognition & Fun Facts") as demo:
247
+ # State variables
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  selected_language = gr.State("en")
249
  song_info_state = gr.State(None)
250
  artist_info_state = gr.State("")
251
+ audio_status = gr.State("no_audio") # States: no_audio, loading, ready
252
+
253
+ # Title and intro
254
+ gr.Markdown("# 🎵 Music Recognition & Fun Facts")
255
+ gr.Markdown("Identify songs, learn interesting facts about artists, and chat about music")
256
+
257
+ # Language selection
258
  with gr.Row():
259
  language_dropdown = gr.Dropdown(
260
+ choices=list(LANGUAGES.keys()),
261
+ value="English",
262
+ label="Choose your language"
263
  )
264
+
265
+ # Combined recognition and chat interface
266
  with gr.Tab("Song Recognition & Chat"):
267
+ # Audio status message
268
+ audio_status_msg = gr.Markdown("*Por favor, graba o sube un clip de audio*")
269
+
270
+ # Song recognition section
271
  with gr.Row():
272
  with gr.Column(scale=1):
273
+ # Configuramos el componente de audio para usar el micrófono directamente
274
+ audio_input = gr.Audio(source="microphone", type="filepath", visible=False)
275
+ record_btn = gr.Button("🎙 REC MUSIC", size="lg", variant="primary")
276
+ recognize_btn = gr.Button("🔍 RECOGNIZE SONG", variant="secondary")
277
+
278
+ # Recognition results section (separate from chat)
279
  with gr.Row():
280
  recognition_results = gr.Markdown("")
281
+
282
+ # Artist info section
283
  with gr.Row():
284
+ artist_facts = gr.Markdown("")
285
+
286
+ # Chat section
287
+ gr.Markdown("### Pregúntame más sobre este artista o música en general")
288
+ chat_history = gr.Chatbot(label="Music Chat")
289
+
290
  with gr.Row():
291
  chat_input = gr.Textbox(
292
+ placeholder="Pregunta sobre el artista, la canción o cualquier tema musical...",
293
+ label="Tu pregunta"
 
294
  )
295
+ chat_btn = gr.Button("Enviar", variant="primary")
296
+
297
+ # Function to handle audio recording
298
+ def toggle_audio_widget():
299
+ return gr.update(visible=True), "loading", "*Espera mientras se graba el audio... Haz clic en Stop cuando termines*"
300
+
301
+ # Function to update status when audio is recorded
302
+ def update_audio_status(audio_path):
303
+ if audio_path:
304
+ return "ready", "✅ *¡Audio cargado! Listo para reconocer. Presiona RECOGNIZE SONG*"
305
+ else:
306
+ return "no_audio", "*Por favor, graba o sube un clip de audio*"
307
+
308
+ # Recognition function (sin alemán)
309
+ def process_audio(audio_path, language_name, status):
310
+ if not audio_path or status != "ready":
311
+ return None, "", "", "*Por favor, graba un clip de audio primero*"
312
+
313
+ lang_code = LANGUAGES.get(language_name, "en")
314
+
315
+ try:
316
+ result = recognize_song(audio_path)
317
+
318
+ if "error" in result:
319
+ return None, "", "", f"Error al reconocer la canción: {result['error']}"
320
+
321
+ # Get artist information in selected language
322
+ artist_info = get_artist_info(result['Artist'], lang_code)
323
+
324
+ # Format recognition result based on language
325
+ if lang_code == "en":
326
+ recognition_msg = f"### 🎵 Recognized Song: {result['Song']}\n\n"
327
+ recognition_msg += f"**🎤 Artist:** {result['Artist']}\n"
328
+ recognition_msg += f"**📀 Album:** {result['Album']}\n\n"
329
+ if result['Spotify'] != "Not available":
330
+ recognition_msg += f"**🎧 [Listen on Spotify]({result['Spotify']})**\n"
331
+ if result['Apple Music'] != "Not available":
332
+ recognition_msg += f"**🍏 [Listen on Apple Music]({result['Apple Music']})**\n"
333
+ elif lang_code == "es":
334
+ recognition_msg = f"### 🎵 Canción Reconocida: {result['Song']}\n\n"
335
+ recognition_msg += f"**🎤 Artista:** {result['Artist']}\n"
336
+ recognition_msg += f"**📀 Álbum:** {result['Album']}\n\n"
337
+ if result['Spotify'] != "Not available":
338
+ recognition_msg += f"**🎧 [Escuchar en Spotify]({result['Spotify']})**\n"
339
+ if result['Apple Music'] != "Not available":
340
+ recognition_msg += f"**🍏 [Escuchar en Apple Music]({result['Apple Music']})**\n"
341
+ elif lang_code == "fr":
342
+ recognition_msg = f"### 🎵 Chanson Reconnue: {result['Song']}\n\n"
343
+ recognition_msg += f"**🎤 Artiste:** {result['Artist']}\n"
344
+ recognition_msg += f"**📀 Album:** {result['Album']}\n\n"
345
+ if result['Spotify'] != "Not available":
346
+ recognition_msg += f"**🎧 [Écouter sur Spotify]({result['Spotify']})**\n"
347
+ if result['Apple Music'] != "Not available":
348
+ recognition_msg += f"**🍏 [Écouter sur Apple Music]({result['Apple Music']})**\n"
349
+
350
+ # Artist info section title based on language
351
+ if lang_code == "en":
352
+ artist_facts_title = f"### 🌟 About {result['Artist']}\n\n"
353
+ elif lang_code == "es":
354
+ artist_facts_title = f"### 🌟 Sobre {result['Artist']}\n\n"
355
+ elif lang_code == "fr":
356
+ artist_facts_title = f"### 🌟 À propos de {result['Artist']}\n\n"
357
+
358
+ # Format the artist info with a title
359
+ artist_facts_content = artist_facts_title + artist_info
360
+
361
+ # Update status message
362
+ status_msg = "*¡Canción reconocida con éxito! Haz preguntas sobre el artista en el chat abajo*"
363
+
364
+ return result, recognition_msg, artist_facts_content, status_msg
365
+
366
+ except Exception as e:
367
+ return None, "", "", f"❌ Error procesando el audio: {str(e)}"
368
+
369
+ # Chat function
370
+ def process_chat(query, language_name, song_info, artist_info):
371
+ if not query:
372
+ return []
373
+
374
+ lang_code = LANGUAGES.get(language_name, "en")
375
+
376
+ try:
377
+ # Get response
378
+ response = chat_with_assistant(query, artist_info, lang_code)
379
+
380
+ return [(query, response)]
381
+ except Exception as e:
382
+ return [(query, f"Lo siento, no pude procesar tu solicitud: {str(e)}")]
383
+
384
+ # Event handlers
385
+ record_btn.click(
386
+ fn=toggle_audio_widget,
387
+ inputs=[],
388
+ outputs=[audio_input, audio_status, audio_status_msg]
389
+ )
390
+
391
+ audio_input.change(
392
+ fn=update_audio_status,
393
+ inputs=[audio_input],
394
+ outputs=[audio_status, audio_status_msg]
395
+ )
396
+
397
+ recognize_btn.click(
398
+ fn=process_audio,
399
+ inputs=[audio_input, language_dropdown, audio_status],
400
+ outputs=[song_info_state, recognition_results, artist_facts, audio_status_msg]
401
+ ).then(
402
+ fn=lambda a: a,
403
+ inputs=[artist_facts],
404
+ outputs=[artist_info_state]
405
+ )
406
+
407
+ chat_btn.click(
408
+ fn=process_chat,
409
+ inputs=[chat_input, language_dropdown, song_info_state, artist_info_state],
410
+ outputs=[chat_history]
411
+ ).then(
412
+ fn=lambda: "", # Clear input after sending
413
+ inputs=[],
414
+ outputs=[chat_input]
415
+ )
416
+
417
  with gr.Tab("Song History"):
418
+ gr.Markdown("### Historial de canciones reconocidas")
419
+
420
  with gr.Row():
421
+ history_limit = gr.Slider(minimum=5, maximum=50, value=10, step=5, label="Número de canciones a mostrar")
422
+ view_history_btn = gr.Button("📋 Ver Historial")
423
+
424
  history_output = gr.Markdown()
425
+
426
+ def view_history_process(limit):
427
+ return view_song_history(int(limit))
428
+
429
+ view_history_btn.click(
430
+ fn=view_history_process,
431
+ inputs=[history_limit],
432
+ outputs=[history_output]
 
 
 
 
 
 
433
  )
434
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  demo.launch()