Ffgsd commited on
Commit
df3cf5f
·
verified ·
1 Parent(s): 6b29301

KiaraSasatImage Setup.py

Browse files
Files changed (1) hide show
  1. KiaraSasatImage Setup.py +439 -0
KiaraSasatImage Setup.py ADDED
@@ -0,0 +1,439 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ ========================================================================
4
+ KiaraSuperSpace v2 — ПОЛНЫЙ SETUP
5
+ ========================================================================
6
+ Скачивает модели + устанавливает кастомные ноды + создаёт start script.
7
+
8
+ Checkpoint: GonzaLomo v6.0 Photo XL DMD (LCM/Karras/cfg1)
9
+ LoRA: Super Skin Detailer + Realism Lora v3
10
+ Stage II: FLUX Klein 4B
11
+ Custom Nodes: KiaraPanels (ControlPanelSD + ControlPanelFlux + KiaraReferenceLatent)
12
+
13
+ Запуск:
14
+ python3 /workspace/setup_KiaraSuperSpace.py
15
+ ========================================================================
16
+ """
17
+
18
+ import os, subprocess, time, textwrap
19
+
20
+ HF_TOKEN = "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"
21
+ CIVITAI_TOKEN = "c371cc55e5bc388aba3083f9ad9b2cb7"
22
+ B = "/workspace/ComfyUI/models"
23
+ CN = "/workspace/ComfyUI/custom_nodes"
24
+
25
+ # =====================================================================
26
+ # МОДЕЛИ
27
+ # =====================================================================
28
+ HF = [
29
+ ("Comfy-Org/flux2-klein-4B", "split_files/diffusion_models/flux-2-klein-4b.safetensors",
30
+ f"{B}/diffusion_models", "flux-2-klein-4b.safetensors"),
31
+ ("Comfy-Org/flux2-klein-4B", "split_files/text_encoders/qwen_3_4b.safetensors",
32
+ f"{B}/text_encoders", "qwen_3_4b.safetensors"),
33
+ ("Comfy-Org/flux2-klein-4B", "split_files/vae/flux2-vae.safetensors",
34
+ f"{B}/vae", "flux2-vae.safetensors"),
35
+ ("Kim2091/UltraSharp", "4x-UltraSharp.pth",
36
+ f"{B}/upscale_models", "4x-UltraSharp.pth"),
37
+ ]
38
+
39
+ DIRECT = [
40
+ ("https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth",
41
+ f"{B}/sams", "sam_vit_b_01ec64.pth", "SAM ViT-B"),
42
+ ("https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8m.pt",
43
+ f"{B}/ultralytics/bbox", "face_yolov8m.pt", "Face YOLOv8m"),
44
+ ("https://huggingface.co/Bingsu/adetailer/resolve/main/hand_yolov8s.pt",
45
+ f"{B}/ultralytics/bbox", "hand_yolov8s.pt", "Hand YOLOv8s"),
46
+ ("https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8m-seg.pt",
47
+ f"{B}/ultralytics/segm", "person_yolov8m-seg.pt", "Person Segmenter"),
48
+ ]
49
+
50
+ CIVITAI = [
51
+ (f"https://civitai.com/api/download/models/2368123?type=Model&format=SafeTensor&size=pruned&fp=fp16&token={CIVITAI_TOKEN}",
52
+ f"{B}/checkpoints", "gonzalomoXLFluxPony_v60PhotoXLDMD.safetensors",
53
+ "GonzaLomo v6.0 Photo XL DMD (checkpoint)", 3000),
54
+ (f"https://civitai.com/api/download/models/1089573?token={CIVITAI_TOKEN}",
55
+ f"{B}/loras", None, "Super Skin Detailer (LoRA)", 50),
56
+ (f"https://civitai.com/api/download/models/2074888?token={CIVITAI_TOKEN}",
57
+ f"{B}/loras", None, "Realism Lora By Stable Yogi v3 (LoRA)", 50),
58
+ ]
59
+
60
+ # =====================================================================
61
+ # КАСТОМНАЯ НОДА — KiaraPanels
62
+ # =====================================================================
63
+ KIARA_PANELS_CODE = textwrap.dedent('''\
64
+ """
65
+ KiaraPanels - Control Panel nodes for Stage I (SD) and Stage II (Flux) workflows.
66
+ Drop this folder into ComfyUI/custom_nodes/ to use.
67
+ """
68
+
69
+ # ============================================================
70
+ # Stage I - SD Control Panel
71
+ # ============================================================
72
+ class ControlPanelSD:
73
+ CATEGORY = "KiaraPanels"
74
+ FUNCTION = "execute"
75
+ RETURN_TYPES = ("INT", "INT", "INT", "FLOAT")
76
+ RETURN_NAMES = ("width", "height", "steps", "cfg")
77
+
78
+ SD_PRESETS = {
79
+ "1:1 Square 512x512": (512, 512),
80
+ "1:1 Square 768x768": (768, 768),
81
+ "1:1 Square 1024x1024": (1024, 1024),
82
+ "2:3 Portrait 512x768": (512, 768),
83
+ "2:3 Portrait 768x1152": (768, 1152),
84
+ "3:2 Landscape 768x512": (768, 512),
85
+ "3:2 Landscape 1152x768": (1152, 768),
86
+ "9:16 Tall 576x1024": (576, 1024),
87
+ "16:9 Wide 1024x576": (1024, 576),
88
+ "9:16 Tall 720x1280": (720, 1280),
89
+ "16:9 Wide 1280x720": (1280, 720),
90
+ "4:7 Tall 576x1008": (576, 1008),
91
+ "9:16 Tall 896x1536": (896, 1536),
92
+ }
93
+
94
+ QUALITY_PRESETS = {
95
+ "Draft 4 steps": 4,
96
+ "Fast 8 steps": 8,
97
+ "Normal 12 steps": 12,
98
+ "High Quality 20 steps": 20,
99
+ "Ultra 30 steps": 30,
100
+ "Maximum 50 steps": 50,
101
+ }
102
+
103
+ @classmethod
104
+ def INPUT_TYPES(cls):
105
+ return {
106
+ "required": {
107
+ "resolution": (list(cls.SD_PRESETS.keys()), {"default": "9:16 Tall 896x1536"}),
108
+ "quality": (list(cls.QUALITY_PRESETS.keys()), {"default": "Fast 8 steps"}),
109
+ "cfg": ("FLOAT", {"default": 1.0, "min": 1.0, "max": 30.0, "step": 0.5}),
110
+ }
111
+ }
112
+
113
+ def execute(self, resolution, quality, cfg):
114
+ w, h = self.SD_PRESETS[resolution]
115
+ steps = self.QUALITY_PRESETS[quality]
116
+ return (w, h, steps, cfg)
117
+
118
+
119
+ # ============================================================
120
+ # Stage II - Flux Control Panel
121
+ # ============================================================
122
+ class ControlPanelFlux:
123
+ CATEGORY = "KiaraPanels"
124
+ FUNCTION = "execute"
125
+ RETURN_TYPES = ("INT", "INT", "INT")
126
+ RETURN_NAMES = ("width", "height", "steps")
127
+
128
+ FLUX_PRESETS = {
129
+ "1:1 Square 1024x1024": (1024, 1024),
130
+ "3:4 Portrait 896x1152": (896, 1152),
131
+ "4:3 Landscape 1152x896": (1152, 896),
132
+ "9:16 Tall 768x1344": (768, 1344),
133
+ "9:16 Tall 896x1536": (896, 1536),
134
+ "16:9 Wide 1344x768": (1344, 768),
135
+ "2:3 Portrait 832x1216": (832, 1216),
136
+ "3:2 Landscape 1216x832": (1216, 832),
137
+ }
138
+
139
+ QUALITY_PRESETS = {
140
+ "Fast 4 steps": 4,
141
+ "Normal 8 steps": 8,
142
+ "High Quality 16 steps": 16,
143
+ "Ultra 28 steps": 28,
144
+ }
145
+
146
+ @classmethod
147
+ def INPUT_TYPES(cls):
148
+ return {
149
+ "required": {
150
+ "resolution": (list(cls.FLUX_PRESETS.keys()), {"default": "9:16 Tall 896x1536"}),
151
+ "quality": (list(cls.QUALITY_PRESETS.keys()), {"default": "Fast 4 steps"}),
152
+ }
153
+ }
154
+
155
+ def execute(self, resolution, quality):
156
+ w, h = self.FLUX_PRESETS[resolution]
157
+ steps = self.QUALITY_PRESETS[quality]
158
+ return (w, h, steps)
159
+
160
+
161
+ # ============================================================
162
+ # Stage II - Reference Latent for FLUX Klein
163
+ # ============================================================
164
+ class KiaraReferenceLatent:
165
+ """
166
+ Injects VAE-encoded reference latent into conditioning for FLUX Klein.
167
+ Replicates kx7_cb243e9c ("Reference Latent").
168
+ Uses the native FLUX reference_latents mechanism.
169
+ """
170
+ CATEGORY = "KiaraPanels"
171
+ FUNCTION = "execute"
172
+ RETURN_TYPES = ("CONDITIONING",)
173
+
174
+ @classmethod
175
+ def INPUT_TYPES(cls):
176
+ return {
177
+ "required": {
178
+ "conditioning": ("CONDITIONING",),
179
+ },
180
+ "optional": {
181
+ "latent": ("LATENT",),
182
+ }
183
+ }
184
+
185
+ def execute(self, conditioning, latent=None):
186
+ if latent is None:
187
+ return (conditioning,)
188
+ import copy
189
+ c = []
190
+ for t in conditioning:
191
+ d = copy.deepcopy(t[1])
192
+ ref = latent["samples"]
193
+ if "reference_latents" in d:
194
+ d["reference_latents"] = d["reference_latents"] + [ref]
195
+ else:
196
+ d["reference_latents"] = [ref]
197
+ c.append([t[0], d])
198
+ return (c,)
199
+
200
+
201
+ # ============================================================
202
+ # Registration
203
+ # ============================================================
204
+ NODE_CLASS_MAPPINGS = {
205
+ "ControlPanelSD": ControlPanelSD,
206
+ "ControlPanelFlux": ControlPanelFlux,
207
+ "KiaraReferenceLatent": KiaraReferenceLatent,
208
+ }
209
+
210
+ NODE_DISPLAY_NAME_MAPPINGS = {
211
+ "ControlPanelSD": "Control Panel - SD",
212
+ "ControlPanelFlux": "Control Panel - Flux",
213
+ "KiaraReferenceLatent": "Reference Latent (FLUX)",
214
+ }
215
+ ''')
216
+
217
+ # =====================================================================
218
+ # УТИЛИТЫ
219
+ # =====================================================================
220
+ def fmt(b):
221
+ if b < 1024**2: return f"{b/1024:.1f} KB"
222
+ if b < 1024**3: return f"{b/1024**2:.1f} MB"
223
+ return f"{b/1024**3:.2f} GB"
224
+
225
+ def ok(p, mb=1): return os.path.exists(p) and os.path.getsize(p) >= mb*1024*1024
226
+ def md(p): os.makedirs(p, exist_ok=True)
227
+
228
+ def install_hf():
229
+ try:
230
+ import huggingface_hub
231
+ print(f" ✓ huggingface_hub {huggingface_hub.__version__}")
232
+ except ImportError:
233
+ pip = "/venv/main/bin/pip" if os.path.exists("/venv/main/bin/pip") else "pip3"
234
+ subprocess.run([pip, "install", "-q", "--break-system-packages", "huggingface_hub[hf_xet]"], check=True)
235
+ print(" ✓ Установлен")
236
+
237
+ # =====================================================================
238
+ # ЗАГРУЗЧИКИ
239
+ # =====================================================================
240
+ def dl_hf():
241
+ from huggingface_hub import hf_hub_download
242
+ print("\n" + "="*70 + "\n📦 HUGGINGFACE\n" + "="*70)
243
+ for i, (repo, fn, dd, dn) in enumerate(HF, 1):
244
+ dest = os.path.join(dd, dn)
245
+ print(f"\n[{i}/{len(HF)}] {dn}")
246
+ if ok(dest):
247
+ print(f" ✅ ЕСТЬ ({fmt(os.path.getsize(dest))})")
248
+ continue
249
+ md(dd)
250
+ try:
251
+ t0 = time.time()
252
+ dl = hf_hub_download(repo_id=repo, filename=fn, local_dir="/tmp/hf_cache",
253
+ local_dir_use_symlinks=False, token=HF_TOKEN)
254
+ if dl != dest: subprocess.run(["mv", "-f", dl, dest], check=True)
255
+ print(f" ✅ {fmt(os.path.getsize(dest))} за {time.time()-t0:.0f}с")
256
+ except Exception as e:
257
+ print(f" ❌ {e}")
258
+
259
+ def dl_direct():
260
+ print("\n" + "="*70 + "\n🔍 ДЕТЕКТОРЫ\n" + "="*70)
261
+ for i, (url, dd, dn, desc) in enumerate(DIRECT, 1):
262
+ dest = os.path.join(dd, dn)
263
+ print(f"\n[{i}/{len(DIRECT)}] {desc}")
264
+ if ok(dest):
265
+ print(f" ✅ ЕСТЬ ({fmt(os.path.getsize(dest))})")
266
+ continue
267
+ md(dd)
268
+ h = ["--header", f"Authorization: Bearer {HF_TOKEN}"] if "huggingface" in url else []
269
+ try:
270
+ subprocess.run(["wget", "-q", "--show-progress", "-O", dest, *h, url], timeout=300)
271
+ if ok(dest): print(f" ✅ {fmt(os.path.getsize(dest))}")
272
+ else:
273
+ if os.path.exists(dest): os.remove(dest)
274
+ except Exception as e:
275
+ print(f" ❌ {e}")
276
+
277
+ def dl_civitai():
278
+ print("\n" + "="*70 + "\n🎨 CIVITAI\n" + "="*70)
279
+ for url, dd, dest_name, desc, min_mb in CIVITAI:
280
+ print(f"\n {desc}")
281
+ md(dd)
282
+ if dest_name:
283
+ dest = os.path.join(dd, dest_name)
284
+ if ok(dest, min_mb):
285
+ print(f" ✅ ЕСТЬ ({fmt(os.path.getsize(dest))})")
286
+ continue
287
+ try:
288
+ t0 = time.time()
289
+ subprocess.run(["wget", "-q", "--show-progress", "-O", dest, url], timeout=900)
290
+ if ok(dest, min_mb):
291
+ print(f" ✅ {dest_name} — {fmt(os.path.getsize(dest))} за {time.time()-t0:.0f}с")
292
+ else:
293
+ if os.path.exists(dest) and os.path.getsize(dest) < 1024:
294
+ with open(dest, 'r', errors='ignore') as f:
295
+ print(f" ⚠️ Ошибка: {f.read()[:200]}")
296
+ os.remove(dest)
297
+ except Exception as e:
298
+ print(f" ❌ {e}")
299
+ else:
300
+ existing = set(os.listdir(dd))
301
+ try:
302
+ t0 = time.time()
303
+ subprocess.run(["wget", "-q", "--show-progress", "--content-disposition", "-P", dd, url], timeout=600)
304
+ new = set(os.listdir(dd)) - existing
305
+ for f in new:
306
+ print(f" ✅ {f} — {fmt(os.path.getsize(os.path.join(dd, f)))} за {time.time()-t0:.0f}с")
307
+ if not new:
308
+ print(f" ⚠️ Файл уже был")
309
+ except Exception as e:
310
+ print(f" ❌ {e}")
311
+
312
+ # =====================================================================
313
+ # КАСТОМНЫЕ НОДЫ + CLIP COPY + START SCRIPT
314
+ # =====================================================================
315
+ def setup_custom_nodes():
316
+ print("\n" + "="*70 + "\n🔧 КАСТОМНЫЕ НОДЫ\n" + "="*70)
317
+ path = os.path.join(CN, "KiaraPanels", "__init__.py")
318
+ md(os.path.dirname(path))
319
+ with open(path, 'w') as f:
320
+ f.write(KIARA_PANELS_CODE)
321
+ print(f" ✅ KiaraPanels → {path}")
322
+ print(f" ControlPanelSD + ControlPanelFlux + KiaraReferenceLatent")
323
+
324
+ def setup_clip_copy():
325
+ print("\n" + "="*70 + "\n📋 CLIP COPY\n" + "="*70)
326
+ src = f"{B}/text_encoders/qwen_3_4b.safetensors"
327
+ dst = f"{B}/clip/qwen_3_4b.safetensors"
328
+ md(os.path.dirname(dst))
329
+ if os.path.exists(dst) and os.path.getsize(dst) > 1024*1024*1000:
330
+ print(f" ✅ ЕСТЬ ({fmt(os.path.getsize(dst))})")
331
+ elif os.path.exists(src):
332
+ import shutil
333
+ shutil.copy2(src, dst)
334
+ print(f" ✅ Скопировал → models/clip/ ({fmt(os.path.getsize(dst))})")
335
+ else:
336
+ print(f" ⚠️ Источник не найден, скопируй после загрузки")
337
+
338
+ def setup_start_script():
339
+ print("\n" + "="*70 + "\n🚀 START SCRIPT\n" + "="*70)
340
+ script = textwrap.dedent("""\
341
+ #!/bin/bash
342
+ # KiaraSuperSpace — ComfyUI Start
343
+ export LD_LIBRARY_PATH=/venv/main/lib/python3.12/site-packages/nvidia/cuda_runtime/lib:$LD_LIBRARY_PATH
344
+ cd /workspace/ComfyUI
345
+ fuser -k 8188/tcp 2>/dev/null
346
+ sleep 1
347
+ /venv/main/bin/python main.py --listen --port 8188 &
348
+ echo "ComfyUI запущен на порту 8188"
349
+ """)
350
+ path = "/workspace/start_comfyui.sh"
351
+ with open(path, 'w') as f:
352
+ f.write(script)
353
+ os.chmod(path, 0o755)
354
+ print(f" ✅ {path}")
355
+
356
+ # =====================================================================
357
+ # ИТОГ
358
+ # =====================================================================
359
+ def final():
360
+ print("\n" + "="*70 + "\n📋 ИТОГ\n" + "="*70)
361
+ total = 0
362
+
363
+ for _,_,dd,dn in HF:
364
+ p = os.path.join(dd,dn)
365
+ if os.path.exists(p):
366
+ sz = os.path.getsize(p); total += sz
367
+ print(f" ✅ {dn:<55s} {fmt(sz):>10s}")
368
+ else:
369
+ print(f" ❌ {dn:<55s} MISSING")
370
+
371
+ for _,dd,dn,_ in DIRECT:
372
+ p = os.path.join(dd,dn)
373
+ if os.path.exists(p):
374
+ sz = os.path.getsize(p); total += sz
375
+ print(f" ✅ {dn:<55s} {fmt(sz):>10s}")
376
+ else:
377
+ print(f" ❌ {dn:<55s} MISSING")
378
+
379
+ print()
380
+ for folder, label in [(f"{B}/checkpoints","checkpoints"), (f"{B}/loras","loras")]:
381
+ if os.path.exists(folder):
382
+ for f in sorted(os.listdir(folder)):
383
+ if f.endswith('.safetensors'):
384
+ sz = os.path.getsize(os.path.join(folder,f)); total += sz
385
+ print(f" ✅ {label}/{f:<48s} {fmt(sz):>10s}")
386
+
387
+ print()
388
+ p = os.path.join(CN, "KiaraPanels", "__init__.py")
389
+ print(f" {'✅' if os.path.exists(p) else '❌'} custom_nodes/KiaraPanels")
390
+
391
+ p2 = f"{B}/clip/qwen_3_4b.safetensors"
392
+ print(f" {'✅' if os.path.exists(p2) and os.path.getsize(p2)>1e9 else '❌'} models/clip/qwen_3_4b.safetensors")
393
+
394
+ print(f"\n 💾 Общий размер: {fmt(total)}")
395
+ print("="*70)
396
+ print("""
397
+ 📝 ПОСЛЕ УСТАНОВКИ:
398
+
399
+ 1. bash /workspace/start_comfyui.sh
400
+ 2. Загрузить KiaraSasatImage.json
401
+ 3. Выбрать из дропдауна:
402
+ Checkpoint: gonzalomoXLFluxPony_v60PhotoXLDMD
403
+ LoRA: Realism Lora или Super Skin Detailer
404
+ 4. Reference 1 — Body (фото тела)
405
+ Reference 2 — Face (фото лица)
406
+ 5. Run!
407
+
408
+ Stage I: LCM, Karras, cfg=1, steps=8, 896x1536
409
+ Stage II: FLUX Klein, Euler, steps=4, face swap
410
+ """)
411
+
412
+ # =====================================================================
413
+ def main():
414
+ print("="*70)
415
+ print(" 🚀 KiaraSuperSpace v2 — ПОЛНЫЙ SETUP")
416
+ print("="*70)
417
+ print(f" {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
418
+
419
+ for d in ["checkpoints","loras","diffusion_models","text_encoders",
420
+ "vae","clip","upscale_models","sams","clip_vision",
421
+ "ultralytics/bbox","ultralytics/segm"]:
422
+ md(os.path.join(B, d))
423
+
424
+ print("🔧 Подготовка...")
425
+ install_hf()
426
+ dl_hf()
427
+ dl_direct()
428
+ dl_civitai()
429
+ setup_custom_nodes()
430
+ setup_clip_copy()
431
+ setup_start_script()
432
+ final()
433
+
434
+ import shutil
435
+ if os.path.exists("/tmp/hf_cache"):
436
+ shutil.rmtree("/tmp/hf_cache", ignore_errors=True)
437
+
438
+ if __name__ == "__main__":
439
+ main()