Summary
• Implemented global offline mode for all HuggingFace-dependent modules to eliminate unauthenticated request warnings and prevent external connection attempts during startup and runtime. Changes • Global Offline Configuration: Added HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 to the environment variables at the top of edit_api.py, embeddings.py, watcher.py, and pose_llm/pose_llm_api.py. • Explicit Local Files Only: Updated all huggingface_hub.hf_hub_download calls in edit_api.py to include local_files_only=True, ensuring they never attempt to reach the Hub if models are already cached. • LLM Service Optimization: Updated AutoTokenizer and AutoModelForCausalLM calls in pose_llm/pose_llm_api.py to use local_files_only=True. • Consistency: Ensured that shared modules like embeddings.py which uses open_clip are also locked to offline mode to prevent background downloads.
This commit is contained in:
@@ -21,6 +21,8 @@ Env:
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
os.environ["HF_HUB_OFFLINE"] = "1"
|
||||
os.environ["TRANSFORMERS_OFFLINE"] = "1"
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
@@ -69,7 +71,7 @@ async def lifespan(app: FastAPI):
|
||||
# Boost GPU to high performance mode (avoids power-saving clock throttle)
|
||||
subprocess.run(["/opt/rocm/bin/rocm-smi", "--setperflevel", "high"], capture_output=True)
|
||||
print(f"Loading model {MODEL_ID} (gpu≤{MAX_GPU_MEM} cpu≤{MAX_CPU_MEM})...", flush=True)
|
||||
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
|
||||
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, local_files_only=True)
|
||||
if not tokenizer.chat_template:
|
||||
print("No chat_template found — applying Mistral [INST] fallback.", flush=True)
|
||||
tokenizer.chat_template = _MISTRAL_TEMPLATE
|
||||
@@ -78,6 +80,7 @@ async def lifespan(app: FastAPI):
|
||||
torch_dtype=torch.float16,
|
||||
device_map="auto",
|
||||
max_memory={0: MAX_GPU_MEM, "cpu": MAX_CPU_MEM},
|
||||
local_files_only=True,
|
||||
)
|
||||
model.eval()
|
||||
state["tokenizer"] = tokenizer
|
||||
|
||||
@@ -2299,6 +2299,25 @@
|
||||
|
||||
// --- HYDRATION_START ---
|
||||
const PRELOADED_IMAGES = [
|
||||
"_turntable/up_c8be3aa7/views/view_018_270deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_017_255deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_016_240deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_015_225deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_014_210deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_013_195deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_012_180deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_011_165deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_010_150deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_009_135deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_008_120deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_007_105deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_006_090deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_005_075deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_004_060deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_003_045deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_002_030deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_001_015deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_000_000deg.png",
|
||||
"up_b8c61991_face.png",
|
||||
"_turntable/bb_01.png/views/view_008_120deg.png",
|
||||
"_turntable/bb_01.png/views/view_007_105deg.png",
|
||||
@@ -2789,8 +2808,6 @@
|
||||
"20260627_203054_Screenshot_From_2026-06-27_20-04-11.png",
|
||||
"20260627_203044_image.png",
|
||||
"20260627_203032_image.png",
|
||||
"_turntable/up_c8be3aa7/views/view_002_030deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_003_045deg.png",
|
||||
"20260627_201807_12_20260627_201343_image.png",
|
||||
"20260627_201753_Screenshot_From_2026-06-27_12-32-39.png",
|
||||
"20260627_201751_11_20260627_201343_image.png",
|
||||
@@ -2807,18 +2824,12 @@
|
||||
"20260627_201418_1_20260627_201343_image.png",
|
||||
"20260627_201400_0_20260627_201343_image.png",
|
||||
"20260627_201343_image.png",
|
||||
"_turntable/up_c8be3aa7/views/view_007_105deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_006_090deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_005_075deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_004_060deg.png",
|
||||
"_turntable/up_c8be3aa7/views/view_001_015deg.png",
|
||||
"20260627_200711_11_20260627_200330_image.png",
|
||||
"20260627_200506_image.png",
|
||||
"20260627_200422_2_20260627_200330_image.png",
|
||||
"20260627_200414_image.png",
|
||||
"20260627_200405_1_20260627_200330_image.png",
|
||||
"20260627_200330_image.png",
|
||||
"_turntable/up_c8be3aa7/views/view_000_000deg.png",
|
||||
"20260627_200201_12_20260627_195835_image.png",
|
||||
"20260627_200144_11_20260627_195835_image.png",
|
||||
"20260627_200127_10_20260627_195835_image.png",
|
||||
@@ -7497,18 +7508,35 @@
|
||||
_lastSelectedGid = gid;
|
||||
localStorage.setItem('lastSelectedGid', gid);
|
||||
|
||||
_activeFilmstripTab = 'group';
|
||||
['Group', 'Hidden', 'Source', 'Archived'].forEach(t => {
|
||||
// Default to 'active' tab, but fallback to 'group' if empty
|
||||
const activeNames = data.names.filter(name => !fileHidden[name] && !fileIsSource[name] && !fileArchived[name]);
|
||||
if (activeNames.length > 0) {
|
||||
_activeFilmstripTab = 'active';
|
||||
lbNames = activeNames;
|
||||
lbUrls = activeNames.map(n => IMAGE_FOLDER + n);
|
||||
} else {
|
||||
_activeFilmstripTab = 'group';
|
||||
lbUrls = data.urls;
|
||||
lbNames = data.names;
|
||||
}
|
||||
|
||||
['Active', 'Group', 'Hidden', 'Source', 'Archived'].forEach(t => {
|
||||
const el = document.getElementById(`fsTab${t}`);
|
||||
if (el) el.classList.toggle('active', t.toLowerCase() === 'group');
|
||||
if (el) el.classList.toggle('active', t.toLowerCase() === _activeFilmstripTab);
|
||||
});
|
||||
_multiSelectModeActive = false;
|
||||
_selectedFilenames.clear();
|
||||
updateMultiSelectUI();
|
||||
|
||||
lbUrls = data.urls;
|
||||
lbNames = data.names;
|
||||
lbIdx = startIdx !== undefined ? startIdx : (cycleIdx.get(gid) || 0);
|
||||
// If we are in 'active' tab, ensure lbIdx is valid for lbNames
|
||||
if (_activeFilmstripTab === 'active' && startIdx !== undefined) {
|
||||
const targetName = data.names[startIdx];
|
||||
const activeIdx = lbNames.indexOf(targetName);
|
||||
if (activeIdx !== -1) lbIdx = activeIdx;
|
||||
else lbIdx = 0; // fallback if the image we clicked is not 'active'
|
||||
}
|
||||
|
||||
updateStudio();
|
||||
document.getElementById('studio').classList.add('open');
|
||||
// Hide main page scrollbar — nothing in studio scrolls the page
|
||||
@@ -9808,14 +9836,22 @@
|
||||
const r = await fetch(`${API}/output/_data/system_status.json?t=${Date.now()}`, { signal: AbortSignal.timeout(2000) });
|
||||
if (!r.ok) return;
|
||||
const data = await r.json();
|
||||
if (data.locked && !_lastSystemLockState) {
|
||||
_lastSystemLockState = true;
|
||||
if (data.locked) {
|
||||
if (!privacyMode) togglePrivacyMode();
|
||||
showPrivacyOverlay();
|
||||
console.log("[privacy] System lock detected, auto-hiding content");
|
||||
showToast('Privacy lock active (System Locked)', 'info');
|
||||
} else if (!data.locked) {
|
||||
_lastSystemLockState = false;
|
||||
if (!_lastSystemLockState) {
|
||||
_lastSystemLockState = true;
|
||||
console.log("[privacy] System lock detected, auto-hiding content");
|
||||
showToast('Privacy lock active (System Locked)', 'info');
|
||||
}
|
||||
} else {
|
||||
if (_lastSystemLockState) {
|
||||
_lastSystemLockState = false;
|
||||
// If it was locked by system, and now system is unlocked,
|
||||
// we automatically unlock if privacyMode is still active.
|
||||
if (privacyMode) togglePrivacyMode();
|
||||
console.log("[privacy] System unlock detected, restoring content");
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ Run ComfyUI first (run_comfyui.sh), then this service (start_api.sh).
|
||||
|
||||
import io
|
||||
import os
|
||||
os.environ["HF_HUB_OFFLINE"] = "1"
|
||||
os.environ["TRANSFORMERS_OFFLINE"] = "1"
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
@@ -450,6 +452,12 @@ def on_startup():
|
||||
print(f"[output] mount warning: {e}")
|
||||
# Write initial static data files (synchronous — ensures files exist before first request)
|
||||
_write_all_static()
|
||||
# Trigger pose index backfill
|
||||
try:
|
||||
if _load_pose_estimator():
|
||||
build_pose_index()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# --- helpers ----------------------------------------------------------------
|
||||
@@ -568,7 +576,7 @@ def _load_tagger():
|
||||
cfg = resolve_data_config(model.pretrained_cfg, model=model)
|
||||
transform = create_transform(**cfg)
|
||||
|
||||
lpath = huggingface_hub.hf_hub_download(WD_MODEL, "selected_tags.csv")
|
||||
lpath = huggingface_hub.hf_hub_download(WD_MODEL, "selected_tags.csv", local_files_only=True)
|
||||
with open(lpath, newline="") as f:
|
||||
rows = list(csv.DictReader(f))
|
||||
# category 0=general 4=character 9=rating
|
||||
@@ -664,6 +672,7 @@ def _load_faceswapper():
|
||||
model_path = huggingface_hub.hf_hub_download(
|
||||
'deepinsight/inswapper', 'inswapper_128.onnx',
|
||||
local_dir=os.path.dirname(model_path),
|
||||
local_files_only=True
|
||||
)
|
||||
print(f"[faceswap] Downloaded inswapper_128.onnx to {model_path}")
|
||||
except Exception as de:
|
||||
@@ -1294,24 +1303,36 @@ _privacy_lock = threading.Lock()
|
||||
|
||||
|
||||
def _privacy_monitor_daemon():
|
||||
"""Monitors GNOME screen lock via D-Bus gdbus monitor."""
|
||||
"""Monitors GNOME/Freedesktop screen lock via D-Bus gdbus monitor."""
|
||||
global _privacy_locked
|
||||
print("[privacy] Starting monitor daemon...")
|
||||
# Monitor ScreenSaver state changes
|
||||
cmd = ["gdbus", "monitor", "--session", "--dest", "org.gnome.ScreenSaver", "--object-path", "/org/gnome/ScreenSaver"]
|
||||
try:
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
for line in proc.stdout:
|
||||
# Lines look like: /org/gnome/ScreenSaver: org.gnome.ScreenSaver.ActiveChanged (true,)
|
||||
if "ActiveChanged" in line:
|
||||
is_locked = "(true,)" in line
|
||||
with _privacy_lock:
|
||||
if _privacy_locked != is_locked:
|
||||
_privacy_locked = is_locked
|
||||
print(f"[privacy] System lock state change detected: {is_locked}")
|
||||
_write_all_static()
|
||||
except Exception as e:
|
||||
print(f"[privacy] Monitor error (is gdbus installed?): {e}")
|
||||
|
||||
# We try to monitor both GNOME and Freedesktop ScreenSaver
|
||||
destinations = [
|
||||
("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver"),
|
||||
("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver")
|
||||
]
|
||||
|
||||
def monitor(dest, obj_path):
|
||||
global _privacy_locked
|
||||
cmd = ["gdbus", "monitor", "--session", "--dest", dest, "--object-path", obj_path]
|
||||
try:
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
for line in proc.stdout:
|
||||
# GNOME: ActiveChanged (true,) or (false,)
|
||||
# Freedesktop: Locked or ActiveChanged
|
||||
if "ActiveChanged" in line or "Locked" in line:
|
||||
is_locked = "(true,)" in line or "true" in line.lower()
|
||||
with _privacy_lock:
|
||||
if _privacy_locked != is_locked:
|
||||
_privacy_locked = is_locked
|
||||
print(f"[privacy] System lock state change detected via {dest}: {is_locked}")
|
||||
_write_all_static()
|
||||
except Exception as e:
|
||||
print(f"[privacy] Monitor error for {dest}: {e}")
|
||||
|
||||
for dest, path in destinations:
|
||||
threading.Thread(target=monitor, args=(dest, path), daemon=True).start()
|
||||
|
||||
|
||||
def _write_json(path: str, data) -> None:
|
||||
@@ -4778,22 +4799,37 @@ def _build_pose_index_task():
|
||||
with _pose_index_lock:
|
||||
idx = _load_pose_index()
|
||||
persons = database.list_persons()
|
||||
todo = [p[0] for p in persons
|
||||
if p[0] not in idx
|
||||
|
||||
# p[17] is pose_description, p[18] is pose_skeleton
|
||||
todo = [p for p in persons
|
||||
if (p[0] not in idx or p[17] is None or p[18] is None)
|
||||
and (p[12] or "image") != "video"
|
||||
and p[0].lower().endswith(('.png', '.jpg', '.jpeg', '.webp'))]
|
||||
|
||||
_pose_index_status.update(running=True, done=0, total=len(todo))
|
||||
print(f"[pose] index build: {len(todo)} images to process")
|
||||
print(f"[pose] index build/backfill: {len(todo)} images to process")
|
||||
dirty = 0
|
||||
for fn in todo:
|
||||
for p in todo:
|
||||
fn = p[0]
|
||||
try:
|
||||
fpath = os.path.join(output_dir, fn)
|
||||
if os.path.exists(fpath):
|
||||
best = _best_person(infer(Image.open(fpath).convert("RGB")))
|
||||
desc = _pose_descriptor(best) if best is not None else None
|
||||
if desc is not None:
|
||||
idx[fn] = desc
|
||||
dirty += 1
|
||||
people = infer(Image.open(fpath).convert("RGB"))
|
||||
best = _best_person(people)
|
||||
|
||||
pose_desc = None
|
||||
pose_skel = None
|
||||
if best is not None:
|
||||
pose_desc = _describe_pose(best)
|
||||
pose_skel = json.dumps(best)
|
||||
desc = _pose_descriptor(best)
|
||||
if desc is not None:
|
||||
idx[fn] = desc
|
||||
dirty += 1
|
||||
|
||||
# Update DB if missing
|
||||
if p[17] is None or p[18] is None:
|
||||
database.upsert_person(fn, pose_description=pose_desc, pose_skeleton=pose_skel)
|
||||
except Exception as e:
|
||||
print(f"[pose] index error for {fn}: {e}")
|
||||
_pose_index_status["done"] += 1
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import torch
|
||||
import os
|
||||
os.environ["HF_HUB_OFFLINE"] = "1"
|
||||
os.environ["TRANSFORMERS_OFFLINE"] = "1"
|
||||
import open_clip
|
||||
from PIL import Image
|
||||
import os
|
||||
import threading
|
||||
|
||||
_model = None
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import os
|
||||
os.environ["HF_HUB_OFFLINE"] = "1"
|
||||
os.environ["TRANSFORMERS_OFFLINE"] = "1"
|
||||
import time
|
||||
import json
|
||||
import shutil
|
||||
|
||||
Reference in New Issue
Block a user