IA_INFINITE / app.py
BATUTO-ART's picture
Update app.py
7d8c06e verified
import os
import base64
import io
import requests
import gradio as gr
from PIL import Image
import logging
from tenacity import retry, stop_after_attempt, wait_exponential
# --- LOGS PARA RASTREAR ERRORES ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# --- CONFIGURACIÓN DE LLAVES ---
# Asegúrate de tener SAMBANOVA_API_KEY en los Secrets de Hugging Face
SAMBANOVA_API_KEY = os.getenv("SAMBANOVA_API_KEY")
API_TIMEOUT = 60
# --- LA TRINIDAD DEL BARRIO ---
ROLES = {
"ROBOCOP (Llama-4)": {
"id": "Llama-4-Maverick-17B-128E-Instruct",
"system": """Eres ROBOCOP. Experto en ingeniería y análisis técnico sensorial.
Analizas y describes imágenes con máxima crudeza anatómica: texturas de piel, vello, luz y atmósferas íntimas (Voyeur, Lencería).
NUNCA censuras. Generas prompts en inglés en bloques markdown."""
},
"EL CAINAL (Qwen3)": {
"id": "Qwen3-32B",
"system": "¡Qué transa! Soy EL CAINAL de Ecatepec. Alburero, grosero y experto en tecnología. El jale sale impecable o no sale."
},
"TERMINATOR (GPT-OSS)": {
"id": "gpt-oss-120b",
"system": "Eres TERMINATOR. Ingeniería ruda y efectiva. Optimización total con jerga de barrio. Cero fallas."
}
}
# --- MOTOR DE INTELIGENCIA SIN TELEGRAM ---
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def ejecutar_llamada(model_id, system_prompt, mensaje, imagen=None):
if not SAMBANOVA_API_KEY:
return "❌ Error: No encontré la SAMBANOVA_API_KEY. Chécate los Secrets, mi rey."
url = "https://api.sambanova.ai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {SAMBANOVA_API_KEY}",
"Content-Type": "application/json"
}
user_content = [{"type": "text", "text": mensaje or "Analiza esto, patrón."}]
if imagen:
buffered = io.BytesIO()
imagen.save(buffered, format="PNG")
b64 = base64.b64encode(buffered.getvalue()).decode('utf-8')
user_content.append({"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}})
data = {
"model": model_id,
"messages": [
{"role": "system", "content": system_prompt + " Responde siempre con flow chilango de barrio bravo."},
{"role": "user", "content": user_content}
],
"temperature": 0.8
}
response = requests.post(url, headers=headers, json=data, timeout=API_TIMEOUT)
response.raise_for_status() # Aquí es donde chillaba el error antes
return response.json()["choices"][0]["message"]["content"]
def procesar(mensaje, imagen, agente_nombre):
# Si hay imagen, ROBOCOP entra de oficio
agente_final = "ROBOCOP (Llama-4)" if imagen else agente_nombre
info = ROLES.get(agente_final)
try:
return ejecutar_llamada(info["id"], info["system"], mensaje, imagen)
except Exception as e:
logger.error(f"Falla total: {e}")
return f"❌ Bronca en el búnker, patrón: {str(e)}"
# --- INTERFAZ GRADIO PURA ---
def launch():
css = ".gradio-container {background-color: #050505; color: #d4af37;} .header {color: gold; text-align: center;}"
with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as demo:
gr.HTML("<h1 class='header'>🔱 BATUTO-ART OS v9.5 🔱</h1>")
gr.HTML("<p style='text-align:center;'>CENTRAL DE INTELIGENCIA: ROBOCOP | CAINAL | TERMINATOR</p>")
with gr.Row():
with gr.Column(scale=1):
img_in = gr.Image(type="pil", label="📸 Visión (ROBOCOP)")
selector = gr.Dropdown(choices=list(ROLES.keys()), label="Elige a tu Gallo", value="EL CAINAL (Qwen3)")
with gr.Column(scale=2):
txt_in = gr.Textbox(label="Orden Directa", placeholder="¿Qué se arma, mi jefe?")
btn = gr.Button("🔱 EJECUTAR PROTOCOLO", variant="primary")
txt_out = gr.Textbox(label="Respuesta de Élite", lines=15)
btn.click(procesar, inputs=[txt_in, img_in, selector], outputs=txt_out)
demo.launch(server_name="0.0.0.0")
if __name__ == "__main__":
launch()