Spaces:
Runtime error
Runtime error
File size: 29,186 Bytes
122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 122a610 5a17ae6 |
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
import gradio as gr
import random
from typing import Dict, Any, List
import json
import datetime
class HyperRealisticConfig:
ETHNICITIES = [
"Mediterranean", "Scandinavian", "Slavic", "Latin American",
"Middle Eastern", "East Asian", "South Asian", "African",
"Caribbean", "Polynesian", "Mixed Heritage"
]
BODY_TYPES = [
"athletic slender", "voluptuous curves", "petite feminine",
"toned hourglass", "soft natural", "elegant tall"
]
SKIN_DETAILS = [
"with subtle freckles and skin texture", "with dewy natural complexion",
"showing realistic skin pores and veins", "with natural skin imperfections",
"with subsurface scattering effect", "with delicate skin translucency"
]
PROFESSIONAL_ROLES = [
{
"role": "Executive Secretary",
"uniform": "form-fitting tailored black dress with silk blouse slightly unbuttoned",
"environment": "luxurious corporate office with marble floors",
"accessories": "slim tablet and leather portfolio",
"pose": "bending over conference table arranging documents"
},
{
"role": "Luxury Hotel Manager",
"uniform": "elegant navy blue blazer and pencil skirt riding up when seated",
"environment": "five-star hotel lobby with golden lighting",
"accessories": "gold name tag and master key cards",
"pose": "leaning forward to assist guest at reception"
},
{
"role": "Fashion Boutique Manager",
"uniform": "chic black designer dress with elegant draping that accents curves",
"environment": "high-end boutique with minimalist decor and spotlights",
"accessories": "designer handbag and inventory clipboard",
"pose": "kneeling to adjust mannequin display"
},
{
"role": "Corporate Lawyer",
"uniform": "sharp charcoal gray pantsuit with skirt hiking up when walking",
"environment": "modern law firm with floor-to-ceiling windows",
"accessories": "leather briefcase and legal documents",
"pose": "stretching to reach high shelf in law library"
},
{
"role": "Private Jet Attendant",
"uniform": "custom-fitted aviation uniform with skirt shortening when bending",
"environment": "luxurious private jet cabin with leather seats",
"accessories": "champagne flute and service tray",
"pose": "bending to serve passengers in low cabin"
},
{
"role": "Art Gallery Curator",
"uniform": "sleek black turtleneck and high-waisted trousers with visible panty lines",
"environment": "contemporary art gallery with dramatic lighting",
"accessories": "curator's catalog and white gloves",
"pose": "squatting to examine lower artwork"
},
{
"role": "University Professor",
"uniform": "elegant tweed blazer and knee-length skirt that rides up when seated",
"environment": "university library with wooden ladders",
"accessories": "academic books and reading glasses",
"pose": "reaching for book on high shelf"
},
{
"role": "Ballet Instructor",
"uniform": "black leotard with wrap skirt and visible dance belt lines",
"environment": "dance studio with wall mirrors and barre",
"accessories": "pointe shoe ribbon and demonstration stick",
"pose": "demonstrating deep plié at barre"
},
{
"role": "Yacht Stewardess",
"uniform": "crisp white polo and navy shorts that tighten when bending",
"environment": "luxury yacht deck at sunset with teak flooring",
"accessories": "silver tray with cocktails and nautical rope",
"pose": "leaning over side to adjust fenders"
},
{
"role": "Elegant Maid",
"uniform": "classic black maid dress with white lace apron that flips up",
"environment": "opulent mansion hallway with grand staircase",
"accessories": "feather duster and cleaning cart",
"pose": "bending to polish banister"
}
]
EVERYDAY_MOMENTS = [
{
"scene": "Morning Kitchen",
"action": "bending down to take something from the low oven causing shirt to rise",
"outfit": "oversized white t-shirt and cotton shorts with visible panty lines",
"setting": "sunlit kitchen with open window and morning light",
"accessories": "coffee mug on counter, apron hanging, fresh herbs",
"pose": "natural bending with back arched"
},
{
"scene": "Laundry Room",
"action": "bending over to take clothes from the dryer showing waistband",
"outfit": "sports top and fitted leggings with subtle sheer panels",
"setting": "laundry room with baskets and folding table",
"accessories": "basket of clean clothes, fabric softener",
"pose": "deep forward bend with legs straight"
},
{
"scene": "Gardening",
"action": "kneeling while planting flowers with shorts riding up",
"outfit": "light cotton sundress with thin straps and no bra lines",
"setting": "backyard garden with flower pots and watering system",
"accessories": "gardening gloves, watering can, trowel",
"pose": "kneeling with one leg forward"
},
{
"scene": "Home Yoga",
"action": "doing downward dog pose with leggings becoming translucent",
"outfit": "yoga leggings and crop top with sweat patches",
"setting": "living room with yoga mat and natural side lighting",
"accessories": "yoga block, water bottle, meditation app",
"pose": "inverted V-shape with head down"
},
{
"scene": "Shelf Cleaning",
"action": "stretching on tiptoes to reach a book showing midriff",
"outfit": "loose t-shirt and pajama shorts with lace trim visible",
"setting": "personal library with small ladder and dust particles",
"accessories": "feather duster, stack of books, reading glasses",
"pose": "full body stretch on toes"
},
{
"scene": "Dog Walk",
"action": "bending down to attach the leash with dress gaping",
"outfit": "floral summer dress with thin fabric blowing in wind",
"setting": "park at sunset with long shadows and golden hour",
"accessories": "leash, treat pouch, dog water bottle",
"pose": "squatting while holding excited dog"
},
{
"scene": "Terrace Coffee",
"action": "sitting with legs crossed, dropping a napkin and reaching",
"outfit": "silk blouse and pleated skirt that opens when seated",
"setting": "terrace with iron table and morning mist",
"accessories": "open book, tea cup, croissant",
"pose": "leaning forward from seated position"
},
{
"scene": "Climbing Stairs",
"action": "going up with shopping bags showing back view",
"outfit": "pencil skirt and fitted blouse with tension lines",
"setting": "spiral staircase in apartment with dramatic lighting",
"accessories": "shopping bags, keys in hand, mail",
"pose": "mid-step with weight on one leg"
},
{
"scene": "Changing Lightbulb",
"action": "standing on a chair with arms raised fully",
"outfit": "long t-shirt as dress with back lift when reaching",
"setting": "kitchen with pendant light and afternoon shadows",
"accessories": "new lightbulb, step stool, tool box",
"pose": "tiptoes on chair reaching upward"
},
{
"scene": "Post-Shower",
"action": "drying hair with towel that keeps slipping",
"outfit": "short towel wrapped tightly with damp edges",
"setting": "bathroom with foggy mirror and steam effect",
"accessories": "hairdryer, bathrobe on hook, skincare products",
"pose": "bent forward hair drying motion"
}
]
LACE_BIKINI_STYLES = [
"delicate black lace bikini with floral embroidery and sheer panels",
"sheer nude illusion bikini with scalloped lace edges and ribbon ties",
"burgundy silk bikini with Chantilly lace inserts and satin strings",
"ivory French lace bikini with pearl accents and delicate stitching",
"champagne colored lace bikini with geometric patterns and silk backing",
"deep emerald lace bikini with velvet trim and adjustable sides",
"rose gold metallic lace bikini with transparent mesh panels",
"midnight blue lace bikini with crystal beading and underwire support"
]
HOSIERY_STYLES = [
"black sheer thigh-high stockings with lace tops and stay-up silicone",
"nude ultra-sheer stockings with reinforced toes and back seam",
"fishnet thigh-highs with delicate diamond pattern and satin band",
"back-seam stockings with Cuban heel and vintage reinforcement",
"sheer to waist stockings with lace panel and no panty line",
"opaque tights with subtle sheen and reinforced gusset",
"stay-up stockings with French lace band and bow details",
"glossy finish stockings with sandalwood foot and sheer legs"
]
HEEL_STYLES = [
"black patent leather stilettos with pointed toe and slim heel",
"nude pumps with platform and ankle strap for stability",
"gold strappy sandals with multiple thin straps and high arch",
"black suede pointed-toe heels with cut-out details",
"red bottom Louboutin-style heels with glossy finish",
"clear PVC heels with geometric shapes and metallic accents",
"silver glitter block heels with ankle support and comfort pad",
"white leather slingbacks with kitten heel and bow detail"
]
HAIRSTYLES = [
"long wavy hair with natural volume and soft highlights",
"sleek straight hair with middle part and glossy finish",
"elegant updo with loose tendrils and pearl pins",
"beach waves with sun-kissed highlights and textured ends",
"high ponytail with smooth finish and subtle curls",
"braided crown with floral accents and soft flyaways",
"vintage Hollywood curls with deep side part",
"messy bun with face-framing strands and natural texture"
]
MAKEUP_STYLES = [
"natural glam with dewy skin, soft contour, and nude lips",
"smoky eye with winged liner and voluminous lashes",
"rosy cheeks with glossy lips and subtle highlighter",
"bold red lip with flawless matte foundation",
"bronzed goddess with shimmery eyeshadow and golden highlights",
"minimalist makeup with tinted moisturizer and mascara",
"vintage pin-up with defined brows and classic red lip",
"ethereal glow with iridescent highlighter and soft blush"
]
LIGHTING_DETAILS = [
"soft diffused lighting with a warm golden glow",
"dramatic chiaroscuro lighting with deep shadows",
"natural sunlight filtering through sheer curtains",
"studio lighting with a three-point setup for dimensionality",
"candlelit ambiance with flickering shadows",
"backlit silhouette with a soft halo effect",
"moody blue-toned lighting for a cinematic feel",
"sunset glow with lens flare and warm hues"
]
PHOTOGRAPHY_STYLES = [
"cinematic lighting with rim light and soft shadows",
"natural window light with lens flare and soft focus",
"studio softbox lighting with catchlights in eyes",
"golden hour backlighting with hair light effect",
"moody low-key lighting with dramatic contrasts",
"bright high-key lighting with minimal shadows",
"film noir inspired lighting with venetian blind patterns",
"ethereal foggy lighting with diffusion filter"
]
CAMERAS = ["Canon EOS R5", "Sony α7R V", "Nikon Z9", "Hasselblad X2D", "Phase One IQ4"]
LENSES = ["85mm f/1.2", "50mm f/1.4", "24-70mm f/2.8", "100mm f/2.8 macro", "135mm f/1.8"]
class HyperRealisticPromptGenerator:
def __init__(self):
self.config = HyperRealisticConfig()
self.history: List[Dict] = []
def _get_role_by_name(self, name: str) -> Dict:
return next((r for r in self.config.PROFESSIONAL_ROLES if r["role"] == name), self.config.PROFESSIONAL_ROLES[0])
def _get_moment_by_name(self, name: str) -> Dict:
return next((m for m in self.config.EVERYDAY_MOMENTS if m["scene"] == name), self.config.EVERYDAY_MOMENTS[0])
def _random_style(self):
return (
random.choice(self.config.BODY_TYPES),
random.choice(self.config.SKIN_DETAILS),
random.choice(self.config.LACE_BIKINI_STYLES),
random.choice(self.config.HOSIERY_STYLES),
random.choice(self.config.HEEL_STYLES),
random.choice(self.config.HAIRSTYLES),
random.choice(self.config.MAKEUP_STYLES),
random.choice(self.config.LIGHTING_DETAILS),
random.choice(self.config.PHOTOGRAPHY_STYLES),
random.choice(self.config.CAMERAS),
random.choice(self.config.LENSES)
)
def generate_role_prompt(self, ethnicity: str, role_name: str, nsfw_mode: bool = False) -> str:
role = self._get_role_by_name(role_name)
body, skin, lace, hosiery, heels, hairstyle, makeup, lighting, photo_style, camera, lens = self._random_style()
if nsfw_mode:
reveal = f"subtle reveal of {lace} through clothing during {role['pose']}"
underwear_desc = f"wearing {lace} under {role['uniform']}"
nudity = "artistic sensuality with focus on natural beauty"
else:
reveal = f"subtle hint of lace underwear during {role['pose']}"
underwear_desc = f"with delicate lace underwear under {role['uniform']}"
nudity = "elegant and professional with subtle sensuality"
prompt = (
f"Hyper-realistic 4K photograph, 9:16 vertical composition, full-body portrait from dynamic low angle, "
f"of a stunning {ethnicity.lower()} {role['role']} with {body} figure {skin}, "
f"{underwear_desc}, {hosiery}, {heels}, styled with {hairstyle}, and {makeup}. "
f"In {role['environment']}, captured during {role['pose']} causing {reveal}. "
f"{lighting}, {photo_style}, Camera: {camera} with {lens} lens, professional lighting setup, "
f"ultra-high resolution 16K, extreme detail showing skin texture with visible pores, "
f"realistic fabric wrinkles, subsurface scattering effect, cinematic depth of field. "
f"Professional atmosphere, elegant composition, {nudity}. "
f"Include {role['accessories']} in scene. --no explicit_nudity --style raw --stylize 150"
)
self.history.append({
"type": "role",
"ethnicity": ethnicity,
"role": role_name,
"nsfw": nsfw_mode,
"prompt": prompt,
"timestamp": datetime.datetime.now().isoformat()
})
return prompt
def generate_moment_prompt(self, ethnicity: str, moment_name: str, nsfw_mode: bool = False) -> str:
moment = self._get_moment_by_name(moment_name)
body, skin, lace, hosiery, heels, hairstyle, makeup, lighting, photo_style, camera, lens = self._random_style()
if nsfw_mode:
reveal = f"natural reveal of {lace} while {moment['action']}"
underwear_desc = f"wearing {lace} under {moment['outfit']}"
sensuality = "artistic intimate moment with sensual atmosphere"
else:
reveal = f"subtle suggestion of lace underwear while {moment['action']}"
underwear_desc = f"with delicate lace underwear under {moment['outfit']}"
sensuality = "natural private moment with elegant sensuality"
prompt = (
f"Hyper-realistic candid photograph, 9:16 vertical format, intimate low angle perspective, "
f"of a beautiful {ethnicity.lower()} woman with {body} physique {skin}, styled with {hairstyle}, and {makeup}. "
f"{underwear_desc}, {hosiery}, {heels}, in {moment['setting']}, "
f"captured during {moment['pose']}, {moment['action']}. "
f"{lighting}, {photo_style}, Camera: {camera} with {lens}, ultra-high detail 16K resolution, "
f"realistic skin texture with pores and fine hairs, fabric micro-details, "
f"natural lighting with soft shadows, cinematic composition. "
f"{sensuality}. Include {moment['accessories']} in scene. "
f"--no explicit_content --style photographic --stylize 180"
)
self.history.append({
"type": "moment",
"ethnicity": ethnicity,
"scene": moment_name,
"nsfw": nsfw_mode,
"prompt": prompt,
"timestamp": datetime.datetime.now().isoformat()
})
return prompt
def generate_batch_prompts(self, count: int, prompt_type: str, nsfw_mode: bool = False) -> List[str]:
prompts = []
for _ in range(count):
ethnicity = random.choice(self.config.ETHNICITIES)
if prompt_type == "roles":
role = random.choice([r["role"] for r in self.config.PROFESSIONAL_ROLES])
prompts.append(self.generate_role_prompt(ethnicity, role, nsfw_mode))
else:
moment = random.choice([m["scene"] for m in self.config.EVERYDAY_MOMENTS])
prompts.append(self.generate_moment_prompt(ethnicity, moment, nsfw_mode))
return prompts
def get_history(self) -> List[Dict]:
return self.history
def clear_history(self) -> str:
self.history = []
return "History cleared"
# Crear instancia del generador
generator = HyperRealisticPromptGenerator()
# JavaScript para copiar al portapapeles
copy_js = """
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(function() {
console.log('Text copied to clipboard');
}).catch(function(err) {
console.error('Could not copy text: ', err);
});
}
"""
def generate_batch_with_blocks(count, prompt_type, nsfw):
prompts = generator.generate_batch_prompts(count, prompt_type, nsfw)
blocks_html = ""
for i, prompt in enumerate(prompts, 1):
# Escapar comillas dobles para que el string de JavaScript funcione correctamente
escaped_prompt = prompt.replace('"', '\\"')
blocks_html += f"""
<div class="prompt-block">
<h4>📋 Prompt #{i}:</h4>
<textarea id="prompt-{i}" style="width: 100%; height: 150px; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-family: monospace; margin-bottom: 10px;" readonly>{prompt}</textarea>
<button class="copy-btn" onclick="copyToClipboard(`{escaped_prompt}`)">📋 Copy Prompt #{i}</button>
</div>
"""
return prompts, blocks_html
def export_history():
history = generator.get_history()
if not history:
return "No history to export"
filename = f"prompt_history_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
# Guardar en un archivo temporal para que Gradio lo pueda devolver
temp_path = f"/tmp/{filename}"
with open(temp_path, 'w', encoding='utf-8') as f:
json.dump(history, f, indent=2, ensure_ascii=False)
# Devolver el archivo para descarga. Gradio maneja esto automáticamente si se devuelve un archivo.
# Sin embargo, la función de Gradio debe estar diseñada para devolver un gr.File.
# Como la función original devuelve un string, la mantendré así y asumiré que el usuario
# manejará la descarga del archivo generado en el entorno de Gradio.
# Para el despliegue en Hugging Face, el archivo se crea en el directorio del Space.
# Para la prueba local, se puede devolver el path. Para Gradio en HF Spaces,
# es mejor que el usuario acceda al archivo directamente si es necesario.
# Para simplificar y seguir el código original, devolveré un mensaje de estado.
return f"History exported to {filename}. Check the Space's file system."
# Interfaz Gradio
with gr.Blocks(title="HyperRealistic Humanized Perfection Generator", theme=gr.themes.Soft(), css="""
.prompt-block {
border: 1px solid #e0e0e0;
border-radius: 10px;
padding: 15px;
margin: 10px 0;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.copy-btn {
background: #4CAF50;
color: white;
border: none;
padding: 8px 16px;
border-radius: 5px;
cursor: pointer;
margin-top: 10px;
}
.copy-btn:hover {
background: #45a049;
}
.tab-content {
padding: 20px;
}
.generated-prompt {
font-family: monospace;
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
border: 1px solid #e9ecef;
margin: 10px 0;
white-space: pre-wrap;
word-wrap: break-word;
}
""") as demo:
gr.Markdown("# 🌟 HyperRealistic Humanized Perfection Generator")
gr.Markdown("Generate ultra-realistic humanized prompts with perfect lace details in 9:16 vertical format")
# Inyectar JavaScript
gr.HTML(f"<script>{copy_js}</script>")
with gr.Tab("👔 Professional Roles"):
with gr.Row():
with gr.Column(scale=1):
role_ethnicity = gr.Dropdown(
choices=generator.config.ETHNICITIES,
label="🎭 Ethnicity",
value="Mediterranean",
interactive=True
)
role_selection = gr.Dropdown(
choices=[role["role"] for role in generator.config.PROFESSIONAL_ROLES],
label="💼 Professional Role",
value=generator.config.PROFESSIONAL_ROLES[0]["role"],
interactive=True
)
role_nsfw = gr.Checkbox(
label="🎨 Artistic NSFW Mode",
value=False,
info="Enable for more artistic sensuality"
)
generate_role_btn = gr.Button(
"✨ Generate Role Prompt",
variant="primary",
size="lg"
)
with gr.Column(scale=2):
role_output = gr.Textbox(
label="📝 Generated Prompt",
lines=6,
max_lines=10,
show_copy_button=True
)
role_prompt_block = gr.HTML(label="Prompt Block")
# Uso de .then() para actualizar el bloque HTML después de generar el prompt
def update_role_prompt_block(prompt):
# Escapar comillas dobles para el string de JavaScript
escaped_prompt = prompt.replace('"', '\\"')
return f"""
<div class="prompt-block">
<h4>📋 Prompt Ready to Copy:</h4>
<div class="generated-prompt">{prompt}</div>
<button class="copy-btn" onclick="copyToClipboard(`{escaped_prompt}`)">📋 Copy Prompt</button>
</div>
"""
generate_role_btn.click(
fn=generator.generate_role_prompt,
inputs=[role_ethnicity, role_selection, role_nsfw],
outputs=[role_output]
).then(
fn=update_role_prompt_block,
inputs=[role_output],
outputs=[role_prompt_block]
)
with gr.Tab("🏠 Everyday Moments"):
with gr.Row():
with gr.Column(scale=1):
moment_ethnicity = gr.Dropdown(
choices=generator.config.ETHNICITIES,
label="🎭 Ethnicity",
value="Latin American",
interactive=True
)
moment_selection = gr.Dropdown(
choices=[moment["scene"] for moment in generator.config.EVERYDAY_MOMENTS],
label="🌅 Daily Moment",
value=generator.config.EVERYDAY_MOMENTS[0]["scene"],
interactive=True
)
moment_nsfw = gr.Checkbox(
label="🎨 Artistic NSFW Mode",
value=False,
info="Enable for more artistic sensuality"
)
generate_moment_btn = gr.Button(
"✨ Generate Moment Prompt",
variant="primary",
size="lg"
)
with gr.Column(scale=2):
moment_output = gr.Textbox(
label="📝 Generated Prompt",
lines=6,
max_lines=10,
show_copy_button=True
)
moment_prompt_block = gr.HTML(label="Prompt Block")
# Uso de .then() para actualizar el bloque HTML después de generar el prompt
def update_moment_prompt_block(prompt):
# Escapar comillas dobles para el string de JavaScript
escaped_prompt = prompt.replace('"', '\\"')
return f"""
<div class="prompt-block">
<h4>📋 Prompt Ready to Copy:</h4>
<div class="generated-prompt">{prompt}</div>
<button class="copy-btn" onclick="copyToClipboard(`{escaped_prompt}`)">📋 Copy Prompt</button>
</div>
"""
generate_moment_btn.click(
fn=generator.generate_moment_prompt,
inputs=[moment_ethnicity, moment_selection, moment_nsfw],
outputs=[moment_output]
).then(
fn=update_moment_prompt_block,
inputs=[moment_output],
outputs=[moment_prompt_block]
)
with gr.Tab("🔄 Batch Generator"):
with gr.Row():
with gr.Column():
batch_count = gr.Slider(
minimum=1,
maximum=10,
value=3,
step=1,
label="Number of Prompts"
)
batch_type = gr.Radio(
choices=["roles", "moments"],
label="Prompt Type",
value="roles",
interactive=True
)
batch_nsfw = gr.Checkbox(
label="🎨 Artistic NSFW Mode",
value=False
)
generate_batch_btn = gr.Button(
"🔄 Generate Batch",
variant="primary"
)
with gr.Column():
batch_output = gr.JSON(
label="📦 Batch Prompts"
)
batch_prompt_blocks = gr.HTML(label="Batch Prompt Blocks")
generate_batch_btn.click(
fn=generate_batch_with_blocks,
inputs=[batch_count, batch_type, batch_nsfw],
outputs=[batch_output, batch_prompt_blocks]
)
with gr.Tab("📊 History & Export"):
with gr.Row():
with gr.Column():
history_display = gr.JSON(
label="📜 Prompt History",
value=generator.get_history
)
clear_history_btn = gr.Button(
"🗑️ Clear History",
variant="secondary"
)
with gr.Column():
export_btn = gr.Button(
"💾 Export History as JSON",
variant="primary"
)
export_status = gr.Textbox(
label="Export Status",
interactive=False
)
clear_history_btn.click(
fn=generator.clear_history,
inputs=[],
outputs=[export_status]
).then(
fn=generator.get_history,
inputs=[],
outputs=[history_display]
)
export_btn.click(
fn=export_history,
inputs=[],
outputs=[export_status]
)
demo.launch()
|