File size: 4,253 Bytes
5d1041b
 
 
 
 
 
912160b
 
5d1041b
7d8c06e
912160b
 
 
d878eb6
7d8c06e
912160b
d878eb6
5d1041b
7d8c06e
5d1041b
 
 
912160b
 
2d09e12
5d1041b
 
 
2d09e12
5d1041b
 
 
2d09e12
5d1041b
 
 
7d8c06e
912160b
 
d878eb6
7d8c06e
d878eb6
5d1041b
7d8c06e
 
 
 
5d1041b
d878eb6
912160b
5d1041b
 
 
 
 
 
 
912160b
5d1041b
7d8c06e
5d1041b
 
d878eb6
5d1041b
 
912160b
7d8c06e
912160b
5d1041b
d878eb6
7d8c06e
912160b
 
 
 
 
7d8c06e
 
5d1041b
7d8c06e
5d1041b
7d8c06e
5d1041b
d878eb6
7d8c06e
 
d878eb6
5d1041b
 
912160b
7d8c06e
5d1041b
7d8c06e
 
d878eb6
912160b
d878eb6
 
 
5d1041b
912160b
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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()