Integrate trained NumZoo LoRA into the app
Browse files- Bundle the step-1250 FLUX.2-klein-4B style LoRA (lora/numzoo_klein.safetensors,
88MB via Git LFS) β chosen for strongest style + clean multi-animal, no overfit
- Load it in _load_pipeline_cpu() after from_pretrained (module/CPU scope, outside
the ZeroGPU budget); bulletproof try/except falls back to base model
- build_prompt() now prepends the "NUMZOO" trigger and appends "no text" (the
distilled 4-step klein otherwise renders the trigger word as a literal sign)
- Add peft to requirements.txt (required by load_lora_weights)
Local MPS test: cozy NumZoo style renders correctly, no trigger text, multi-animal
works. All 10 Puppeteer checks pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- .gitattributes +1 -0
- image_generator.py +24 -1
- lora/numzoo_klein.safetensors +3 -0
- requirements.txt +1 -0
.gitattributes
CHANGED
|
@@ -1 +1,2 @@
|
|
| 1 |
training/*.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 1 |
training/*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
lora/*.safetensors filter=lfs diff=lfs merge=lfs -text
|
image_generator.py
CHANGED
|
@@ -215,8 +215,17 @@ def build_subject(animals: list[str], places: list[str]) -> str:
|
|
| 215 |
return f"A cute {animal_text} {place_text}"
|
| 216 |
|
| 217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
def build_prompt(animals: list[str], places: list[str]) -> str:
|
| 219 |
-
|
|
|
|
|
|
|
| 220 |
|
| 221 |
# ---------------------------------------------------------------------------
|
| 222 |
# Pipeline loader β two-phase, following the reference ZeroGPU pattern:
|
|
@@ -254,6 +263,20 @@ def _load_pipeline_cpu() -> None:
|
|
| 254 |
torch_dtype=_dtype,
|
| 255 |
token=hf_token,
|
| 256 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
print("Pipeline loaded on CPU β ready for device placement.")
|
| 258 |
|
| 259 |
|
|
|
|
| 215 |
return f"A cute {animal_text} {place_text}"
|
| 216 |
|
| 217 |
|
| 218 |
+
# Trigger word the NumZoo LoRA learned to associate with the whole cozy aesthetic.
|
| 219 |
+
# Training captions were "NUMZOO. A cute {animals} {places}, <detail>", so the live
|
| 220 |
+
# prompt mirrors that prefix exactly β the trigger now carries the style, making the
|
| 221 |
+
# verbose NUMZOO_STYLE suffix redundant (kept as a constant for the dataset generator).
|
| 222 |
+
NUMZOO_TRIGGER = "NUMZOO"
|
| 223 |
+
|
| 224 |
+
|
| 225 |
def build_prompt(animals: list[str], places: list[str]) -> str:
|
| 226 |
+
# "no text" suppresses the model rendering the NUMZOO trigger word as a literal
|
| 227 |
+
# sign/title (the distilled 4-step klein is prone to this without it).
|
| 228 |
+
return f"{NUMZOO_TRIGGER}. {build_subject(animals, places)}, no text"
|
| 229 |
|
| 230 |
# ---------------------------------------------------------------------------
|
| 231 |
# Pipeline loader β two-phase, following the reference ZeroGPU pattern:
|
|
|
|
| 263 |
torch_dtype=_dtype,
|
| 264 |
token=hf_token,
|
| 265 |
)
|
| 266 |
+
|
| 267 |
+
# Apply the NumZoo style LoRA (trained on FLUX.2-klein-base-4B, loads on distilled).
|
| 268 |
+
# Bundled in the repo via Git LFS. Loaded here at module/CPU scope so it stays out
|
| 269 |
+
# of the ZeroGPU 60 s budget. Never crash the import β fall back to the base model.
|
| 270 |
+
lora_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lora", "numzoo_klein.safetensors")
|
| 271 |
+
if os.path.isfile(lora_path):
|
| 272 |
+
try:
|
| 273 |
+
_pipe.load_lora_weights(lora_path)
|
| 274 |
+
print(f"β
NumZoo LoRA loaded from {lora_path}")
|
| 275 |
+
except Exception as e:
|
| 276 |
+
print(f"β οΈ Could not load NumZoo LoRA ({e}) β using base model")
|
| 277 |
+
else:
|
| 278 |
+
print(f"β οΈ NumZoo LoRA not found at {lora_path} β using base model")
|
| 279 |
+
|
| 280 |
print("Pipeline loaded on CPU β ready for device placement.")
|
| 281 |
|
| 282 |
|
lora/numzoo_klein.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:077173e834475031559123fbdc5bed64a267aa8a3e7e389e6ac7ed1b8af8e2ae
|
| 3 |
+
size 92426536
|
requirements.txt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
diffusers>=0.30.0
|
| 2 |
transformers>=4.44.0
|
| 3 |
accelerate>=0.33.0
|
|
|
|
| 4 |
torch>=2.2.0
|
| 5 |
numpy<2
|
| 6 |
sentencepiece
|
|
|
|
| 1 |
diffusers>=0.30.0
|
| 2 |
transformers>=4.44.0
|
| 3 |
accelerate>=0.33.0
|
| 4 |
+
peft>=0.11.0
|
| 5 |
torch>=2.2.0
|
| 6 |
numpy<2
|
| 7 |
sentencepiece
|