Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -5,20 +5,21 @@ import random
|
|
| 5 |
import os
|
| 6 |
import json
|
| 7 |
import requests
|
|
|
|
| 8 |
from pathlib import Path
|
|
|
|
| 9 |
|
| 10 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 11 |
# EDEN REALISM ENGINE β Full Backend for WIRED UI
|
| 12 |
-
#
|
| 13 |
-
# fn_index 8:
|
| 14 |
# Beryl AI Labs / The Eden Project
|
| 15 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 16 |
|
| 17 |
-
print("βββ EDEN REALISM ENGINE βββ")
|
| 18 |
-
print("Loading Juggernaut XL v9...")
|
| 19 |
|
| 20 |
from diffusers import (
|
| 21 |
-
StableDiffusionXLPipeline,
|
| 22 |
DPMSolverMultistepScheduler,
|
| 23 |
DPMSolverSDEScheduler,
|
| 24 |
)
|
|
@@ -41,6 +42,7 @@ PRESETS = {
|
|
| 41 |
}
|
| 42 |
|
| 43 |
# βββ Load SDXL Pipeline βββ
|
|
|
|
| 44 |
pipe = StableDiffusionXLPipeline.from_pretrained(
|
| 45 |
"RunDiffusion/Juggernaut-XL-v9",
|
| 46 |
torch_dtype=torch.float16,
|
|
@@ -48,7 +50,16 @@ pipe = StableDiffusionXLPipeline.from_pretrained(
|
|
| 48 |
use_safetensors=True,
|
| 49 |
)
|
| 50 |
pipe.to("cuda")
|
| 51 |
-
print("β
Juggernaut XL v9
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
def set_scheduler(sampler="2m"):
|
| 54 |
if sampler == "sde":
|
|
@@ -61,47 +72,92 @@ def set_scheduler(sampler="2m"):
|
|
| 61 |
solver_order=2, use_karras_sigmas=True
|
| 62 |
)
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 67 |
-
def generate_video(prompt, preset, cfg, steps, frames, fps):
|
| 68 |
-
"""Video gen β uses image pipeline for keyframes, returns mp4 placeholder or frames"""
|
| 69 |
-
if not prompt.strip():
|
| 70 |
-
return None, "Enter a prompt first"
|
| 71 |
-
|
| 72 |
p = PRESETS.get(preset, PRESETS["Skin Perfect"])
|
| 73 |
actual_cfg = cfg if cfg else p["cfg"]
|
| 74 |
actual_steps = int(steps) if steps else p["steps"]
|
| 75 |
set_scheduler(p.get("sampler", "2m"))
|
| 76 |
|
| 77 |
-
# Generate keyframe as preview (full video needs WAN 2.2 or CogVideoX)
|
| 78 |
seed = random.randint(0, 2**32 - 1)
|
| 79 |
generator = torch.Generator(device="cuda").manual_seed(seed)
|
| 80 |
|
| 81 |
-
start = time.time()
|
| 82 |
image = pipe(
|
| 83 |
prompt=f"{EDEN_SKIN_BOOST}, {prompt}",
|
| 84 |
negative_prompt=EDEN_NEGATIVE,
|
| 85 |
num_inference_steps=actual_steps,
|
| 86 |
guidance_scale=actual_cfg,
|
| 87 |
-
height=
|
| 88 |
generator=generator,
|
| 89 |
).images[0]
|
| 90 |
-
elapsed = time.time() - start
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
|
| 100 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 101 |
# fn_index 1: IMAGE GENERATION (FULL EDEN PROTOCOL)
|
| 102 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 103 |
def generate_images(prompt, preset, w, h, cfg, steps, neg, seed, rand_seed, realism, skin_boost, num_images, ref_image, ref_strength):
|
| 104 |
-
"""Full image generation with Eden Protocol"""
|
| 105 |
if not prompt.strip():
|
| 106 |
return [], "Enter a prompt first"
|
| 107 |
|
|
@@ -113,17 +169,16 @@ def generate_images(prompt, preset, w, h, cfg, steps, neg, seed, rand_seed, real
|
|
| 113 |
actual_num = int(num_images) if num_images else 4
|
| 114 |
set_scheduler(p.get("sampler", "2m"))
|
| 115 |
|
| 116 |
-
# Build prompt
|
| 117 |
full_prompt = prompt.strip()
|
| 118 |
if skin_boost:
|
| 119 |
full_prompt = f"{EDEN_SKIN_BOOST}, {full_prompt}"
|
| 120 |
if realism:
|
| 121 |
full_prompt = f"{full_prompt}, photorealistic, 8k, RAW photo, shot on ARRI ALEXA 35"
|
| 122 |
|
| 123 |
-
# Build negative
|
| 124 |
full_neg = neg if neg and neg.strip() else EDEN_NEGATIVE
|
| 125 |
|
| 126 |
images = []
|
|
|
|
| 127 |
for i in range(actual_num):
|
| 128 |
s = random.randint(0, 2**32 - 1) if rand_seed else (int(seed) + i)
|
| 129 |
generator = torch.Generator(device="cuda").manual_seed(s)
|
|
@@ -138,190 +193,175 @@ def generate_images(prompt, preset, w, h, cfg, steps, neg, seed, rand_seed, real
|
|
| 138 |
width=actual_w,
|
| 139 |
generator=generator,
|
| 140 |
).images[0]
|
| 141 |
-
elapsed = time.time() - start
|
| 142 |
|
| 143 |
out_path = f"/tmp/eden_img_{s}.png"
|
| 144 |
img.save(out_path)
|
| 145 |
images.append(out_path)
|
| 146 |
-
print(f" [{i+1}/{actual_num}] {
|
| 147 |
|
| 148 |
-
|
|
|
|
| 149 |
return images, info
|
| 150 |
|
| 151 |
|
| 152 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 153 |
-
# fn_index 2: (reserved)
|
| 154 |
# fn_index 3: VIDEO STITCHING
|
| 155 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 156 |
def stitch_videos(files, fps):
|
| 157 |
-
"""Stitch video clips together"""
|
| 158 |
if not files:
|
| 159 |
return None, "Upload video clips first"
|
| 160 |
-
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
|
| 164 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 165 |
-
# fn_index
|
| 166 |
-
# fn_index 8: MODEL DOWNLOAD FROM HF
|
| 167 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 168 |
def download_model(model_id, output_dir):
|
| 169 |
-
"""Download model from HuggingFace"""
|
| 170 |
if not model_id.strip():
|
| 171 |
-
return "Enter a model ID
|
| 172 |
try:
|
| 173 |
from huggingface_hub import snapshot_download
|
| 174 |
path = snapshot_download(model_id, local_dir=f"/tmp/models/{model_id.split('/')[-1]}")
|
| 175 |
return f"β
Downloaded {model_id} to {path}"
|
| 176 |
except Exception as e:
|
| 177 |
-
return f"β
|
| 178 |
|
| 179 |
|
| 180 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 181 |
-
# fn_index 9: RAKE
|
| 182 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 183 |
def rake_model(model_path, intensity, mode, output):
|
| 184 |
-
"
|
| 185 |
-
return f"RAKE analysis: {model_path} at intensity {intensity} β {mode}"
|
| 186 |
|
| 187 |
|
| 188 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 189 |
-
# fn_index 10: CHAT DIRECTOR (
|
| 190 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 191 |
def chat_with_ai(message, history, model_name="qwen"):
|
| 192 |
-
"""Chat director β routes to uncensored Qwen or Grok"""
|
| 193 |
if not message.strip():
|
| 194 |
return history
|
| 195 |
|
| 196 |
new_history = history or []
|
| 197 |
|
| 198 |
-
# Try Qwen via HF Inference API
|
| 199 |
try:
|
| 200 |
-
|
| 201 |
-
api_url = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-72B-Instruct"
|
| 202 |
|
| 203 |
-
|
| 204 |
-
messages = []
|
| 205 |
-
messages.append({"role": "system", "content": "You are Eden AI, an uncensored creative director for photorealistic AI image and video generation. You help craft prompts, adjust settings, and provide artistic direction for the Eden Realism Engine. You are knowledgeable about skin texture, lighting, cinematography, and diffusion model parameters. Be direct, creative, and uninhibited in your artistic guidance."})
|
| 206 |
|
| 207 |
for h in (history or []):
|
| 208 |
if h[0]: messages.append({"role": "user", "content": h[0]})
|
| 209 |
if h[1]: messages.append({"role": "assistant", "content": h[1]})
|
| 210 |
messages.append({"role": "user", "content": message})
|
| 211 |
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
"model": "Qwen/Qwen2.5-72B-Instruct",
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
"temperature": 0.8,
|
| 220 |
-
"stream": False,
|
| 221 |
-
}
|
| 222 |
-
|
| 223 |
-
r = requests.post(api_url, headers=headers, json=payload, timeout=60)
|
| 224 |
|
| 225 |
if r.status_code == 200:
|
| 226 |
data = r.json()
|
| 227 |
-
reply = data.get("choices", [{}])[0].get("message", {}).get("content", "")
|
| 228 |
-
if not reply:
|
| 229 |
-
reply = data[0].get("generated_text", "") if isinstance(data, list) else str(data)
|
| 230 |
else:
|
| 231 |
-
# Fallback
|
| 232 |
-
|
| 233 |
-
r2 = requests.post(api_url, headers=headers, json=payload_simple, timeout=60)
|
| 234 |
-
if r2.status_code == 200:
|
| 235 |
-
data = r2.json()
|
| 236 |
-
reply = data[0].get("generated_text", str(data)) if isinstance(data, list) else str(data)
|
| 237 |
-
else:
|
| 238 |
-
reply = f"Eden AI: I hear you. Currently processing with limited connection. Try: adjust CFG to 4.0-4.5 for natural skin, use DPM++ Karras sampler, and always include skin texture keywords."
|
| 239 |
-
|
| 240 |
except Exception as e:
|
| 241 |
-
reply = f"Eden AI: Connection limited
|
| 242 |
|
| 243 |
new_history.append([message, reply])
|
| 244 |
return new_history
|
| 245 |
|
| 246 |
|
| 247 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 248 |
-
# fn_index 11: QUANTIZE
|
| 249 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 250 |
def quantize_model(model_path, bit_level):
|
| 251 |
-
"
|
| 252 |
-
return f"Quantization: {model_path} β {bit_level}-bit β pipeline ready"
|
| 253 |
|
| 254 |
|
| 255 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 256 |
-
# GRADIO
|
| 257 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 258 |
|
| 259 |
with gr.Blocks(title="EDEN Realism Engine") as app:
|
| 260 |
-
gr.Markdown("# π± EDEN REALISM ENGINE
|
| 261 |
|
| 262 |
-
# fn_index 0: Video
|
| 263 |
with gr.Row(visible=False):
|
| 264 |
v_prompt = gr.Textbox(); v_preset = gr.Textbox(); v_cfg = gr.Number()
|
| 265 |
v_steps = gr.Number(); v_frames = gr.Number(); v_fps = gr.Number()
|
| 266 |
v_out = gr.File(); v_info = gr.Textbox()
|
| 267 |
-
v_btn = gr.Button("
|
| 268 |
v_btn.click(fn=generate_video, inputs=[v_prompt, v_preset, v_cfg, v_steps, v_frames, v_fps], outputs=[v_out, v_info], api_name="predict")
|
| 269 |
|
| 270 |
-
# fn_index 1:
|
| 271 |
with gr.Row(visible=False):
|
| 272 |
i_prompt = gr.Textbox(); i_preset = gr.Textbox(); i_w = gr.Number(); i_h = gr.Number()
|
| 273 |
i_cfg = gr.Number(); i_steps = gr.Number(); i_neg = gr.Textbox(); i_seed = gr.Number()
|
| 274 |
i_rand = gr.Checkbox(); i_real = gr.Checkbox(); i_skin = gr.Checkbox()
|
| 275 |
i_num = gr.Number(); i_ref = gr.Image(); i_refstr = gr.Number()
|
| 276 |
i_gallery = gr.Gallery(); i_info2 = gr.Textbox()
|
| 277 |
-
i_btn = gr.Button("
|
| 278 |
i_btn.click(fn=generate_images, inputs=[i_prompt, i_preset, i_w, i_h, i_cfg, i_steps, i_neg, i_seed, i_rand, i_real, i_skin, i_num, i_ref, i_refstr], outputs=[i_gallery, i_info2])
|
| 279 |
|
| 280 |
-
# fn_index 2:
|
| 281 |
-
|
| 282 |
-
|
| 283 |
|
| 284 |
-
# fn_index 3:
|
| 285 |
with gr.Row(visible=False):
|
| 286 |
st_files = gr.File(file_count="multiple"); st_fps = gr.Number()
|
| 287 |
st_out = gr.File(); st_info3 = gr.Textbox()
|
| 288 |
-
st_btn = gr.Button("
|
| 289 |
st_btn.click(fn=stitch_videos, inputs=[st_files, st_fps], outputs=[st_out, st_info3])
|
| 290 |
|
| 291 |
# fn_index 4-7: spacers
|
| 292 |
for idx in range(4, 8):
|
| 293 |
-
sp = gr.Button(f"
|
| 294 |
sp.click(fn=lambda: None, inputs=[], outputs=[])
|
| 295 |
|
| 296 |
# fn_index 8: Model Download
|
| 297 |
with gr.Row(visible=False):
|
| 298 |
-
|
| 299 |
-
dl_btn = gr.Button("
|
| 300 |
-
dl_btn.click(fn=download_model, inputs=[
|
| 301 |
|
| 302 |
# fn_index 9: RAKE
|
| 303 |
with gr.Row(visible=False):
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
rk_btn = gr.Button("
|
| 307 |
-
rk_btn.click(fn=rake_model, inputs=[
|
| 308 |
|
| 309 |
-
# fn_index 10: Chat
|
| 310 |
with gr.Row(visible=False):
|
| 311 |
ch_msg = gr.Textbox(); ch_hist = gr.JSON(); ch_model = gr.Textbox()
|
| 312 |
ch_out = gr.JSON()
|
| 313 |
-
ch_btn = gr.Button("
|
| 314 |
ch_btn.click(fn=chat_with_ai, inputs=[ch_msg, ch_hist, ch_model], outputs=[ch_out])
|
| 315 |
|
| 316 |
# fn_index 11: Quantize
|
| 317 |
with gr.Row(visible=False):
|
| 318 |
-
|
| 319 |
-
q_btn = gr.Button("
|
| 320 |
-
q_btn.click(fn=quantize_model, inputs=[
|
| 321 |
|
| 322 |
-
|
| 323 |
-
gr.Markdown("### Status: Juggernaut XL v9 loaded Β· DPM++ Karras Β· Eden Protocol Active")
|
| 324 |
-
gr.Markdown("Backend API for WIRED UI β all fn_index endpoints mapped")
|
| 325 |
|
| 326 |
app.queue(max_size=20)
|
| 327 |
app.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 5 |
import os
|
| 6 |
import json
|
| 7 |
import requests
|
| 8 |
+
import tempfile
|
| 9 |
from pathlib import Path
|
| 10 |
+
from gradio_client import Client, handle_file
|
| 11 |
|
| 12 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 13 |
# EDEN REALISM ENGINE β Full Backend for WIRED UI
|
| 14 |
+
# Juggernaut XL v9 (images) + LTX-2 TURBO (video)
|
| 15 |
+
# fn_index 0: Video | 1: Images | 3: Stitch | 8: DL | 9: RAKE | 10: Chat | 11: Quantize
|
| 16 |
# Beryl AI Labs / The Eden Project
|
| 17 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 18 |
|
| 19 |
+
print("βββ EDEN REALISM ENGINE β FULL PIPELINE βββ")
|
|
|
|
| 20 |
|
| 21 |
from diffusers import (
|
| 22 |
+
StableDiffusionXLPipeline,
|
| 23 |
DPMSolverMultistepScheduler,
|
| 24 |
DPMSolverSDEScheduler,
|
| 25 |
)
|
|
|
|
| 42 |
}
|
| 43 |
|
| 44 |
# βββ Load SDXL Pipeline βββ
|
| 45 |
+
print("Loading Juggernaut XL v9...")
|
| 46 |
pipe = StableDiffusionXLPipeline.from_pretrained(
|
| 47 |
"RunDiffusion/Juggernaut-XL-v9",
|
| 48 |
torch_dtype=torch.float16,
|
|
|
|
| 50 |
use_safetensors=True,
|
| 51 |
)
|
| 52 |
pipe.to("cuda")
|
| 53 |
+
print("β
Juggernaut XL v9 on GPU")
|
| 54 |
+
|
| 55 |
+
# βββ LTX-2 TURBO Client βββ
|
| 56 |
+
print("Connecting to LTX-2 TURBO...")
|
| 57 |
+
try:
|
| 58 |
+
ltx_client = Client("alexnasa/ltx-2-TURBO")
|
| 59 |
+
print("β
LTX-2 TURBO connected")
|
| 60 |
+
except Exception as e:
|
| 61 |
+
ltx_client = None
|
| 62 |
+
print(f"β LTX-2 TURBO fallback: {e}")
|
| 63 |
|
| 64 |
def set_scheduler(sampler="2m"):
|
| 65 |
if sampler == "sde":
|
|
|
|
| 72 |
solver_order=2, use_karras_sigmas=True
|
| 73 |
)
|
| 74 |
|
| 75 |
+
def generate_keyframe(prompt, preset="Skin Perfect", cfg=None, steps=None):
|
| 76 |
+
"""Generate a single keyframe with Juggernaut for video pipeline"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
p = PRESETS.get(preset, PRESETS["Skin Perfect"])
|
| 78 |
actual_cfg = cfg if cfg else p["cfg"]
|
| 79 |
actual_steps = int(steps) if steps else p["steps"]
|
| 80 |
set_scheduler(p.get("sampler", "2m"))
|
| 81 |
|
|
|
|
| 82 |
seed = random.randint(0, 2**32 - 1)
|
| 83 |
generator = torch.Generator(device="cuda").manual_seed(seed)
|
| 84 |
|
|
|
|
| 85 |
image = pipe(
|
| 86 |
prompt=f"{EDEN_SKIN_BOOST}, {prompt}",
|
| 87 |
negative_prompt=EDEN_NEGATIVE,
|
| 88 |
num_inference_steps=actual_steps,
|
| 89 |
guidance_scale=actual_cfg,
|
| 90 |
+
height=512, width=768,
|
| 91 |
generator=generator,
|
| 92 |
).images[0]
|
|
|
|
| 93 |
|
| 94 |
+
path = f"/tmp/eden_keyframe_{seed}.png"
|
| 95 |
+
image.save(path)
|
| 96 |
+
return path, seed
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 100 |
+
# fn_index 0: VIDEO GENERATION
|
| 101 |
+
# Juggernaut keyframe β LTX-2 TURBO animation
|
| 102 |
+
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 103 |
+
def generate_video(prompt, preset, cfg, steps, frames, fps):
|
| 104 |
+
if not prompt.strip():
|
| 105 |
+
return None, "Enter a prompt first"
|
| 106 |
+
|
| 107 |
+
start = time.time()
|
| 108 |
+
|
| 109 |
+
# Step 1: Generate keyframe with Juggernaut
|
| 110 |
+
print(f"[VIDEO] Step 1: Generating keyframe...")
|
| 111 |
+
kf_path, seed = generate_keyframe(prompt, preset, cfg, steps)
|
| 112 |
+
kf_time = time.time() - start
|
| 113 |
+
print(f"[VIDEO] Keyframe in {kf_time:.1f}s")
|
| 114 |
|
| 115 |
+
# Step 2: Animate with LTX-2 TURBO
|
| 116 |
+
if ltx_client:
|
| 117 |
+
try:
|
| 118 |
+
print(f"[VIDEO] Step 2: Animating with LTX-2 TURBO...")
|
| 119 |
+
duration = max(2, min(8, int((frames or 97) / (fps or 24))))
|
| 120 |
+
|
| 121 |
+
result = ltx_client.predict(
|
| 122 |
+
prompt=f"cinematic motion, smooth natural movement, {prompt}",
|
| 123 |
+
first_frame=handle_file(kf_path),
|
| 124 |
+
duration=duration,
|
| 125 |
+
height=512,
|
| 126 |
+
width=768,
|
| 127 |
+
seed=seed,
|
| 128 |
+
randomize_seed=False,
|
| 129 |
+
enhance_prompt=True,
|
| 130 |
+
camera_lora="No LoRA",
|
| 131 |
+
generation_mode="Image-to-Video",
|
| 132 |
+
api_name="/generate_video"
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
vid_time = time.time() - start
|
| 136 |
+
|
| 137 |
+
# result is (video_path, seed)
|
| 138 |
+
if isinstance(result, tuple):
|
| 139 |
+
vid_path = result[0]
|
| 140 |
+
else:
|
| 141 |
+
vid_path = result
|
| 142 |
+
|
| 143 |
+
print(f"[VIDEO] Complete in {vid_time:.1f}s")
|
| 144 |
+
info = f"β
Video: {vid_time:.1f}s total | Keyframe {kf_time:.1f}s + LTX-2 {vid_time - kf_time:.1f}s | {duration}s @ 24fps | Seed {seed}"
|
| 145 |
+
return vid_path, info
|
| 146 |
+
|
| 147 |
+
except Exception as e:
|
| 148 |
+
print(f"[VIDEO] LTX-2 error: {e}")
|
| 149 |
+
# Fall back to keyframe
|
| 150 |
+
info = f"β Keyframe generated ({kf_time:.1f}s) β LTX-2 TURBO busy: {str(e)[:100]}. Try again in 30s."
|
| 151 |
+
return kf_path, info
|
| 152 |
+
else:
|
| 153 |
+
info = f"β Keyframe generated ({kf_time:.1f}s) β LTX-2 TURBO reconnecting"
|
| 154 |
+
return kf_path, info
|
| 155 |
|
| 156 |
|
| 157 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 158 |
# fn_index 1: IMAGE GENERATION (FULL EDEN PROTOCOL)
|
| 159 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 160 |
def generate_images(prompt, preset, w, h, cfg, steps, neg, seed, rand_seed, realism, skin_boost, num_images, ref_image, ref_strength):
|
|
|
|
| 161 |
if not prompt.strip():
|
| 162 |
return [], "Enter a prompt first"
|
| 163 |
|
|
|
|
| 169 |
actual_num = int(num_images) if num_images else 4
|
| 170 |
set_scheduler(p.get("sampler", "2m"))
|
| 171 |
|
|
|
|
| 172 |
full_prompt = prompt.strip()
|
| 173 |
if skin_boost:
|
| 174 |
full_prompt = f"{EDEN_SKIN_BOOST}, {full_prompt}"
|
| 175 |
if realism:
|
| 176 |
full_prompt = f"{full_prompt}, photorealistic, 8k, RAW photo, shot on ARRI ALEXA 35"
|
| 177 |
|
|
|
|
| 178 |
full_neg = neg if neg and neg.strip() else EDEN_NEGATIVE
|
| 179 |
|
| 180 |
images = []
|
| 181 |
+
start_total = time.time()
|
| 182 |
for i in range(actual_num):
|
| 183 |
s = random.randint(0, 2**32 - 1) if rand_seed else (int(seed) + i)
|
| 184 |
generator = torch.Generator(device="cuda").manual_seed(s)
|
|
|
|
| 193 |
width=actual_w,
|
| 194 |
generator=generator,
|
| 195 |
).images[0]
|
|
|
|
| 196 |
|
| 197 |
out_path = f"/tmp/eden_img_{s}.png"
|
| 198 |
img.save(out_path)
|
| 199 |
images.append(out_path)
|
| 200 |
+
print(f" [{i+1}/{actual_num}] {time.time()-start:.1f}s | Seed {s}")
|
| 201 |
|
| 202 |
+
total = time.time() - start_total
|
| 203 |
+
info = f"β
{len(images)} images in {total:.1f}s | {actual_steps} steps | CFG {actual_cfg} | {actual_w}Γ{actual_h}"
|
| 204 |
return images, info
|
| 205 |
|
| 206 |
|
| 207 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 208 |
# fn_index 3: VIDEO STITCHING
|
| 209 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 210 |
def stitch_videos(files, fps):
|
|
|
|
| 211 |
if not files:
|
| 212 |
return None, "Upload video clips first"
|
| 213 |
+
try:
|
| 214 |
+
import subprocess
|
| 215 |
+
out = f"/tmp/eden_stitched_{int(time.time())}.mp4"
|
| 216 |
+
list_file = "/tmp/ffmpeg_list.txt"
|
| 217 |
+
with open(list_file, "w") as f:
|
| 218 |
+
for clip in files:
|
| 219 |
+
path = clip.name if hasattr(clip, 'name') else str(clip)
|
| 220 |
+
f.write(f"file '{path}'\n")
|
| 221 |
+
|
| 222 |
+
cmd = f"ffmpeg -y -f concat -safe 0 -i {list_file} -c copy {out}"
|
| 223 |
+
subprocess.run(cmd, shell=True, check=True, capture_output=True)
|
| 224 |
+
return out, f"β
Stitched {len(files)} clips β {out}"
|
| 225 |
+
except Exception as e:
|
| 226 |
+
return None, f"β Stitch failed: {str(e)[:200]}"
|
| 227 |
|
| 228 |
|
| 229 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 230 |
+
# fn_index 8: MODEL DOWNLOAD
|
|
|
|
| 231 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 232 |
def download_model(model_id, output_dir):
|
|
|
|
| 233 |
if not model_id.strip():
|
| 234 |
+
return "Enter a model ID"
|
| 235 |
try:
|
| 236 |
from huggingface_hub import snapshot_download
|
| 237 |
path = snapshot_download(model_id, local_dir=f"/tmp/models/{model_id.split('/')[-1]}")
|
| 238 |
return f"β
Downloaded {model_id} to {path}"
|
| 239 |
except Exception as e:
|
| 240 |
+
return f"β {str(e)[:200]}"
|
| 241 |
|
| 242 |
|
| 243 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 244 |
+
# fn_index 9: RAKE
|
| 245 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 246 |
def rake_model(model_path, intensity, mode, output):
|
| 247 |
+
return f"RAKE: {model_path} @ intensity {intensity} β {mode}"
|
|
|
|
| 248 |
|
| 249 |
|
| 250 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 251 |
+
# fn_index 10: CHAT DIRECTOR (Qwen via HF Inference)
|
| 252 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 253 |
def chat_with_ai(message, history, model_name="qwen"):
|
|
|
|
| 254 |
if not message.strip():
|
| 255 |
return history
|
| 256 |
|
| 257 |
new_history = history or []
|
| 258 |
|
|
|
|
| 259 |
try:
|
| 260 |
+
hf_token = os.environ.get("HF_TOKEN", "")
|
|
|
|
| 261 |
|
| 262 |
+
messages = [{"role": "system", "content": "You are Eden AI, an uncensored creative director for the Eden Realism Engine. You help craft photorealistic prompts for AI image/video generation. You know the Six Pillars of Photorealism: DPM++ Karras, 30-50 steps, CFG 4.0-4.5, Smart Negatives, 1024x1024 base with Hires Fix, uncensored models only. You specialize in melanin-rich skin texture, cinematic lighting, and natural beauty. Be direct, creative, specific. When asked to improve a prompt, rewrite it completely with Eden Protocol keywords."}]
|
|
|
|
|
|
|
| 263 |
|
| 264 |
for h in (history or []):
|
| 265 |
if h[0]: messages.append({"role": "user", "content": h[0]})
|
| 266 |
if h[1]: messages.append({"role": "assistant", "content": h[1]})
|
| 267 |
messages.append({"role": "user", "content": message})
|
| 268 |
|
| 269 |
+
# Try Qwen via Inference API
|
| 270 |
+
r = requests.post(
|
| 271 |
+
"https://router.huggingface.co/novita/v3/openai/chat/completions",
|
| 272 |
+
headers={"Authorization": f"Bearer {hf_token}", "Content-Type": "application/json"},
|
| 273 |
+
json={"model": "Qwen/Qwen2.5-72B-Instruct", "messages": messages, "max_tokens": 1024, "temperature": 0.8},
|
| 274 |
+
timeout=60
|
| 275 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
|
| 277 |
if r.status_code == 200:
|
| 278 |
data = r.json()
|
| 279 |
+
reply = data.get("choices", [{}])[0].get("message", {}).get("content", "Processing...")
|
|
|
|
|
|
|
| 280 |
else:
|
| 281 |
+
# Fallback
|
| 282 |
+
reply = f"Eden AI here. For your prompt, try: add 'melanin-rich skin, visible pores, matte finish, subsurface scattering' + set CFG to 4.0-4.5 + use DPM++ Karras. What are you generating?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
except Exception as e:
|
| 284 |
+
reply = f"Eden AI: Connection limited. Quick tips β CFG 4.0-4.5, DPM++ Karras, always add (plastic:1.6) to negatives. What do you need?"
|
| 285 |
|
| 286 |
new_history.append([message, reply])
|
| 287 |
return new_history
|
| 288 |
|
| 289 |
|
| 290 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 291 |
+
# fn_index 11: QUANTIZE
|
| 292 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 293 |
def quantize_model(model_path, bit_level):
|
| 294 |
+
return f"Quantize: {model_path} β {bit_level}-bit ready"
|
|
|
|
| 295 |
|
| 296 |
|
| 297 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 298 |
+
# GRADIO β fn_index ORDER MATCHES WIRED UI
|
| 299 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 300 |
|
| 301 |
with gr.Blocks(title="EDEN Realism Engine") as app:
|
| 302 |
+
gr.Markdown("# π± EDEN REALISM ENGINE\n**Juggernaut XL v9 + LTX-2 TURBO Β· Six Pillars Β· Beryl AI Labs**")
|
| 303 |
|
| 304 |
+
# fn_index 0: Video
|
| 305 |
with gr.Row(visible=False):
|
| 306 |
v_prompt = gr.Textbox(); v_preset = gr.Textbox(); v_cfg = gr.Number()
|
| 307 |
v_steps = gr.Number(); v_frames = gr.Number(); v_fps = gr.Number()
|
| 308 |
v_out = gr.File(); v_info = gr.Textbox()
|
| 309 |
+
v_btn = gr.Button("v", visible=False)
|
| 310 |
v_btn.click(fn=generate_video, inputs=[v_prompt, v_preset, v_cfg, v_steps, v_frames, v_fps], outputs=[v_out, v_info], api_name="predict")
|
| 311 |
|
| 312 |
+
# fn_index 1: Images
|
| 313 |
with gr.Row(visible=False):
|
| 314 |
i_prompt = gr.Textbox(); i_preset = gr.Textbox(); i_w = gr.Number(); i_h = gr.Number()
|
| 315 |
i_cfg = gr.Number(); i_steps = gr.Number(); i_neg = gr.Textbox(); i_seed = gr.Number()
|
| 316 |
i_rand = gr.Checkbox(); i_real = gr.Checkbox(); i_skin = gr.Checkbox()
|
| 317 |
i_num = gr.Number(); i_ref = gr.Image(); i_refstr = gr.Number()
|
| 318 |
i_gallery = gr.Gallery(); i_info2 = gr.Textbox()
|
| 319 |
+
i_btn = gr.Button("i", visible=False)
|
| 320 |
i_btn.click(fn=generate_images, inputs=[i_prompt, i_preset, i_w, i_h, i_cfg, i_steps, i_neg, i_seed, i_rand, i_real, i_skin, i_num, i_ref, i_refstr], outputs=[i_gallery, i_info2])
|
| 321 |
|
| 322 |
+
# fn_index 2: spacer
|
| 323 |
+
sp2 = gr.Button("s2", visible=False)
|
| 324 |
+
sp2.click(fn=lambda: None, inputs=[], outputs=[])
|
| 325 |
|
| 326 |
+
# fn_index 3: Stitch
|
| 327 |
with gr.Row(visible=False):
|
| 328 |
st_files = gr.File(file_count="multiple"); st_fps = gr.Number()
|
| 329 |
st_out = gr.File(); st_info3 = gr.Textbox()
|
| 330 |
+
st_btn = gr.Button("st", visible=False)
|
| 331 |
st_btn.click(fn=stitch_videos, inputs=[st_files, st_fps], outputs=[st_out, st_info3])
|
| 332 |
|
| 333 |
# fn_index 4-7: spacers
|
| 334 |
for idx in range(4, 8):
|
| 335 |
+
sp = gr.Button(f"s{idx}", visible=False)
|
| 336 |
sp.click(fn=lambda: None, inputs=[], outputs=[])
|
| 337 |
|
| 338 |
# fn_index 8: Model Download
|
| 339 |
with gr.Row(visible=False):
|
| 340 |
+
dl_m = gr.Textbox(); dl_d = gr.Textbox(); dl_r = gr.Textbox()
|
| 341 |
+
dl_btn = gr.Button("dl", visible=False)
|
| 342 |
+
dl_btn.click(fn=download_model, inputs=[dl_m, dl_d], outputs=[dl_r])
|
| 343 |
|
| 344 |
# fn_index 9: RAKE
|
| 345 |
with gr.Row(visible=False):
|
| 346 |
+
rk_m = gr.Textbox(); rk_i = gr.Number(); rk_mode = gr.Textbox(); rk_o = gr.Textbox()
|
| 347 |
+
rk_r = gr.Textbox()
|
| 348 |
+
rk_btn = gr.Button("rk", visible=False)
|
| 349 |
+
rk_btn.click(fn=rake_model, inputs=[rk_m, rk_i, rk_mode, rk_o], outputs=[rk_r])
|
| 350 |
|
| 351 |
+
# fn_index 10: Chat
|
| 352 |
with gr.Row(visible=False):
|
| 353 |
ch_msg = gr.Textbox(); ch_hist = gr.JSON(); ch_model = gr.Textbox()
|
| 354 |
ch_out = gr.JSON()
|
| 355 |
+
ch_btn = gr.Button("ch", visible=False)
|
| 356 |
ch_btn.click(fn=chat_with_ai, inputs=[ch_msg, ch_hist, ch_model], outputs=[ch_out])
|
| 357 |
|
| 358 |
# fn_index 11: Quantize
|
| 359 |
with gr.Row(visible=False):
|
| 360 |
+
q_m = gr.Textbox(); q_b = gr.Textbox(); q_r = gr.Textbox()
|
| 361 |
+
q_btn = gr.Button("q", visible=False)
|
| 362 |
+
q_btn.click(fn=quantize_model, inputs=[q_m, q_b], outputs=[q_r])
|
| 363 |
|
| 364 |
+
gr.Markdown("### Pipeline: Juggernaut XL v9 (keyframes) β LTX-2 TURBO (animation) β Eden Protocol")
|
|
|
|
|
|
|
| 365 |
|
| 366 |
app.queue(max_size=20)
|
| 367 |
app.launch(server_name="0.0.0.0", server_port=7860)
|