""" Face embedding model — stores per-face detection + recognition vectors. cluster_id FKs to tags.id where kind='face_cluster'. Null means unclustered (will be assigned by recluster_faces). """ from sqlalchemy import Column, String, Float, ForeignKey, DateTime, func from sqlalchemy.dialects.postgresql import JSONB from pgvector.sqlalchemy import Vector import uuid from app.database import Base class FaceEmbedding(Base): __tablename__ = 'face_embeddings' id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) photo_id = Column(String, ForeignKey('photos.id', ondelete='CASCADE'), nullable=False, index=True) bbox = Column(JSONB) # [x1, y1, x2, y2] normalized 0-1 vector = Column(Vector(512)) # ArcFace → 512-d cluster_id = Column(String, ForeignKey('tags.id', ondelete='SET NULL'), nullable=True, index=True) quality = Column(Float) created_at = Column(DateTime(timezone=True), server_default=func.now())