Remove streak from prompt; support up to 3 animals and places
Browse files- build_prompt() no longer takes a streak argument — mood/extras tiers
removed in favour of a single fixed style (NUMZOO_STYLE)
- All selected places (up to 3) are now included in the prompt, same
as animals — previously only one random place was picked
- Pre-selection in the emoji picker bumped from 2 → 3 for both
animals and places so users start with a richer default selection
- Removed unused streak variable from pregenerate_image and
generate_on_demand call sites
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- app.py +4 -6
- image_generator.py +20 -28
app.py
CHANGED
|
@@ -121,8 +121,8 @@ def enter_name(player_name: str, state: dict):
|
|
| 121 |
gr.update(visible=True), # emoji picker
|
| 122 |
gr.update(visible=False), # game
|
| 123 |
gr.update(visible=False), # picker_level_md
|
| 124 |
-
random.sample(ANIMAL_EMOJIS,
|
| 125 |
-
random.sample(PLACE_EMOJIS,
|
| 126 |
)
|
| 127 |
except Exception as e:
|
| 128 |
print(f"enter_name error: {e}")
|
|
@@ -177,10 +177,9 @@ def pregenerate_image(state: dict):
|
|
| 177 |
try:
|
| 178 |
animals = state.get("selected_animals", [random.choice(ANIMAL_EMOJIS)])
|
| 179 |
places = state.get("selected_places", [random.choice(PLACE_EMOJIS)])
|
| 180 |
-
streak = state.get("streak", 0)
|
| 181 |
|
| 182 |
print(f"[pregenerate] level={level} | animals={animals} | places={places}")
|
| 183 |
-
result, prompt = generate_reward_image(
|
| 184 |
print(f"[pregenerate] level={level} done | prompt={prompt!r}")
|
| 185 |
|
| 186 |
if result is not None:
|
|
@@ -313,10 +312,9 @@ def generate_on_demand(state: dict, coll_items: list):
|
|
| 313 |
try:
|
| 314 |
animals = state.get("selected_animals", [random.choice(ANIMAL_EMOJIS)])
|
| 315 |
places = state.get("selected_places", [random.choice(PLACE_EMOJIS)])
|
| 316 |
-
streak = state.get("streak", 0)
|
| 317 |
|
| 318 |
print(f"[on_demand] level={level}")
|
| 319 |
-
result, prompt = generate_reward_image(
|
| 320 |
print(f"[on_demand] level={level} done")
|
| 321 |
|
| 322 |
if result is not None:
|
|
|
|
| 121 |
gr.update(visible=True), # emoji picker
|
| 122 |
gr.update(visible=False), # game
|
| 123 |
gr.update(visible=False), # picker_level_md
|
| 124 |
+
random.sample(ANIMAL_EMOJIS, 3),
|
| 125 |
+
random.sample(PLACE_EMOJIS, 3),
|
| 126 |
)
|
| 127 |
except Exception as e:
|
| 128 |
print(f"enter_name error: {e}")
|
|
|
|
| 177 |
try:
|
| 178 |
animals = state.get("selected_animals", [random.choice(ANIMAL_EMOJIS)])
|
| 179 |
places = state.get("selected_places", [random.choice(PLACE_EMOJIS)])
|
|
|
|
| 180 |
|
| 181 |
print(f"[pregenerate] level={level} | animals={animals} | places={places}")
|
| 182 |
+
result, prompt = generate_reward_image(animals, places)
|
| 183 |
print(f"[pregenerate] level={level} done | prompt={prompt!r}")
|
| 184 |
|
| 185 |
if result is not None:
|
|
|
|
| 312 |
try:
|
| 313 |
animals = state.get("selected_animals", [random.choice(ANIMAL_EMOJIS)])
|
| 314 |
places = state.get("selected_places", [random.choice(PLACE_EMOJIS)])
|
|
|
|
| 315 |
|
| 316 |
print(f"[on_demand] level={level}")
|
| 317 |
+
result, prompt = generate_reward_image(animals, places)
|
| 318 |
print(f"[on_demand] level={level} done")
|
| 319 |
|
| 320 |
if result is not None:
|
image_generator.py
CHANGED
|
@@ -71,11 +71,12 @@ NUMZOO_STYLE = (
|
|
| 71 |
# Prompt builder
|
| 72 |
# ---------------------------------------------------------------------------
|
| 73 |
|
| 74 |
-
def build_prompt(
|
| 75 |
-
#
|
| 76 |
-
animal_list
|
| 77 |
-
|
| 78 |
|
|
|
|
| 79 |
animal_names = [ANIMAL_MAP.get(a, "bunny") for a in animal_list]
|
| 80 |
if len(animal_names) == 1:
|
| 81 |
animal_text = animal_names[0]
|
|
@@ -84,25 +85,16 @@ def build_prompt(streak: int, animals: list[str], places: list[str]) -> str:
|
|
| 84 |
else:
|
| 85 |
animal_text = f"{animal_names[0]}, {animal_names[1]} and {animal_names[2]}"
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
if
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
mood = "super cute and happy"
|
| 94 |
-
extras = "glitter, pastel rainbow colors, big smile, joyful expression"
|
| 95 |
else:
|
| 96 |
-
|
| 97 |
-
extras = (
|
| 98 |
-
"magical sparkles, rainbow aura, tiny crown, looking amazed, "
|
| 99 |
-
"pastel colors, surrounded by glowing stars"
|
| 100 |
-
)
|
| 101 |
|
| 102 |
-
|
| 103 |
-
f"A {mood} {animal_text} {place_text}, {extras}, {NUMZOO_STYLE}"
|
| 104 |
-
)
|
| 105 |
-
return prompt
|
| 106 |
|
| 107 |
# ---------------------------------------------------------------------------
|
| 108 |
# Pipeline loader (cached globally — survives between ZeroGPU calls)
|
|
@@ -150,11 +142,11 @@ def get_pipeline():
|
|
| 150 |
# Core generation (always wrapped in try/except)
|
| 151 |
# ---------------------------------------------------------------------------
|
| 152 |
|
| 153 |
-
def _generate(
|
| 154 |
try:
|
| 155 |
pipe = get_pipeline()
|
| 156 |
-
prompt = build_prompt(
|
| 157 |
-
print(f"Generating |
|
| 158 |
|
| 159 |
result = pipe(
|
| 160 |
prompt=prompt,
|
|
@@ -180,10 +172,10 @@ if IS_HF_SPACE:
|
|
| 180 |
# duration=120: covers first-run model download (~30s) + load (~10s) + generate (~5s).
|
| 181 |
# On subsequent calls _pipe is already loaded so only ~5s of GPU time is used.
|
| 182 |
@spaces.GPU(duration=120)
|
| 183 |
-
def generate_reward_image(
|
| 184 |
"""Generate reward image on HF Spaces ZeroGPU."""
|
| 185 |
-
return _generate(
|
| 186 |
else:
|
| 187 |
-
def generate_reward_image(
|
| 188 |
"""Generate reward image locally."""
|
| 189 |
-
return _generate(
|
|
|
|
| 71 |
# Prompt builder
|
| 72 |
# ---------------------------------------------------------------------------
|
| 73 |
|
| 74 |
+
def build_prompt(animals: list[str], places: list[str]) -> str:
|
| 75 |
+
# Use ALL selected animals and places (up to 3 each)
|
| 76 |
+
animal_list = animals[:3] if animals else [random.choice(list(ANIMAL_MAP))]
|
| 77 |
+
place_list = places[:3] if places else [random.choice(list(PLACE_MAP))]
|
| 78 |
|
| 79 |
+
# Build animal text: "puppy", "puppy and bunny", "puppy, bunny and kitten"
|
| 80 |
animal_names = [ANIMAL_MAP.get(a, "bunny") for a in animal_list]
|
| 81 |
if len(animal_names) == 1:
|
| 82 |
animal_text = animal_names[0]
|
|
|
|
| 85 |
else:
|
| 86 |
animal_text = f"{animal_names[0]}, {animal_names[1]} and {animal_names[2]}"
|
| 87 |
|
| 88 |
+
# Build place text: "in a garden", "in a garden and under a rainbow", ...
|
| 89 |
+
place_texts = [PLACE_MAP.get(p, "in a magical garden") for p in place_list]
|
| 90 |
+
if len(place_texts) == 1:
|
| 91 |
+
place_text = place_texts[0]
|
| 92 |
+
elif len(place_texts) == 2:
|
| 93 |
+
place_text = f"{place_texts[0]} and {place_texts[1]}"
|
|
|
|
|
|
|
| 94 |
else:
|
| 95 |
+
place_text = f"{place_texts[0]}, {place_texts[1]} and {place_texts[2]}"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
+
return f"A cute {animal_text} {place_text}, {NUMZOO_STYLE}"
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
# ---------------------------------------------------------------------------
|
| 100 |
# Pipeline loader (cached globally — survives between ZeroGPU calls)
|
|
|
|
| 142 |
# Core generation (always wrapped in try/except)
|
| 143 |
# ---------------------------------------------------------------------------
|
| 144 |
|
| 145 |
+
def _generate(animals: list[str], places: list[str]):
|
| 146 |
try:
|
| 147 |
pipe = get_pipeline()
|
| 148 |
+
prompt = build_prompt(animals, places)
|
| 149 |
+
print(f"Generating | prompt: {prompt}")
|
| 150 |
|
| 151 |
result = pipe(
|
| 152 |
prompt=prompt,
|
|
|
|
| 172 |
# duration=120: covers first-run model download (~30s) + load (~10s) + generate (~5s).
|
| 173 |
# On subsequent calls _pipe is already loaded so only ~5s of GPU time is used.
|
| 174 |
@spaces.GPU(duration=120)
|
| 175 |
+
def generate_reward_image(animals: list[str], places: list[str]):
|
| 176 |
"""Generate reward image on HF Spaces ZeroGPU."""
|
| 177 |
+
return _generate(animals, places)
|
| 178 |
else:
|
| 179 |
+
def generate_reward_image(animals: list[str], places: list[str]):
|
| 180 |
"""Generate reward image locally."""
|
| 181 |
+
return _generate(animals, places)
|