"""face_embeddings table Revision ID: 0005_face_embeddings Revises: 0004_ocr_fts Create Date: 2026-04-10 Create face_embeddings table with pgvector Vector(128) for SFace recognition embeddings and HNSW index. """ from typing import Sequence, Union from alembic import op revision: str = "0005_face_embeddings" down_revision: Union[str, None] = "0004_ocr_fts" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute(""" CREATE TABLE IF NOT EXISTS face_embeddings ( id VARCHAR PRIMARY KEY, photo_id VARCHAR NOT NULL REFERENCES photos(id) ON DELETE CASCADE, bbox JSONB, vector vector(128), cluster_id VARCHAR REFERENCES tags(id) ON DELETE SET NULL, quality FLOAT, created_at TIMESTAMPTZ DEFAULT now() ) """) op.execute("CREATE INDEX IF NOT EXISTS ix_face_embeddings_photo_id ON face_embeddings(photo_id)") op.execute("CREATE INDEX IF NOT EXISTS ix_face_embeddings_cluster_id ON face_embeddings(cluster_id)") op.execute(""" CREATE INDEX IF NOT EXISTS ix_face_embeddings_vector_hnsw ON face_embeddings USING hnsw (vector vector_cosine_ops) """) def downgrade() -> None: op.execute("DROP TABLE IF EXISTS face_embeddings")