BATUTO-ART commited on
Commit
610d436
·
verified ·
1 Parent(s): 4d19917

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +244 -59
app.py CHANGED
@@ -4,13 +4,22 @@ import time
4
  import json
5
  import base64
6
  import asyncio
 
7
  import datetime
8
  from io import BytesIO
9
- from typing import AsyncGenerator
10
 
11
  import aiohttp
12
  import gradio as gr
13
  from PIL import Image
 
 
 
 
 
 
 
 
14
 
15
  SAMBANOVA_API_KEY = os.getenv("SAMBANOVA_API_KEY", "").strip()
16
  HF_TOKEN = os.getenv("HF_TOKEN", "").strip()
@@ -46,6 +55,8 @@ CSS = """
46
  :root{--primary:#00C896;--secondary:#00FFE0;--bg:#000;--border:rgba(0,200,150,.35);}
47
  body,.gradio-container{background:#000!important; color: #fff !important;}
48
  .panel{border:1px solid var(--border);border-radius:16px;padding:12px}
 
 
49
  """
50
 
51
  def log_event(data: dict):
@@ -62,14 +73,20 @@ def save_generation(content, model_name, type="text"):
62
 
63
  def smart_select(prompt: str) -> str:
64
  p = prompt.lower()
65
- if any(x in p for x in ["código", "python", "script"]): return "DeepSeek-Coder-V2"
66
- if any(x in p for x in ["razona", "piensa", "matemáticas"]): return "DeepSeek-R1"
67
- if any(x in p for x in ["vision", "mira", "describe"]): return "Meta-Llama-3.2-11B-Vision-Instruct"
 
 
 
 
 
68
  return "DeepSeek-V3.1"
69
 
70
- async def stream_samba(model, prompt, temp, tokens):
 
71
  url = "https://api.sambanova.ai/v1/chat/completions"
72
- headers = {"Authorization": f"Bearer {SAMBANOVA_API_KEY}"}
73
  payload = {
74
  "model": model,
75
  "messages": [{"role": "user", "content": prompt}],
@@ -77,70 +94,238 @@ async def stream_samba(model, prompt, temp, tokens):
77
  "max_tokens": tokens,
78
  "stream": True
79
  }
 
80
  full_res = ""
81
- async with aiohttp.ClientSession() as session:
82
- async with session.post(url, headers=headers, json=payload) as resp:
83
- async for line in resp.content:
84
- line = line.decode("utf-8").strip()
85
- if line.startswith("data: "):
86
- data_str = line[6:]
87
- if data_str == "[DONE]": break
88
- try:
89
- data = json.loads(data_str)
90
- delta = data["choices"][0]["delta"].get("content", "")
91
- full_res += delta
92
- yield full_res
93
- except: continue
94
- save_generation(full_res, model)
95
- log_event({"model": model, "prompt": prompt})
96
-
97
- async def run_reve(prompt, n):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  url = "https://api.reve.com/v1/image/create"
99
- headers = {"Authorization": f"Bearer {REVE_API_KEY}"}
100
  imgs = []
101
- async with aiohttp.ClientSession() as session:
102
- for _ in range(n):
103
- async with session.post(url, headers=headers, json={"prompt": prompt}) as r:
104
- if r.status == 200:
105
- j = await r.json()
106
- for b in j.get("images", []):
107
- imgs.append(Image.open(BytesIO(base64.b64decode(b))))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  return imgs
109
 
110
- def handle_execution(model, prompt, temp, tokens, n):
 
 
 
 
111
  active_model = smart_select(prompt) if model == "AUTO-SELECT" else model
112
 
 
 
 
 
113
  if active_model == "REVE":
114
- imgs = asyncio.run(run_reve(prompt, n))
115
- return "Imágenes generadas.", imgs
 
 
 
 
 
 
 
 
 
 
116
 
 
117
  return stream_samba(active_model, prompt, temp, tokens)
118
 
119
- with gr.Blocks(title="BATUTO X • Neurocore") as demo:
120
- gr.HTML("<h1 style='color:#00C896; text-align:center;'>⚡ BATUTO X • NEUROCORE PRO</h1>")
121
-
122
- with gr.Row():
123
- with gr.Column(scale=1):
124
- model_opt = gr.Dropdown(ALL_MODELS, value="AUTO-SELECT", label="Model")
125
- temp_opt = gr.Slider(0, 1.5, 0.7, label="Temperature")
126
- tokens_opt = gr.Slider(128, 8192, 2048, label="Max Tokens")
127
- num_opt = gr.Slider(1, 4, 1, step=1, label="Image Count")
128
 
129
- with gr.Column(scale=2):
130
- prompt_input = gr.Textbox(lines=5, label="Input", placeholder="Comando...")
131
- send_btn = gr.Button("EJECUTAR", variant="primary")
132
-
133
- canvas = gr.Textbox(lines=12, label="Output", interactive=False)
134
- gallery = gr.Gallery(label="Gallery", columns=2)
135
-
136
- send_btn.click(handle_execution, [model_opt, prompt_input, temp_opt, tokens_opt, num_opt], [canvas, gallery])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  if __name__ == "__main__":
139
- demo.launch(
140
- server_name="0.0.0.0",
141
- server_port=int(os.getenv("PORT", "7860")),
142
- ssr_mode=False,
143
- theme=gr.themes.Default(primary_hue="emerald", neutral_hue="zinc"),
144
- css=CSS
145
- )
146
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import json
5
  import base64
6
  import asyncio
7
+ import threading
8
  import datetime
9
  from io import BytesIO
10
+ from typing import AsyncGenerator, List, Tuple, Optional
11
 
12
  import aiohttp
13
  import gradio as gr
14
  from PIL import Image
15
+ import warnings
16
+
17
+ # 忽略asyncio警告
18
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
19
+
20
+ # 设置事件循环策略(修复Python 3.13+兼容性问题)
21
+ if hasattr(asyncio, 'WindowsProactorEventLoopPolicy') and isinstance(asyncio.get_event_loop_policy(), asyncio.WindowsProactorEventLoopPolicy):
22
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
23
 
24
  SAMBANOVA_API_KEY = os.getenv("SAMBANOVA_API_KEY", "").strip()
25
  HF_TOKEN = os.getenv("HF_TOKEN", "").strip()
 
55
  :root{--primary:#00C896;--secondary:#00FFE0;--bg:#000;--border:rgba(0,200,150,.35);}
56
  body,.gradio-container{background:#000!important; color: #fff !important;}
57
  .panel{border:1px solid var(--border);border-radius:16px;padding:12px}
58
+ .dark .gradio-container {background: #000 !important;}
59
+ .dark .gr-button-primary {background: linear-gradient(45deg, #00C896, #00FFE0) !important;}
60
  """
61
 
62
  def log_event(data: dict):
 
73
 
74
  def smart_select(prompt: str) -> str:
75
  p = prompt.lower()
76
+ if any(x in p for x in ["código", "python", "script", "programa", "code"]):
77
+ return "DeepSeek-Coder-V2"
78
+ if any(x in p for x in ["razona", "piensa", "matemáticas", "math", "logic"]):
79
+ return "DeepSeek-R1"
80
+ if any(x in p for x in ["vision", "mira", "describe", "imagen", "image"]):
81
+ return "Meta-Llama-3.2-11B-Vision-Instruct"
82
+ if any(x in p for x in ["audio", "sonido", "speech", "voz"]):
83
+ return "Qwen/Qwen2-Audio-7B-Instruct"
84
  return "DeepSeek-V3.1"
85
 
86
+ async def stream_samba(model: str, prompt: str, temp: float, tokens: int) -> AsyncGenerator[str, None]:
87
+ """Stream response from Sambanova API"""
88
  url = "https://api.sambanova.ai/v1/chat/completions"
89
+ headers = {"Authorization": f"Bearer {SAMBANOVA_API_KEY}", "Content-Type": "application/json"}
90
  payload = {
91
  "model": model,
92
  "messages": [{"role": "user", "content": prompt}],
 
94
  "max_tokens": tokens,
95
  "stream": True
96
  }
97
+
98
  full_res = ""
99
+ timeout = aiohttp.ClientTimeout(total=60.0)
100
+
101
+ try:
102
+ async with aiohttp.ClientSession(timeout=timeout) as session:
103
+ async with session.post(url, headers=headers, json=payload) as resp:
104
+ if resp.status != 200:
105
+ error_text = await resp.text()
106
+ yield f"Error {resp.status}: {error_text}"
107
+ return
108
+
109
+ async for line in resp.content:
110
+ if line:
111
+ line = line.decode("utf-8").strip()
112
+ if line.startswith("data: "):
113
+ data_str = line[6:]
114
+ if data_str == "[DONE]":
115
+ break
116
+ try:
117
+ data = json.loads(data_str)
118
+ if "choices" in data and data["choices"]:
119
+ delta = data["choices"][0]["delta"].get("content", "")
120
+ full_res += delta
121
+ yield full_res
122
+ except json.JSONDecodeError:
123
+ continue
124
+ except Exception as e:
125
+ yield f"Error de conexión: {str(e)}"
126
+
127
+ if full_res:
128
+ save_generation(full_res, model)
129
+ log_event({"model": model, "prompt": prompt[:100], "response_length": len(full_res)})
130
+
131
+ async def run_reve(prompt: str, n: int) -> List[Image.Image]:
132
+ """Generate images using REVE API"""
133
+ if not REVE_API_KEY:
134
+ return []
135
+
136
  url = "https://api.reve.com/v1/image/create"
137
+ headers = {"Authorization": f"Bearer {REVE_API_KEY}", "Content-Type": "application/json"}
138
  imgs = []
139
+
140
+ try:
141
+ timeout = aiohttp.ClientTimeout(total=120.0)
142
+ async with aiohttp.ClientSession(timeout=timeout) as session:
143
+ tasks = []
144
+ for i in range(n):
145
+ task = session.post(url, headers=headers, json={"prompt": prompt})
146
+ tasks.append(task)
147
+
148
+ responses = await asyncio.gather(*tasks, return_exceptions=True)
149
+
150
+ for response in responses:
151
+ if isinstance(response, Exception):
152
+ continue
153
+ if response.status == 200:
154
+ try:
155
+ data = await response.json()
156
+ for img_data in data.get("images", []):
157
+ img_bytes = base64.b64decode(img_data)
158
+ img = Image.open(BytesIO(img_bytes))
159
+ imgs.append(img)
160
+ except Exception as e:
161
+ print(f"Error procesando imagen: {e}")
162
+ except Exception as e:
163
+ print(f"Error en REVE API: {e}")
164
+
165
  return imgs
166
 
167
+ def handle_execution(model: str, prompt: str, temp: float, tokens: int, n: int):
168
+ """Handle execution based on model selection"""
169
+ if not prompt.strip():
170
+ return "Por favor ingresa un comando.", []
171
+
172
  active_model = smart_select(prompt) if model == "AUTO-SELECT" else model
173
 
174
+ # Verificar que tenemos la API key necesaria
175
+ if active_model in SAMBA_MODELS and not SAMBANOVA_API_KEY:
176
+ return "Error: Falta SAMBANOVA_API_KEY en las variables de entorno.", []
177
+
178
  if active_model == "REVE":
179
+ if not REVE_API_KEY:
180
+ return "Error: Falta REVE_API_KEY en las variables de entorno.", []
181
+
182
+ # Ejecutar en un nuevo evento de asyncio
183
+ try:
184
+ loop = asyncio.new_event_loop()
185
+ asyncio.set_event_loop(loop)
186
+ images = loop.run_until_complete(run_reve(prompt, n))
187
+ loop.close()
188
+ return f"✅ Generadas {len(images)} imágenes con REVE.", images
189
+ except Exception as e:
190
+ return f"Error generando imágenes: {str(e)}", []
191
 
192
+ # Para modelos de texto, retornamos un generador
193
  return stream_samba(active_model, prompt, temp, tokens)
194
 
195
+ def create_interface():
196
+ """Create the Gradio interface"""
197
+ with gr.Blocks(title="BATUTO X • Neurocore", css=CSS, theme=gr.themes.Default(primary_hue="emerald", neutral_hue="zinc")) as demo:
198
+ gr.HTML("""
199
+ <div style="text-align: center; padding: 20px; background: linear-gradient(45deg, #000, #001a14); border-radius: 16px; margin-bottom: 20px;">
200
+ <h1 style="color: #00C896; margin: 0; font-size: 2.5em;">⚡ BATUTO X • NEUROCORE PRO</h1>
201
+ <p style="color: #00FFE0; margin-top: 10px;">Interfaz de Generación Multimodal Avanzada</p>
202
+ </div>
203
+ """)
204
 
205
+ with gr.Row():
206
+ with gr.Column(scale=1):
207
+ with gr.Group():
208
+ model_opt = gr.Dropdown(
209
+ ALL_MODELS,
210
+ value="AUTO-SELECT",
211
+ label="🧠 Modelo",
212
+ info="Selecciona un modelo o usa AUTO-SELECT para detección inteligente"
213
+ )
214
+ temp_opt = gr.Slider(
215
+ 0, 1.5, 0.7,
216
+ label="🌡️ Temperature",
217
+ info="Controla la aleatoriedad (0 = determinístico, 1.5 = muy creativo)"
218
+ )
219
+ tokens_opt = gr.Slider(
220
+ 128, 8192, 2048,
221
+ step=128,
222
+ label="📏 Máximo Tokens",
223
+ info="Longitud máxima de la respuesta"
224
+ )
225
+ num_opt = gr.Slider(
226
+ 1, 4, 1, step=1,
227
+ label="🖼️ Cantidad de Imágenes",
228
+ visible=False,
229
+ info="Solo aplica para modelos de imagen"
230
+ )
231
+
232
+ with gr.Column(scale=2):
233
+ with gr.Group():
234
+ prompt_input = gr.Textbox(
235
+ lines=5,
236
+ label="💬 Entrada",
237
+ placeholder="Escribe tu comando aquí...\nEjemplo: 'Genera un código Python para ordenar una lista' o 'Describe esta imagen: [URL o descripción]'",
238
+ elem_classes=["prompt-box"]
239
+ )
240
+
241
+ send_btn = gr.Button(
242
+ "🚀 EJECUTAR COMANDO",
243
+ variant="primary",
244
+ size="lg",
245
+ elem_classes=["execute-btn"]
246
+ )
247
+
248
+ with gr.Group():
249
+ canvas = gr.Textbox(
250
+ lines=12,
251
+ label="📤 Salida",
252
+ interactive=False,
253
+ elem_classes=["output-box"]
254
+ )
255
+
256
+ gallery = gr.Gallery(
257
+ label="🎨 Galería de Imágenes",
258
+ columns=2,
259
+ height=400,
260
+ visible=False
261
+ )
262
+
263
+ # Mostrar/ocultar controles basado en selección de modelo
264
+ def toggle_controls(model):
265
+ if model == "REVE":
266
+ return [gr.Slider(visible=True), gr.Gallery(visible=True)]
267
+ else:
268
+ return [gr.Slider(visible=False), gr.Gallery(visible=False)]
269
+
270
+ model_opt.change(
271
+ fn=toggle_controls,
272
+ inputs=model_opt,
273
+ outputs=[num_opt, gallery]
274
+ )
275
+
276
+ # Conectar el botón
277
+ send_btn.click(
278
+ fn=handle_execution,
279
+ inputs=[model_opt, prompt_input, temp_opt, tokens_opt, num_opt],
280
+ outputs=[canvas, gallery]
281
+ )
282
+
283
+ # Ejemplos
284
+ with gr.Accordion("📚 Ejemplos de Uso", open=False):
285
+ gr.Examples(
286
+ examples=[
287
+ ["Escribe un programa en Python que implemente el algoritmo de ordenamiento quicksort", "AUTO-SELECT"],
288
+ ["Explica la teoría de la relatividad de Einstein en términos simples", "AUTO-SELECT"],
289
+ ["Genera una imagen de un dragón cibernético en una ciudad futurista", "REVE"],
290
+ ["Analiza este código y sugiere mejoras: def factorial(n): return 1 if n==0 else n*factorial(n-1)", "AUTO-SELECT"],
291
+ ["Resuelve esta ecuación: x² + 5x + 6 = 0", "AUTO-SELECT"]
292
+ ],
293
+ inputs=[prompt_input, model_opt],
294
+ label="Haz clic en un ejemplo para cargarlo"
295
+ )
296
+
297
+ return demo
298
 
299
  if __name__ == "__main__":
300
+ # Configurar logging
301
+ print(f"🚀 Iniciando BATUTO X Neurocore")
302
+ print(f"📁 Directorio de salida: {os.path.abspath(OUTPUT_DIR)}")
303
+ print(f"📝 Archivo de logs: {os.path.abspath(LOG_FILE)}")
304
+
305
+ if SAMBANOVA_API_KEY:
306
+ print("✅ SAMBANOVA_API_KEY configurada")
307
+ else:
308
+ print("⚠️ SAMBANOVA_API_KEY no encontrada - algunos modelos no funcionarán")
309
+
310
+ if REVE_API_KEY:
311
+ print("✅ REVE_API_KEY configurada")
312
+ else:
313
+ print("⚠️ REVE_API_KEY no encontrada - generación de imágenes no disponible")
314
+
315
+ # Crear y lanzar la interfaz
316
+ demo = create_interface()
317
+
318
+ try:
319
+ demo.launch(
320
+ server_name="0.0.0.0",
321
+ server_port=int(os.getenv("PORT", "7860")),
322
+ share=os.getenv("GRADIO_SHARE", "False").lower() == "true",
323
+ debug=False,
324
+ show_error=True,
325
+ quiet=True
326
+ )
327
+ except KeyboardInterrupt:
328
+ print("\n🛑 Aplicación detenida por el usuario")
329
+ except Exception as e:
330
+ print(f"❌ Error al iniciar la aplicación: {e}")
331
+ raise