from datetime import datetime from pgvector.sqlalchemy import Vector from sqlalchemy import Column, DateTime, String from sqlalchemy.orm import declared_attr, deferred from app.config import settings class Embeddable: """Retrieval columns shared by every searchable corpus. `embedding_model` is what makes a model change detectable: vectors from two models share no space, so a mixed corpus returns meaningless distances. Deferred because a vector is large and never wanted in a list query. """ # Mixin columns must be declared attributes, one per mapped class. @declared_attr def embedding(cls): return deferred(Column(Vector(settings.EMBEDDING_DIMENSIONS), nullable=True)) @declared_attr def embedding_model(cls): return Column(String(120), nullable=True, index=True) @declared_attr def embedded_at(cls): return Column(DateTime, nullable=True)