salomonsky commited on
Commit
1cb13bf
·
verified ·
1 Parent(s): a9b4f5e

Upload web_app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. web_app.py +270 -0
web_app.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask
2
+ from tts_utils import TTSUtils
3
+ from inference import InferenceManager
4
+ from huggingface_utils import HuggingFaceUtils
5
+ from flow_bot import FlowBot
6
+ from tunnel_manager import TunnelManager
7
+ from routes import Routes
8
+ from session_manager import SessionManager
9
+ from data_manager import DataManager
10
+ import yaml
11
+ import os
12
+ import webbrowser
13
+ import threading
14
+ import time
15
+ import sys
16
+ from datetime import timedelta
17
+ import logging
18
+ from colorama import init, Fore, Back, Style
19
+
20
+ # Inicializar colorama para Windows
21
+ init()
22
+
23
+ def print_startup_checklist():
24
+ """Muestra el checklist de inicio con colores"""
25
+ print(f"\n{Fore.CYAN}{'='*50}")
26
+ print(f"{Fore.YELLOW}🤖 Iniciando Asistente Virtual...")
27
+ print(f"{Fore.CYAN}{'='*50}{Style.RESET_ALL}\n")
28
+
29
+ # Checklist de Modelos
30
+ print(f"{Fore.MAGENTA}📋 Modelos de IA:{Style.RESET_ALL}")
31
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Principal: {Fore.YELLOW}Gemini 8b 🧠")
32
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Respaldo: {Fore.YELLOW}Mixtral 7b ⚡\n")
33
+
34
+ # Checklist de TTS
35
+ print(f"{Fore.MAGENTA}🎤 Motores TTS:{Style.RESET_ALL}")
36
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}EDGE (Principal)")
37
+ print(f" {Fore.CYAN}└─ Voz: Jorge (MX) 📢")
38
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}EDGE_ES")
39
+ print(f" {Fore.CYAN}└─ Voz: Álvaro (ES) 🌐")
40
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}VITS")
41
+ print(f" {Fore.CYAN}└─ Modelo Local 🔊\n")
42
+
43
+ # Checklist de Modos
44
+ print(f"{Fore.MAGENTA}📋 Modos Disponibles:{Style.RESET_ALL}")
45
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Créditos 💰")
46
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Seguros 🛡️")
47
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Cobranza 💵\n")
48
+
49
+ # Estado del Sistema
50
+ print(f"{Fore.MAGENTA}🔄 Estado del Sistema:{Style.RESET_ALL}")
51
+
52
+ class WebChatbotApp:
53
+ def __init__(self):
54
+ # Mostrar checklist inicial
55
+ print_startup_checklist()
56
+
57
+ self.flask_app = Flask(__name__)
58
+ self.flask_app.config['SECRET_KEY'] = os.urandom(24)
59
+ self.flask_app.config['SESSION_TYPE'] = 'filesystem'
60
+ self.flask_app.config['SESSION_FILE_DIR'] = './flask_session'
61
+ self.flask_app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=2)
62
+ self.tunnel_url = None
63
+
64
+ self.load_config()
65
+ self.init_components()
66
+ self.routes = Routes(self.flask_app, self)
67
+
68
+ # Inicializar DataManager
69
+ self.data_manager = DataManager()
70
+
71
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Aplicación inicializada correctamente{Style.RESET_ALL}")
72
+
73
+ def load_config(self):
74
+ try:
75
+ config_path = os.path.join(os.path.dirname(__file__), 'config.yaml')
76
+ with open(config_path, 'r', encoding='utf-8') as f:
77
+ self.config = yaml.safe_load(f)
78
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Configuración cargada")
79
+ except Exception as e:
80
+ print(f"{Fore.RED}✗ Error cargando config.yaml: {e}{Style.RESET_ALL}")
81
+ self.config = {}
82
+
83
+ def init_components(self):
84
+ try:
85
+ print(f"{Fore.CYAN}⚙️ Iniciando componentes...{Style.RESET_ALL}")
86
+
87
+ elevenlabs_key = self.config.get('ELEVENLABS_API_KEY', '')
88
+ huggingface_token = self.config.get('api_keys', {}).get('HUGGINGFACE_TOKEN', '')
89
+
90
+ self.tts = TTSUtils(
91
+ model_name='EDGE',
92
+ elevenlabs_api_key=elevenlabs_key
93
+ )
94
+ self.inference = InferenceManager(self.config)
95
+ self.hf_utils = HuggingFaceUtils(huggingface_token)
96
+ self.flow_bot = FlowBot()
97
+ self.session_manager = SessionManager()
98
+
99
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Componentes iniciados correctamente{Style.RESET_ALL}")
100
+
101
+ except Exception as e:
102
+ print(f"{Fore.RED}✗ Error iniciando componentes: {e}{Style.RESET_ALL}")
103
+ raise
104
+
105
+ def reinit_components(self):
106
+ try:
107
+ self.load_config()
108
+
109
+ elevenlabs_key = self.config.get('ELEVENLABS_API_KEY', '')
110
+ huggingface_token = self.config.get('api_keys', {}).get('HUGGINGFACE_TOKEN', '')
111
+
112
+ print(f"{Fore.CYAN}⚙️ Reiniciando componentes...{Style.RESET_ALL}")
113
+
114
+ self.tts = TTSUtils(
115
+ model_name='EDGE',
116
+ elevenlabs_api_key=elevenlabs_key
117
+ )
118
+ self.inference = InferenceManager(self.config)
119
+ self.hf_utils = HuggingFaceUtils(huggingface_token)
120
+
121
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Componentes reiniciados correctamente{Style.RESET_ALL}")
122
+
123
+ except Exception as e:
124
+ print(f"{Fore.RED}✗ Error reiniciando componentes: {e}{Style.RESET_ALL}")
125
+ raise
126
+
127
+ def procesar_mensaje(self, mensaje):
128
+ """Procesa un mensaje de texto y retorna la respuesta"""
129
+ try:
130
+ # Obtener el modo actual de la sesión
131
+ session_id = self.session_manager.get_session()
132
+ current_mode = self.session_manager.get_session_data(session_id, 'mode')
133
+
134
+ # Verificar si estamos en proceso de recolección de datos
135
+ if self.data_manager.is_collecting_data():
136
+ respuesta = self.data_manager.handle_data_collection(
137
+ mensaje,
138
+ current_mode,
139
+ self.flow_bot.get_data_collection_steps
140
+ )
141
+ if respuesta:
142
+ return respuesta
143
+
144
+ # Obtener contexto del flow_bot usando el modo actual
145
+ contexto = self.flow_bot.get_context(current_mode, mensaje)
146
+
147
+ # Obtener respuesta usando el inference manager
148
+ respuesta = self.inference.get_response(
149
+ prompt=mensaje,
150
+ context=contexto
151
+ )
152
+
153
+ # Verificar que la respuesta no sea un mensaje de error o predeterminado
154
+ mensajes_error = [
155
+ "No se proporcionó un mensaje",
156
+ "Lo siento, hubo un error",
157
+ "Error de autenticación",
158
+ "El servicio está ocupado",
159
+ "No se pudo generar una respuesta coherente",
160
+ "¡Hola! Soy tu asistente virtual"
161
+ ]
162
+
163
+ if not respuesta or any(msg in respuesta for msg in mensajes_error):
164
+ print("Respuesta no válida del modelo, usando contexto directo")
165
+ respuesta = self.flow_bot.get_success_message(current_mode)
166
+ # Iniciar recolección de datos si es necesario
167
+ if "nombre" in respuesta.lower():
168
+ self.data_manager.start_data_collection()
169
+
170
+ return respuesta
171
+
172
+ except Exception as e:
173
+ print(f"Error procesando mensaje: {e}")
174
+ return self.flow_bot.get_negative_response(current_mode)
175
+
176
+ def procesar_audio(self, audio_path):
177
+ """Procesa un archivo de audio y retorna mensaje y audio de respuesta"""
178
+ try:
179
+ # Transcribir audio a texto
180
+ mensaje = self.inference.transcribe_audio(audio_path)
181
+ print(f"Audio transcrito: {mensaje}")
182
+
183
+ # Obtener respuesta
184
+ respuesta = self.procesar_mensaje(mensaje)
185
+ print(f"Respuesta generada: {respuesta}")
186
+
187
+ # Convertir respuesta a audio
188
+ audio_path = self.tts.text_to_speech(respuesta)
189
+ return mensaje, audio_path
190
+
191
+ except Exception as e:
192
+ print(f"Error procesando audio: {e}")
193
+ return "Error al procesar el audio", None
194
+
195
+ def open_browser(self, url):
196
+ time.sleep(2)
197
+ webbrowser.open(url)
198
+
199
+ def run(self, host='127.0.0.1', port=5000, debug=False, use_tunnel=True):
200
+ try:
201
+ if use_tunnel:
202
+ try:
203
+ tunnel_manager = TunnelManager()
204
+ # Primero intentar obtener un túnel activo
205
+ self.tunnel_url = tunnel_manager.get_active_tunnel()
206
+
207
+ if not self.tunnel_url:
208
+ # Si no hay túnel activo, limpiar y crear uno nuevo
209
+ tunnel_manager.setup_ngrok()
210
+ tunnel_manager.cleanup()
211
+ self.tunnel_url = tunnel_manager.start(port)
212
+
213
+ if self.tunnel_url:
214
+ print(f"{Fore.GREEN}✓ {Fore.WHITE}Túnel iniciado en: {Fore.CYAN}{self.tunnel_url}{Style.RESET_ALL}")
215
+ threading.Thread(target=self.open_browser, args=(self.tunnel_url,)).start()
216
+ else:
217
+ print(f"{Fore.YELLOW}⚠️ No se pudo iniciar el túnel, continuando en modo local{Style.RESET_ALL}")
218
+ except Exception as tunnel_error:
219
+ print(f"{Fore.YELLOW}⚠️ Continuando en modo local{Style.RESET_ALL}")
220
+
221
+ print(f"\n{Fore.GREEN}✓ {Fore.WHITE}Servidor iniciado en: {Fore.CYAN}http://{host}:{port}{Style.RESET_ALL}\n")
222
+ self.flask_app.run(host=host, port=port, debug=debug, threaded=True)
223
+
224
+ except Exception as e:
225
+ print(f"{Fore.RED}✗ Error iniciando el servidor: {e}{Style.RESET_ALL}")
226
+ raise
227
+
228
+ @property
229
+ def app(self):
230
+ return self.flask_app
231
+
232
+ if __name__ == '__main__':
233
+ import os
234
+ import psutil
235
+ import socket
236
+
237
+ def is_port_in_use(port):
238
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
239
+ return s.connect_ex(('localhost', port)) == 0
240
+
241
+ def kill_process_on_port(port):
242
+ for proc in psutil.process_iter(['pid', 'name', 'connections']):
243
+ try:
244
+ for conn in proc.connections():
245
+ if conn.laddr.port == port:
246
+ print(f"Terminando proceso anterior en puerto {port}")
247
+ proc.terminate()
248
+ proc.wait()
249
+ return True
250
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
251
+ pass
252
+ return False
253
+
254
+ try:
255
+ port = 5000
256
+ if is_port_in_use(port):
257
+ print(f"Puerto {port} en uso. Intentando liberar...")
258
+ if kill_process_on_port(port):
259
+ print("Proceso anterior terminado")
260
+ else:
261
+ print(f"No se pudo liberar el puerto {port}. Por favor, cierre la aplicación anterior manualmente.")
262
+ exit(1)
263
+
264
+ print("Iniciando nueva instancia de la aplicación...")
265
+ app = WebChatbotApp()
266
+ app.run()
267
+
268
+ except Exception as e:
269
+ print(f"Error al iniciar la aplicación: {e}")
270
+ exit(1)