• 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:
mike
2026-06-29 12:27:10 +02:00
parent 3b9b9e829b
commit 150ef6dab0
10 changed files with 2078 additions and 119 deletions

View File

@@ -2,6 +2,8 @@ import psycopg2
from psycopg2 import pool as _pgpool
import threading
import json
import time
import random
DB_CONFIG = {
"host": "192.168.1.160",
@@ -115,6 +117,10 @@ def migrate_schema():
"ALTER TABLE person ADD COLUMN IF NOT EXISTS is_source BOOLEAN DEFAULT FALSE",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS pose_description TEXT",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS pose_skeleton TEXT",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS people_count INTEGER DEFAULT NULL",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS anatomical_completeness BOOLEAN DEFAULT NULL",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS facial_direction TEXT DEFAULT NULL",
"ALTER TABLE person ADD COLUMN IF NOT EXISTS objects JSONB DEFAULT NULL",
]:
cur.execute(sql)
conn.commit()
@@ -209,7 +215,8 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
has_background=None, source_refs=None, has_clothing=None,
content_type=None, faceswap_source_video=None, archived=None,
face_embedding=None, is_source=None,
pose_description=None, pose_skeleton=None):
pose_description=None, pose_skeleton=None,
people_count=None, anatomical_completeness=None, facial_direction=None, objects=None):
conn = get_db_connection()
cur = conn.cursor()
face_embedding_str = ("[" + ",".join(map(str, face_embedding)) + "]") if face_embedding is not None else None
@@ -219,8 +226,8 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
clip_description, prompt, pose, sort_order, group_name, hidden,
has_background, source_refs, has_clothing,
content_type, faceswap_source_video, archived, face_embedding, is_source,
pose_description, pose_skeleton)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
pose_description, pose_skeleton, people_count, anatomical_completeness, facial_direction, objects)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
ON CONFLICT (filename) DO UPDATE
SET filepath = COALESCE(EXCLUDED.filepath, person.filepath),
name = COALESCE(EXCLUDED.name, person.name),
@@ -242,13 +249,18 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
face_embedding = COALESCE(EXCLUDED.face_embedding, person.face_embedding),
is_source = COALESCE(EXCLUDED.is_source, person.is_source),
pose_description = COALESCE(EXCLUDED.pose_description, person.pose_description),
pose_skeleton = COALESCE(EXCLUDED.pose_skeleton, person.pose_skeleton);
pose_skeleton = COALESCE(EXCLUDED.pose_skeleton, person.pose_skeleton),
people_count = COALESCE(EXCLUDED.people_count, person.people_count),
anatomical_completeness = COALESCE(EXCLUDED.anatomical_completeness, person.anatomical_completeness),
facial_direction = COALESCE(EXCLUDED.facial_direction, person.facial_direction),
objects = COALESCE(EXCLUDED.objects, person.objects);
""", (filename, filepath, name, group_id,
json.dumps(tags) if tags else None,
embedding, clip_description, prompt, pose, sort_order, group_name, hidden,
has_background, source_refs, has_clothing,
content_type, faceswap_source_video, archived, face_embedding_str, is_source,
pose_description, pose_skeleton))
pose_description, pose_skeleton, people_count, anatomical_completeness, facial_direction,
json.dumps(objects) if objects else None))
conn.commit()
finally:
cur.close()
@@ -306,7 +318,8 @@ def get_person(filename):
cur.execute("""
SELECT name, group_id, tags, embedding, clip_description, filepath,
prompt, pose, sort_order, group_name, hidden, has_background, source_refs,
has_clothing, is_source, pose_description, pose_skeleton
has_clothing, is_source, pose_description, pose_skeleton,
people_count, anatomical_completeness, facial_direction, objects
FROM person WHERE filename = %s
""", (filename,))
return cur.fetchone()
@@ -323,7 +336,7 @@ def list_persons(include_archived=False):
SELECT filename, name, group_id, clip_description,
prompt, pose, sort_order, group_name, hidden, has_background, source_refs,
has_clothing, content_type, faceswap_source_video, archived, is_source, tags,
pose_description, pose_skeleton
pose_description, pose_skeleton, people_count, anatomical_completeness, facial_direction, objects
FROM person
{where}
""")
@@ -380,19 +393,43 @@ def get_group_files(group_id):
_put_db_connection(conn)
def set_group_order(group_id, ordered_filenames):
"""Assign sort_order 0,1,2,... to filenames in the given order."""
conn = get_db_connection()
cur = conn.cursor()
try:
for idx, fname in enumerate(ordered_filenames):
cur.execute(
"UPDATE person SET sort_order = %s WHERE filename = %s",
(idx, fname)
)
conn.commit()
finally:
cur.close()
_put_db_connection(conn)
"""Assign sort_order 0,1,2,... to filenames in the given order, resiliently."""
max_retries = 5
for attempt in range(max_retries):
conn = get_db_connection()
cur = conn.cursor()
try:
# Deterministic lock ordering to prevent deadlocks:
# Fetch and lock all unique filenames alphabetically
unique_filenames = sorted(list(set(ordered_filenames)))
if unique_filenames:
cur.execute(
"SELECT filename FROM person WHERE filename = ANY(%s) ORDER BY filename FOR UPDATE",
(unique_filenames,)
)
for idx, fname in enumerate(ordered_filenames):
cur.execute(
"UPDATE person SET sort_order = %s WHERE filename = %s",
(idx, fname)
)
conn.commit()
break
except (psycopg2.OperationalError, psycopg2.extensions.TransactionRollbackError) as e:
pgcode = getattr(e, 'pgcode', None)
if pgcode in ('40P01', '40001') or "deadlock" in str(e).lower():
try:
conn.rollback()
except Exception:
pass
if attempt == max_retries - 1:
raise
sleep_time = (0.1 * (2 ** attempt)) + random.uniform(0.01, 0.1)
time.sleep(sleep_time)
else:
raise
finally:
cur.close()
_put_db_connection(conn)
def get_group_order(group_id):
"""Return [(filename, sort_order), ...] sorted by sort_order NULLS LAST."""