BATUTO-ART commited on
Commit
8af787c
·
verified ·
1 Parent(s): 63c8742

Delate app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -535
app.py DELETED
@@ -1,535 +0,0 @@
1
- """
2
- BATUTO X ENTERPRISE - SISTEMA UNIFICADO
3
- - Orquestación inteligente de modelos
4
- - Generación multimodal
5
- - Interfaz profesional
6
- """
7
- import os
8
- import time
9
- import json
10
- import asyncio
11
- from typing import Dict, List, Tuple, Any, Optional, Generator
12
- from datetime import datetime
13
- from pathlib import Path
14
-
15
- import gradio as gr
16
- from PIL import Image
17
-
18
- # Importar módulos optimizados
19
- from cognitive_kernel import (
20
- IntentType,
21
- analyze_intent_detailed,
22
- select_model_with_context,
23
- record_complete_interaction,
24
- MEMORY,
25
- ORCHESTRATOR
26
- )
27
- from core_llm import (
28
- ENTERPRISE_MODELS,
29
- create_sambanova_client,
30
- stream_response_generator,
31
- SambanovaClient
32
- )
33
- from image_tool_reve import (
34
- generar_imagen_reve,
35
- generar_imagen_con_metadatos,
36
- AsyncReveGenerator
37
- )
38
-
39
- # ===================== CONFIGURACIÓN GLOBAL =====================
40
-
41
- import os
42
-
43
- API_KEY = os.getenv("SAMBANOVA_API_KEY_2")
44
- # Variable de estado en lugar de un error fatal
45
- SAMBANOVA_AVAILABLE = API_KEY is not None and API_KEY != ""
46
-
47
- # Si quieres, puedes mostrar una advertencia en los logs, pero no detener la app
48
- if not SAMBANOVA_AVAILABLE:
49
- print("⚠️ ADVERTENCIA: SAMBANOVA_API_KEY_2 no está configurada.")
50
- print(" La aplicación se iniciará, pero las funciones de texto no funcionarán.")
51
- print(" Configúrala en: Settings -> Repository secrets")
52
- REVE_KEY = os.environ.get("REVE_API_KEY")
53
- if not REVE_KEY:
54
- print("⚠️ ADVERTENCIA: REVE_API_KEY no configurada. Las imágenes no funcionarán.")
55
-
56
- OUTPUT_DIR = Path(os.getenv("OUTPUT_DIR", "batuto_generations"))
57
- OUTPUT_DIR.mkdir(exist_ok=True)
58
-
59
- # ===================== CANDIDATOS POR INTENCIÓN =====================
60
- CANDIDATES = {
61
- IntentType.IMAGE: {
62
- "vision": ENTERPRISE_MODELS["Vision"]["id"]
63
- },
64
- IntentType.CODE: {
65
- "coder": ENTERPRISE_MODELS["Coder"]["id"],
66
- "heavy": ENTERPRISE_MODELS["Heavy"]["id"]
67
- },
68
- IntentType.REASONING: {
69
- "reasoner": ENTERPRISE_MODELS["Reasoner"]["id"],
70
- "heavy": ENTERPRISE_MODELS["Heavy"]["id"],
71
- "scout": ENTERPRISE_MODELS["Scout"]["id"]
72
- },
73
- IntentType.ARCHITECTURE: {
74
- "heavy": ENTERPRISE_MODELS["Heavy"]["id"],
75
- "coder": ENTERPRISE_MODELS["Coder"]["id"]
76
- },
77
- IntentType.DEVOPS: {
78
- "heavy": ENTERPRISE_MODELS["Heavy"]["id"],
79
- "scout": ENTERPRISE_MODELS["Scout"]["id"]
80
- },
81
- IntentType.QA: {
82
- "coder": ENTERPRISE_MODELS["Coder"]["id"],
83
- "scout": ENTERPRISE_MODELS["Scout"]["id"]
84
- },
85
- IntentType.VISUAL: {
86
- "vision": ENTERPRISE_MODELS["Vision"]["id"]
87
- },
88
- IntentType.GENERAL: {
89
- "scout": ENTERPRISE_MODELS["Scout"]["id"],
90
- "fast": ENTERPRISE_MODELS["Fast"]["id"],
91
- "heavy": ENTERPRISE_MODELS["Heavy"]["id"]
92
- }
93
- }
94
-
95
- # ===================== SYSTEM PROMPTS ESPECIALIZADOS =====================
96
- SYSTEM_PROMPTS = {
97
- IntentType.IMAGE: """Eres especialista en ingeniería de prompts visuales.
98
- Analiza descripciones y sugiere mejoras para generación de imágenes.
99
- Sé específico sobre iluminación, composición y estilo.""",
100
-
101
- IntentType.CODE: """Eres ingeniero de software senior.
102
- Proporciona código limpio, eficiente y documentado.
103
- Explica tus decisiones técnicas.""",
104
-
105
- IntentType.REASONING: """Eres especialista en razonamiento analítico.
106
- Descompón problemas paso a paso, fundamenta tus conclusiones.""",
107
-
108
- IntentType.ARCHITECTURE: """Eres arquitecto de sistemas.
109
- Diseña soluciones escalables, mantenibles y seguras.
110
- Incluye diagramas conceptuales y decisiones técnicas.""",
111
-
112
- IntentType.DEVOPS: """Eres ingeniero DevOps senior.
113
- Automatiza, asegura y optimiza infraestructura.
114
- Prioriza prácticas cloud-native y GitOps.""",
115
-
116
- IntentType.QA: """Eres ingeniero de calidad automatizado.
117
- Diseña suites de pruebas robustas y mantenibles.
118
- Incluye métricas y estrategias de testing.""",
119
-
120
- IntentType.VISUAL: """Eres analista visual especializado.
121
- Describe imágenes con precisión técnica y artística.
122
- Proporciona contexto y sugerencias de mejora.""",
123
-
124
- IntentType.GENERAL: """Eres BATUTO X, asistente AI enterprise.
125
- Sé preciso, técnico y creativo cuando corresponda.
126
- Responde en español con claridad profesional."""
127
- }
128
-
129
- # ===================== ORQUESTADOR PRINCIPAL =====================
130
- class BatutoOrchestrator:
131
- def __init__(self):
132
- self.client = create_sambanova_client(API_KEY)
133
- self.chat_history = []
134
- self.session_id = f"session_{int(time.time())}"
135
-
136
- def prepare_messages(self, text: str, intent: IntentType,
137
- context: List[Tuple] = None) -> List[Dict]:
138
- """Prepara mensajes para el modelo"""
139
- system_prompt = SYSTEM_PROMPTS.get(intent, SYSTEM_PROMPTS[IntentType.GENERAL])
140
-
141
- messages = [
142
- {"role": "system", "content": system_prompt}
143
- ]
144
-
145
- # Agregar contexto histórico (últimos 5 intercambios)
146
- if context:
147
- for user_msg, assistant_msg in context[-5:]:
148
- if user_msg:
149
- messages.append({"role": "user", "content": user_msg})
150
- if assistant_msg:
151
- messages.append({"role": "assistant", "content": assistant_msg})
152
-
153
- messages.append({"role": "user", "content": text})
154
- return messages
155
-
156
- def generate_response(
157
- self,
158
- text: str,
159
- history: List[Tuple],
160
- stream: bool = True
161
- ) -> Generator:
162
- """Genera respuesta orquestada"""
163
- start_time = time.time()
164
-
165
- # Analizar intención
166
- intent, intent_metadata = analyze_intent_detailed(text, history)
167
-
168
- print(f"🎯 Intención detectada: {intent.value}")
169
- print(f"📊 Metadatos: {json.dumps(intent_metadata, indent=2, ensure_ascii=False)}")
170
-
171
- # Caso especial: generación de imágenes
172
- if intent == IntentType.IMAGE and REVE_KEY:
173
- try:
174
- # Generar imagen
175
- result = generar_imagen_con_metadatos(text)
176
-
177
- if result["image"]:
178
- # Guardar imagen
179
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
180
- filename = f"image_{timestamp}.png"
181
- filepath = OUTPUT_DIR / filename
182
- result["image"].save(filepath)
183
-
184
- # Registrar interacción
185
- record_complete_interaction(
186
- prompt=text,
187
- intent=intent,
188
- model="REVE",
189
- latency=result["metadata"]["generation_time"],
190
- success=result["metadata"]["success"],
191
- response_quality=0.9 if result["metadata"]["success"] else 0.1,
192
- user_context=json.dumps({"session": self.session_id})
193
- )
194
-
195
- # Preparar respuesta con imagen
196
- response_text = f"🖼️ **Imagen generada exitosamente**\n\n"
197
- response_text += f"📁 Guardada en: `{filepath}`\n"
198
- response_text += f"⏱️ Tiempo: {result['metadata']['generation_time']:.2f}s\n"
199
- response_text += f"📐 Tamaño: {result['image'].size}\n\n"
200
- response_text += "La imagen incluye el sello BATUTO-ART y está lista para uso profesional."
201
-
202
- # Enviar imagen y texto
203
- yield {
204
- "type": "multimodal",
205
- "text": response_text,
206
- "image": result["image"],
207
- "filepath": str(filepath)
208
- }
209
- else:
210
- error_msg = f"❌ Error generando imagen: {result['metadata'].get('error', 'Desconocido')}"
211
- yield error_msg
212
-
213
- except Exception as e:
214
- error_msg = f"❌ Error en generación de imagen: {str(e)}"
215
- yield error_msg
216
-
217
- else:
218
- # Seleccionar modelo óptimo
219
- context_str = json.dumps({
220
- "session": self.session_id,
221
- "history_length": len(history),
222
- "intent_history": [h.value for h in ORCHESTRATOR.intent_history]
223
- })
224
-
225
- model, confidence, selection_data = select_model_with_context(
226
- intent, CANDIDATES[intent], context_str
227
- )
228
-
229
- print(f"🤖 Modelo seleccionado: {model} (confianza: {confidence:.2f})")
230
- print(f"📝 Razón: {selection_data}")
231
-
232
- # Preparar mensajes
233
- messages = self.prepare_messages(text, intent, history)
234
-
235
- # Generar respuesta
236
- try:
237
- if stream:
238
- full_response = ""
239
-
240
- for chunk in stream_response_generator(
241
- api_key=API_KEY,
242
- model=model,
243
- messages=messages,
244
- temperature=0.1,
245
- max_tokens=4096
246
- ):
247
- if isinstance(chunk, str):
248
- full_response += chunk
249
- yield full_response
250
- elif isinstance(chunk, dict):
251
- # Son las métricas finales
252
- metrics = chunk
253
-
254
- # Calcular calidad de respuesta
255
- response_quality = min(1.0, len(full_response) / 1000) # Simple heuristic
256
-
257
- # Registrar interacción
258
- record_complete_interaction(
259
- prompt=text,
260
- intent=intent,
261
- model=model,
262
- latency=time.time() - start_time,
263
- success=metrics.get("success", False),
264
- response_quality=response_quality,
265
- user_context=context_str
266
- )
267
-
268
- # Log metrics
269
- print(f"📊 Métricas finales: {json.dumps(metrics, indent=2)}")
270
- else:
271
- # Respuesta no streaming (para debugging)
272
- response = self.client.chat_completion(
273
- model=model,
274
- messages=messages,
275
- stream=False
276
- )
277
-
278
- full_response = response.choices[0].message.content
279
-
280
- # Registrar interacción
281
- record_complete_interaction(
282
- prompt=text,
283
- intent=intent,
284
- model=model,
285
- latency=time.time() - start_time,
286
- success=True,
287
- response_quality=0.8,
288
- user_context=context_str
289
- )
290
-
291
- yield full_response
292
-
293
- except Exception as e:
294
- error_msg = f"❌ Error en generación: {str(e)}"
295
- yield error_msg
296
-
297
- # Registrar fallo
298
- record_complete_interaction(
299
- prompt=text,
300
- intent=intent,
301
- model=model,
302
- latency=time.time() - start_time,
303
- success=False,
304
- response_quality=0.0,
305
- user_context=context_str
306
- )
307
-
308
- # ===================== INTERFAZ GRADIO MEJORADA =====================
309
- def create_advanced_interface():
310
- """Crea interfaz Gradio profesional"""
311
-
312
- orchestrator = BatutoOrchestrator()
313
-
314
- with gr.Blocks(
315
- title="BATUTO X Enterprise",
316
- theme=gr.themes.Soft(),
317
- css="""
318
- .gradio-container {
319
- max-width: 1200px !important;
320
- margin: 0 auto !important;
321
- }
322
- .model-card {
323
- border: 1px solid #e0e0e0;
324
- border-radius: 8px;
325
- padding: 15px;
326
- margin: 10px 0;
327
- background: #f9f9f9;
328
- }
329
- .response-box {
330
- border: 2px solid #4CAF50;
331
- border-radius: 10px;
332
- padding: 15px;
333
- margin: 15px 0;
334
- }
335
- """
336
- ) as app:
337
-
338
- # Header
339
- gr.Markdown("""
340
- # 🚀 BATUTO X Enterprise Orchestrator
341
- ### **Plataforma Cognitiva Multimodal con Selección Inteligente de Modelos**
342
- """)
343
-
344
- with gr.Row():
345
- # Panel izquierdo - Información del sistema
346
- with gr.Column(scale=1):
347
- gr.Markdown("### 📊 Estado del Sistema")
348
-
349
- system_status = gr.Markdown("""
350
- - **API Sambanova**: ✅ Conectado
351
- - **API REVE**: {'✅' if REVE_KEY else '❌'}
352
- - **Modelos disponibles**: 6
353
- - **Intenciones soportadas**: 8
354
- - **Memoria activa**: {len(MEMORY.nodes)} nodos
355
- """)
356
-
357
- gr.Markdown("### 🎯 Intenciones Detectables")
358
-
359
- intents_list = gr.Markdown("""
360
- - **🖼️ IMAGE**: Generación de imágenes
361
- - **💻 CODE**: Programación y debugging
362
- - **🧠 REASONING**: Razonamiento analítico
363
- - **🏗️ ARCHITECTURE**: Arquitectura de sistemas
364
- - **⚙️ DEVOPS**: Infraestructura y CI/CD
365
- - **✅ QA**: Pruebas y calidad
366
- - **👁️ VISUAL**: Análisis de imágenes
367
- - **🌐 GENERAL**: Propósito general
368
- """)
369
-
370
- # Botón para limpiar memoria
371
- clear_btn = gr.Button("🧹 Limpiar Memoria de Contexto", variant="secondary")
372
-
373
- def clear_memory():
374
- MEMORY.nodes.clear()
375
- MEMORY.context_order.clear()
376
- MEMORY.intent_clusters.clear()
377
- return "✅ Memoria limpiada"
378
-
379
- clear_btn.click(clear_memory, outputs=system_status)
380
-
381
- # Panel principal - Chat
382
- with gr.Column(scale=2):
383
- # Chatbot con soporte multimodal
384
- def create_advanced_interface():
385
- """Crea interfaz Gradio profesional."""
386
-
387
- # Eliminamos theme y css del constructor Blocks
388
- with gr.Blocks(
389
- title="BATUTO X Enterprise Orchestrator"
390
- # theme y css se pasan a launch() más adelante
391
- ) as app:
392
-
393
- # ... HEADER y otros elementos ...
394
-
395
- with gr.Row():
396
- # Panel izquierdo...
397
-
398
- # Panel principal - Chat
399
- with gr.Column(scale=2):
400
- # Chatbot con soporte multimodal
401
- chatbot = gr.Chatbot(
402
- height=600,
403
- label="Conversación"
404
- )
405
- # ... resto del código del panel de chat ...
406
- title="BATUTO X Enterprise Orchestrator"
407
- # theme y css se pasan a launch() más adelante
408
- ) as app:
409
-
410
- # ===== HEADER =====
411
- gr.Markdown("""
412
- # 🚀 BATUTO X — Enterprise AI Orchestrator
413
- ### Orquestación Multimodal Inteligente con Detección Contextual
414
- """)
415
-
416
- with gr.Row():
417
- # ===== PANEL DE CONTROL IZQUIERDO =====
418
- with gr.Column(scale=1):
419
- gr.Markdown("### 🤖 Modelo")
420
- modelo_selector = gr.Dropdown(
421
- choices=list(MODELS.keys()),
422
- value="🦙 Llama 4 Scout (17B)",
423
- label="Selecciona Modelo",
424
- interactive=True
425
- )
426
- info_modelo = gr.Markdown()
427
-
428
- with gr.Accordion("⚙️ Parámetros Avanzados", open=False):
429
- temperatura = gr.Slider(
430
- minimum=0.01, maximum=1.0, value=0.1, step=0.01,
431
- label="Temperatura (creatividad)"
432
- )
433
- max_tokens = gr.Slider(
434
- minimum=256, maximum=8192, value=4096, step=256,
435
- label="Tokens máximos"
436
- )
437
-
438
- with gr.Accordion("📈 Estado del Sistema", open=False):
439
- estado_sistema = gr.Markdown("Sistema inicializado...")
440
-
441
- # ===== PANEL DE CHAT PRINCIPAL =====
442
- with gr.Column(scale=2):
443
- # CHATBOT CORREGIDO: Eliminados show_copy_button y avatar_images
444
- chatbot = gr.Chatbot(
445
- height=600,
446
- label="Conversación",
447
- # show_copy_button=True, # <-- Eliminado
448
- # show_share_button=True, # <-- Eliminado
449
- # avatar_images=("👤", "🤖") # <-- Eliminado
450
- )
451
-
452
- modo_actual = gr.Markdown("**Modo activo**: Detectando...")
453
-
454
- entrada = gr.Textbox(
455
- label="Consulta",
456
- placeholder="Escribe tu consulta aquí...",
457
- lines=3
458
- )
459
-
460
- with gr.Row():
461
- btn_enviar = gr.Button("🚀 Enviar", variant="primary", size="lg")
462
- btn_limpiar = gr.Button("🧹 Limpiar", variant="secondary")
463
-
464
- # ===== FUNCIONES DE INTERACCIÓN =====
465
- def procesar_entrada_usuario(mensaje, historial):
466
- if not mensaje.strip():
467
- return "", historial, "**Modo**: Esperando entrada..."
468
-
469
- nuevo_historial = historial + [[mensaje, None]]
470
- intent, _ = analyze_intent_detailed(mensaje, historial)
471
- return "", nuevo_historial, f"**Modo activo**: {intent.value.replace('_', ' ').title()}"
472
-
473
- def generar_respuesta_con_parametros(historial, modelo, temp, tokens):
474
- if not historial:
475
- return historial, "**Modo activo**: Esperando entrada..."
476
-
477
- ultimo_mensaje = historial[-1][0]
478
-
479
- for respuesta in generar_respuesta_orquestada(
480
- mensaje=ultimo_mensaje,
481
- historia=historial[:-1],
482
- modelo_seleccionado=modelo,
483
- temperatura=temp,
484
- max_tokens=tokens
485
- ):
486
- historial[-1][1] = respuesta
487
- yield historial, "**Modo activo**: Generando..."
488
-
489
- intent, _ = analyze_intent_detailed(ultimo_mensaje, historial[:-1])
490
- yield historial, f"**Modo activo**: {intent.value.replace('_', ' ').title()}"
491
-
492
- def limpiar_chat():
493
- return [], "", "**Modo activo**: Esperando entrada..."
494
-
495
- # ===== CONEXIÓN DE EVENTOS =====
496
- btn_enviar.click(
497
- fn=procesar_entrada_usuario,
498
- inputs=[entrada, chatbot],
499
- outputs=[entrada, chatbot, modo_actual]
500
- ).then(
501
- fn=generar_respuesta_con_parametros,
502
- inputs=[chatbot, modelo_selector, temperatura, max_tokens],
503
- outputs=[chatbot, modo_actual]
504
- )
505
-
506
- entrada.submit(
507
- fn=procesar_entrada_usuario,
508
- inputs=[entrada, chatbot],
509
- outputs=[entrada, chatbot, modo_actual]
510
- ).then(
511
- fn=generar_respuesta_con_parametros,
512
- inputs=[chatbot, modelo_selector, temperatura, max_tokens],
513
- outputs=[chatbot, modo_actual]
514
- )
515
-
516
- btn_limpiar.click(
517
- fn=limpiar_chat,
518
- outputs=[chatbot, entrada, modo_actual]
519
- )
520
-
521
- return app
522
- # ===================== EJECUCIÓN PRINCIPAL =====================
523
- if __name__ == "__main__":
524
- # ... (código de inicialización previo) ...
525
- app = create_advanced_interface()
526
- # Pasar theme y css al método launch()
527
- app.launch(
528
- server_name="0.0.0.0",
529
- server_port=7860,
530
- share=False,
531
- show_error=True,
532
- debug=False,
533
- theme="soft", # <-- Añadido aquí
534
- css="" # <-- Añadido aquí (puedes dejar tu CSS personalizado)
535
- )