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:
@@ -111,6 +111,7 @@ def migrate_schema():
|
||||
"ALTER TABLE person ADD COLUMN IF NOT EXISTS content_type TEXT DEFAULT 'image'",
|
||||
"ALTER TABLE person ADD COLUMN IF NOT EXISTS faceswap_source_video TEXT",
|
||||
"ALTER TABLE person ADD COLUMN IF NOT EXISTS archived BOOLEAN DEFAULT FALSE",
|
||||
"ALTER TABLE person ADD COLUMN IF NOT EXISTS face_embedding vector(512)",
|
||||
]:
|
||||
cur.execute(sql)
|
||||
conn.commit()
|
||||
@@ -122,16 +123,18 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
|
||||
embedding=None, clip_description=None, prompt=None, pose=None,
|
||||
sort_order=None, group_name=None, hidden=None,
|
||||
has_background=None, source_refs=None, has_clothing=None,
|
||||
content_type=None, faceswap_source_video=None, archived=None):
|
||||
content_type=None, faceswap_source_video=None, archived=None,
|
||||
face_embedding=None):
|
||||
conn = get_db_connection()
|
||||
cur = conn.cursor()
|
||||
face_embedding_str = ("[" + ",".join(map(str, face_embedding)) + "]") if face_embedding is not None else None
|
||||
try:
|
||||
cur.execute("""
|
||||
INSERT INTO person (filename, filepath, name, group_id, tags, embedding,
|
||||
clip_description, prompt, pose, sort_order, group_name, hidden,
|
||||
has_background, source_refs, has_clothing,
|
||||
content_type, faceswap_source_video, archived)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
content_type, faceswap_source_video, archived, face_embedding)
|
||||
VALUES (%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),
|
||||
@@ -149,12 +152,13 @@ def upsert_person(filename, filepath=None, name=None, group_id=None, tags=None,
|
||||
has_clothing = COALESCE(EXCLUDED.has_clothing, person.has_clothing),
|
||||
content_type = COALESCE(EXCLUDED.content_type, person.content_type),
|
||||
faceswap_source_video = COALESCE(EXCLUDED.faceswap_source_video, person.faceswap_source_video),
|
||||
archived = COALESCE(EXCLUDED.archived, person.archived);
|
||||
archived = COALESCE(EXCLUDED.archived, person.archived),
|
||||
face_embedding = COALESCE(EXCLUDED.face_embedding, person.face_embedding);
|
||||
""", (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))
|
||||
content_type, faceswap_source_video, archived, face_embedding_str))
|
||||
conn.commit()
|
||||
finally:
|
||||
cur.close()
|
||||
@@ -330,3 +334,55 @@ def get_all_group_names():
|
||||
finally:
|
||||
cur.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
|
||||
def get_face_embedding(filename):
|
||||
"""Return the face_embedding as a list of floats for a filename, or None."""
|
||||
conn = get_db_connection()
|
||||
cur = conn.cursor()
|
||||
try:
|
||||
cur.execute("SELECT face_embedding FROM person WHERE filename = %s", (filename,))
|
||||
row = cur.fetchone()
|
||||
if row and row[0] is not None:
|
||||
val = row[0]
|
||||
# psycopg2 without a pgvector adapter returns vectors as plain strings "[f,f,...]"
|
||||
if isinstance(val, str):
|
||||
return [float(x) for x in val.strip("[]").split(",")]
|
||||
return list(val)
|
||||
return None
|
||||
finally:
|
||||
cur.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
|
||||
def search_similar_face(embedding, limit=12, exclude_group_id=None):
|
||||
"""Cosine search on face_embedding (stored only for *_face.png rows).
|
||||
|
||||
Returns [(filename, group_id, distance), ...] sorted ascending by distance.
|
||||
Rows belonging to exclude_group_id are skipped so a group doesn't match itself.
|
||||
"""
|
||||
conn = get_db_connection()
|
||||
cur = conn.cursor()
|
||||
try:
|
||||
embedding_str = "[" + ",".join(map(str, embedding)) + "]"
|
||||
if exclude_group_id:
|
||||
cur.execute("""
|
||||
SELECT filename, group_id, face_embedding <=> %s AS distance
|
||||
FROM person
|
||||
WHERE face_embedding IS NOT NULL
|
||||
AND (group_id IS NULL OR group_id != %s)
|
||||
ORDER BY distance ASC
|
||||
LIMIT %s
|
||||
""", (embedding_str, exclude_group_id, limit))
|
||||
else:
|
||||
cur.execute("""
|
||||
SELECT filename, group_id, face_embedding <=> %s AS distance
|
||||
FROM person
|
||||
WHERE face_embedding IS NOT NULL
|
||||
ORDER BY distance ASC
|
||||
LIMIT %s
|
||||
""", (embedding_str, limit))
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
cur.close()
|
||||
_put_db_connection(conn)
|
||||
|
||||
Reference in New Issue
Block a user