alex16052G commited on
Commit
dc8e88e
·
verified ·
1 Parent(s): 0b0b778

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -478
app.py CHANGED
@@ -1,495 +1,63 @@
1
- # chat_ai_full.py
2
 
3
  import subprocess
4
  import sys
5
-
6
- def install_packages():
7
- """
8
- Instala todas las dependencias necesarias utilizando pip.
9
- Primero desinstala el paquete 'Spanish-F5' si está instalado,
10
- luego lo reinstala desde el repositorio de GitHub.
11
- Finalmente, instala todas las demás dependencias listadas.
12
- """
13
- # Lista de paquetes a instalar
14
- packages = [
15
- "gradio>=3.0",
16
- "numpy>=1.21.0",
17
- "soundfile>=0.10.3",
18
- "torchaudio>=0.10.0",
19
- "cached_path>=0.1.0",
20
- "transformers>=4.0.0",
21
- "torch>=1.10.0",
22
- "num2words>=0.5.10",
23
- "click>=8.0.0"
24
- ]
25
-
26
- # Desinstalar Spanish-F5 si está instalado
27
- try:
28
- print("Desinstalando 'Spanish-F5' si está instalado...")
29
- subprocess.run([sys.executable, "-m", "pip", "uninstall", "-y", "Spanish-F5"], check=True)
30
- except subprocess.CalledProcessError:
31
- print("'Spanish-F5' no estaba instalado o hubo un error al desinstalarlo.")
32
-
33
- # Instalar Spanish-F5 desde GitHub
34
  try:
35
- print("Instalando 'Spanish-F5' desde GitHub...")
36
- subprocess.run([
37
- sys.executable, "-m", "pip", "install",
38
- "--upgrade",
39
- "git+https://github.com/jpgallegoar/Spanish-F5.git",
40
- "--no-cache-dir"
41
- ], check=True)
42
  except subprocess.CalledProcessError as e:
43
- print("Error al instalar 'Spanish-F5':", e)
44
  sys.exit(1)
45
-
46
- # Instalar las demás dependencias
47
- for package in packages:
48
- try:
49
- print(f"Instalando '{package}'...")
50
- subprocess.run([sys.executable, "-m", "pip", "install", package], check=True)
51
- except subprocess.CalledProcessError as e:
52
- print(f"Error al instalar '{package}':", e)
53
- sys.exit(1)
54
-
55
- print("Todas las dependencias han sido instaladas correctamente.")
56
-
57
- # Instalar dependencias antes de importar
58
- install_packages()
59
-
60
- # Importar las bibliotecas necesarias
61
- import re
62
- import tempfile
63
-
64
- import gradio as gr
65
- import numpy as np
66
- import soundfile as sf
67
- import torchaudio
68
- from cached_path import cached_path
69
- from transformers import AutoModelForCausalLM, AutoTokenizer
70
- import torch
71
-
72
- from f5_tts.model import DiT
73
- from f5_tts.infer.utils_infer import (
74
- load_vocoder,
75
- load_model,
76
- preprocess_ref_audio_text,
77
- infer_process,
78
- remove_silence_for_generated_wav,
79
- )
80
- from num2words import num2words
81
-
82
- # Intentar importar 'spaces' para determinar si se está usando Hugging Face Spaces
83
- try:
84
- import spaces
85
- USING_SPACES = True
86
- except ImportError:
87
- USING_SPACES = False
88
-
89
- # Decorador para utilizar GPU si está disponible
90
- def gpu_decorator(func):
91
- if USING_SPACES:
92
- return spaces.GPU(func)
93
- else:
94
- return func
95
-
96
- # Cargar el vocoder
97
- vocoder = load_vocoder()
98
-
99
- # Cargar el modelo F5-TTS
100
- F5TTS_model_cfg = dict(dim=1024, depth=22, heads=16, ff_mult=2, text_dim=512, conv_layers=4)
101
- F5TTS_ema_model = load_model(
102
- DiT, F5TTS_model_cfg, str(cached_path("hf://jpgallegoar/F5-Spanish/model_1200000.safetensors"))
103
- )
104
-
105
- # Variables globales para el modelo de chat
106
- chat_model_state = None
107
- chat_tokenizer_state = None
108
-
109
- @gpu_decorator
110
- def generate_response(messages, model, tokenizer):
111
- """
112
- Genera una respuesta utilizando el modelo de chat.
113
-
114
- Args:
115
- messages (list): Lista de mensajes en la conversación.
116
- model: Modelo de lenguaje.
117
- tokenizer: Tokenizer correspondiente al modelo.
118
-
119
- Returns:
120
- str: Respuesta generada por el modelo.
121
- """
122
- text = tokenizer.apply_chat_template(
123
- messages,
124
- tokenize=False,
125
- add_generation_prompt=True,
126
- )
127
-
128
- model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
129
- generated_ids = model.generate(
130
- **model_inputs,
131
- max_new_tokens=512,
132
- temperature=0.7,
133
- top_p=0.95,
134
- )
135
-
136
- generated_ids = [
137
- output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
138
- ]
139
- return tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
140
-
141
- def traducir_numero_a_texto(texto):
142
- """
143
- Convierte números en texto a su representación en palabras en español.
144
-
145
- Args:
146
- texto (str): Texto que contiene números.
147
-
148
- Returns:
149
- str: Texto con números convertidos a palabras.
150
- """
151
- texto_separado = re.sub(r'([A-Za-z])(\d)', r'\1 \2', texto)
152
- texto_separado = re.sub(r'(\d)([A-Za-z])', r'\1 \2', texto_separado)
153
-
154
- def reemplazar_numero(match):
155
- numero = match.group()
156
- return num2words(int(numero), lang='es')
157
-
158
- texto_traducido = re.sub(r'\b\d+\b', reemplazar_numero, texto_separado)
159
-
160
- return texto_traducido
161
-
162
- @gpu_decorator
163
- def infer(
164
- ref_audio_orig, ref_text, gen_text, model, remove_silence, cross_fade_duration=0.15, speed=1, show_info=gr.Info
165
- ):
166
- """
167
- Genera el audio sintetizado a partir del texto.
168
-
169
- Args:
170
- ref_audio_orig (str): Ruta al audio de referencia.
171
- ref_text (str): Texto de referencia.
172
- gen_text (str): Texto para generar el audio.
173
- model: Modelo TTS.
174
- remove_silence (bool): Si se debe eliminar silencios.
175
- cross_fade_duration (float): Duración del cross-fade.
176
- speed (float): Velocidad de reproducción.
177
- show_info: Función para mostrar información (Gradio Info).
178
-
179
- Returns:
180
- tuple: (sample_rate, audio_data), ruta al espectrograma.
181
- """
182
- ref_audio, ref_text = preprocess_ref_audio_text(ref_audio_orig, ref_text, show_info=show_info)
183
-
184
- ema_model = F5TTS_ema_model
185
-
186
- if not gen_text.startswith(" "):
187
- gen_text = " " + gen_text
188
- if not gen_text.endswith(". "):
189
- gen_text += ". "
190
-
191
- gen_text = gen_text.lower()
192
- gen_text = traducir_numero_a_texto(gen_text)
193
-
194
- final_wave, final_sample_rate, combined_spectrogram = infer_process(
195
- ref_audio,
196
- ref_text,
197
- gen_text,
198
- ema_model,
199
- vocoder,
200
- cross_fade_duration=cross_fade_duration,
201
- speed=speed,
202
- show_info=show_info,
203
- progress=gr.Progress(),
204
- )
205
-
206
- # Eliminar silencios si está activado
207
- if remove_silence:
208
- with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as f:
209
- sf.write(f.name, final_wave, final_sample_rate)
210
- remove_silence_for_generated_wav(f.name)
211
- final_wave, _ = torchaudio.load(f.name)
212
- final_wave = final_wave.squeeze().cpu().numpy()
213
 
214
- return (final_sample_rate, final_wave)
215
-
216
- def load_chat_model():
217
  """
218
- Carga el modelo de chat y el tokenizer.
219
-
220
- Returns:
221
- tuple: (modelo, tokenizer)
222
  """
223
- global chat_model_state, chat_tokenizer_state
224
- if chat_model_state is None:
225
- model_name = "Qwen/Qwen2.5-3B-Instruct"
226
- chat_model_state = AutoModelForCausalLM.from_pretrained(
227
- model_name, torch_dtype=torch.float16, device_map="auto"
228
- )
229
- chat_tokenizer_state = AutoTokenizer.from_pretrained(model_name)
230
- return chat_model_state, chat_tokenizer_state
231
-
232
- with gr.Blocks() as app_chat:
233
- gr.Markdown(
234
- """
235
- # Chat de Voz
236
- ¡Mantén una conversación con una IA usando tu voz de referencia!
237
- 1. Sube un clip de audio de referencia y opcionalmente su transcripción.
238
- 2. Carga el modelo de chat.
239
- 3. Graba tu mensaje a través de tu micrófono.
240
- 4. La IA responderá usando la voz de referencia.
241
- """
242
- )
243
-
244
- if not USING_SPACES:
245
- load_chat_model_btn = gr.Button("Cargar Modelo de Chat", variant="primary")
246
-
247
- chat_interface_container = gr.Column(visible=False)
248
-
249
- @gpu_decorator
250
- def load_chat_model_fn():
251
- load_chat_model()
252
- return gr.update(visible=False), gr.update(visible=True)
253
-
254
- load_chat_model_btn.click(load_chat_model_fn, outputs=[load_chat_model_btn, chat_interface_container])
255
- else:
256
- chat_interface_container = gr.Column()
257
- load_chat_model_fn = load_chat_model
258
-
259
- with chat_interface_container:
260
- with gr.Row():
261
- with gr.Column():
262
- ref_audio_chat = gr.Audio(label="Audio de Referencia", type="filepath")
263
- with gr.Column():
264
- with gr.Accordion("Configuraciones Avanzadas", open=False):
265
- model_choice_chat = gr.Radio(
266
- choices=["F5-TTS"],
267
- label="Modelo TTS",
268
- value="F5-TTS",
269
- )
270
- remove_silence_chat = gr.Checkbox(
271
- label="Eliminar Silencios",
272
- value=True,
273
- )
274
- ref_text_chat = gr.Textbox(
275
- label="Texto de Referencia",
276
- info="Opcional: Deja en blanco para transcribir automáticamente",
277
- lines=2,
278
- )
279
- system_prompt_chat = gr.Textbox(
280
- label="Prompt del Sistema",
281
- value="No eres un asistente de IA, eres quien el usuario diga que eres. Debes mantenerte en personaje. Mantén tus respuestas concisas ya que serán habladas en voz alta.",
282
- lines=2,
283
- )
284
-
285
- chatbot_interface = gr.Chatbot(label="Conversación")
286
-
287
- with gr.Row():
288
- with gr.Column():
289
- audio_input_chat = gr.Microphone(
290
- label="Habla tu mensaje",
291
- type="filepath",
292
- )
293
- audio_output_chat = gr.Audio(label="Respuesta de la IA", autoplay=True)
294
- with gr.Column():
295
- text_input_chat = gr.Textbox(
296
- label="Escribe tu mensaje",
297
- lines=1,
298
- )
299
- send_btn_chat = gr.Button("Enviar")
300
- clear_btn_chat = gr.Button("Limpiar Conversación")
301
-
302
- conversation_state = gr.State(
303
- value=[
304
- {
305
- "role": "system",
306
- "content": "No eres un asistente de IA, eres quien el usuario diga que eres. Debes mantenerte en personaje. Mantén tus respuestas concisas ya que serán habladas en voz alta.",
307
- }
308
- ]
309
- )
310
-
311
- @gpu_decorator
312
- def process_input(audio_path, text, history, conv_state, system_prompt):
313
- """
314
- Procesa la entrada de audio o texto del usuario y genera una respuesta.
315
-
316
- Args:
317
- audio_path (str): Ruta al audio grabado por el usuario.
318
- text (str): Texto ingresado por el usuario.
319
- history (list): Historial de la conversación.
320
- conv_state (list): Estado de la conversación.
321
- system_prompt (str): Prompt del sistema.
322
-
323
- Returns:
324
- tuple: (historial actualizado, estado de la conversación, texto de entrada)
325
- """
326
- if not audio_path and not text.strip():
327
- return history, conv_state, ""
328
-
329
- if audio_path:
330
- # Aquí podrías integrar una transcripción automática si lo deseas
331
- # Por simplicidad, asumimos que el texto es proporcionado
332
- pass
333
-
334
- if not text.strip():
335
- return history, conv_state, ""
336
-
337
- conv_state.append({"role": "user", "content": text})
338
- history.append((text, None))
339
-
340
- response = generate_response(conv_state, chat_model_state, chat_tokenizer_state)
341
-
342
- conv_state.append({"role": "assistant", "content": response})
343
- history[-1] = (text, response)
344
-
345
- return history, conv_state, response
346
-
347
- @gpu_decorator
348
- def generate_audio_response(response, ref_audio, ref_text, model, remove_silence):
349
- """
350
- Genera el audio de respuesta para la IA.
351
-
352
- Args:
353
- response (str): Respuesta de la IA en texto.
354
- ref_audio (str): Ruta al audio de referencia.
355
- ref_text (str): Texto de referencia.
356
- model (str): Modelo TTS a utilizar.
357
- remove_silence (bool): Si se debe eliminar silencios.
358
-
359
- Returns:
360
- tuple: (sample_rate, audio_data)
361
- """
362
- if not response or not ref_audio:
363
- return None
364
-
365
- audio_result, _ = infer(
366
- ref_audio,
367
- ref_text,
368
- response,
369
- model,
370
- remove_silence,
371
- cross_fade_duration=0.15,
372
- speed=1.0,
373
- show_info=gr.Info(),
374
- )
375
- return audio_result
376
-
377
- def clear_conversation_fn():
378
- """
379
- Limpia la conversación.
380
-
381
- Returns:
382
- tuple: (historial vacío, estado de la conversación reiniciado)
383
- """
384
- return [], [
385
- {
386
- "role": "system",
387
- "content": "No eres un asistente de IA, eres quien el usuario diga que eres. Debes mantenerte en personaje. Mantén tus respuestas concisas ya que serán habladas en voz alta.",
388
- }
389
- ]
390
-
391
- def update_system_prompt_fn(new_prompt):
392
- """
393
- Actualiza el prompt del sistema y reinicia la conversación.
394
-
395
- Args:
396
- new_prompt (str): Nuevo prompt del sistema.
397
-
398
- Returns:
399
- tuple: (historial vacío, estado de la conversación actualizado)
400
- """
401
- new_conv_state = [{"role": "system", "content": new_prompt}]
402
- return [], new_conv_state
403
-
404
- # Manejar la entrada de audio
405
- audio_input_chat.stop_recording(
406
- process_input,
407
- inputs=[audio_input_chat, text_input_chat, chatbot_interface, conversation_state, system_prompt_chat],
408
- outputs=[chatbot_interface, conversation_state, text_input_chat],
409
- ).then(
410
- generate_audio_response,
411
- inputs=[text_input_chat, ref_audio_chat, ref_text_chat, model_choice_chat, remove_silence_chat],
412
- outputs=[audio_output_chat],
413
- ).then(
414
- lambda: None,
415
- None,
416
- audio_input_chat,
417
- )
418
-
419
- # Manejar la entrada de texto
420
- text_input_chat.submit(
421
- process_input,
422
- inputs=[audio_input_chat, text_input_chat, chatbot_interface, conversation_state, system_prompt_chat],
423
- outputs=[chatbot_interface, conversation_state, text_input_chat],
424
- ).then(
425
- generate_audio_response,
426
- inputs=[text_input_chat, ref_audio_chat, ref_text_chat, model_choice_chat, remove_silence_chat],
427
- outputs=[audio_output_chat],
428
- ).then(
429
- lambda: None,
430
- None,
431
- text_input_chat,
432
- )
433
-
434
- # Manejar el botón de enviar
435
- send_btn_chat.click(
436
- process_input,
437
- inputs=[audio_input_chat, text_input_chat, chatbot_interface, conversation_state, system_prompt_chat],
438
- outputs=[chatbot_interface, conversation_state, text_input_chat],
439
- ).then(
440
- generate_audio_response,
441
- inputs=[text_input_chat, ref_audio_chat, ref_text_chat, model_choice_chat, remove_silence_chat],
442
- outputs=[audio_output_chat],
443
- ).then(
444
- lambda: None,
445
- None,
446
- text_input_chat,
447
- )
448
-
449
- # Manejar el botón de limpiar conversación
450
- clear_btn_chat.click(
451
- clear_conversation_fn,
452
- outputs=[chatbot_interface, conversation_state],
453
- )
454
 
455
- # Manejar cambios en el prompt del sistema
456
- system_prompt_chat.change(
457
- update_system_prompt_fn,
458
- inputs=system_prompt_chat,
459
- outputs=[chatbot_interface, conversation_state],
460
- )
 
461
 
462
  def main():
463
  """
464
- Función principal para lanzar la aplicación Gradio.
465
- Maneja si se está ejecutando en Hugging Face Spaces o localmente.
466
  """
467
- import click
468
-
469
- @click.command()
470
- @click.option("--port", "-p", default=None, type=int, help="Puerto para ejecutar la aplicación")
471
- @click.option("--host", "-H", default=None, help="Host para ejecutar la aplicación")
472
- @click.option(
473
- "--share",
474
- "-s",
475
- default=False,
476
- is_flag=True,
477
- help="Compartir la aplicación a través de un enlace compartido de Gradio",
478
- )
479
- @click.option("--api", "-a", default=True, is_flag=True, help="Permitir acceso a la API")
480
- def run_app(port, host, share, api):
481
- """
482
- Ejecuta la aplicación Gradio con las opciones proporcionadas.
483
- """
484
- print("Iniciando la aplicación de Chat AI...")
485
- app_chat.queue(api_open=api).launch(
486
- server_name=host,
487
- server_port=port,
488
- share=share,
489
- show_api=api
490
- )
491
-
492
- run_app()
493
 
494
  if __name__ == "__main__":
495
  main()
 
1
+ # app.py
2
 
3
  import subprocess
4
  import sys
5
+ import os
6
+
7
+ def install_requirements(requirements_file="requirements.txt"):
8
+ """
9
+ Instala las dependencias listadas en el archivo requirements.txt.
10
+ Si el archivo no existe, crea uno con las dependencias necesarias.
11
+ """
12
+ # Verificar si el archivo requirements.txt existe
13
+ if not os.path.isfile(requirements_file):
14
+ # Crear el archivo con las dependencias necesarias
15
+ with open(requirements_file, "w") as f:
16
+ f.write("""gradio>=3.0
17
+ numpy>=1.21.0
18
+ soundfile>=0.10.3
19
+ torchaudio>=0.10.0
20
+ cached_path>=0.1.0
21
+ transformers>=4.0.0
22
+ torch>=1.10.0
23
+ num2words>=0.5.10
24
+ click>=8.0.0
25
+ git+https://github.com/jpgallegoar/Spanish-F5.git
26
+ """)
27
+ print(f"Creado archivo {requirements_file} con las dependencias necesarias.")
28
+
29
+ # Instalar las dependencias usando pip
30
+ print("Instalando dependencias desde requirements.txt...")
 
 
 
31
  try:
32
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", requirements_file])
33
+ print("Dependencias instaladas correctamente.")
 
 
 
 
 
34
  except subprocess.CalledProcessError as e:
35
+ print(f"Error al instalar las dependencias: {e}")
36
  sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ def run_chat_ai():
 
 
39
  """
40
+ Ejecuta el script chat_ai.py.
 
 
 
41
  """
42
+ # Verificar si chat_ai.py existe
43
+ if not os.path.isfile("chat_ai.py"):
44
+ print("Error: 'chat_ai.py' no se encuentra en el directorio actual.")
45
+ sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ # Ejecutar chat_ai.py
48
+ print("Ejecutando 'chat_ai.py'...")
49
+ try:
50
+ subprocess.check_call([sys.executable, "chat_ai.py"])
51
+ except subprocess.CalledProcessError as e:
52
+ print(f"Error al ejecutar 'chat_ai.py': {e}")
53
+ sys.exit(1)
54
 
55
  def main():
56
  """
57
+ Función principal que instala las dependencias y ejecuta chat_ai.py.
 
58
  """
59
+ install_requirements()
60
+ run_chat_ai()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  if __name__ == "__main__":
63
  main()