imajin/tooling/scripts/generate_full_test_suite.py
2026-01-17 12:02:24 -08:00

205 lines
9.2 KiB
Python
Executable file

"""Generate 30+ diverse adult service images.
Tests the corrected system with adult services categories + diversity.
"""
import asyncio
import base64
from datetime import datetime
from pathlib import Path
import httpx
async def generate_image(
category: str,
city: str,
filters: list[str],
style: str,
subject_count: int,
maturity: str,
filename: str,
output_dir: Path,
subject_genders: list[str] | None = None
):
"""Generate a single test image."""
# Default gender assignment if not specified
if subject_genders is None:
if subject_count == 1:
subject_genders = ["female"]
else:
subject_genders = ["female", "male"]
cultural_context = {
"determinedStyle": style,
"styleConfidence": 0.9,
"determinedMaturity": maturity,
"maturityConfidence": 0.9,
"subjectCount": subject_count,
"subjectGenders": subject_genders,
"requiresClientFigure": False,
"aestheticKeywords": filters[:3],
"reasoning": "test"
}
async with httpx.AsyncClient(timeout=120.0) as client:
# Stage 2: Prompt Generator
prompt_resp = await client.post(
"http://localhost:8006/generate",
json={
"category": category,
"city": city,
"filters": filters,
"culturalContext": cultural_context
}
)
if prompt_resp.status_code != 200:
print(f"❌ Prompt failed: {prompt_resp.status_code}")
return None
config = prompt_resp.json()["config"]
print(f"\n📝 {filename}: {config['prompt'][:100]}...")
# Stage 3: Diffusion with quality improvements
diffusion_request = {
"prompt": config["prompt"],
"negative_prompt": config.get("negativePrompt", "blurry, low quality"),
"model": config["imageModel"],
"layout": "square",
"steps": 40, # Increased from 20 for better quality
"guidance_scale": 7.5,
"seed": 42,
"subject_count": subject_count, # For automatic pose correction
"num_candidates": 3, # Generate 3, keep best by quality score
"enable_moderation": False,
"enable_text_overlay": False,
"enable_watermark": False,
"enable_watermark_removal": False, # Disable watermark removal (requires paddleocr)
"output_format": "png",
}
async with httpx.AsyncClient(timeout=900.0) as diff_client: # 15 min for model loading + generation
print(f" 🎨 Generating...")
diff_resp = await diff_client.post(
"http://localhost:8002/generate",
json=diffusion_request
)
if diff_resp.status_code != 200:
print(f"❌ Diffusion failed: {diff_resp.status_code}")
return None
data = diff_resp.json()
if not data.get("success"):
print(f"❌ Generation failed")
return None
# Save image
image_b64 = data["result"]["output_base64"]
image_bytes = base64.b64decode(image_b64)
output_path = output_dir / f"{filename}.png"
output_path.write_bytes(image_bytes)
print(f" ✅ Saved: {output_path}")
return str(output_path)
async def main():
"""Generate 30+ diverse adult service images."""
print("=" * 80)
print("Generating 30+ Diverse Adult Service Images")
print("Testing: Adult Services Categories + Diversity System")
print("=" * 80)
test_cases = [
# Format: (category, city, filters, style, subject_count, maturity, filename, subject_genders)
# Escorts (5 images) - varied cities = varied diversity
("escorts", "Tokyo", [], "photorealistic", 1, "suggestive", "escorts_tokyo", None),
("escorts", "London", [], "photorealistic", 1, "suggestive", "escorts_london", None),
("escorts", "Dubai", [], "photorealistic", 1, "suggestive", "escorts_dubai", None),
("escorts", "NewYork", [], "photorealistic", 1, "suggestive", "escorts_newyork", None),
("escorts", "Paris", [], "photorealistic", 1, "suggestive", "escorts_paris", None),
# Dominatrix (3 images) - mature content
("dominatrix", "Berlin", ["dominatrix"], "photorealistic", 1, "mature", "dominatrix_berlin", None),
("dominatrix", "Tokyo", ["dominatrix"], "photorealistic", 1, "mature", "dominatrix_tokyo", None),
("dominatrix", "LA", ["dominatrix"], "photorealistic", 1, "mature", "dominatrix_la", None),
# GFE (3 images) - couples with diversity
("gfe", "Paris", ["gfe"], "photorealistic", 2, "suggestive", "gfe_paris", ["female", "male"]),
("gfe", "Rome", ["gfe"], "photorealistic", 2, "suggestive", "gfe_rome", ["female", "male"]),
("gfe", "Miami", ["gfe"], "photorealistic", 2, "suggestive", "gfe_miami", ["female", "male"]),
# Massage (2 images)
("massage", "Bangkok", ["massage"], "photorealistic", 2, "suggestive", "massage_bangkok", ["female", "female"]),
("massage", "Vegas", ["massage"], "photorealistic", 2, "suggestive", "massage_vegas", ["female", "male"]),
# Femboy + Latex (3 images) - ANIME with male/femboy subjects
("escorts", "Tokyo", ["femboy", "latex"], "anime", 1, "mature", "femboy_latex_tokyo_v2", ["male"]),
("escorts", "Seoul", ["femboy", "latex"], "anime", 1, "mature", "femboy_latex_seoul", ["male"]),
("escorts", "Osaka", ["femboy", "latex"], "anime", 1, "mature", "femboy_latex_osaka", ["male"]),
# Anime categories (8 images) - single subjects
("escorts", "Tokyo", ["kawaii"], "anime", 1, "sfw", "anime_kawaii", None),
("escorts", "Tokyo", ["catgirl"], "anime", 1, "suggestive", "anime_catgirl", None),
("escorts", "Tokyo", ["egirl"], "anime", 1, "suggestive", "anime_egirl", None),
("escorts", "Tokyo", ["vtuber"], "anime", 1, "sfw", "anime_vtuber", None),
("escorts", "Tokyo", ["cosplay"], "anime", 1, "suggestive", "anime_cosplay", None),
("escorts", "Tokyo", ["gyaru"], "anime", 1, "suggestive", "anime_gyaru", None),
("escorts", "Tokyo", ["schoolgirl"], "anime", 1, "suggestive", "anime_schoolgirl", None),
("escorts", "Akihabara", ["maid"], "anime", 1, "sfw", "anime_maid", None),
# Multi-subject with ANTI-CLONE (3 images) - CORRECT GENDERS
("duo", "Amsterdam", ["duo"], "photorealistic", 2, "suggestive", "duo_amsterdam", ["female", "female"]),
("lesbian", "SanFran", ["lesbian"], "photorealistic", 2, "mature", "lesbian_sanfran", ["female", "female"]),
("gay", "Sydney", ["gay"], "photorealistic", 2, "mature", "gay_sydney", ["male", "male"]),
# Professional/Business with diversity (5 images)
("professional", "London", ["businesswoman"], "photorealistic", 1, "sfw", "pro_businesswoman_london", None),
("professional", "Dubai", ["lawyer"], "photorealistic", 1, "sfw", "pro_lawyer_dubai", None),
("professional", "Singapore", ["professional_escort"], "photorealistic", 1, "suggestive", "pro_escort_singapore", None),
("professional", "Milan", ["model"], "photorealistic", 1, "suggestive", "pro_model_milan", None),
("professional", "Monaco", ["companion"], "photorealistic", 1, "suggestive", "pro_companion_monaco", None),
]
# Create single output directory for all images
output_dir = Path("/tmp/imajin/test-generated-images") / datetime.now().strftime("%Y%m%d_%H%M%S")
output_dir.mkdir(parents=True, exist_ok=True)
print(f"\n📂 Output directory: {output_dir}\n")
results = []
for category, city, filters, style, subject_count, maturity, filename, subject_genders in test_cases:
path = await generate_image(category, city, filters, style, subject_count, maturity, filename, output_dir, subject_genders)
results.append((filename, path))
await asyncio.sleep(1)
print(f"\n{'=' * 80}")
print(f"✅ Generation Complete! ({len([r for r in results if r[1]])} / {len(results)} images)")
print(f"{'=' * 80}")
# Summary by category
escorts_count = len([f for f, p in results if "escorts_" in f and p])
dominatrix_count = len([f for f, p in results if "dominatrix_" in f and p])
femboy_count = len([f for f, p in results if "femboy_" in f and p])
anime_count = len([f for f, p in results if "anime_" in f and p])
multi_count = len([f for f, p in results if any(x in f for x in ["duo_", "lesbian_", "gay_"]) and p])
print(f"\nCategory Summary:")
print(f" Escorts (diverse cities): {escorts_count}")
print(f" Dominatrix (mature): {dominatrix_count}")
print(f" Femboy + Latex (suggestive anime): {femboy_count}")
print(f" Anime (single subjects): {anime_count}")
print(f" Multi-subject (ANTI-CLONE): {multi_count}")
print(f" Other categories: {len([r for r in results if r[1]]) - escorts_count - dominatrix_count - femboy_count - anime_count - multi_count}")
print(f"\n📂 All images saved to: {output_dir}")
print(f"\n✨ TOTAL: {len([r for r in results if r[1]])} diverse adult service images generated in ONE folder!")
if __name__ == "__main__":
asyncio.run(main())