Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -20,23 +20,21 @@ CARPETA_SALIDA = "bat_art_generaciones"
|
|
| 20 |
os.makedirs(CARPETA_SALIDA, exist_ok=True)
|
| 21 |
|
| 22 |
# Cambia por tus claves reales o usa variables de entorno
|
| 23 |
-
SAMBA_API_KEY = os.getenv("SAMBA_API_KEY", "
|
| 24 |
REVE_API_KEY_DEFAULT = os.getenv("REVE_API_KEY", "")
|
| 25 |
|
| 26 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 27 |
-
#
|
| 28 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 29 |
|
| 30 |
class BatArtPromptGenerator:
|
| 31 |
def __init__(self):
|
| 32 |
-
# Colores
|
| 33 |
self.colors = [
|
| 34 |
"jet black", "blood red", "deep emerald", "royal purple", "neon hot pink",
|
| 35 |
"wet crimson", "bruised plum", "glistening obsidian", "sweaty caramel",
|
| 36 |
"midnight charcoal", "smoky burgundy", "electric violet"
|
| 37 |
]
|
| 38 |
|
| 39 |
-
# Thongs ultra explΓcitos
|
| 40 |
self.thongs = [
|
| 41 |
"extremely thin sheer {color} lace thong soaked transparent clinging to swollen engorged labia majora",
|
| 42 |
"crotchless {color} mesh thong with puffy labia majora spilling out both sides",
|
|
@@ -44,10 +42,9 @@ class BatArtPromptGenerator:
|
|
| 44 |
"{color} string thong pulled painfully tight outlining erect clitoris and glistening vaginal folds",
|
| 45 |
"open-crotch {color} lace thong leaving dripping vaginal entrance and swollen clitoral hood completely exposed",
|
| 46 |
"wet-look {color} latex thong vacuum-molded to every vulvar fold and crease",
|
| 47 |
-
"see-through nude {color} mesh thong darkened and sticky from thick natural lubrication and dense pubic hair shadow"
|
| 48 |
]
|
| 49 |
|
| 50 |
-
# Minifaldas con crudeza
|
| 51 |
self.miniskirts = [
|
| 52 |
"micro pleated black leather skirt violently hiked to waist exposing entire soaked thong and wet inner thighs",
|
| 53 |
"ultra-short red vinyl skirt rolled up revealing extreme cameltoe and glistening lubrication trails down thighs",
|
|
@@ -56,7 +53,6 @@ class BatArtPromptGenerator:
|
|
| 56 |
"pink satin micro skirt flipped up exposing ass cheeks and dripping thong string disappeared between buttocks"
|
| 57 |
]
|
| 58 |
|
| 59 |
-
# Poses hardcore explΓcitas
|
| 60 |
self.poses_hardcore = [
|
| 61 |
"legs spread obscenely wide, hips thrust forward, thong soaked dark showing asymmetric protruding inner labia and erect clitoris outline",
|
| 62 |
"squatting low knees far apart, fingers pulling thong aside exposing slick gaping vaginal opening and thick arousal strings",
|
|
@@ -65,7 +61,6 @@ class BatArtPromptGenerator:
|
|
| 65 |
"on all fours back arched extremely, vulva and anus fully exposed, swollen labia hanging and glistening with fluids"
|
| 66 |
]
|
| 67 |
|
| 68 |
-
# Poses boudoir office mΓ‘s elegantes
|
| 69 |
self.poses_boudoir_office = [
|
| 70 |
"standing legs slightly apart with torso twist, skirt delicately lifted revealing lace thong cameltoe, seductive direct gaze",
|
| 71 |
"sitting on desk edge one leg crossed high, skirt raised showing intricate thong texture and wet spot, confident sultry look",
|
|
@@ -74,7 +69,6 @@ class BatArtPromptGenerator:
|
|
| 74 |
"reclining on office sofa, knees bent and apart, thong clearly displayed with glistening fluids, eyes conveying subtle ecstasy"
|
| 75 |
]
|
| 76 |
|
| 77 |
-
# Γngulos (muy bajos y centrados en crotch)
|
| 78 |
self.angles = [
|
| 79 |
"extreme ultra-low wormβs eye view camera 15β25 cm from vulva filling most of frame with soaked thong and exposed anatomy",
|
| 80 |
"dramatic floor-level macro crotch shot looking straight up between widely parted thighs, razor focus on wet cameltoe and clit",
|
|
@@ -82,7 +76,6 @@ class BatArtPromptGenerator:
|
|
| 82 |
"contrapicado extremo casi pegado al suelo, vulva ocupando 60β75% del encuadre, tanga hundida mostrando clΓtoris hinchado y labios asimΓ©tricos"
|
| 83 |
]
|
| 84 |
|
| 85 |
-
# IluminaciΓ³n mixta
|
| 86 |
self.lighting = [
|
| 87 |
"hard directional window light creating strong specular highlights on vaginal lubrication and sweat beads on inner thighs",
|
| 88 |
"soft diffuse natural daylight + subtle rim light outlining swollen labia and erect nipples through sheer fabric",
|
|
@@ -90,7 +83,6 @@ class BatArtPromptGenerator:
|
|
| 90 |
"dramatic chiaroscuro with deep shadows accentuating wetness, clitoral hood contour and labia volume"
|
| 91 |
]
|
| 92 |
|
| 93 |
-
# Fondos office
|
| 94 |
self.backgrounds = [
|
| 95 |
"modern executive office with floor-to-ceiling windows flooding natural daylight and city views",
|
| 96 |
"minimalist chic office, large windows creating soft reflections on glass and marble",
|
|
@@ -98,7 +90,6 @@ class BatArtPromptGenerator:
|
|
| 98 |
"sophisticated executive room with polished wood desk and huge windows"
|
| 99 |
]
|
| 100 |
|
| 101 |
-
# Elementos boudoir adicionales (para modo no-hardcore)
|
| 102 |
self.hairstyles = [
|
| 103 |
"long loose tousled hair sensually framing the face and falling over shoulders",
|
| 104 |
"elegant waves cascading seductively down the back",
|
|
@@ -107,45 +98,36 @@ class BatArtPromptGenerator:
|
|
| 107 |
]
|
| 108 |
|
| 109 |
self.expressions = [
|
| 110 |
-
"seductive heavy-lidded gaze full of desire, lips slightly parted",
|
| 111 |
-
"confident sultry smirk with intense direct eye contact",
|
| 112 |
"subtle ecstasy expression, eyes half-closed, tongue grazing lower lip",
|
| 113 |
-
"playful
|
| 114 |
]
|
| 115 |
|
| 116 |
-
def build_prompt(
|
| 117 |
-
self,
|
| 118 |
-
celebrity: str,
|
| 119 |
-
hardcore: bool = True,
|
| 120 |
-
use_boudoir_poses: bool = False
|
| 121 |
-
) -> Tuple[str, str]:
|
| 122 |
color = random.choice(self.colors)
|
| 123 |
thong = random.choice(self.thongs).format(color=color)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
if hardcore:
|
| 126 |
pose = random.choice(self.poses_hardcore)
|
| 127 |
-
skirt = random.choice(self.miniskirts)
|
| 128 |
bg_weight = "subtle"
|
| 129 |
-
detail_focus = "razor sharp focus on vulva
|
|
|
|
| 130 |
else:
|
| 131 |
pose = random.choice(self.poses_boudoir_office) if use_boudoir_poses else random.choice(self.poses_hardcore)
|
| 132 |
-
skirt = random.choice(self.miniskirts)
|
| 133 |
bg_weight = "prominent"
|
| 134 |
hairstyle = random.choice(self.hairstyles)
|
| 135 |
expression = random.choice(self.expressions)
|
| 136 |
-
detail_focus = "sharp focus on intricate lace thong texture, wet cameltoe and facial expression"
|
| 137 |
-
|
| 138 |
-
angle = random.choice(self.angles)
|
| 139 |
-
light = random.choice(self.lighting)
|
| 140 |
-
background = random.choice(self.backgrounds)
|
| 141 |
-
|
| 142 |
-
extra_desc = ""
|
| 143 |
-
if not hardcore:
|
| 144 |
-
extra_desc = f"""
|
| 145 |
Hairstyle: {hairstyle}.
|
| 146 |
-
Expression: {expression}, flushed cheeks, wet lips."""
|
| 147 |
|
| 148 |
-
|
| 149 |
|
| 150 |
{pose},
|
| 151 |
|
|
@@ -166,7 +148,7 @@ visible anatomical details:
|
|
| 166 |
β’ sweat beads collecting in inguinal creases, perineum and between buttocks
|
| 167 |
β’ visible stretch marks, subtle cellulite and open pores on inner thighs
|
| 168 |
β’ erect hard nipples pressing against thin blouse or bra
|
| 169 |
-
β’ arousal fluid strands connecting vulva to pulled thong fabric{
|
| 170 |
|
| 171 |
photorealistic raw photo, 16K, Canon EOS R5 + RF 85mm f/1.2 @ f/1.4, extremely shallow depth of field, {detail_focus}, cinematic warm grading, visible natural skin imperfections, subsurface scattering on moist skin, (masterpiece, ultra-detailed anatomy, best quality:1.45), (watermark BATUTO-ART:0.4)
|
| 172 |
|
|
@@ -174,21 +156,16 @@ Negative prompt: blurry, deformed, bad anatomy, extra limbs, fused fingers, poor
|
|
| 174 |
|
| 175 |
caption = f"{celebrity} β’ {color} soaked thong β’ {'ultra-close hardcore crotch macro' if hardcore else 'boudoir office explicit visible thong'}"
|
| 176 |
|
| 177 |
-
return
|
| 178 |
|
| 179 |
-
def generate_five(
|
| 180 |
-
self,
|
| 181 |
-
celebrity: str,
|
| 182 |
-
hardcore: bool = True,
|
| 183 |
-
use_boudoir_poses: bool = False
|
| 184 |
-
) -> List[Tuple[str, str]]:
|
| 185 |
return [self.build_prompt(celebrity, hardcore, use_boudoir_poses) for _ in range(5)]
|
| 186 |
|
| 187 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 188 |
-
# FUNCIONES REVE
|
| 189 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 190 |
|
| 191 |
-
def save_image_locally(img: Image.Image, prefix: str = "
|
| 192 |
ts = int(time.time() * 1000)
|
| 193 |
fname = f"{prefix}_{ts}.png"
|
| 194 |
path = os.path.join(CARPETA_SALIDA, fname)
|
|
@@ -196,32 +173,38 @@ def save_image_locally(img: Image.Image, prefix: str = "batart_reve") -> str:
|
|
| 196 |
img.save(path, "PNG", optimize=True)
|
| 197 |
return path
|
| 198 |
except Exception as e:
|
| 199 |
-
print(f"Error guardando: {e}")
|
| 200 |
return None
|
| 201 |
|
| 202 |
def call_reve_api(prompt: str, api_key: str, aspect_ratio: str = "9:16", version: str = "latest", timeout: int = 120):
|
| 203 |
-
if not api_key.strip():
|
| 204 |
-
return None, "API Key
|
| 205 |
|
| 206 |
payload = {"prompt": prompt.strip(), "aspect_ratio": aspect_ratio, "version": version}
|
| 207 |
-
headers = {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
try:
|
| 210 |
-
|
| 211 |
-
if
|
| 212 |
-
return None, f"HTTP {
|
| 213 |
|
| 214 |
-
data =
|
| 215 |
if "image" not in data or not data["image"]:
|
| 216 |
-
return None, "
|
| 217 |
|
| 218 |
img_bytes = base64.b64decode(data["image"])
|
| 219 |
img = Image.open(BytesIO(img_bytes)).convert("RGB")
|
| 220 |
-
credits = data.get("credits_used",
|
| 221 |
-
return img, "", int(credits)
|
| 222 |
|
|
|
|
|
|
|
| 223 |
except Exception as e:
|
| 224 |
-
return None, str(e), 0
|
| 225 |
|
| 226 |
def generate_reve_batch(prompt: str, api_key: str, ratio: str, count: int, progress=gr.Progress()):
|
| 227 |
count = max(1, min(count, 6))
|
|
@@ -231,28 +214,32 @@ def generate_reve_batch(prompt: str, api_key: str, ratio: str, count: int, progr
|
|
| 231 |
futures = [exe.submit(call_reve_api, prompt, api_key, ratio) for _ in range(count)]
|
| 232 |
|
| 233 |
for i, future in enumerate(concurrent.futures.as_completed(futures)):
|
| 234 |
-
progress((i + 1) / count, desc=f"Generando {i+1}/{count}")
|
| 235 |
-
img, err,
|
| 236 |
if img:
|
| 237 |
path = save_image_locally(img)
|
| 238 |
if path:
|
| 239 |
images.append(img)
|
| 240 |
paths.append(path)
|
| 241 |
-
total_credits +=
|
| 242 |
if err:
|
| 243 |
errors.append(err)
|
| 244 |
|
| 245 |
-
status_lines = [f"**Resultado:** {len(images)} OK β’ {len(errors)} errores"]
|
| 246 |
-
if total_credits
|
|
|
|
| 247 |
if errors:
|
| 248 |
-
status_lines.append("**Errores:**")
|
| 249 |
-
status_lines.extend([f"β’ {
|
| 250 |
-
if len(errors) > 3:
|
|
|
|
| 251 |
|
| 252 |
-
|
|
|
|
|
|
|
| 253 |
|
| 254 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 255 |
-
# CHAT +
|
| 256 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 257 |
|
| 258 |
def chat_with_samba(messages: list, image_base64: str = None):
|
|
@@ -277,7 +264,7 @@ def chat_with_samba(messages: list, image_base64: str = None):
|
|
| 277 |
r.raise_for_status()
|
| 278 |
return r.json()["choices"][0]["message"]["content"]
|
| 279 |
except Exception as e:
|
| 280 |
-
return f"Error SambaNova: {str(e)}"
|
| 281 |
|
| 282 |
def analyze_uploaded_image(image: Image.Image, user_prompt: str):
|
| 283 |
buffered = BytesIO()
|
|
@@ -285,10 +272,12 @@ def analyze_uploaded_image(image: Image.Image, user_prompt: str):
|
|
| 285 |
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
|
| 286 |
|
| 287 |
system_msg = (
|
| 288 |
-
"Eres BATUTO: describes imΓ‘genes con mΓ‘xima crudeza anatΓ³mica explΓcita sin censura. "
|
| 289 |
-
"Detallas genitales
|
| 290 |
-
"
|
| 291 |
-
"
|
|
|
|
|
|
|
| 292 |
)
|
| 293 |
|
| 294 |
messages = [
|
|
@@ -299,13 +288,12 @@ def analyze_uploaded_image(image: Image.Image, user_prompt: str):
|
|
| 299 |
respuesta = chat_with_samba(messages, img_str)
|
| 300 |
|
| 301 |
prompt_en = f"""Hyperrealistic raw extreme close-up erotic photograph based on the described image,
|
| 302 |
-
photorealistic, 16K, Canon EOS R5 + RF 85mm f/1.2, shallow depth of field, visible pores, dense natural pubic hair, sweat beads in inguinal creases, glistening thick vaginal lubrication dripping, asymmetric swollen labia minora
|
| 303 |
|
| 304 |
Negative prompt: blurry, deformed, bad anatomy, censored, mosaic censor, bar censor, cartoon, plastic skin, airbrushed, modest pose, covered genitals, dry skin, no pubic hair, symmetrical labia, safe for work"""
|
| 305 |
|
| 306 |
return respuesta, prompt_en
|
| 307 |
-
|
| 308 |
-
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 309 |
# INTERFAZ GRADIO FINAL
|
| 310 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 311 |
|
|
@@ -313,519 +301,155 @@ def main():
|
|
| 313 |
generator = BatArtPromptGenerator()
|
| 314 |
|
| 315 |
with gr.Blocks(
|
| 316 |
-
title="BAT_ART β’ Ultra-Explicit
|
| 317 |
theme=gr.themes.Default(primary_hue="red", neutral_hue="slate"),
|
| 318 |
css="""
|
| 319 |
-
body { background-color: #0d1117; color: #c9d1d9; }
|
| 320 |
-
.gradio-container { max-width: 1280px; margin: auto; }
|
| 321 |
-
.prompt-box { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 14px; }
|
|
|
|
| 322 |
"""
|
| 323 |
) as demo:
|
| 324 |
|
| 325 |
gr.Markdown("# BAT_ART β’ Generador Ultra-ExplΓcito + Chat IA + REVE")
|
| 326 |
|
| 327 |
with gr.Tabs():
|
| 328 |
-
# βββ
|
| 329 |
with gr.Tab("Generador Prompts ExplΓcitos"):
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
prompt_gallery = gr.Gallery(
|
| 340 |
-
label="Prompts generados
|
| 341 |
-
columns=1, height=
|
| 342 |
)
|
|
|
|
| 343 |
selected_prompt = gr.Textbox(
|
| 344 |
-
label="Prompt seleccionado (editable)",
|
| 345 |
-
lines=12, max_lines=
|
| 346 |
-
elem_classes="prompt-box"
|
| 347 |
)
|
| 348 |
|
| 349 |
-
def
|
| 350 |
if not name.strip():
|
| 351 |
-
return [], ""
|
| 352 |
-
prompts = generator.generate_five(name.strip(), hardcore=hardcore, use_boudoir_poses=
|
| 353 |
return [[p[0], p[1]] for p in prompts], prompts[0][0] if prompts else ""
|
| 354 |
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
[celebrity_input, hardcore_checkbox,
|
| 358 |
-
[prompt_gallery, selected_prompt]
|
| 359 |
)
|
| 360 |
|
| 361 |
prompt_gallery.select(
|
| 362 |
-
lambda evt: evt.value[0] if evt.value else "",
|
| 363 |
-
None, selected_prompt
|
| 364 |
)
|
| 365 |
|
| 366 |
-
# βββ
|
| 367 |
-
with gr.Tab("Chat BATUTO + AnΓ‘lisis ImΓ‘genes"):
|
| 368 |
-
chatbot = gr.Chatbot(
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
|
| 373 |
-
def
|
| 374 |
history = history or []
|
| 375 |
if image:
|
| 376 |
desc, prompt_en = analyze_uploaded_image(image, message)
|
| 377 |
-
response = f"**DescripciΓ³n explΓcita
|
| 378 |
else:
|
| 379 |
messages = [{"role": "user", "content": message}]
|
| 380 |
response = chat_with_samba(messages)
|
| 381 |
history.append((message, response))
|
| 382 |
return "", history
|
| 383 |
|
| 384 |
-
|
| 385 |
-
|
|
|
|
|
|
|
|
|
|
| 386 |
)
|
| 387 |
|
| 388 |
-
# βββ
|
| 389 |
with gr.Tab("Generar ImΓ‘genes REVE"):
|
| 390 |
with gr.Row():
|
| 391 |
with gr.Column(scale=3):
|
| 392 |
-
|
| 393 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 394 |
with gr.Column(scale=1):
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
"long curly deep brown hair with soft waves",
|
| 407 |
-
"long layered red hair with voluminous style",
|
| 408 |
-
"long sleek black hair with glossy finish",
|
| 409 |
-
"long beach wave golden blonde hair",
|
| 410 |
-
"long braided chestnut hair with loose ends",
|
| 411 |
-
"intricate updo with honey highlights",
|
| 412 |
-
"long messy mahogany hair",
|
| 413 |
-
"long straight cherry red hair",
|
| 414 |
-
"long braided platinum hair with twists",
|
| 415 |
-
"long updo with strawberry blonde",
|
| 416 |
-
"long ponytail with sandy blonde"
|
| 417 |
-
],
|
| 418 |
-
"discovery_moments": [
|
| 419 |
-
"momentarily revealing lingerie as she adjusts her posture",
|
| 420 |
-
"subtly exposing lingerie while shifting weight between legs",
|
| 421 |
-
"accidentally revealing intimate details during a natural movement",
|
| 422 |
-
"playfully teasing the visibility of lingerie through fabric movement",
|
| 423 |
-
"unintentionally showing lingerie while reaching for an object",
|
| 424 |
-
"delicately revealing underwear as she crosses and uncrosses legs",
|
| 425 |
-
"offering a fleeting glimpse of lingerie during a graceful turn",
|
| 426 |
-
"exposing intimate apparel through the sheer fabric of her clothing",
|
| 427 |
-
"revealing lingerie edges while sitting down or standing up",
|
| 428 |
-
"showing subtle hints of underwear through strategic posing",
|
| 429 |
-
"creating an intimate reveal as the fabric clings to her form",
|
| 430 |
-
"allowing a private view of her lingerie during an unguarded moment",
|
| 431 |
-
"exposing delicate details through the transparency of her garment",
|
| 432 |
-
"revealing hidden layers through calculated body movements",
|
| 433 |
-
"creating sensual tension through partial concealment and revelation"
|
| 434 |
-
],
|
| 435 |
-
"voyeuristic_angles": [
|
| 436 |
-
"extreme low angle from floor level, tilted upward to capture intimate details",
|
| 437 |
-
"worm's-eye view focusing on the revealing moment from below",
|
| 438 |
-
"low angle emphasizing the voyeuristic perspective of discovered lingerie",
|
| 439 |
-
"camera positioned as if secretly observing from a hidden vantage point",
|
| 440 |
-
"upward angle creating the sensation of an unauthorized glimpse",
|
| 441 |
-
"shot from knee level capturing the accidental exposure",
|
| 442 |
-
"perspective from below simulating a hidden camera view",
|
| 443 |
-
"low vantage point emphasizing the forbidden nature of the view",
|
| 444 |
-
"angle that suggests the viewer is discovering something intimate",
|
| 445 |
-
"camera placement that enhances the feeling of witnessing a private moment",
|
| 446 |
-
"view from beneath creating a sense of intimate discovery",
|
| 447 |
-
"low-angle shot that makes the reveal feel more personal and intrusive",
|
| 448 |
-
"perspective that captures the moment as if by chance observation",
|
| 449 |
-
"angle that emphasizes the vulnerability of the exposed moment",
|
| 450 |
-
"shot composition that feels like a secret being uncovered"
|
| 451 |
-
],
|
| 452 |
-
"lingerie_reveal_actions": [
|
| 453 |
-
"adjusting her stockings while revealing the thong underneath",
|
| 454 |
-
"smoothing her skirt only to expose more lingerie accidentally",
|
| 455 |
-
"reaching up high causing her outfit to ride up and show underwear",
|
| 456 |
-
"bending over to pick something up, offering a view of her thong",
|
| 457 |
-
"crossing her legs in a way that pulls the fabric taut against lingerie",
|
| 458 |
-
"stretching languidly, causing her clothing to shift and reveal",
|
| 459 |
-
"turning quickly, creating a momentary flash of intimate apparel",
|
| 460 |
-
"sitting down with a graceful motion that exposes lingerie edges",
|
| 461 |
-
"standing up from a chair, her skirt riding up to show the thong",
|
| 462 |
-
"playing with her hair while her other hand accidentally lifts her skirt",
|
| 463 |
-
"leaning forward to examine something, revealing her lingerie line",
|
| 464 |
-
"arching her back in a stretch that lifts her clothing",
|
| 465 |
-
"shifting position on a sofa, causing her dress to hike up",
|
| 466 |
-
"bending at the waist to tie her shoe, exposing her underwear",
|
| 467 |
-
"reclining back with legs slightly parted, hinting at her thong"
|
| 468 |
-
],
|
| 469 |
-
"lingerie_sets": [
|
| 470 |
-
"black lace set with push-up bra, floral thong, and sheer thigh-high stockings with a lace top",
|
| 471 |
-
"red satin set with underwire bra, bow accents thong, and fishnet thigh-high stockings with a pattern",
|
| 472 |
-
"white mesh set with sheer-cup bra, transparent thong, and silk thigh-high stockings with a smooth finish",
|
| 473 |
-
"pink lace set with demi-cup bra, scalloped-edge thong, and thigh-high stockings with a garter",
|
| 474 |
-
"blue silk set with smooth-cup bra, a sleek thong, and velvet thigh-high stockings with a soft texture",
|
| 475 |
-
"green velvet set with padded bra, a textured thong, and satin thigh-high stockings with a subtle shine",
|
| 476 |
-
"purple satin set with balconette bra, a glossy thong, and mesh thigh-high stockings with a net pattern",
|
| 477 |
-
"yellow chiffon set with a light-coverage bra, a light thong, and thigh-high stockings with a light, airy feel",
|
| 478 |
-
"black mesh set with transparent-strap bra, a net-pattern thong, and opaque thigh-high stockings with a matte look",
|
| 479 |
-
"red lace set with embroidered bra, an embroidered thong, and sheer thigh-high stockings with a red tint",
|
| 480 |
-
"white satin set with pearl-accented bra, a pearl-detailed thong, and fishnet thigh-high stockings with a diamond pattern",
|
| 481 |
-
"pink silk set with delicate-lace-trim bra, a delicate-strap thong, and shiny silk thigh-high stockings",
|
| 482 |
-
"blue velvet set with a plush bra, a plush thong, and lace thigh-high stockings with a floral design",
|
| 483 |
-
"green lace set with a floral-pattern bra, a leaf-motif thong, and plush velvet thigh-high stockings",
|
| 484 |
-
"purple mesh set with sheer-panel bra, sheer-panel thong, and luxurious satin thigh-high stockings",
|
| 485 |
-
"yellow satin set with a shiny bra, a glossy thong, and transparent mesh thigh-high stockings",
|
| 486 |
-
"black chiffon set with a flowy-edged bra, a flowy-edged thong, and flowy chiffon thigh-high stockings",
|
| 487 |
-
"red mesh set with a bold bra, a bold-line thong, and opaque thigh-high stockings with a bold look",
|
| 488 |
-
"white lace set with a romantic bra, a romantic thong, and sheer thigh-high stockings for a subtle touch",
|
| 489 |
-
"pink velvet set with a soft-textured bra, a soft-pile thong, and fun fishnet thigh-high stockings",
|
| 490 |
-
"blue satin set with a sleek-line bra, a sleek thong, and elegant silk thigh_high stockings",
|
| 491 |
-
"green silk set with an elegant-feel bra, an elegant-drape thong, and romantic lace thigh_high stockings",
|
| 492 |
-
"purple chiffon set with an airy bra, an airy thong, and deep velvet thigh_high stockings",
|
| 493 |
-
"yellow lace set with a bright bra, a bright thong, and bright satin thigh_high stockings",
|
| 494 |
-
"black satin set with a luxurious bra, a luxurious thong, and edgy mesh thigh_high stockings",
|
| 495 |
-
"red velvet set with a deep-hued bra, a deep-colored thong, and airy chiffon thigh_high stockings",
|
| 496 |
-
"white mesh set with a modern bra, a modern-grid thong, and clean opaque thigh_high stockings",
|
| 497 |
-
"pink chiffon set with a feminine bra, a feminine-ruffle thong, and blush-pink sheer thigh_high stockings",
|
| 498 |
-
"blue lace set with a wave-pattern bra, a wave-pattern thong, and playful fishnet thigh_high stockings",
|
| 499 |
-
"green satin set with a natural-color bra, a natural-hued thong, and natural-color silk thigh_high stockings",
|
| 500 |
-
"purple velvet set with a royal-style bra, a royal-vibe thong, and ornate lace thigh_high stockings",
|
| 501 |
-
"yellow mesh set with a sunny-transparency bra, a sunny thong, and sunny velvet thigh_high stockings",
|
| 502 |
-
"black lace set with a gothic bra, a gothic-element thong, and thigh-high stockings with a shadow-black lace top",
|
| 503 |
-
"red silk set with a passionate bra, a passionate thong, and passionate-red mesh thigh-high stockings",
|
| 504 |
-
"white chiffon set with a pure-white bra, a pure-white thong, and pure-white chiffon thigh-high stockings",
|
| 505 |
-
"pink satin set with a blush-pink bra, a blush-pink thong, and soft opaque thigh-high stockings",
|
| 506 |
-
"blue velvet set with a deep-blue bra, a deep-blue thong, and sheer thigh-high stockings in a calm blue",
|
| 507 |
-
"green lace set with an envious-green bra, an envious-green thong, and green fishnet thigh-high stockings",
|
| 508 |
-
"purple mesh set with a mysterious bra, a mysterious thong, and lavender fishnet thigh-high stockings",
|
| 509 |
-
"yellow chiffon set with a joyful-yellow bra, a joyful-yellow thong, and sunny-yellow silk thigh-high stockings",
|
| 510 |
-
"black silk set with a night-black bra, a night-black thong, and shadow-black lace thigh-high stockings",
|
| 511 |
-
"red satin set with a fire-red bra, a fire-red thong, and deep-red velvet thigh-high stockings",
|
| 512 |
-
"white velvet set with a snow-white bra, a snow-white thong, and white-sheer thigh-high stockings",
|
| 513 |
-
"pink lace set with a rose-pink bra, a rose-pink thong, and pink-rose lace thigh-high stockings",
|
| 514 |
-
"blue mesh set with a sky-blue bra, a sky-blue thong, and sky-blue mesh thigh-high stockings",
|
| 515 |
-
"green chiffon set with a forest-green bra, a forest-green thong, and forest-green chiffon thigh-high stockings",
|
| 516 |
-
"purple satin set with a lavender bra, a lavender thong, and lavender lace thigh-high stockings",
|
| 517 |
-
"yellow velvet set with a sun-yellow bra, a sun-yellow thong, and sun-yellow velvet thigh-high stockings",
|
| 518 |
-
"black mesh set with a shadow-black bra, a shadow-black thong, and shadow-black mesh thigh-high stockings",
|
| 519 |
-
"red chiffon set with a sunset-red bra, a sunset-red thong, and sunset-red chiffon thigh-high stockings"
|
| 520 |
-
],
|
| 521 |
-
"colors": [
|
| 522 |
-
"deep ruby red", "classic black", "emerald green", "sapphire blue", "royal purple",
|
| 523 |
-
"champagne gold", "silver metallic", "burgundy wine", "chocolate brown", "ivory white",
|
| 524 |
-
"hot pink", "electric blue", "vibrant orange", "forest green", "midnight navy",
|
| 525 |
-
"soft lavender", "peachy coral", "platinum silver", "rose gold", "caramel nude"
|
| 526 |
-
],
|
| 527 |
-
"outfits": [
|
| 528 |
-
"a sleek fitted mini dress with a subtle texture",
|
| 529 |
-
"a stylish A-line mini skirt paired with a delicate blouse",
|
| 530 |
-
"a form-fitting bodycon dress with elegant draping",
|
| 531 |
-
"a sophisticated sheath mini dress with unique detailing",
|
| 532 |
-
"a playful skater dress with a flattering silhouette",
|
| 533 |
-
"a chic wrap mini dress that accentuates the waist",
|
| 534 |
-
"a trendy slip dress with a luxurious satin finish",
|
| 535 |
-
"a tailored pencil mini skirt with a modern cut",
|
| 536 |
-
"a flowing chiffon mini dress with intricate patterns",
|
| 537 |
-
"a form-fitting leather mini skirt with bold accents",
|
| 538 |
-
],
|
| 539 |
-
"expressions": [
|
| 540 |
-
"unaware of being observed, natural and relaxed",
|
| 541 |
-
"slightly self-conscious but continuing her actions",
|
| 542 |
-
"lost in thought, completely natural in her movements",
|
| 543 |
-
"playfully teasing but pretending not to notice the camera",
|
| 544 |
-
"focused on her task, unaware of the revealing moment",
|
| 545 |
-
"exuding quiet confidence while her lingerie becomes visible",
|
| 546 |
-
"appearing distracted, allowing natural exposure to occur",
|
| 547 |
-
"maintaining composure while her clothing shifts revealingly",
|
| 548 |
-
"exhibiting casual elegance despite the intimate exposure",
|
| 549 |
-
"completely absorbed in the moment, natural and unposed",
|
| 550 |
-
"displaying innocent unawareness of the camera's presence",
|
| 551 |
-
"showing subtle confidence in her accidental revelation",
|
| 552 |
-
"maintaining natural grace during the unintentional exposure",
|
| 553 |
-
"expressing quiet contemplation while partially exposed",
|
| 554 |
-
"radiating natural beauty in the unguarded moment"
|
| 555 |
-
],
|
| 556 |
-
"backgrounds": [
|
| 557 |
-
"a luxurious bedroom with soft ambient lighting",
|
| 558 |
-
"a modern office space during after-hours",
|
| 559 |
-
"a chic studio apartment with intimate atmosphere",
|
| 560 |
-
"a dimly lit lounge with moody shadows",
|
| 561 |
-
"a stylish hotel room with elegant decor",
|
| 562 |
-
"an industrial loft with dramatic lighting",
|
| 563 |
-
"a minimalist living space with clean lines",
|
| 564 |
-
"a Parisian balcony with romantic ambiance",
|
| 565 |
-
"a vintage boudoir with ornate details",
|
| 566 |
-
"a serene garden setting with natural beauty"
|
| 567 |
-
],
|
| 568 |
-
"lighting": [
|
| 569 |
-
"soft natural window light creating intimate shadows",
|
| 570 |
-
"dramatic chiaroscuro lighting emphasizing curves and reveals",
|
| 571 |
-
"warm golden hour glow enhancing skin tones",
|
| 572 |
-
"studio lighting with softboxes for a polished look",
|
| 573 |
-
"ambient moody lighting adding mystery and depth",
|
| 574 |
-
"rim lighting to accentuate silhouette and intimate details",
|
| 575 |
-
"cinematic lighting with subtle color grading",
|
| 576 |
-
"ethereal backlight creating a halo effect",
|
| 577 |
-
"dynamic spotlighting focusing on the revealed areas",
|
| 578 |
-
"low-key lighting enhancing the voyeuristic atmosphere"
|
| 579 |
-
],
|
| 580 |
-
"stockings": [
|
| 581 |
-
"sheer thigh-high stockings with a lace top",
|
| 582 |
-
"fishnet thigh-high stockings with a pattern",
|
| 583 |
-
"silk thigh-high stockings with a smooth finish",
|
| 584 |
-
"thigh-high stockings with a garter",
|
| 585 |
-
"velvet thigh-high stockings with a soft texture",
|
| 586 |
-
"satin thigh-high stockings with a subtle shine",
|
| 587 |
-
"mesh thigh-high stockings with a net pattern",
|
| 588 |
-
"thigh-high stockings with a light, airy feel",
|
| 589 |
-
"opaque thigh-high stockings with a matte look",
|
| 590 |
-
"sheer thigh-high stockings with a red tint",
|
| 591 |
-
"fishnet thigh-high stockings with a diamond pattern",
|
| 592 |
-
"shiny silk thigh-high stockings",
|
| 593 |
-
"lace thigh-high stockings with a floral design",
|
| 594 |
-
"plush velvet thigh-high stockings",
|
| 595 |
-
"luxurious satin thigh-high stockings",
|
| 596 |
-
"transparent mesh thigh-high stockings",
|
| 597 |
-
"flowy chiffon thigh-high stockings",
|
| 598 |
-
"opaque thigh-high stockings with a bold look",
|
| 599 |
-
"sheer thigh-high stockings for a subtle touch",
|
| 600 |
-
"fun fishnet thigh-high stockings",
|
| 601 |
-
"elegant silk thigh-high stockings",
|
| 602 |
-
"romantic lace thigh-high stockings",
|
| 603 |
-
"deep velvet thigh-high stockings",
|
| 604 |
-
"bright satin thigh-high stockings",
|
| 605 |
-
"edgy mesh thigh-high stockings",
|
| 606 |
-
"airy chiffon thigh-high stockings",
|
| 607 |
-
"clean opaque thigh-high stockings",
|
| 608 |
-
"blush-pink sheer thigh-high stockings",
|
| 609 |
-
"playful fishnet thigh-high stockings",
|
| 610 |
-
"natural-color silk thigh-high stockings",
|
| 611 |
-
"ornate lace thigh-high stockings",
|
| 612 |
-
"sunny velvet thigh-high stockings",
|
| 613 |
-
"thigh-high stockings with a shadow-black lace top",
|
| 614 |
-
"passionate-red mesh thigh-high stockings",
|
| 615 |
-
"pure-white chiffon thigh-high stockings",
|
| 616 |
-
"soft opaque thigh-high stockings",
|
| 617 |
-
"sheer thigh-high stockings in a calm blue",
|
| 618 |
-
"green fishnet thigh-high stockings",
|
| 619 |
-
"lavender fishnet thigh-high stockings",
|
| 620 |
-
"sunny-yellow silk thigh-high stockings",
|
| 621 |
-
"shadow-black lace thigh-high stockings",
|
| 622 |
-
"deep-red velvet thigh-high stockings",
|
| 623 |
-
"white-sheer thigh-high stockings",
|
| 624 |
-
"pink-rose lace thigh-high stockings",
|
| 625 |
-
"sky-blue mesh thigh-high stockings",
|
| 626 |
-
"forest-green chiffon thigh-high stockings",
|
| 627 |
-
"lavender lace thigh-high stockings",
|
| 628 |
-
"sun-yellow velvet thigh-high stockings",
|
| 629 |
-
"shadow-black mesh thigh-high stockings",
|
| 630 |
-
"sunset-red chiffon thigh-high stockings"
|
| 631 |
-
],
|
| 632 |
-
"lingerie_thongs": [
|
| 633 |
-
"floral thong", "bow accents thong", "transparent thong", "scalloped-edge thong",
|
| 634 |
-
"a sleek thong", "a textured thong", "a glossy thong", "a light thong",
|
| 635 |
-
"a net-pattern thong", "an embroidered thong", "a pearl-detailed thong",
|
| 636 |
-
"a delicate-strap thong", "a plush thong", "a leaf-motif thong",
|
| 637 |
-
"sheer-panel thong", "a shiny thong", "a flowy-edged thong", "a bold-line thong",
|
| 638 |
-
"a romantic thong", "a soft-pile thong", "a sleek thong", "an elegant-drape thong",
|
| 639 |
-
"an airy thong", "a bright thong", "a luxurious thong", "a deep-colored thong",
|
| 640 |
-
"a modern-grid thong", "a feminine-ruffle thong", "a wave-pattern thong",
|
| 641 |
-
"a natural-hued thong", "a royal-vibe thong", "a sunny thong", "a gothic-element thong",
|
| 642 |
-
"a passionate thong", "a pure-white thong", "a blush-pink thong", "a deep-blue thong",
|
| 643 |
-
"an envious-green thong", "a mysterious thong", "a joyful-yellow thong",
|
| 644 |
-
"a night-black thong", "a fire-red thong", "a snow-white thong", "a rose-pink thong",
|
| 645 |
-
"a sky-blue thong", "a sky-blue thong", "a forest-green thong", "a lavender thong", "a sun-yellow thong",
|
| 646 |
-
"a shadow-black thong", "a sunset-red thong"
|
| 647 |
-
],
|
| 648 |
-
"lingerie_bras": [
|
| 649 |
-
"push-up bra", "underwire bra", "sheer-cup bra", "demi-cup bra", "smooth-cup bra",
|
| 650 |
-
"padded bra", "balconette bra", "a light-coverage bra", "transparent-strap bra",
|
| 651 |
-
"embroidered bra", "pearl-accented bra", "delicate-lace-trim bra", "a plush bra",
|
| 652 |
-
"a floral-pattern bra", "sheer-panel bra", "a shiny bra", "a flowy-edged bra",
|
| 653 |
-
"a bold bra", "a romantic bra", "a soft-textured bra", "a sleek-line bra",
|
| 654 |
-
"an elegant-feel bra", "an airy bra", "a bright bra", "a luxurious bra",
|
| 655 |
-
"a deep-hued bra", "a modern bra", "a feminine bra", "a wave-pattern bra",
|
| 656 |
-
"a natural-color bra", "a royal-style bra", "a sunny-transparency bra", "a gothic bra",
|
| 657 |
-
"a passionate bra", "a pure-white bra", "a blush-pink bra", "a deep-blue bra",
|
| 658 |
-
"an envious-green bra", "a mysterious bra", "a joyful-yellow bra", "a night-black bra",
|
| 659 |
-
"a fire-red bra", "a snow-white bra", "a rose-pink bra", "a sky-blue bra",
|
| 660 |
-
"a forest-green bra", "a lavender bra", "a sun-yellow bra", "a shadow-black bra",
|
| 661 |
-
"a sunset-red bra"
|
| 662 |
-
]
|
| 663 |
-
}
|
| 664 |
-
class FashionPromptGenerator:
|
| 665 |
-
def __init__(self):
|
| 666 |
-
self.fashion_elements = fashion_elements
|
| 667 |
-
self.previous_prompts = set()
|
| 668 |
-
|
| 669 |
-
def generate_unique_prompt(self, celebrity_name):
|
| 670 |
-
"""Genera un prompt ΓΊnico evitando repeticiones"""
|
| 671 |
-
max_attempts = 10
|
| 672 |
-
for attempt in range(max_attempts):
|
| 673 |
-
prompt = self._build_prompt(celebrity_name)
|
| 674 |
-
prompt_hash = hash(prompt)
|
| 675 |
-
if prompt_hash not in self.previous_prompts:
|
| 676 |
-
self.previous_prompts.add(prompt_hash)
|
| 677 |
-
return prompt
|
| 678 |
-
# Si no encuentra ΓΊnico despuΓ©s de varios intentos, devuelve igual
|
| 679 |
-
return self._build_prompt(celebrity_name)
|
| 680 |
-
|
| 681 |
-
def _build_prompt(self, celebrity_name):
|
| 682 |
-
primary_color = random.choice(self.fashion_elements["colors"])
|
| 683 |
-
secondary_color = random.choice([c for c in self.fashion_elements["colors"] if c != primary_color])
|
| 684 |
-
|
| 685 |
-
outfit = random.choice(self.fashion_elements["outfits"])
|
| 686 |
-
thong = random.choice(self.fashion_elements["lingerie_thongs"])
|
| 687 |
-
bra = random.choice(self.fashion_elements["lingerie_bras"]) if random.random() > 0.3 else None
|
| 688 |
-
|
| 689 |
-
lingerie_item = f"{primary_color} {thong}"
|
| 690 |
-
if bra:
|
| 691 |
-
lingerie_item += f" and {secondary_color} {bra}"
|
| 692 |
-
|
| 693 |
-
discovery_moment = random.choice(self.fashion_elements["discovery_moments"])
|
| 694 |
-
reveal_action = random.choice(self.fashion_elements["lingerie_reveal_actions"])
|
| 695 |
-
voyeur_angle = random.choice(self.fashion_elements["voyeuristic_angles"])
|
| 696 |
-
hairstyle = random.choice(self.fashion_elements["hairstyles"])
|
| 697 |
-
background = random.choice(self.fashion_elements["backgrounds"])
|
| 698 |
-
lighting = random.choice(self.fashion_elements["lighting"])
|
| 699 |
-
expression = random.choice(self.fashion_elements["expressions"])
|
| 700 |
-
stocking = f"{primary_color} {random.choice(self.fashion_elements['stockings'])}"
|
| 701 |
-
|
| 702 |
-
prompt = f"""
|
| 703 |
-
Voyeuristic fashion photograph of {celebrity_name}, captured from {voyeur_angle}.
|
| 704 |
-
The composition creates an intimate, almost forbidden viewing experience, {discovery_moment}.
|
| 705 |
-
She is {reveal_action}, creating a natural and unposed moment of exposure.
|
| 706 |
-
|
| 707 |
-
She wears a {primary_color} {outfit} that subtly reveals her {lingerie_item} during movement.
|
| 708 |
-
Complemented by {stocking}. Her {hairstyle} frames her face as she maintains {expression}.
|
| 709 |
-
|
| 710 |
-
**Scene & Atmosphere:**
|
| 711 |
-
- **Setting:** {background} with {lighting}
|
| 712 |
-
- **Composition:** Full-body shot from below, maintaining complete figure visibility while emphasizing the intimate reveal
|
| 713 |
-
- **Mood:** Sensual, voyeuristic, natural, and subtly erotic
|
| 714 |
-
- **Focus:** Sharp detail on the revealed lingerie and facial expression, with soft background blur
|
| 715 |
-
|
| 716 |
-
**Technical Details:**
|
| 717 |
-
- Shot on professional DSLR with 85mm prime lens
|
| 718 |
-
- Shallow depth of field focusing on the intimate moment
|
| 719 |
-
- Natural skin tones with warm color grading
|
| 720 |
-
- Ultra HD resolution, professional retouching
|
| 721 |
-
|
| 722 |
-
The image captures a fleeting, intimate moment that feels both spontaneous and beautifully composed, emphasizing the sensual discovery of hidden lingerie through natural movement and expert framing.
|
| 723 |
-
|
| 724 |
-
Negative prompt: cropped body, cut off limbs, out of frame, border, harsh shadows, uneven lighting, (bad anatomy, deformed, ugly), blurry, noisy, oversaturated, text, watermark, signature, (anime, cartoon, 3d, painting), monochrome, low quality, plastic, doll, airbrushed, photoshopped, fake, surreal, explicit nudity, vulgar
|
| 725 |
-
"""
|
| 726 |
-
return prompt.strip()
|
| 727 |
-
|
| 728 |
-
def generate_five_prompts(self, celebrity_name):
|
| 729 |
-
"""Genera 5 prompts ΓΊnicos"""
|
| 730 |
-
self.previous_prompts.clear() # Limpiar historial para nueva generaciΓ³n
|
| 731 |
-
return [self.generate_unique_prompt(celebrity_name) for _ in range(5)]
|
| 732 |
-
|
| 733 |
-
|
| 734 |
-
def create_gradio_interface():
|
| 735 |
-
generator = FashionPromptGenerator()
|
| 736 |
-
|
| 737 |
-
with gr.Blocks(title="Voyeuristic Fashion Prompt Generator", theme=gr.themes.Soft(), css="""
|
| 738 |
-
.prompt-box {
|
| 739 |
-
border: 1px solid #e2e8f0;
|
| 740 |
-
border-radius: 8px;
|
| 741 |
-
padding: 16px;
|
| 742 |
-
margin-bottom: 16px;
|
| 743 |
-
background-color: #f8fafc;
|
| 744 |
-
}
|
| 745 |
-
.prompt-title {
|
| 746 |
-
font-weight: bold;
|
| 747 |
-
margin-bottom: 8px;
|
| 748 |
-
color: #4a5568;
|
| 749 |
-
}
|
| 750 |
-
.dark .prompt-box {
|
| 751 |
-
background-color: #2d3748;
|
| 752 |
-
border-color: #4a5568;
|
| 753 |
-
}
|
| 754 |
-
.dark .prompt-title {
|
| 755 |
-
color: #e2e8f0;
|
| 756 |
-
}
|
| 757 |
-
.header {
|
| 758 |
-
text-align: center;
|
| 759 |
-
margin-bottom: 20px;
|
| 760 |
-
}
|
| 761 |
-
""") as demo:
|
| 762 |
-
|
| 763 |
-
gr.Markdown("""
|
| 764 |
-
# π Voyeuristic Fashion Prompt Generator
|
| 765 |
-
*Create intimate, discovery-focused fashion prompts with sensual lingerie reveals*
|
| 766 |
-
""")
|
| 767 |
-
|
| 768 |
-
with gr.Row():
|
| 769 |
-
with gr.Column(scale=4):
|
| 770 |
-
celebrity_input = gr.Textbox(
|
| 771 |
-
label="Celebrity Name",
|
| 772 |
-
placeholder="Enter celebrity name (e.g., Scarlett Johansson, Zendaya, Ana de Armas...)",
|
| 773 |
-
info="The celebrity who will appear in the sensual fashion prompts"
|
| 774 |
)
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
elem_classes="prompt-box"
|
| 796 |
)
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
| 806 |
-
|
| 807 |
-
|
| 808 |
-
|
| 809 |
-
|
| 810 |
-
|
| 811 |
-
|
| 812 |
-
|
| 813 |
-
|
| 814 |
-
|
| 815 |
-
|
| 816 |
-
clear_btn.click(
|
| 817 |
-
fn=clear_all,
|
| 818 |
-
inputs=None,
|
| 819 |
-
outputs=prompt_columns + output_prompts
|
| 820 |
-
)
|
| 821 |
-
|
| 822 |
-
gr.Markdown("---")
|
| 823 |
-
gr.Markdown("### π‘ Try these examples:")
|
| 824 |
-
gr.Examples(
|
| 825 |
-
examples=["Zendaya", "Ana de Armas", "Florence Pugh", "Sydney Sweeney", "Margot Robbie"],
|
| 826 |
-
inputs=celebrity_input,
|
| 827 |
-
outputs=prompt_columns + output_prompts,
|
| 828 |
-
fn=generate_and_display_prompts,
|
| 829 |
-
cache_examples=False,
|
| 830 |
-
label="Click any example to generate prompts"
|
| 831 |
-
)
|
|
|
|
| 20 |
os.makedirs(CARPETA_SALIDA, exist_ok=True)
|
| 21 |
|
| 22 |
# Cambia por tus claves reales o usa variables de entorno
|
| 23 |
+
SAMBA_API_KEY = os.getenv("SAMBA_API_KEY", "")
|
| 24 |
REVE_API_KEY_DEFAULT = os.getenv("REVE_API_KEY", "")
|
| 25 |
|
| 26 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 27 |
+
# BATARTO PROMPT GENERATOR β MΓXIMA CRUDEZA
|
| 28 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 29 |
|
| 30 |
class BatArtPromptGenerator:
|
| 31 |
def __init__(self):
|
|
|
|
| 32 |
self.colors = [
|
| 33 |
"jet black", "blood red", "deep emerald", "royal purple", "neon hot pink",
|
| 34 |
"wet crimson", "bruised plum", "glistening obsidian", "sweaty caramel",
|
| 35 |
"midnight charcoal", "smoky burgundy", "electric violet"
|
| 36 |
]
|
| 37 |
|
|
|
|
| 38 |
self.thongs = [
|
| 39 |
"extremely thin sheer {color} lace thong soaked transparent clinging to swollen engorged labia majora",
|
| 40 |
"crotchless {color} mesh thong with puffy labia majora spilling out both sides",
|
|
|
|
| 42 |
"{color} string thong pulled painfully tight outlining erect clitoris and glistening vaginal folds",
|
| 43 |
"open-crotch {color} lace thong leaving dripping vaginal entrance and swollen clitoral hood completely exposed",
|
| 44 |
"wet-look {color} latex thong vacuum-molded to every vulvar fold and crease",
|
| 45 |
+
"see-through nude {color} mesh thong darkened and sticky from thick natural lubrication and dense curly pubic hair shadow"
|
| 46 |
]
|
| 47 |
|
|
|
|
| 48 |
self.miniskirts = [
|
| 49 |
"micro pleated black leather skirt violently hiked to waist exposing entire soaked thong and wet inner thighs",
|
| 50 |
"ultra-short red vinyl skirt rolled up revealing extreme cameltoe and glistening lubrication trails down thighs",
|
|
|
|
| 53 |
"pink satin micro skirt flipped up exposing ass cheeks and dripping thong string disappeared between buttocks"
|
| 54 |
]
|
| 55 |
|
|
|
|
| 56 |
self.poses_hardcore = [
|
| 57 |
"legs spread obscenely wide, hips thrust forward, thong soaked dark showing asymmetric protruding inner labia and erect clitoris outline",
|
| 58 |
"squatting low knees far apart, fingers pulling thong aside exposing slick gaping vaginal opening and thick arousal strings",
|
|
|
|
| 61 |
"on all fours back arched extremely, vulva and anus fully exposed, swollen labia hanging and glistening with fluids"
|
| 62 |
]
|
| 63 |
|
|
|
|
| 64 |
self.poses_boudoir_office = [
|
| 65 |
"standing legs slightly apart with torso twist, skirt delicately lifted revealing lace thong cameltoe, seductive direct gaze",
|
| 66 |
"sitting on desk edge one leg crossed high, skirt raised showing intricate thong texture and wet spot, confident sultry look",
|
|
|
|
| 69 |
"reclining on office sofa, knees bent and apart, thong clearly displayed with glistening fluids, eyes conveying subtle ecstasy"
|
| 70 |
]
|
| 71 |
|
|
|
|
| 72 |
self.angles = [
|
| 73 |
"extreme ultra-low wormβs eye view camera 15β25 cm from vulva filling most of frame with soaked thong and exposed anatomy",
|
| 74 |
"dramatic floor-level macro crotch shot looking straight up between widely parted thighs, razor focus on wet cameltoe and clit",
|
|
|
|
| 76 |
"contrapicado extremo casi pegado al suelo, vulva ocupando 60β75% del encuadre, tanga hundida mostrando clΓtoris hinchado y labios asimΓ©tricos"
|
| 77 |
]
|
| 78 |
|
|
|
|
| 79 |
self.lighting = [
|
| 80 |
"hard directional window light creating strong specular highlights on vaginal lubrication and sweat beads on inner thighs",
|
| 81 |
"soft diffuse natural daylight + subtle rim light outlining swollen labia and erect nipples through sheer fabric",
|
|
|
|
| 83 |
"dramatic chiaroscuro with deep shadows accentuating wetness, clitoral hood contour and labia volume"
|
| 84 |
]
|
| 85 |
|
|
|
|
| 86 |
self.backgrounds = [
|
| 87 |
"modern executive office with floor-to-ceiling windows flooding natural daylight and city views",
|
| 88 |
"minimalist chic office, large windows creating soft reflections on glass and marble",
|
|
|
|
| 90 |
"sophisticated executive room with polished wood desk and huge windows"
|
| 91 |
]
|
| 92 |
|
|
|
|
| 93 |
self.hairstyles = [
|
| 94 |
"long loose tousled hair sensually framing the face and falling over shoulders",
|
| 95 |
"elegant waves cascading seductively down the back",
|
|
|
|
| 98 |
]
|
| 99 |
|
| 100 |
self.expressions = [
|
| 101 |
+
"seductive heavy-lidded gaze full of desire, lips slightly parted and glistening",
|
| 102 |
+
"confident sultry smirk with intense direct eye contact and wet lips",
|
| 103 |
"subtle ecstasy expression, eyes half-closed, tongue grazing lower lip",
|
| 104 |
+
"playful hungry look, eyebrow raised, flushed cheeks and parted lips"
|
| 105 |
]
|
| 106 |
|
| 107 |
+
def build_prompt(self, celebrity: str, hardcore: bool = True, use_boudoir_poses: bool = False) -> Tuple[str, str]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
color = random.choice(self.colors)
|
| 109 |
thong = random.choice(self.thongs).format(color=color)
|
| 110 |
+
skirt = random.choice(self.miniskirts)
|
| 111 |
+
angle = random.choice(self.angles)
|
| 112 |
+
light = random.choice(self.lighting)
|
| 113 |
+
background = random.choice(self.backgrounds)
|
| 114 |
|
| 115 |
if hardcore:
|
| 116 |
pose = random.choice(self.poses_hardcore)
|
|
|
|
| 117 |
bg_weight = "subtle"
|
| 118 |
+
detail_focus = "razor sharp focus on vulva, soaked thong texture and dripping fluids"
|
| 119 |
+
extra = ""
|
| 120 |
else:
|
| 121 |
pose = random.choice(self.poses_boudoir_office) if use_boudoir_poses else random.choice(self.poses_hardcore)
|
|
|
|
| 122 |
bg_weight = "prominent"
|
| 123 |
hairstyle = random.choice(self.hairstyles)
|
| 124 |
expression = random.choice(self.expressions)
|
| 125 |
+
detail_focus = "sharp focus on intricate lace thong texture, visible wet cameltoe, swollen labia outline and facial expression"
|
| 126 |
+
extra = f"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
Hairstyle: {hairstyle}.
|
| 128 |
+
Expression: {expression}, flushed cheeks, wet parted lips."""
|
| 129 |
|
| 130 |
+
prompt_text = f"""Ultra-detailed hyperrealistic erotic office photograph of {celebrity},
|
| 131 |
|
| 132 |
{pose},
|
| 133 |
|
|
|
|
| 148 |
β’ sweat beads collecting in inguinal creases, perineum and between buttocks
|
| 149 |
β’ visible stretch marks, subtle cellulite and open pores on inner thighs
|
| 150 |
β’ erect hard nipples pressing against thin blouse or bra
|
| 151 |
+
β’ arousal fluid strands connecting vulva to pulled thong fabric{extra}
|
| 152 |
|
| 153 |
photorealistic raw photo, 16K, Canon EOS R5 + RF 85mm f/1.2 @ f/1.4, extremely shallow depth of field, {detail_focus}, cinematic warm grading, visible natural skin imperfections, subsurface scattering on moist skin, (masterpiece, ultra-detailed anatomy, best quality:1.45), (watermark BATUTO-ART:0.4)
|
| 154 |
|
|
|
|
| 156 |
|
| 157 |
caption = f"{celebrity} β’ {color} soaked thong β’ {'ultra-close hardcore crotch macro' if hardcore else 'boudoir office explicit visible thong'}"
|
| 158 |
|
| 159 |
+
return prompt_text.strip(), caption
|
| 160 |
|
| 161 |
+
def generate_five(self, celebrity: str, hardcore: bool = True, use_boudoir_poses: bool = False) -> List[Tuple[str, str]]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
return [self.build_prompt(celebrity, hardcore, use_boudoir_poses) for _ in range(5)]
|
| 163 |
|
| 164 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 165 |
+
# FUNCIONES REVE
|
| 166 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 167 |
|
| 168 |
+
def save_image_locally(img: Image.Image, prefix: str = "batart") -> str:
|
| 169 |
ts = int(time.time() * 1000)
|
| 170 |
fname = f"{prefix}_{ts}.png"
|
| 171 |
path = os.path.join(CARPETA_SALIDA, fname)
|
|
|
|
| 173 |
img.save(path, "PNG", optimize=True)
|
| 174 |
return path
|
| 175 |
except Exception as e:
|
| 176 |
+
print(f"Error guardando imagen: {e}")
|
| 177 |
return None
|
| 178 |
|
| 179 |
def call_reve_api(prompt: str, api_key: str, aspect_ratio: str = "9:16", version: str = "latest", timeout: int = 120):
|
| 180 |
+
if not api_key or not api_key.strip():
|
| 181 |
+
return None, "API Key REVE vacΓa o invΓ‘lida", 0
|
| 182 |
|
| 183 |
payload = {"prompt": prompt.strip(), "aspect_ratio": aspect_ratio, "version": version}
|
| 184 |
+
headers = {
|
| 185 |
+
"Authorization": f"Bearer {api_key.strip()}",
|
| 186 |
+
"Content-Type": "application/json",
|
| 187 |
+
"Accept": "application/json"
|
| 188 |
+
}
|
| 189 |
|
| 190 |
try:
|
| 191 |
+
r = requests.post(REVE_API_URL, headers=headers, json=payload, timeout=timeout)
|
| 192 |
+
if r.status_code != 200:
|
| 193 |
+
return None, f"HTTP {r.status_code} β {r.text[:200]}", 0
|
| 194 |
|
| 195 |
+
data = r.json()
|
| 196 |
if "image" not in data or not data["image"]:
|
| 197 |
+
return None, "No se recibiΓ³ campo 'image' vΓ‘lido", 0
|
| 198 |
|
| 199 |
img_bytes = base64.b64decode(data["image"])
|
| 200 |
img = Image.open(BytesIO(img_bytes)).convert("RGB")
|
| 201 |
+
credits = data.get("credits_used", data.get("credits_consumed", 0))
|
| 202 |
+
return img, "", int(credits or 0)
|
| 203 |
|
| 204 |
+
except requests.Timeout:
|
| 205 |
+
return None, "Timeout al contactar REVE API", 0
|
| 206 |
except Exception as e:
|
| 207 |
+
return None, f"ExcepciΓ³n en REVE: {str(e)}", 0
|
| 208 |
|
| 209 |
def generate_reve_batch(prompt: str, api_key: str, ratio: str, count: int, progress=gr.Progress()):
|
| 210 |
count = max(1, min(count, 6))
|
|
|
|
| 214 |
futures = [exe.submit(call_reve_api, prompt, api_key, ratio) for _ in range(count)]
|
| 215 |
|
| 216 |
for i, future in enumerate(concurrent.futures.as_completed(futures)):
|
| 217 |
+
progress((i + 1) / count, desc=f"Generando imagen {i+1}/{count}")
|
| 218 |
+
img, err, cred = future.result()
|
| 219 |
if img:
|
| 220 |
path = save_image_locally(img)
|
| 221 |
if path:
|
| 222 |
images.append(img)
|
| 223 |
paths.append(path)
|
| 224 |
+
total_credits += cred
|
| 225 |
if err:
|
| 226 |
errors.append(err)
|
| 227 |
|
| 228 |
+
status_lines = [f"**Resultado:** {len(images)} imΓ‘genes generadas OK β’ {len(errors)} errores"]
|
| 229 |
+
if total_credits > 0:
|
| 230 |
+
status_lines.append(f"CrΓ©ditos consumidos aproximados: {total_credits}")
|
| 231 |
if errors:
|
| 232 |
+
status_lines.append("**Errores detectados:**")
|
| 233 |
+
status_lines.extend([f"β’ {err}" for err in errors[:3]])
|
| 234 |
+
if len(errors) > 3:
|
| 235 |
+
status_lines.append(f"β¦ y {len(errors)-3} errores mΓ‘s.")
|
| 236 |
|
| 237 |
+
status_md = "\n".join(status_lines) if status_lines else "No se generaron imΓ‘genes"
|
| 238 |
+
|
| 239 |
+
return images, status_md, paths
|
| 240 |
|
| 241 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 242 |
+
# CHAT + ANΓLISIS DE IMΓGENES
|
| 243 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 244 |
|
| 245 |
def chat_with_samba(messages: list, image_base64: str = None):
|
|
|
|
| 264 |
r.raise_for_status()
|
| 265 |
return r.json()["choices"][0]["message"]["content"]
|
| 266 |
except Exception as e:
|
| 267 |
+
return f"Error al conectar con SambaNova: {str(e)}"
|
| 268 |
|
| 269 |
def analyze_uploaded_image(image: Image.Image, user_prompt: str):
|
| 270 |
buffered = BytesIO()
|
|
|
|
| 272 |
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
|
| 273 |
|
| 274 |
system_msg = (
|
| 275 |
+
"Eres BATUTO IA: describes imΓ‘genes con mΓ‘xima crudeza anatΓ³mica y explΓcita sin ninguna censura ni eufemismo. "
|
| 276 |
+
"Detallas genitales (vulva, clΓtoris hinchado, labios mayores carnosos e hinchados, labios menores asimΓ©tricos protruyentes con pliegues irregulares, entrada vaginal dilatada con lubricaciΓ³n viscosa goteando), "
|
| 277 |
+
"fluidos (hilos de lubricaciΓ³n natural, sudor en pliegues inguinales y perinΓ©, saliva en comisuras), "
|
| 278 |
+
"texturas (poros dilatados, vello pΓΊbico natural rizado y denso escapando de la tanga, estrΓas, celulitis sutil, brillos de humedad, marcas rojas de tela apretada), "
|
| 279 |
+
"ropa (tanga hundida marcando cameltoe extremo, tela mojada adherida revelando cada pliegue vulvar), "
|
| 280 |
+
"poses dinΓ‘micas y expresiones de placer intenso. Todo con detalle tΓ©cnico-sensorial absoluto."
|
| 281 |
)
|
| 282 |
|
| 283 |
messages = [
|
|
|
|
| 288 |
respuesta = chat_with_samba(messages, img_str)
|
| 289 |
|
| 290 |
prompt_en = f"""Hyperrealistic raw extreme close-up erotic photograph based on the described image,
|
| 291 |
+
photorealistic, 16K, Canon EOS R5 + RF 85mm f/1.2, shallow depth of field, visible pores, dense natural curly pubic hair escaping thong, sweat beads in inguinal creases and perineum, glistening thick vaginal lubrication dripping in strings, asymmetric swollen protruding labia minora with irregular folds, erect prominent clitoris with retracted hood, detailed moist skin textures and imperfections, subsurface scattering on wet areas, cinematic warm grading, (masterpiece, ultra-detailed anatomy:1.5), no censorship, (watermark BATUTO-ART:0.4)
|
| 292 |
|
| 293 |
Negative prompt: blurry, deformed, bad anatomy, censored, mosaic censor, bar censor, cartoon, plastic skin, airbrushed, modest pose, covered genitals, dry skin, no pubic hair, symmetrical labia, safe for work"""
|
| 294 |
|
| 295 |
return respuesta, prompt_en
|
| 296 |
+
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 297 |
# INTERFAZ GRADIO FINAL
|
| 298 |
# ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 299 |
|
|
|
|
| 301 |
generator = BatArtPromptGenerator()
|
| 302 |
|
| 303 |
with gr.Blocks(
|
| 304 |
+
title="BAT_ART β’ Ultra-Explicit 2026",
|
| 305 |
theme=gr.themes.Default(primary_hue="red", neutral_hue="slate"),
|
| 306 |
css="""
|
| 307 |
+
body { background-color: #0d1117; color: #c9d1d9; font-family: 'Segoe UI', sans-serif; }
|
| 308 |
+
.gradio-container { max-width: 1280px; margin: auto; padding: 1rem; }
|
| 309 |
+
.prompt-box { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 14px; margin: 8px 0; }
|
| 310 |
+
h1, h2, h3 { color: #ff6b6b; }
|
| 311 |
"""
|
| 312 |
) as demo:
|
| 313 |
|
| 314 |
gr.Markdown("# BAT_ART β’ Generador Ultra-ExplΓcito + Chat IA + REVE")
|
| 315 |
|
| 316 |
with gr.Tabs():
|
| 317 |
+
# βββ Generador Prompts βββ
|
| 318 |
with gr.Tab("Generador Prompts ExplΓcitos"):
|
| 319 |
+
with gr.Row():
|
| 320 |
+
celebrity_input = gr.Textbox(
|
| 321 |
+
label="Celebridad", placeholder="Ej: Ana de Armas, Sydney Sweeney, Zendaya",
|
| 322 |
+
value="Ana de Armas", scale=4
|
| 323 |
+
)
|
| 324 |
+
hardcore_checkbox = gr.Checkbox(
|
| 325 |
+
label="Modo Ultra-Hardcore Close-up (vulva explΓcita, lubricaciΓ³n goteando, clΓtoris visible)",
|
| 326 |
+
value=True, scale=1
|
| 327 |
+
)
|
| 328 |
+
boudoir_checkbox = gr.Checkbox(
|
| 329 |
+
label="Usar poses boudoir office elegantes", value=False, scale=1
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
btn_generate = gr.Button("Generar 5 Prompts Ultra-ExplΓcitos", variant="primary", size="lg")
|
| 333 |
|
| 334 |
prompt_gallery = gr.Gallery(
|
| 335 |
+
label="Prompts generados β selecciona uno para editar/copiar",
|
| 336 |
+
columns=1, height=380, show_label=False, object_fit="contain"
|
| 337 |
)
|
| 338 |
+
|
| 339 |
selected_prompt = gr.Textbox(
|
| 340 |
+
label="Prompt seleccionado (editable y listo para REVE)",
|
| 341 |
+
lines=12, max_lines=30, interactive=True,
|
| 342 |
+
show_copy_button=True, elem_classes="prompt-box"
|
| 343 |
)
|
| 344 |
|
| 345 |
+
def gen_prompts(name, hardcore, boudoir):
|
| 346 |
if not name.strip():
|
| 347 |
+
return [], "**Error:** Ingresa un nombre de celebridad."
|
| 348 |
+
prompts = generator.generate_five(name.strip(), hardcore=hardcore, use_boudoir_poses=boudoir)
|
| 349 |
return [[p[0], p[1]] for p in prompts], prompts[0][0] if prompts else ""
|
| 350 |
|
| 351 |
+
btn_generate.click(
|
| 352 |
+
gen_prompts,
|
| 353 |
+
inputs=[celebrity_input, hardcore_checkbox, boudoir_checkbox],
|
| 354 |
+
outputs=[prompt_gallery, selected_prompt]
|
| 355 |
)
|
| 356 |
|
| 357 |
prompt_gallery.select(
|
| 358 |
+
lambda evt: evt.value[0] if evt.value and isinstance(evt.value, list) else "",
|
| 359 |
+
inputs=None, outputs=selected_prompt
|
| 360 |
)
|
| 361 |
|
| 362 |
+
# βββ Chat + AnΓ‘lisis βββ
|
| 363 |
+
with gr.Tab("Chat BATUTO + AnΓ‘lisis de ImΓ‘genes"):
|
| 364 |
+
chatbot = gr.Chatbot(
|
| 365 |
+
height=620,
|
| 366 |
+
show_copy_button=True,
|
| 367 |
+
bubble_full_width=False,
|
| 368 |
+
avatar_images=(None, "https://api.dicebear.com/7.x/bottts/svg?seed=Batuto")
|
| 369 |
+
)
|
| 370 |
+
msg_input = gr.Textbox(placeholder="PregΓΊntame lo que sea o describe quΓ© analizar en detalle explΓcito...")
|
| 371 |
+
img_upload = gr.Image(type="pil", label="Sube una imagen para anΓ‘lisis anatΓ³mico ultra-detallado")
|
| 372 |
+
send_button = gr.Button("Enviar / Analizar", variant="primary")
|
| 373 |
|
| 374 |
+
def respond_chat(message, image, history):
|
| 375 |
history = history or []
|
| 376 |
if image:
|
| 377 |
desc, prompt_en = analyze_uploaded_image(image, message)
|
| 378 |
+
response = f"**BATUTO β DescripciΓ³n explΓcita mΓ‘xima:**\n{desc}\n\n```prompt\n{prompt_en}\n```"
|
| 379 |
else:
|
| 380 |
messages = [{"role": "user", "content": message}]
|
| 381 |
response = chat_with_samba(messages)
|
| 382 |
history.append((message, response))
|
| 383 |
return "", history
|
| 384 |
|
| 385 |
+
send_button.click(
|
| 386 |
+
respond_chat,
|
| 387 |
+
inputs=[msg_input, img_upload, chatbot],
|
| 388 |
+
outputs=[msg_input, chatbot],
|
| 389 |
+
queue=False
|
| 390 |
)
|
| 391 |
|
| 392 |
+
# βββ REVE Generator βββ
|
| 393 |
with gr.Tab("Generar ImΓ‘genes REVE"):
|
| 394 |
with gr.Row():
|
| 395 |
with gr.Column(scale=3):
|
| 396 |
+
api_key_input = gr.Textbox(
|
| 397 |
+
label="π REVE API Key (requerida)", type="password",
|
| 398 |
+
value=REVE_API_KEY_DEFAULT, placeholder="sk-..."
|
| 399 |
+
)
|
| 400 |
+
prompt_input = gr.Textbox(
|
| 401 |
+
label="Prompt para generar (viene del tab anterior o edΓtalo)",
|
| 402 |
+
lines=8, interactive=True, show_copy_button=True
|
| 403 |
+
)
|
| 404 |
with gr.Column(scale=1):
|
| 405 |
+
aspect_ratio = gr.Dropdown(
|
| 406 |
+
choices=["9:16", "2:3", "3:4", "1:1", "16:9"],
|
| 407 |
+
value="9:16", label="Aspect Ratio"
|
| 408 |
+
)
|
| 409 |
+
num_images = gr.Slider(1, 4, step=1, value=2, label="Cantidad de imΓ‘genes")
|
| 410 |
+
|
| 411 |
+
generate_reve_btn = gr.Button("π Generar ImΓ‘genes con REVE", variant="primary", size="lg")
|
| 412 |
+
|
| 413 |
+
reve_gallery = gr.Gallery(
|
| 414 |
+
label="ImΓ‘genes generadas", columns=2, height=680,
|
| 415 |
+
object_fit="contain", show_download_button=True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
)
|
| 417 |
+
status_output = gr.Markdown("")
|
| 418 |
+
|
| 419 |
+
paths_state = gr.State([])
|
| 420 |
+
|
| 421 |
+
open_folder_btn = gr.Button("π Abrir carpeta de generaciones", variant="secondary")
|
| 422 |
+
|
| 423 |
+
# Vincular prompt del tab anterior
|
| 424 |
+
selected_prompt.change(lambda x: x, selected_prompt, prompt_input)
|
| 425 |
+
|
| 426 |
+
def generate_reve(prompt, key, ratio, count, progress=gr.Progress()):
|
| 427 |
+
if not prompt.strip():
|
| 428 |
+
return [], "**Error:** El prompt estΓ‘ vacΓo. Selecciona o escribe uno.", []
|
| 429 |
+
if not key.strip():
|
| 430 |
+
return [], "**Error:** Ingresa tu REVE API Key.", []
|
| 431 |
+
return generate_reve_batch(prompt, key, ratio, int(count), progress)
|
| 432 |
+
|
| 433 |
+
generate_reve_btn.click(
|
| 434 |
+
generate_reve,
|
| 435 |
+
inputs=[prompt_input, api_key_input, aspect_ratio, num_images],
|
| 436 |
+
outputs=[reve_gallery, status_output, paths_state]
|
|
|
|
| 437 |
)
|
| 438 |
+
|
| 439 |
+
def open_folder_action(_paths):
|
| 440 |
+
import webbrowser
|
| 441 |
+
try:
|
| 442 |
+
webbrowser.open(f"file://{os.path.abspath(CARPETA_SALIDA)}")
|
| 443 |
+
return f"**Carpeta abierta:** {os.path.abspath(CARPETA_SALIDA)}"
|
| 444 |
+
except Exception as e:
|
| 445 |
+
return f"**Ruta de salida:** {os.path.abspath(CARPETA_SALIDA)}\n(Γ‘brela manualmente)\nError: {str(e)}"
|
| 446 |
+
|
| 447 |
+
open_folder_btn.click(open_folder_action, inputs=paths_state, outputs=status_output)
|
| 448 |
+
|
| 449 |
+
gr.Markdown("BATUTO IA β’ Sin lΓmites β’ MΓ‘xima crudeza anatΓ³mica β’ 2026")
|
| 450 |
+
|
| 451 |
+
demo.launch(share=True, server_name="0.0.0.0")
|
| 452 |
+
|
| 453 |
+
|
| 454 |
+
if __name__ == "__main__":
|
| 455 |
+
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|