BATUTO-ART commited on
Commit
e72d384
·
verified ·
1 Parent(s): 247e1f7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -666
app.py CHANGED
@@ -1,702 +1,170 @@
1
- import gradio as gr
2
- import asyncio
3
- import json
4
- from typing import List, Dict, Any, Optional, Tuple, Generator
5
- from datetime import datetime
6
- from enum import Enum
7
- import hashlib
8
- import logging
9
- from dataclasses import dataclass
10
- from typing import Literal
11
 
12
- # ==================== CONFIGURACIÓN DE LOGGING ESTRUCTURADO ====================
13
- logging.basicConfig(
14
- level=logging.INFO,
15
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
16
- handlers=[
17
- logging.FileHandler('chat_interface.log'),
18
- logging.StreamHandler()
19
- ]
20
- )
21
- logger = logging.getLogger(__name__)
22
 
23
- # ==================== TIPADO Y ESTRUCTURAS DE DATOS ====================
24
- @dataclass
25
- class ChatMessage:
26
- """Estructura type-safe para mensajes de chat"""
27
- role: Literal["user", "assistant", "system"]
28
- content: str
29
- timestamp: str
30
- message_id: str
31
-
32
- def to_dict(self) -> Dict[str, Any]:
33
- return {
34
- "role": self.role,
35
- "content": self.content,
36
- "timestamp": self.timestamp,
37
- "id": self.message_id
38
- }
39
 
40
- class IntentType(Enum):
41
- """Tipos de intención detectados"""
42
- QUERY = "consulta"
43
- CODE_GENERATION = "generacion_codigo"
44
- SYSTEM_DIAGNOSTIC = "diagnostico_sistema"
45
- OPTIMIZATION = "optimizacion"
46
- UNKNOWN = "desconocido"
 
 
 
 
 
 
 
 
 
47
 
48
- @dataclass
49
- class IntentAnalysis:
50
- """Resultado del análisis de intención"""
51
- intent: IntentType
52
- confidence: float
53
- entities: Dict[str, Any]
54
- requires_streaming: bool
55
 
56
- # ==================== SERVICIO DE ANÁLISIS DE INTENCIÓN ====================
57
- class IntentAnalyzer:
58
- """Servicio para análisis de intención con validación robusta"""
59
-
60
- @staticmethod
61
- def analyze_intent_detailed(
62
- message: str,
63
- history: List[Dict[str, Any]]
64
- ) -> Tuple[IntentType, Dict[str, Any]]:
65
- """
66
- Analiza la intención del mensaje con validación de inputs.
67
-
68
- Args:
69
- message: Mensaje del usuario (validado y sanitizado)
70
- history: Historial de conversación en formato Gradio 4.x
71
-
72
- Returns:
73
- Tuple[IntentType, Dict]: Tipo de intención y metadatos
74
-
75
- Raises:
76
- ValueError: Si el mensaje está vacío o mal formado
77
- """
78
- # Validación de inputs
79
- if not isinstance(message, str):
80
- raise TypeError(f"Mensaje debe ser string, recibido: {type(message)}")
81
-
82
- if not message.strip():
83
- raise ValueError("Mensaje no puede estar vacío")
84
-
85
- # Sanitización básica
86
- sanitized_message = message.strip()[:2000] # Limitación de longitud
87
-
88
- # Patrones de detección de intención
89
- message_lower = sanitized_message.lower()
90
-
91
- # Diccionario de palabras clave para cada intención
92
- intent_patterns = {
93
- IntentType.CODE_GENERATION: [
94
- "código", "programa", "función", "clase", "implementa",
95
- "desarrolla", "escribe un", "crea un", "genera código",
96
- "python", "javascript", "java", "typescript", "html", "css"
97
- ],
98
- IntentType.SYSTEM_DIAGNOSTIC: [
99
- "error", "falla", "problema", "debug", "depurar",
100
- "solucionar", "arreglar", "no funciona", "bug",
101
- "excepción", "traceback", "stack trace"
102
- ],
103
- IntentType.OPTIMIZATION: [
104
- "optimizar", "mejorar", "rendimiento", "eficiencia",
105
- "velocidad", "lento", "bottleneck", "cuello de botella",
106
- "escalar", "scaling", "performance", "memoria", "cpu"
107
- ],
108
- IntentType.QUERY: [
109
- "qué", "cómo", "cuándo", "dónde", "por qué",
110
- "explica", "describe", "información", "ayuda",
111
- "tutorial", "guía", "ejemplo"
112
- ]
113
- }
114
-
115
- # Análisis de frecuencia y confianza
116
- intent_scores = {intent: 0.0 for intent in IntentType}
117
-
118
- for intent, patterns in intent_patterns.items():
119
- for pattern in patterns:
120
- if pattern in message_lower:
121
- intent_scores[intent] += 1.0
122
-
123
- # Ponderación por longitud de palabra clave
124
- word_count = len(sanitized_message.split())
125
- for intent in intent_scores:
126
- if intent_scores[intent] > 0:
127
- intent_scores[intent] = min(1.0, intent_scores[intent] / (word_count * 0.5))
128
-
129
- # Determinación de intención principal
130
- if max(intent_scores.values()) > 0:
131
- main_intent = max(intent_scores, key=intent_scores.get)
132
- confidence = intent_scores[main_intent]
133
- else:
134
- main_intent = IntentType.UNKNOWN
135
- confidence = 0.0
136
-
137
- # Metadatos adicionales
138
- metadata = {
139
- "confidence": round(confidence, 2),
140
- "message_length": len(sanitized_message),
141
- "word_count": word_count,
142
- "has_code_snippet": "```" in sanitized_message,
143
- "timestamp": datetime.now().isoformat(),
144
- "intent_scores": {k.name: v for k, v in intent_scores.items()}
145
- }
146
-
147
- logger.info(f"Intención detectada: {main_intent.value} (confianza: {confidence:.2f})")
148
-
149
- return main_intent, metadata
150
 
151
- # ==================== SERVICIO DE GENERACIÓN DE RESPUESTAS ====================
152
- class ResponseGenerator:
153
- """Servicio para generación de respuestas con streaming"""
154
-
155
- def __init__(self):
156
- self.intent_analyzer = IntentAnalyzer()
157
- self.response_templates = self._load_templates()
158
-
159
- def _load_templates(self) -> Dict[IntentType, str]:
160
- """Carga plantillas de respuesta según intención"""
161
- return {
162
- IntentType.CODE_GENERATION: """
163
- **🔧 Generando solución de código...**
164
-
165
- He analizado tu solicitud y procedo a generar una implementación robusta y lista para producción.
166
-
167
- **Consideraciones técnicas aplicadas:**
168
- • Type hints completos para mypy
169
- • Logging estructurado con niveles apropiados
170
- • Manejo de errores con excepciones específicas
171
- • Principios SOLID y Clean Code
172
- • Validación de inputs y sanitización
173
-
174
- **Código generado:**
175
- ```python
176
- # Implementación específica basada en tu solicitud
177
- """
178
- ,
179
- IntentType.SYSTEM_DIAGNOSTIC: """
180
- **🔍 Analizando diagnóstico del sistema...**
181
-
182
- Procedo a analizar el problema reportado con metodología sistemática:
183
-
184
- 1. **Identificación del root cause**
185
- 2. **Análisis de logs y métricas**
186
- 3. **Propuesta de solución escalable**
187
- 4. **Prevención de recurrencia**
188
-
189
- """
190
- ,
191
- IntentType.OPTIMIZATION: """
192
- **⚡ Iniciando proceso de optimización...**
193
-
194
- Optimización aplicada con enfoque en:
195
- • Complejidad algorítmica (Big O)
196
- • Uso eficiente de memoria
197
- • Paralelización y concurrencia
198
- • Caching estratégico
199
- • Minimización de I/O
200
-
201
- """
202
- ,
203
- IntentType.QUERY: """
204
- **📚 Proporcionando respuesta detallada...**
205
-
206
- Basado en tu consulta, te proporciono información completa y verificada:
207
-
208
- """
209
- ,
210
- IntentType.UNKNOWN: """
211
- **🤖 Procesando tu solicitud...**
212
-
213
- He recibido tu mensaje. Para brindarte la mejor asistencia:
214
-
215
- • ¿Podrías especificar si necesitas generación de código?
216
- • ¿O prefieres una explicación técnica detallada?
217
- • ¿Estás enfrentando un problema específico del sistema?
218
-
219
- Estoy listo para ayudarte en cualquiera de estas áreas.
220
- """
221
- }
222
-
223
- async def generate_streaming_response(
224
- self,
225
- message: str,
226
- history: List[Dict[str, Any]]
227
- ) -> Generator[Tuple[List[Dict[str, Any]], str], None, None]:
228
- """
229
- Genera respuesta con streaming en tiempo real.
230
-
231
- Args:
232
- message: Mensaje del usuario
233
- history: Historial de conversación
234
-
235
- Yields:
236
- Tupla[List[Dict], str]: Historial actualizado y texto de modo
237
- """
238
- try:
239
- # 1. Análisis de intención
240
- intent, metadata = self.intent_analyzer.analyze_intent_detailed(message, history)
241
- mode_text = f"**Modo activo**: {intent.value.replace('_', ' ').title()}"
242
-
243
- # 2. Crear historial temporal para streaming
244
- temp_history = history.copy()
245
-
246
- # 3. Añadir mensaje del usuario al historial
247
- user_message = {
248
- "role": "user",
249
- "content": message,
250
- "timestamp": datetime.now().isoformat()
251
- }
252
- temp_history.append(user_message)
253
-
254
- # 4. Añadir placeholder de asistente
255
- assistant_placeholder = {
256
- "role": "assistant",
257
- "content": "",
258
- "timestamp": datetime.now().isoformat()
259
- }
260
- temp_history.append(assistant_placeholder)
261
-
262
- yield temp_history, mode_text
263
-
264
- # 5. Generar respuesta con streaming simulado
265
- template = self.response_templates.get(intent, self.response_templates[IntentType.UNKNOWN])
266
-
267
- # Streaming chunk por chunk
268
- chunks = self._split_into_chunks(template)
269
- accumulated_response = ""
270
-
271
- for chunk in chunks:
272
- await asyncio.sleep(0.05) # Simular procesamiento
273
- accumulated_response += chunk
274
-
275
- # Actualizar contenido del asistente en el historial
276
- temp_history[-1]["content"] = accumulated_response
277
- yield temp_history, mode_text
278
-
279
- # 6. Añadir sección específica basada en el mensaje
280
- specific_response = f"\n\n**📝 Detalles específicos para tu solicitud:**\n\n"
281
- specific_response += f"• **Mensaje analizado:** `{message[:100]}{'...' if len(message) > 100 else ''}`\n"
282
- specific_response += f"• **Confianza de intención:** {metadata['confidence'] * 100:.1f}%\n"
283
- specific_response += f"• **Longitud del mensaje:** {metadata['message_length']} caracteres\n"
284
-
285
- chunks_specific = self._split_into_chunks(specific_response)
286
- for chunk in chunks_specific:
287
- await asyncio.sleep(0.03)
288
- accumulated_response += chunk
289
- temp_history[-1]["content"] = accumulated_response
290
- yield temp_history, mode_text
291
-
292
- # 7. Añadir marca de finalización
293
- completion_marker = "\n\n---\n*Respuesta generada con SISTEMA_PROTOCOLO_POTENCIACION_ACTIVO v2.0*"
294
- temp_history[-1]["content"] = accumulated_response + completion_marker
295
-
296
- yield temp_history, mode_text
297
-
298
- except Exception as e:
299
- logger.error(f"Error en generación de respuesta: {str(e)}", exc_info=True)
300
-
301
- # Respuesta de error controlada
302
- error_history = history.copy()
303
- error_history.append({
304
- "role": "user",
305
- "content": message,
306
- "timestamp": datetime.now().isoformat()
307
- })
308
- error_history.append({
309
- "role": "assistant",
310
- "content": f"**⚠️ Error en el procesamiento:**\n\n{str(e)}\n\nPor favor, intenta nuevamente o reformula tu solicitud.",
311
- "timestamp": datetime.now().isoformat()
312
- })
313
-
314
- yield error_history, "**Modo activo**: Manejo de errores"
315
-
316
- def _split_into_chunks(self, text: str, chunk_size: int = 20) -> List[str]:
317
- """Divide texto en chunks para streaming"""
318
- words = text.split()
319
- chunks = []
320
- current_chunk = []
321
- current_length = 0
322
-
323
- for word in words:
324
- if current_length + len(word) + 1 > chunk_size and current_chunk:
325
- chunks.append(" ".join(current_chunk) + " ")
326
- current_chunk = [word]
327
- current_length = len(word)
328
- else:
329
- current_chunk.append(word)
330
- current_length += len(word) + 1
331
-
332
- if current_chunk:
333
- chunks.append(" ".join(current_chunk))
334
-
335
- return chunks
336
 
337
- # ==================== INTERFAZ GRADIO 4.x COMPATIBLE ====================
338
- def create_advanced_interface():
339
- """
340
- Crea interfaz avanzada de chat compatible con Gradio 4.x.
341
- Implementa formato correcto de mensajes: {"role": "rol", "content": "texto"}
342
- """
343
-
344
- # Instanciar servicios
345
- intent_analyzer = IntentAnalyzer()
346
- response_generator = ResponseGenerator()
347
-
348
- # Cache para historiales de sesión
349
- session_histories = {}
350
-
351
- def get_session_history(session_id: str) -> List[Dict[str, Any]]:
352
- """Obtiene o crea historial para sesión"""
353
- if session_id not in session_histories:
354
- # Mensaje inicial del sistema
355
- session_histories[session_id] = [{
356
- "role": "system",
357
- "content": "Eres un asistente especializado en ingeniería de software, DevOps y arquitectura de sistemas distribuidos. Proporcionas soluciones técnicas precisas y listas para producción.",
358
- "timestamp": datetime.now().isoformat()
359
- }]
360
- return session_histories[session_id]
361
-
362
- def generate_session_id() -> str:
363
- """Genera ID único de sesión"""
364
- timestamp = datetime.now().isoformat()
365
- hash_obj = hashlib.md5(timestamp.encode())
366
- return hash_obj.hexdigest()[:12]
367
-
368
- # ==================== FUNCIONES DE INTERACCIÓN ====================
369
- def process_message(
370
- message: str,
371
- history: List[Dict[str, Any]],
372
- session_id: str
373
- ) -> Tuple[str, List[Dict[str, Any]], str]:
374
- """
375
- Procesa mensaje del usuario - FORMATO GRADIO 4.x CORRECTO
376
-
377
- Args:
378
- message: Mensaje del usuario
379
- history: Historial en formato {"role": "rol", "content": "texto"}
380
- session_id: ID de sesión para persistencia
381
-
382
- Returns:
383
- Tuple[str, List[Dict], str]: Mensaje vacío, historial actualizado, texto de modo
384
- """
385
- # Validación robusta
386
- if not message or not isinstance(message, str):
387
- return "", history, "**Modo**: Error - Mensaje inválido"
388
-
389
- sanitized_message = message.strip()
390
- if not sanitized_message:
391
- return "", history, "**Modo**: Esperando entrada válida..."
392
-
393
- # Obtener historial de sesión
394
- session_history = get_session_history(session_id)
395
-
396
- # Crear mensaje de usuario en formato Gradio 4.x
397
- user_message = {
398
- "role": "user",
399
- "content": sanitized_message,
400
- "timestamp": datetime.now().isoformat()
401
- }
402
-
403
- # Actualizar historiales
404
- new_history = history + [user_message] if history else [user_message]
405
- session_history.append(user_message)
406
-
407
- try:
408
- # Análisis de intención
409
- intent, metadata = intent_analyzer.analyze_intent_detailed(
410
- sanitized_message,
411
- new_history
412
- )
413
-
414
- mode_text = (
415
- f"**Modo activo**: {intent.value.replace('_', ' ').title()}\n"
416
- f"**Confianza**: {metadata['confidence'] * 100:.1f}%\n"
417
- f"**Tokens**: {metadata['word_count']}"
418
- )
419
-
420
- except Exception as e:
421
- logger.warning(f"Error en análisis de intención: {e}")
422
- mode_text = "**Modo activo**: Procesamiento directo"
423
-
424
- # Limpiar input
425
- return "", new_history, mode_text
426
 
427
- async def generate_response_stream(
428
- message: str,
429
- history: List[Dict[str, Any]],
430
- session_id: str
431
- ):
432
- """
433
- Genera respuesta con streaming - FORMATO GRADIO 4.x CORRECTO
434
-
435
- Args:
436
- message: Mensaje del usuario
437
- history: Historial en formato correcto
438
- session_id: ID de sesión
439
-
440
- Yields:
441
- Historial actualizado y texto de modo
442
- """
443
- async for updated_history, mode_text in response_generator.generate_streaming_response(
444
- message,
445
- history
446
- ):
447
- # Actualizar historial de sesión
448
- session_histories[session_id] = updated_history.copy()
449
- yield updated_history, mode_text
450
 
451
- # ==================== INTERFAZ GRADIO ====================
452
  with gr.Blocks(
453
- title="🧠 SISTEMA_PROTOCOLO_POTENCIACION_ACTIVO v2.0",
454
- theme=gr.themes.Soft(),
455
- css="""
456
- .gradio-container {
457
- max-width: 1200px !important;
458
- margin: 0 auto !important;
459
- }
460
- .chatbot {
461
- height: 600px !important;
462
- overflow-y: auto !important;
463
- border: 1px solid #e0e0e0 !important;
464
- border-radius: 10px !important;
465
- padding: 20px !important;
466
- }
467
- .status-panel {
468
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
469
- color: white !important;
470
- padding: 15px !important;
471
- border-radius: 10px !important;
472
- margin-bottom: 20px !important;
473
- }
474
- """
475
  ) as interface:
476
 
477
- # Estado de sesión
478
- session_state = gr.State(value=generate_session_id())
479
-
480
  gr.Markdown("""
481
- # 🧠 SISTEMA_PROTOCOLO_POTENCIACION_ACTIVO v2.0
482
- ### *Asistente de IA Senior en Ingeniería de Software y DevOps*
 
483
 
484
- ---
 
 
 
 
485
 
486
- **Especialidades:**
487
- Arquitectura de Sistemas Distribuidos • Microservicios • DevOps • Cloud Security
488
- • Optimización de Rendimiento • Code Review Profesional • Soluciones Production-Ready
489
 
490
- **Modo actual:** `OPTIMIZACION_ASCENDENTE_EXCLUSIVA`
491
- """)
 
 
 
 
492
 
 
493
  with gr.Row():
494
- with gr.Column(scale=3):
495
- # Chatbot con formato correcto para Gradio 4.x
496
- chatbot = gr.Chatbot(
497
- label="Conversación",
498
- height=600,
499
- show_label=False,
500
- bubble_full_width=False,
501
- avatar_images=(
502
- "https://cdn-icons-png.flaticon.com/512/3135/3135715.png", # User
503
- "https://cdn-icons-png.flaticon.com/512/4712/4712035.png" # Assistant
504
- ),
505
- sanitize_html=False,
506
- show_copy_button=True
507
- )
508
-
509
- # Panel de estado
510
- status_display = gr.Markdown(
511
- "**Modo**: Inicializando sistema...",
512
- elem_classes="status-panel"
513
- )
514
-
515
- # Input con validación
516
- msg_input = gr.Textbox(
517
- label="Escribe tu mensaje técnico",
518
- placeholder="Ejemplo: 'Optimiza este microservicio Python para alta concurrencia...'",
519
- lines=3,
520
- max_lines=6,
521
- show_label=False
522
- )
523
-
524
- with gr.Row():
525
- submit_btn = gr.Button(
526
- "🚀 Enviar Consulta Técnica",
527
- variant="primary",
528
- scale=2
529
- )
530
- clear_btn = gr.Button(
531
- "🧹 Limpiar Chat",
532
- variant="secondary",
533
- scale=1
534
- )
535
-
536
- with gr.Column(scale=1):
537
- # Panel de información técnica
538
- gr.Markdown("### 📊 Métricas del Sistema")
539
-
540
- session_id_display = gr.Textbox(
541
- label="ID de Sesión",
542
- value=session_state.value,
543
- interactive=False
544
- )
545
-
546
- message_count = gr.Number(
547
- label="Mensajes en sesión",
548
- value=0,
549
- interactive=False
550
- )
551
-
552
- gr.Markdown("""
553
- ### ⚙️ Configuración
554
-
555
- - **Formato:** Gradio 4.x Compatible
556
- - **Streaming:** Activado
557
- - **Persistencia:** Por sesión
558
- - **Logging:** Estructurado
559
- - **Seguridad:** Input Sanitization
560
- """)
561
-
562
- # ==================== EVENT HANDLERS ====================
563
 
564
- def update_message_count(history):
565
- """Actualiza contador de mensajes"""
566
- user_messages = [m for m in history if m.get("role") == "user"]
567
- return len(user_messages)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
 
569
- # Submit handler
570
- submit_event = msg_input.submit(
571
- fn=process_message,
572
- inputs=[msg_input, chatbot, session_state],
573
- outputs=[msg_input, chatbot, status_display],
574
- queue=True
575
- ).then(
576
- fn=update_message_count,
577
- inputs=[chatbot],
578
- outputs=[message_count]
579
- ).then(
580
- fn=generate_response_stream,
581
- inputs=[msg_input, chatbot, session_state],
582
- outputs=[chatbot, status_display]
583
- )
584
 
585
- # Button click handler
586
  submit_btn.click(
587
- fn=process_message,
588
- inputs=[msg_input, chatbot, session_state],
589
- outputs=[msg_input, chatbot, status_display],
590
- queue=True
591
- ).then(
592
- fn=update_message_count,
593
- inputs=[chatbot],
594
- outputs=[message_count]
595
- ).then(
596
- fn=generate_response_stream,
597
- inputs=[msg_input, chatbot, session_state],
598
- outputs=[chatbot, status_display]
599
  )
600
 
601
- # Clear handler
602
- def clear_chat():
603
- """Limpia el chat y genera nueva sesión"""
604
- new_session_id = generate_session_id()
605
- initial_message = [{
606
- "role": "system",
607
- "content": "Sesión reiniciada. Listo para asistencia técnica.",
608
- "timestamp": datetime.now().isoformat()
609
- }]
610
- return (
611
- initial_message, # chatbot
612
- "**Modo**: Sistema reiniciado - Esperando consulta técnica", # status
613
- new_session_id, # session_state
614
- 0, # message_count
615
- new_session_id # session_id_display
616
- )
617
-
618
- clear_btn.click(
619
- fn=clear_chat,
620
- outputs=[chatbot, status_display, session_state, message_count, session_id_display]
621
  )
622
 
623
- # ==================== CONFIGURACIÓN ADICIONAL ====================
624
-
625
- # Ejemplos de consultas
626
- gr.Examples(
627
- examples=[
628
- ["Optimiza este endpoint REST para manejar 10K RPS con Python async/await"],
629
- ["Diseña una arquitectura de microservicios con auto-scaling y circuit breaker"],
630
- ["Implementa un sistema de logging distribuido con OpenTelemetry y Grafana"],
631
- ["Genera un Dockerfile production-ready para aplicación Python con seguridad hardening"],
632
- ["Crea un sistema de CI/CD con GitHub Actions para despliegue blue-green en Kubernetes"]
633
- ],
634
- inputs=msg_input,
635
- label="📋 Ejemplos de consultas técnicas"
636
  )
637
 
638
  # Footer
639
  gr.Markdown("""
640
  ---
641
-
642
- **🔒 Seguridad activa:** Todas las consultas son procesadas con sanitización de inputs y validación de tipos.
643
- **📈 Logging:** Todas las interacciones son registradas para mejora continua del sistema.
644
- **⚡ Performance:** Respuestas optimizadas con streaming en tiempo real.
645
-
646
- *Sistema compatible con Gradio 4.x - Formato de mensajes: `{"role": "rol", "content": "texto"}`*
647
  """)
648
 
649
  return interface
650
 
651
- # ==================== PUNTO DE ENTRADA ====================
652
  if __name__ == "__main__":
653
- # Validación de entorno
654
- try:
655
- import gradio as gr
656
- GRADIO_VERSION = gr.__version__
657
- logger.info(f"Gradio versión detectada: {GRADIO_VERSION}")
658
-
659
- if not GRADIO_VERSION.startswith("4."):
660
- logger.warning(
661
- f"Esta interfaz está optimizada para Gradio 4.x. "
662
- f"Versión actual: {GRADIO_VERSION}. "
663
- f"Puede haber incompatibilidades."
664
- )
665
-
666
- # Crear e iniciar interfaz
667
- interface = create_advanced_interface()
668
-
669
- # Configuración para Hugging Face Spaces
670
- interface.queue(
671
- max_size=20,
672
- default_concurrency_limit=10,
673
- api_open=True
674
- ).launch(
675
- server_name="0.0.0.0" if "SPACE_ID" in os.environ else None,
676
- server_port=7860,
677
- share=False,
678
- debug=False,
679
- show_error=True,
680
- favicon_path="https://cdn-icons-png.flaticon.com/512/4712/4712035.png"
681
- )
682
-
683
- except Exception as e:
684
- logger.critical(f"Error crítico al iniciar la aplicación: {str(e)}", exc_info=True)
685
-
686
- # Interfaz de fallback mínima
687
- with gr.Blocks() as fallback:
688
- gr.Markdown(f"""
689
- # ⚠️ Error en la inicialización del sistema
690
-
691
- **Detalles técnicos:**
692
- ```python
693
- {str(e)}
694
- ```
695
-
696
- Por favor, verifica:
697
- 1. Dependencias de Gradio 4.x instaladas
698
- 2. Formato de mensajes correcto
699
- 3. Logs del sistema para diagnóstico
700
- """)
701
-
702
- fallback.launch()
 
1
+ """
2
+ BATUTO X ENTERPRISE - VERSIÓN COMPATIBLE HUGGING FACE SPACES
3
+ """
4
+ import os
5
+ import sys
6
+ import subprocess
7
+ import time
 
 
 
8
 
9
+ # ==================== VERIFICACIÓN INICIAL OBLIGATORIA ====================
10
+ print("="*70)
11
+ print("🚀 VERIFICANDO ENTORNO DE HUGGING FACE SPACES")
12
+ print("="*70)
 
 
 
 
 
 
13
 
14
+ # 1. Verificar Python
15
+ print(f"Python: {sys.version}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ # 2. Verificar/Instalar Gradio 4.x
18
+ try:
19
+ import gradio as gr
20
+ if not gr.__version__.startswith("4."):
21
+ print(f"⚠️ Versión incorrecta: {gr.__version__}")
22
+ print("📦 Instalando Gradio 4.28.2...")
23
+ subprocess.run([sys.executable, "-m", "pip", "install", "gradio==4.28.2", "--force-reinstall"],
24
+ check=True)
25
+ # Recargar módulo
26
+ import importlib
27
+ importlib.reload(gr)
28
+ print(f"✅ Gradio {gr.__version__} correcto")
29
+ except ImportError:
30
+ print("📦 Instalando Gradio 4.28.2...")
31
+ subprocess.run([sys.executable, "-m", "pip", "install", "gradio==4.28.2"], check=True)
32
+ import gradio as gr
33
 
34
+ # 3. Configurar variables de entorno desde Secrets de Hugging Face
35
+ # NO USAR variables en requirements.txt - usar Secrets del Space
36
+ API_KEY = os.environ.get("SAMBANOVA_API_KEY_2", "")
37
+ REVE_KEY = os.environ.get("REVE_API_KEY", "")
 
 
 
38
 
39
+ print(f"🔑 SAMBANOVA_API_KEY: {'✅' if API_KEY else '❌ No configurada'}")
40
+ print(f"🎨 REVE_API_KEY: {'✅' if REVE_KEY else '❌ No configurada'}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ # 4. Resto de imports DESPUÉS de verificar Gradio
43
+ from datetime import datetime
44
+ from pathlib import Path
45
+ import json
46
+ import asyncio
47
+ from PIL import Image
48
+ from typing import Dict, List, Tuple, Any, Generator
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ # ==================== CONFIGURACIÓN ====================
51
+ OUTPUT_DIR = Path("batuto_generations")
52
+ OUTPUT_DIR.mkdir(exist_ok=True)
53
+
54
+ # ==================== MÓDULOS SIMULADOS (si no existen) ====================
55
+ try:
56
+ from cognitive_kernel import IntentType, analyze_intent_detailed
57
+ MODULES_LOADED = True
58
+ except ImportError:
59
+ MODULES_LOADED = False
60
+ print("⚠️ Módulos personalizados no disponibles - usando simulación")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
+ class IntentType:
63
+ IMAGE = "image"
64
+ CODE = "code"
65
+ GENERAL = "general"
66
+
67
+ # ==================== APLICACIÓN PRINCIPAL ====================
68
+ def create_simple_interface():
69
+ """Interfaz simple y compatible con Hugging Face Spaces"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
 
71
  with gr.Blocks(
72
+ title="BATUTO X - Hugging Face Spaces",
73
+ theme=gr.themes.Soft()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  ) as interface:
75
 
76
+ # Header
 
 
77
  gr.Markdown("""
78
+ # 🤖 BATUTO X Enterprise
79
+ ### Versión compatible con Hugging Face Spaces
80
+ """)
81
 
82
+ # Chatbot
83
+ chatbot = gr.Chatbot(
84
+ label="Conversación",
85
+ height=500
86
+ )
87
 
88
+ # Estado
89
+ status = gr.Markdown("**Estado**: Listo")
 
90
 
91
+ # Input
92
+ msg = gr.Textbox(
93
+ label="Mensaje",
94
+ placeholder="Escribe tu mensaje aquí...",
95
+ lines=3
96
+ )
97
 
98
+ # Botones
99
  with gr.Row():
100
+ submit_btn = gr.Button("Enviar", variant="primary")
101
+ clear_btn = gr.Button("Limpiar", variant="secondary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
+ # Funciones
104
+ def respond(message, history):
105
+ if not message.strip():
106
+ return history, "Escribe algo..."
107
+
108
+ # Respuesta simulada
109
+ response = f"**Simulación**: Recibí: '{message}'"
110
+
111
+ # Formato CORRECTO para Gradio 4.x
112
+ if not history:
113
+ history = []
114
+
115
+ # Agregar mensaje usuario
116
+ history.append({"role": "user", "content": message})
117
+ # Agregar respuesta asistente
118
+ history.append({"role": "assistant", "content": response})
119
+
120
+ return history, f"Respondido a: {message[:20]}..."
121
 
122
+ def clear():
123
+ return [], "Chat limpiado"
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ # Eventos
126
  submit_btn.click(
127
+ fn=respond,
128
+ inputs=[msg, chatbot],
129
+ outputs=[chatbot, status]
 
 
 
 
 
 
 
 
 
130
  )
131
 
132
+ msg.submit(
133
+ fn=respond,
134
+ inputs=[msg, chatbot],
135
+ outputs=[chatbot, status]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  )
137
 
138
+ clear_btn.click(
139
+ fn=clear,
140
+ outputs=[chatbot, status]
 
 
 
 
 
 
 
 
 
 
141
  )
142
 
143
  # Footer
144
  gr.Markdown("""
145
  ---
146
+ **Nota**: Esta es una versión simplificada para debugging.
147
+ Para la versión completa, configura las variables de entorno:
148
+ 1. `SAMBANOVA_API_KEY_2` en Settings > Repository secrets
149
+ 2. `REVE_API_KEY` en Settings > Repository secrets
 
 
150
  """)
151
 
152
  return interface
153
 
154
+ # ==================== EJECUCIÓN ====================
155
  if __name__ == "__main__":
156
+ print("\n" + "="*70)
157
+ print("🚀 INICIANDO APLICACIÓN EN HUGGING FACE SPACES")
158
+ print("="*70)
159
+
160
+ # Crear interfaz
161
+ app = create_simple_interface()
162
+
163
+ # Configuración específica para Spaces
164
+ app.launch(
165
+ server_name="0.0.0.0", # Obligatorio para Spaces
166
+ server_port=7860, # Puerto estándar de Spaces
167
+ share=False,
168
+ debug=False,
169
+ show_error=True
170
+ )