Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -437,7 +437,7 @@ class UnifiedProgressTqdm(tqdm_lib.tqdm):
|
|
| 437 |
# ==========================================================================
|
| 438 |
def execute_workflow(workflow: dict[str, Any]) -> list[str]:
|
| 439 |
import tqdm.std
|
| 440 |
-
global _timing_store
|
| 441 |
original_tqdm = tqdm.std.tqdm
|
| 442 |
tqdm.std.tqdm = UnifiedProgressTqdm
|
| 443 |
|
|
@@ -454,6 +454,7 @@ def execute_workflow(workflow: dict[str, Any]) -> list[str]:
|
|
| 454 |
prompt_id = str(uuid.uuid4())
|
| 455 |
save_id = next(k for k, v in workflow.items() if v.get("class_type") == "SaveImage")
|
| 456 |
|
|
|
|
| 457 |
executor.execute(workflow, prompt_id, extra_data={}, execute_outputs=[save_id])
|
| 458 |
|
| 459 |
_timing_store["T2"] = time.time()
|
|
@@ -514,8 +515,6 @@ def generate_workflow(
|
|
| 514 |
*lora_states,
|
| 515 |
):
|
| 516 |
global _terminal_html, _last_used_engine, _last_used_unet, _timing_store
|
| 517 |
-
global _workflow_done, _workflow_error, _workflow_result
|
| 518 |
-
|
| 519 |
_terminal_html = ""
|
| 520 |
_timing_store = {}
|
| 521 |
|
|
@@ -534,13 +533,16 @@ def generate_workflow(
|
|
| 534 |
yield None, _terminal_html
|
| 535 |
_last_used_engine = engine
|
| 536 |
_last_used_unet = unet_name
|
|
|
|
| 537 |
elif _last_used_unet != unet_name:
|
| 538 |
_append_log("SYS ", "orange", "Swapping UNet weights...")
|
| 539 |
yield None, _terminal_html
|
| 540 |
_last_used_unet = unet_name
|
|
|
|
| 541 |
else:
|
| 542 |
_append_log("SYS ", "green", "Base model cached. Fast inference.")
|
| 543 |
yield None, _terminal_html
|
|
|
|
| 544 |
|
| 545 |
_timing_store["T0"] = time.time()
|
| 546 |
|
|
@@ -581,35 +583,25 @@ def generate_workflow(
|
|
| 581 |
# 初始化 loading 状态
|
| 582 |
_timing_store["phase"] = "loading"
|
| 583 |
_timing_store["load_start"] = time.time()
|
| 584 |
-
|
| 585 |
-
_append_log("SYS ", "blue", "📦 Loading tensors to VRAM... (Elapsed: 0s)")
|
| 586 |
yield None, _terminal_html
|
| 587 |
|
| 588 |
# ==========================================
|
| 589 |
-
# 🌟
|
| 590 |
# ==========================================
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
t = threading.Thread(target=_run_comfy_background, args=(workflow,))
|
| 596 |
-
t.daemon = True
|
| 597 |
-
t.start()
|
| 598 |
-
|
| 599 |
-
# 🌟 主线程以 0.5 秒的间隔疯狂往外吐状态,绝不卡死
|
| 600 |
-
while not _workflow_done:
|
| 601 |
-
time.sleep(0.5)
|
| 602 |
-
yield None, _terminal_html
|
| 603 |
-
|
| 604 |
-
# 检查后台线程是否有报错
|
| 605 |
-
if _workflow_error:
|
| 606 |
-
raise RuntimeError(_workflow_error)
|
| 607 |
|
| 608 |
-
|
|
|
|
| 609 |
|
|
|
|
| 610 |
if "T1" not in _timing_store:
|
| 611 |
-
_timing_store["T1"] = _timing_store["T2"] - 0.1
|
| 612 |
-
|
|
|
|
|
|
|
| 613 |
|
| 614 |
dl_time = _timing_store.get("download_end", _timing_store["T0"]) - _timing_store["T0"]
|
| 615 |
load_time = _timing_store["T1"] - _timing_store.get("load_start", _timing_store["T1"])
|
|
@@ -1232,11 +1224,7 @@ a:hover { opacity: 0.8 !important; text-decoration: underline !important; }
|
|
| 1232 |
flex-wrap: nowrap !important;
|
| 1233 |
width: 100% !important;
|
| 1234 |
}
|
| 1235 |
-
|
| 1236 |
-
/* 去掉图片输出区域gradio output标签 */
|
| 1237 |
-
.column:nth-child(2) .html-container {
|
| 1238 |
-
padding: 0 0 var(--block-padding) 0 !important;
|
| 1239 |
-
}
|
| 1240 |
|
| 1241 |
/* 强行破除 Gradio 默认的 1280/1536 宽度限制,让它永远占满全屏 */
|
| 1242 |
.fillable {
|
|
@@ -1244,20 +1232,16 @@ a:hover { opacity: 0.8 !important; text-decoration: underline !important; }
|
|
| 1244 |
width: 100% !important;
|
| 1245 |
}
|
| 1246 |
|
| 1247 |
-
/*
|
| 1248 |
-
|
| 1249 |
-
.column:nth-child(3) .gr-image > div:first-child
|
|
|
|
|
|
|
|
|
|
| 1250 |
display: none !important;
|
|
|
|
|
|
|
| 1251 |
}
|
| 1252 |
-
|
| 1253 |
-
/* 确保图片区域撑满��个组件 */
|
| 1254 |
-
.column:nth-child(3) .gr-image {
|
| 1255 |
-
padding: 0 !important;
|
| 1256 |
-
background: transparent !important;
|
| 1257 |
-
border: none !important;
|
| 1258 |
-
overflow: hidden !important;
|
| 1259 |
-
}
|
| 1260 |
-
|
| 1261 |
/* ========================================= */
|
| 1262 |
/* 🖥️ 极简终端框样式 */
|
| 1263 |
.terminal-wrapper {
|
|
@@ -1273,26 +1257,31 @@ a:hover { opacity: 0.8 !important; text-decoration: underline !important; }
|
|
| 1273 |
margin-bottom: 12px;
|
| 1274 |
margin-top: 12px;
|
| 1275 |
}
|
| 1276 |
-
|
| 1277 |
-
|
| 1278 |
-
.terminal-content .t-blue { color: #58a6ff !important; }
|
| 1279 |
-
.terminal-content .t-orange { color: #d29922 !important; }
|
| 1280 |
-
/* 把终端框的滚动条换成细细的半透明样式 */
|
| 1281 |
.terminal-wrapper::-webkit-scrollbar {
|
| 1282 |
-
width:
|
| 1283 |
background: transparent !important;
|
| 1284 |
}
|
| 1285 |
|
| 1286 |
-
|
| 1287 |
-
|
| 1288 |
-
|
| 1289 |
}
|
| 1290 |
-
|
| 1291 |
.terminal-wrapper:hover::-webkit-scrollbar-thumb {
|
| 1292 |
-
background: rgba(150, 150, 150, 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1293 |
}
|
| 1294 |
|
| 1295 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1296 |
.terminal-wrapper .prose,
|
| 1297 |
.terminal-wrapper .html-container,
|
| 1298 |
.terminal-wrapper > div {
|
|
@@ -1301,6 +1290,7 @@ a:hover { opacity: 0.8 !important; text-decoration: underline !important; }
|
|
| 1301 |
box-shadow: none !important;
|
| 1302 |
padding: 0 !important;
|
| 1303 |
margin: 0 !important;
|
|
|
|
| 1304 |
}
|
| 1305 |
"""
|
| 1306 |
|
|
|
|
| 437 |
# ==========================================================================
|
| 438 |
def execute_workflow(workflow: dict[str, Any]) -> list[str]:
|
| 439 |
import tqdm.std
|
| 440 |
+
global _timing_store, _terminal_html
|
| 441 |
original_tqdm = tqdm.std.tqdm
|
| 442 |
tqdm.std.tqdm = UnifiedProgressTqdm
|
| 443 |
|
|
|
|
| 454 |
prompt_id = str(uuid.uuid4())
|
| 455 |
save_id = next(k for k, v in workflow.items() if v.get("class_type") == "SaveImage")
|
| 456 |
|
| 457 |
+
# 直接调用,删掉不存在的 on_node_start
|
| 458 |
executor.execute(workflow, prompt_id, extra_data={}, execute_outputs=[save_id])
|
| 459 |
|
| 460 |
_timing_store["T2"] = time.time()
|
|
|
|
| 515 |
*lora_states,
|
| 516 |
):
|
| 517 |
global _terminal_html, _last_used_engine, _last_used_unet, _timing_store
|
|
|
|
|
|
|
| 518 |
_terminal_html = ""
|
| 519 |
_timing_store = {}
|
| 520 |
|
|
|
|
| 533 |
yield None, _terminal_html
|
| 534 |
_last_used_engine = engine
|
| 535 |
_last_used_unet = unet_name
|
| 536 |
+
load_hint = "Initializing heavy weights (approx. 15-20s)..."
|
| 537 |
elif _last_used_unet != unet_name:
|
| 538 |
_append_log("SYS ", "orange", "Swapping UNet weights...")
|
| 539 |
yield None, _terminal_html
|
| 540 |
_last_used_unet = unet_name
|
| 541 |
+
load_hint = "Swapping model checkpoint (approx. 5-10s)..."
|
| 542 |
else:
|
| 543 |
_append_log("SYS ", "green", "Base model cached. Fast inference.")
|
| 544 |
yield None, _terminal_html
|
| 545 |
+
load_hint = "Model cached. Warming up (approx. 1-2s)..."
|
| 546 |
|
| 547 |
_timing_store["T0"] = time.time()
|
| 548 |
|
|
|
|
| 583 |
# 初始化 loading 状态
|
| 584 |
_timing_store["phase"] = "loading"
|
| 585 |
_timing_store["load_start"] = time.time()
|
| 586 |
+
_append_log("SYS ", "blue", f"📦 Loading tensors to VRAM... {load_hint}")
|
|
|
|
| 587 |
yield None, _terminal_html
|
| 588 |
|
| 589 |
# ==========================================
|
| 590 |
+
# 🌟 核心:直接同步执行,放弃后台线程
|
| 591 |
# ==========================================
|
| 592 |
+
|
| 593 |
+
# 执行(阻塞)
|
| 594 |
+
final_images = execute_workflow(workflow)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 595 |
|
| 596 |
+
# 执行结束,补上 T2
|
| 597 |
+
_timing_store["T2"] = time.time()
|
| 598 |
|
| 599 |
+
# 如果 T1 没有被拦截器覆盖,就说明秒出图
|
| 600 |
if "T1" not in _timing_store:
|
| 601 |
+
_timing_store["T1"] = _timing_store["T2"] - 0.1
|
| 602 |
+
|
| 603 |
+
_append_log("SYS ", "blue", "🎨 Running KSampler... (Elapsed: 0s)") # 补一行视觉
|
| 604 |
+
yield None, _terminal_html
|
| 605 |
|
| 606 |
dl_time = _timing_store.get("download_end", _timing_store["T0"]) - _timing_store["T0"]
|
| 607 |
load_time = _timing_store["T1"] - _timing_store.get("load_start", _timing_store["T1"])
|
|
|
|
| 1224 |
flex-wrap: nowrap !important;
|
| 1225 |
width: 100% !important;
|
| 1226 |
}
|
| 1227 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1228 |
|
| 1229 |
/* 强行破除 Gradio 默认的 1280/1536 宽度限制,让它永远占满全屏 */
|
| 1230 |
.fillable {
|
|
|
|
| 1232 |
width: 100% !important;
|
| 1233 |
}
|
| 1234 |
|
| 1235 |
+
/* ========================================= */
|
| 1236 |
+
/* 去掉图片输出区域gradio output标签 */
|
| 1237 |
+
.column:nth-child(3) .gr-image > div:first-child,
|
| 1238 |
+
.column:nth-child(3) .gr-image .label-wrap,
|
| 1239 |
+
.column:nth-child(3) .gr-image [data-testid="block-label"],
|
| 1240 |
+
.column:nth-child(3) .gr-image span[data-testid="block-info"] {
|
| 1241 |
display: none !important;
|
| 1242 |
+
opacity: 0 !important;
|
| 1243 |
+
visibility: hidden !important;
|
| 1244 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1245 |
/* ========================================= */
|
| 1246 |
/* 🖥️ 极简终端框样式 */
|
| 1247 |
.terminal-wrapper {
|
|
|
|
| 1257 |
margin-bottom: 12px;
|
| 1258 |
margin-top: 12px;
|
| 1259 |
}
|
| 1260 |
+
|
| 1261 |
+
/* 👇 关键:默认完全隐藏滚动条,不占位置 */
|
|
|
|
|
|
|
|
|
|
| 1262 |
.terminal-wrapper::-webkit-scrollbar {
|
| 1263 |
+
width: 0px !important;
|
| 1264 |
background: transparent !important;
|
| 1265 |
}
|
| 1266 |
|
| 1267 |
+
/* 👇 关键:只有当鼠标悬浮在终端上时,才显示 6px 的半透明滚动条 */
|
| 1268 |
+
.terminal-wrapper:hover::-webkit-scrollbar {
|
| 1269 |
+
width: 6px !important;
|
| 1270 |
}
|
|
|
|
| 1271 |
.terminal-wrapper:hover::-webkit-scrollbar-thumb {
|
| 1272 |
+
background: rgba(150, 150, 150, 0.4) !important;
|
| 1273 |
+
border-radius: 10px !important;
|
| 1274 |
+
}
|
| 1275 |
+
.terminal-wrapper:hover::-webkit-scrollbar-thumb:hover {
|
| 1276 |
+
background: rgba(150, 150, 150, 0.8) !important;
|
| 1277 |
}
|
| 1278 |
|
| 1279 |
+
.terminal-content { color: #c9d1d9 !important; word-break: break-all !important; white-space: pre-wrap !important; }
|
| 1280 |
+
.terminal-content .t-green { color: #3fb950 !important; }
|
| 1281 |
+
.terminal-content .t-blue { color: #58a6ff !important; }
|
| 1282 |
+
.terminal-content .t-orange { color: #d29922 !important; }
|
| 1283 |
+
|
| 1284 |
+
/* 扒掉终端内部的所有包裹层背景和边框,并强制隐藏内部的滚动条 */
|
| 1285 |
.terminal-wrapper .prose,
|
| 1286 |
.terminal-wrapper .html-container,
|
| 1287 |
.terminal-wrapper > div {
|
|
|
|
| 1290 |
box-shadow: none !important;
|
| 1291 |
padding: 0 !important;
|
| 1292 |
margin: 0 !important;
|
| 1293 |
+
overflow: hidden !important; /* 防止内部再弹出一个滚动条 */
|
| 1294 |
}
|
| 1295 |
"""
|
| 1296 |
|