| import random |
| import os |
| import torch |
|
|
| |
| if not hasattr(torch, "xpu"): |
| class _MockXPU: |
| is_available = staticmethod(lambda: False) |
| device_count = staticmethod(lambda: 0) |
| empty_cache = staticmethod(lambda: None) |
| manual_seed = staticmethod(lambda seed: None) |
| reset_peak_memory_stats = staticmethod(lambda: None) |
| max_memory_allocated = staticmethod(lambda: 0) |
| synchronize = staticmethod(lambda: None) |
| torch.xpu = _MockXPU() |
|
|
| |
| |
| |
|
|
| IS_HF_SPACE = os.environ.get("SPACE_ID") is not None |
| if IS_HF_SPACE: |
| import spaces |
| import sys |
|
|
| |
| |
| _orig_unraisable = sys.unraisablehook |
| def _unraisable_hook(args): |
| if args.exc_type is ValueError and "Invalid file descriptor" in str(args.exc_value): |
| return |
| _orig_unraisable(args) |
| sys.unraisablehook = _unraisable_hook |
|
|
| print("HF Space detected β model will load on first GPU call and stay cached in memory.") |
|
|
| |
| |
| |
|
|
| ANIMAL_MAP: dict[str, str] = { |
| "πΆ": "puppy", "π±": "kitten", "π°": "bunny", |
| "π¦": "baby fox", "πΌ": "baby panda", "π¨": "baby koala", |
| "π¦": "baby lion", "π―": "baby tiger", "πΈ": "baby frog", |
| "π§": "baby penguin", "π¦": "butterfly", "π¦": "unicorn", |
| } |
|
|
| PLACE_MAP: dict[str, str] = { |
| "π": "on a sunny beach with ocean waves", |
| "ποΈ": "on a snowy mountain top", |
| "πΈ": "in a cherry blossom garden", |
| "π": "under a rainbow", |
| "π": "on a glowing crescent moon", |
| "β": "surrounded by sparkling stars", |
| "π΄": "on a tropical island", |
| "π‘": "in a cosy cottage garden", |
| "πΊ": "in a field of tropical flowers", |
| "π": "in an enchanted mushroom forest", |
| } |
|
|
| |
| |
| NUMZOO_STYLE = ( |
| "kawaii children's book illustration, pastel anime art style, " |
| "soft painterly lighting, detailed rich background with warm fairy lights, " |
| "cozy magical atmosphere, cute chibi character with big sparkling eyes, " |
| "soft pastel color palette, highly detailed scene, no text" |
| ) |
|
|
| |
| |
| |
|
|
| def build_prompt(animals: list[str], places: list[str]) -> str: |
| |
| animal_list = animals[:3] if animals else [random.choice(list(ANIMAL_MAP))] |
| place_list = places[:3] if places else [random.choice(list(PLACE_MAP))] |
|
|
| |
| animal_names = [ANIMAL_MAP.get(a, "bunny") for a in animal_list] |
| if len(animal_names) == 1: |
| animal_text = animal_names[0] |
| elif len(animal_names) == 2: |
| animal_text = f"{animal_names[0]} and {animal_names[1]}" |
| else: |
| animal_text = f"{animal_names[0]}, {animal_names[1]} and {animal_names[2]}" |
|
|
| |
| place_texts = [PLACE_MAP.get(p, "in a magical garden") for p in place_list] |
| if len(place_texts) == 1: |
| place_text = place_texts[0] |
| elif len(place_texts) == 2: |
| place_text = f"{place_texts[0]} and {place_texts[1]}" |
| else: |
| place_text = f"{place_texts[0]}, {place_texts[1]} and {place_texts[2]}" |
|
|
| return f"A cute {animal_text} {place_text}, {NUMZOO_STYLE}" |
|
|
| |
| |
| |
|
|
| _pipe = None |
|
|
| def get_pipeline(): |
| global _pipe |
| if _pipe is not None: |
| return _pipe |
|
|
| from diffusers import FluxPipeline |
|
|
| hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN") |
|
|
| use_mps = (not IS_HF_SPACE) and (not torch.cuda.is_available()) and torch.backends.mps.is_available() |
| |
| dtype = torch.float16 if use_mps else torch.bfloat16 |
|
|
| print(f"Loading FLUX.1-schnell pipeline⦠(token={'set' if hf_token else 'NOT SET'}, dtype={dtype})") |
| _pipe = FluxPipeline.from_pretrained( |
| "black-forest-labs/FLUX.1-schnell", |
| torch_dtype=dtype, |
| token=hf_token, |
| ) |
|
|
| if IS_HF_SPACE: |
| |
| |
| _pipe = _pipe.to("cuda") |
| elif torch.cuda.is_available(): |
| _pipe = _pipe.to("cuda") |
| elif use_mps: |
| |
| |
| _pipe.enable_sequential_cpu_offload() |
| else: |
| _pipe = _pipe.to("cpu") |
|
|
| print("Pipeline ready.") |
| return _pipe |
|
|
| |
| |
| |
|
|
| def _generate(animals: list[str], places: list[str]): |
| try: |
| pipe = get_pipeline() |
| prompt = build_prompt(animals, places) |
| print(f"Generating | prompt: {prompt}") |
|
|
| result = pipe( |
| prompt=prompt, |
| num_inference_steps=4, |
| guidance_scale=0.0, |
| height=512, |
| width=512, |
| ) |
| return result.images[0], prompt |
|
|
| except Exception as e: |
| import traceback |
| print(f"[image_generator] β generation failed: {e}") |
| print(traceback.format_exc()) |
| return None, str(e) |
|
|
|
|
| |
| |
| |
|
|
| if IS_HF_SPACE: |
| |
| |
| @spaces.GPU(duration=120) |
| def generate_reward_image(animals: list[str], places: list[str]): |
| """Generate reward image on HF Spaces ZeroGPU.""" |
| return _generate(animals, places) |
| else: |
| def generate_reward_image(animals: list[str], places: list[str]): |
| """Generate reward image locally.""" |
| return _generate(animals, places) |
|
|