Offexb commited on
Commit
e23ca1c
·
verified ·
1 Parent(s): 27a8474

Delete train_style_lora.py

Browse files
Files changed (1) hide show
  1. train_style_lora.py +0 -157
train_style_lora.py DELETED
@@ -1,157 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Real, resumable SDXL LoRA trainer for Hugging Face ZeroGPU Spaces.
3
-
4
- ZeroGPU allocates the GPU per function call, so training is intentionally split
5
- into small resumable chunks. Each call resumes from weights/checkpoints/.
6
- The final REAL LoRA is weights/offex3dstyle.safetensors.
7
- """
8
- from __future__ import annotations
9
-
10
- import json
11
- import os
12
- import re
13
- import shutil
14
- import subprocess
15
- import sys
16
- import urllib.request
17
- from pathlib import Path
18
-
19
- import spaces # import before torch/diffusers in a ZeroGPU Space
20
-
21
- ROOT = Path(__file__).resolve().parent
22
- DATA = ROOT / "training_data"
23
- OUT = ROOT / "weights"
24
- CKPT = OUT / "checkpoints"
25
- TRAIN_SCRIPT = ROOT / "_hf_train_dreambooth_lora_sdxl.py"
26
- FINAL = OUT / "offex3dstyle.safetensors"
27
- STATE = OUT / "training_state.json"
28
-
29
- MODEL = os.getenv("MODEL_ID", "stabilityai/stable-diffusion-xl-base-1.0")
30
- HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("HF_HUB_TOKEN", "")
31
- TRAIN_SCRIPT_URL = os.getenv(
32
- "DIFFUSERS_TRAIN_SCRIPT_URL",
33
- "https://raw.githubusercontent.com/huggingface/diffusers/main/"
34
- "examples/dreambooth/train_dreambooth_lora_sdxl.py",
35
- )
36
-
37
- # Keep each ZeroGPU request bounded. Run Train again to continue the next chunk.
38
- CHUNK_STEPS = int(os.getenv("LORA_CHUNK_STEPS", "40"))
39
- TOTAL_STEPS = int(os.getenv("MAX_TRAIN_STEPS", "800"))
40
- RESOLUTION = int(os.getenv("TRAIN_RESOLUTION", "1024"))
41
- LR = float(os.getenv("LEARNING_RATE", "1e-4"))
42
- RANK = int(os.getenv("LORA_RANK", "16"))
43
- BATCH = int(os.getenv("TRAIN_BATCH_SIZE", "1"))
44
- ACCUM = int(os.getenv("GRAD_ACCUM", "1"))
45
- SEED = int(os.getenv("TRAIN_SEED", "42"))
46
- INSTANCE = os.getenv("LORA_TRIGGER", "offex3dstyle")
47
-
48
- OUT.mkdir(exist_ok=True)
49
- CKPT.mkdir(exist_ok=True)
50
-
51
-
52
- def images():
53
- return sorted(p for p in DATA.iterdir() if p.suffix.lower() in {".png", ".jpg", ".jpeg", ".webp"})
54
-
55
-
56
- def latest_checkpoint():
57
- found = []
58
- for p in CKPT.glob("checkpoint-*"):
59
- m = re.fullmatch(r"checkpoint-(\d+)", p.name)
60
- if m and p.is_dir():
61
- found.append((int(m.group(1)), p))
62
- return str(max(found)[1]) if found else None
63
-
64
-
65
- def current_step():
66
- p = latest_checkpoint()
67
- if not p:
68
- return 0
69
- m = re.search(r"checkpoint-(\d+)$", p)
70
- return int(m.group(1)) if m else 0
71
-
72
-
73
- def write_state(status, step, message=""):
74
- STATE.write_text(json.dumps({
75
- "status": status,
76
- "step": step,
77
- "total_steps": TOTAL_STEPS,
78
- "images": len(images()),
79
- "message": message,
80
- "final": str(FINAL) if FINAL.exists() else None,
81
- }, indent=2), encoding="utf-8")
82
-
83
-
84
- def download_trainer():
85
- if not TRAIN_SCRIPT.exists():
86
- print("Downloading official Diffusers SDXL LoRA trainer...")
87
- urllib.request.urlretrieve(TRAIN_SCRIPT_URL, TRAIN_SCRIPT)
88
-
89
-
90
- def build_command(target_steps, resume):
91
- cmd = [
92
- sys.executable, str(TRAIN_SCRIPT),
93
- "--pretrained_model_name_or_path", MODEL,
94
- "--instance_data_dir", str(DATA),
95
- "--output_dir", str(OUT),
96
- "--instance_prompt", f"a {INSTANCE} stylized 3D character",
97
- "--resolution", str(RESOLUTION),
98
- "--train_batch_size", str(BATCH),
99
- "--gradient_accumulation_steps", str(ACCUM),
100
- "--gradient_checkpointing",
101
- "--learning_rate", str(LR),
102
- "--lr_scheduler", "constant",
103
- "--lr_warmup_steps", "0",
104
- "--max_train_steps", str(target_steps),
105
- "--checkpointing_steps", str(max(10, min(40, CHUNK_STEPS))),
106
- "--seed", str(SEED),
107
- "--rank", str(RANK),
108
- "--mixed_precision", "fp16",
109
- "--use_8bit_adam",
110
- "--cache_latents",
111
- ]
112
- if HF_TOKEN:
113
- cmd += ["--token", HF_TOKEN]
114
- if resume:
115
- cmd += ["--resume_from_checkpoint", resume]
116
- return cmd
117
-
118
-
119
- @spaces.GPU(duration=60, size="large")
120
- def train_chunk():
121
- """Run one real training chunk on ZeroGPU and return a status message."""
122
- imgs = images()
123
- if len(imgs) < 5:
124
- return f"❌ training_data में कम से कम 5 images चाहिए; मिली {len(imgs)}।"
125
- if FINAL.exists():
126
- return f"✅ LoRA पहले से मौजूद है: {FINAL}"
127
-
128
- download_trainer()
129
- start = current_step()
130
- if start >= TOTAL_STEPS:
131
- return f"ℹ️ {start}/{TOTAL_STEPS} steps पूरे हैं; final export verify करें।"
132
-
133
- target = min(start + CHUNK_STEPS, TOTAL_STEPS)
134
- resume = latest_checkpoint()
135
- write_state("training", start, f"Running {start} -> {target}")
136
- print(f"REAL SDXL LoRA chunk: {start} -> {target}; resume={resume}")
137
-
138
- try:
139
- subprocess.run(build_command(target, resume), check=True)
140
- except subprocess.CalledProcessError as e:
141
- write_state("error", start, f"trainer exited with code {e.returncode}")
142
- return f"❌ Training failed (exit {e.returncode}). Logs में error देखें।"
143
-
144
- exported = OUT / "pytorch_lora_weights.safetensors"
145
- if target >= TOTAL_STEPS and exported.exists():
146
- shutil.copy2(exported, FINAL)
147
- write_state("complete", target, "Final LoRA exported.")
148
- return f"🎉 Training complete: {FINAL.name}"
149
-
150
- step = current_step()
151
- write_state("paused", step, "Chunk complete; run Train again to continue.")
152
- return f"✅ Chunk complete: {step}/{TOTAL_STEPS}. Train फिर दबाओ।"
153
-
154
-
155
- if __name__ == "__main__":
156
- print("This trainer is intended to be called from the Space UI via train_chunk().")
157
- print("It creates a REAL safetensors LoRA only after actual CUDA training completes.")