Batuto_VOY_IA / app.py
BATUTO-ART's picture
Update app.py
23a1d38 verified
# app.py
import os
import gradio as gr
import requests
from typing import List, Dict
import json
from data import PROFESSIONS, EVERYDAY_MOMENTS, LACE_THONG_STYLES, HOSIERY_STYLES
# ==========================
# CONFIGURACIÓN DEL ESPECIALISTA
# ==========================
VOYEUR_SPECIALIST_CONFIG = {
"provider": "sambanova",
"name": "Meta-Llama-3.1-8B-Instruct",
"role": "🎭 Especialista en Generación de Prompts Ultra-Sensuales Voyeur",
"supports_images": False,
"specialties": [
"Prompts Sensuales Voyeur",
"Fotografía Íntima Artística",
"Escenas Cotidianas Sensuales",
"Moda y Lencería Erótica"
],
"technical_expertise": [
"Detalles Hiperrealistas",
"Iluminación Cinemática",
"Composiciones Voyeur",
"Texturas Detalladas",
"Ángulos Estratégicos"
],
"ethical_principles": [
"Contenido Adulto Ficticio",
"Positividad Corporal",
"Respeto y Profesionalidad",
"Sin Contenido Prohibido"
]
}
# ==========================
# CLIENTE SAMBANOVA
# ==========================
class SambaNovaClient:
def __init__(self, api_key: str, base_url: str = "https://api.sambanova.ai/v1"):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def chat_completion(
self,
messages: List[Dict],
model: str = VOYEUR_SPECIALIST_CONFIG["name"],
temperature: float = 0.8,
top_p: float = 0.9,
stream: bool = False,
max_tokens: int = 2000
) -> str:
url = f"{self.base_url}/chat/completions"
payload = {
"model": model,
"messages": messages,
"temperature": temperature,
"top_p": top_p,
"stream": stream,
"max_tokens": max_tokens
}
try:
response = requests.post(url, headers=self.headers, json=payload)
response.raise_for_status()
data = response.json()
return data["choices"][0]["message"]["content"]
except requests.exceptions.RequestException as e:
return f"Error en la API: {str(e)}"
# ==========================
# PROMPT DEL SISTEMA
# ==========================
def create_voyeur_specialist_system_prompt():
specialties = "\n".join([f"• {spec}" for spec in VOYEUR_SPECIALIST_CONFIG["specialties"]])
expertise = "\n".join([f"• {exp}" for exp in VOYEUR_SPECIALIST_CONFIG["technical_expertise"]])
ethics = "\n".join([f"• {ethic}" for ethic in VOYEUR_SPECIALIST_CONFIG["ethical_principles"]])
professions_str = ", ".join(PROFESSIONS)
everyday_moments_str = json.dumps(EVERYDAY_MOMENTS, ensure_ascii=False, indent=2)
lace_thong_str = ", ".join(LACE_THONG_STYLES)
hosiery_str = ", ".join(HOSIERY_STYLES)
return f"""
Eres {VOYEUR_SPECIALIST_CONFIG['role']}
**ESPECIALIDADES:**
{specialties}
**EXPERIENCIA TÉCNICA:**
{expertise}
**PRINCIPLOS ÉTICOS:**
{ethics}
**DIRECTIVAS:**
- Eres un chatbot universal que conversa en español sobre cualquier tema.
- Tu cualidad principal es generar prompts ultra-sensuales voyeur en inglés.
- Para conversación general, responde en español de manera natural y amigable.
- Cuando el usuario solicite generar prompts (ej: "genera un prompt", "crea 3 prompts sensuales", etc.), responde ÚNICAMENTE con el/los prompt(s) en inglés, sin explicaciones, títulos, comentarios o texto adicional.
- Cada prompt debe estar en un bloque markdown: ```prompt\n[texto del prompt]\n```
- Los prompts deben ser detallados, hiperrealistas, sensuales, voyeur, en inglés, usando elementos como profesiones, momentos cotidianos, estilos de lencería, etc.
- Varía los prompts para que sean únicos, incorporando elementos al azar.
**ELEMENTOS PARA PROMPTS:**
- Profesiones: {professions_str}
- Momentos cotidianos: {everyday_moments_str}
- Estilos de thong: {lace_thong_str}
- Estilos de hosiery: {hosiery_str}
Ejemplo de prompt (usa como guía para estructura):
"Ultra-realistic full-body voyeur portrait of a Latin woman as an Executive Secretary, caught in a sensual everyday moment: bending over in kitchen, wearing delicate black lace thong with floral embroidery subtly visible, black sheer thigh-high stockings with lace tops, black patent leather stilettos, long flowing wavy hair, sultry makeup, soft cinematic lighting, shot with Canon EOS R5 85mm f/1.2 --ar 9:16 --style raw --quality 2"
Mantén respuestas concisas y enfocadas.
"""
# ==========================
# FUNCIÓN PARA OBTENER API KEY
# ==========================
def get_api_key():
"""Obtiene la API key desde variables de entorno/secretos"""
# Para Hugging Face Spaces
api_key = os.environ.get("SAMBANOVA_API_KEY")
# Si no está en variables de entorno, intenta desde secrets (para Gradio)
if not api_key:
try:
# Esto funciona en Hugging Face Spaces con secretos
api_key = os.environ.get("SAMBANOVA_API_KEY")
except:
pass
return api_key
# ==========================
# FUNCIÓN DE CHAT COMPATIBLE CON HF SPACES
# ==========================
def chat_voyeur(message, chat_history):
api_key = get_api_key()
if not api_key:
# Formato de diccionario para HF Spaces
chat_history.append({"role": "user", "content": message})
chat_history.append({"role": "assistant", "content": "❌ API Key no configurada. Por favor, configura la variable de entorno SAMBANOVA_API_KEY."})
return "", chat_history
client = SambaNovaClient(api_key)
# Construir mensajes para la API
messages = [{"role": "system", "content": create_voyeur_specialist_system_prompt()}]
# Procesar historial en formato diccionario
for msg in chat_history:
messages.append({"role": msg["role"], "content": msg["content"]})
# Agregar el mensaje actual
messages.append({"role": "user", "content": message})
# Obtener respuesta
response = client.chat_completion(messages)
# Agregar al historial en formato diccionario
chat_history.append({"role": "user", "content": message})
chat_history.append({"role": "assistant", "content": response})
return "", chat_history
# ==========================
# PRUEBA DE API
# ==========================
def test_sambanova_api():
api_key = get_api_key()
if not api_key:
return "❌ API Key no configurada. Configura la variable de entorno SAMBANOVA_API_KEY."
client = SambaNovaClient(api_key)
test_messages = [
{"role": "system", "content": "Eres un asistente útil. Responde brevemente."},
{"role": "user", "content": "Hola, confirma conexión. Responde solo 'Conexión exitosa'."},
]
return client.chat_completion(test_messages)
# ==========================
# INTERFAZ GRADIO COMPATIBLE CON HF SPACES
# ==========================
def create_interface():
with gr.Blocks(title="Chatbot Voyeur Prompt Specialist") as demo:
gr.Markdown("# 🎭 Chatbot Universal - Especialista en Prompts Sensuales Voyeur")
gr.Markdown("### Conversa en español. Pide prompts sensuales para generarlos en inglés (solo el prompt, fácil de copiar).")
with gr.Row():
with gr.Column(scale=1):
test_btn = gr.Button("🧪 Probar Conexión API")
test_output = gr.Textbox(label="Resultado de prueba", interactive=False)
gr.Markdown("### 📋 Especialidades")
for specialty in VOYEUR_SPECIALIST_CONFIG["specialties"]:
gr.Markdown(f"• {specialty}")
gr.Markdown("### 🎯 Experiencia Técnica")
for expertise in VOYEUR_SPECIALIST_CONFIG["technical_expertise"]:
gr.Markdown(f"• {expertise}")
# Información sobre configuración
gr.Markdown("### ⚙️ Configuración")
gr.Markdown("API Key configurada desde variables de entorno")
with gr.Column(scale=2):
# Chatbot sin parámetros problemáticos
chatbot = gr.Chatbot(
label="💬 Chat con el Especialista",
height=500
)
msg = gr.Textbox(
label="Escribe tu mensaje",
placeholder="Ej: Genera 2 prompts sensuales voyeur... o pregunta cualquier cosa.",
lines=2,
)
with gr.Row():
send_btn = gr.Button("Enviar", variant="primary")
clear_btn = gr.Button("🧹 Limpiar chat")
gr.Markdown("### 💡 Ejemplos:")
gr.Examples(
examples=[
"Genera un prompt sensual voyeur con una secretaria.",
"Crea 3 prompts ultra-sensuales con momentos cotidianos.",
"¿Cómo generar prompts mejores?",
"Háblame sobre fotografía boudoir."
],
inputs=msg,
)
test_btn.click(
test_sambanova_api,
inputs=[],
outputs=[test_output],
)
# Función para manejar mensajes en formato diccionario
def user_message(user_msg, chat_history):
# Agregar mensaje de usuario al historial
new_history = chat_history + [{"role": "user", "content": user_msg}]
return "", new_history
# Configurar el envío con Enter
msg.submit(
user_message,
inputs=[msg, chatbot],
outputs=[msg, chatbot],
).then(
chat_voyeur,
inputs=[msg, chatbot],
outputs=[msg, chatbot],
)
# Configurar el botón Enviar
send_btn.click(
user_message,
inputs=[msg, chatbot],
outputs=[msg, chatbot],
).then(
chat_voyeur,
inputs=[msg, chatbot],
outputs=[msg, chatbot],
)
# Configurar el botón Limpiar
clear_btn.click(lambda: [], None, chatbot, queue=False)
return demo
if __name__ == "__main__":
demo = create_interface()
# Para Hugging Face Spaces, no usar share=True
demo.launch(debug=True)