dphn/Dolphin3.0-Mistral-24B is the ungated mirror of the Dolphin 3.0 Mistral 24B — exactly what you asked for. It's ~48GB fp16, which needs GPU+CPU split (device_map="auto" with 32GB on GPU, ~16GB in RAM). Let me kick off the download and update the service in parallel.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import psycopg2
|
||||
from psycopg2 import pool as _pgpool
|
||||
import threading
|
||||
import json
|
||||
|
||||
DB_CONFIG = {
|
||||
@@ -9,9 +11,89 @@ DB_CONFIG = {
|
||||
"password": "dev"
|
||||
}
|
||||
|
||||
# A pooled connection is reused across requests instead of paying a fresh TCP +
|
||||
# auth round-trip (~40 ms) on every single query. Under load (a generation
|
||||
# running, a burst of reorders) the old open-per-call design starved the web
|
||||
# threadpool and occasionally tripped Postgres' connection ceiling → 500s.
|
||||
# The pool bounds connections and keeps them warm. If the pool can't be
|
||||
# created or is momentarily exhausted, get_db_connection() falls back to a
|
||||
# direct connect so callers never block or fail.
|
||||
# Cover the web server's sync threadpool (uvicorn/anyio default = 40 workers)
|
||||
# with headroom for background workers, while staying well under Postgres'
|
||||
# max_connections (100).
|
||||
_POOL_MIN = 2
|
||||
_POOL_MAX = 48
|
||||
_pool = None
|
||||
_pool_lock = threading.Lock()
|
||||
|
||||
|
||||
def _get_pool():
|
||||
global _pool
|
||||
if _pool is not None:
|
||||
return _pool
|
||||
with _pool_lock:
|
||||
if _pool is None:
|
||||
try:
|
||||
_pool = _pgpool.ThreadedConnectionPool(
|
||||
_POOL_MIN, _POOL_MAX, **DB_CONFIG)
|
||||
except Exception as e:
|
||||
print(f"[db] pool init failed, using direct connections: {e}")
|
||||
_pool = False # sentinel: don't retry on every call
|
||||
return _pool
|
||||
|
||||
|
||||
def get_db_connection():
|
||||
"""Return a live DB connection, preferring the pool.
|
||||
|
||||
Always pair with _put_db_connection() (the existing finally: conn.close()
|
||||
callsites are rewritten to call it) so pooled connections are returned
|
||||
rather than dropped.
|
||||
"""
|
||||
p = _get_pool()
|
||||
if p:
|
||||
try:
|
||||
conn = p.getconn()
|
||||
# Guard against a stale/dead pooled connection.
|
||||
if getattr(conn, "closed", 0):
|
||||
try:
|
||||
p.putconn(conn, close=True)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
return conn
|
||||
except _pgpool.PoolError:
|
||||
# Pool momentarily exhausted — expected under burst; fall back to a
|
||||
# direct connection silently rather than blocking or failing.
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"[db] pool getconn failed, direct connect: {e}")
|
||||
return psycopg2.connect(**DB_CONFIG)
|
||||
|
||||
|
||||
def _put_db_connection(conn):
|
||||
"""Return a connection to the pool (rolling back any open txn) or close it.
|
||||
|
||||
Safe for both pooled and direct/fallback connections: putconn raises for a
|
||||
connection the pool doesn't own, in which case we just close it.
|
||||
"""
|
||||
if conn is None:
|
||||
return
|
||||
p = _pool
|
||||
try:
|
||||
if p:
|
||||
try:
|
||||
conn.rollback() # clear any aborted/idle-in-txn state before reuse
|
||||
except Exception:
|
||||
pass
|
||||
p.putconn(conn)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def migrate_schema():
|
||||
"""Add new columns to person table if they don't exist. Safe to call repeatedly."""
|
||||
conn = get_db_connection()
|
||||
@@ -34,7 +116,7 @@ def migrate_schema():
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
|
||||
embedding=None, clip_description=None, prompt=None, pose=None,
|
||||
@@ -76,7 +158,7 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def set_archived(filename, archived: bool):
|
||||
conn = get_db_connection()
|
||||
@@ -86,7 +168,7 @@ def set_archived(filename, archived: bool):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def set_hidden(filename, hidden: bool):
|
||||
conn = get_db_connection()
|
||||
@@ -96,7 +178,7 @@ def set_hidden(filename, hidden: bool):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def get_person(filename):
|
||||
conn = get_db_connection()
|
||||
@@ -111,7 +193,7 @@ def get_person(filename):
|
||||
return cur.fetchone()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def list_persons(include_archived=False):
|
||||
conn = get_db_connection()
|
||||
@@ -128,7 +210,7 @@ def list_persons(include_archived=False):
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def search_similar(embedding, limit=10):
|
||||
conn = get_db_connection()
|
||||
@@ -145,7 +227,7 @@ def search_similar(embedding, limit=10):
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def delete_person(filename):
|
||||
conn = get_db_connection()
|
||||
@@ -155,7 +237,7 @@ def delete_person(filename):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def delete_group(group_id):
|
||||
conn = get_db_connection()
|
||||
@@ -165,7 +247,7 @@ def delete_group(group_id):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def get_group_files(group_id):
|
||||
conn = get_db_connection()
|
||||
@@ -175,7 +257,7 @@ def get_group_files(group_id):
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def set_group_order(group_id, ordered_filenames):
|
||||
"""Assign sort_order 0,1,2,... to filenames in the given order."""
|
||||
@@ -190,7 +272,7 @@ def set_group_order(group_id, ordered_filenames):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def get_group_order(group_id):
|
||||
"""Return [(filename, sort_order), ...] sorted by sort_order NULLS LAST."""
|
||||
@@ -206,7 +288,7 @@ def get_group_order(group_id):
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def set_group_name(group_id, name):
|
||||
"""Set group_name for every file in the group."""
|
||||
@@ -217,7 +299,7 @@ def set_group_name(group_id, name):
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
def get_next_sort_order(group_id):
|
||||
"""Return max(sort_order)+1 for the group, or 1 if no sorted members exist."""
|
||||
@@ -231,7 +313,7 @@ def get_next_sort_order(group_id):
|
||||
return cur.fetchone()[0]
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
|
||||
def get_all_group_names():
|
||||
@@ -247,4 +329,4 @@ def get_all_group_names():
|
||||
return {row[0]: row[1] for row in cur.fetchall()}
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
Reference in New Issue
Block a user