eye-dentify-api / app /models /__init__.py
truegleai's picture
Deploy Eye-Dentify backend to HF Spaces
216de21 verified
from sqlalchemy import (
Column,
Integer,
String,
Text,
Float,
Boolean,
DateTime,
JSON,
Enum,
ForeignKey,
Index,
)
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
import enum
import uuid
from app.database import Base
class VideoStatus(enum.Enum):
PENDING = "pending"
DOWNLOADING = "downloading"
EXTRACTING = "extracting"
ENCODING = "encoding"
INDEXING = "indexing"
COMPLETED = "completed"
FAILED = "failed"
class AnalysisType(enum.Enum):
SEARCH = "search"
GPS = "gps"
AI_DETECTION = "ai_detection"
FULL = "full"
class AnalysisStatus(enum.Enum):
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
class Video(Base):
__tablename__ = "videos"
__table_args__ = (
Index("idx_videos_youtube_id", "youtube_id", unique=True),
Index("idx_videos_status", "status"),
Index("idx_videos_created_at", "created_at"),
)
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
youtube_id = Column(String(20), unique=True, nullable=False, index=True)
youtube_url = Column(String(500), nullable=False)
title = Column(String(500), nullable=True)
description = Column(Text, nullable=True)
channel = Column(String(300), nullable=True)
duration = Column(Integer, nullable=True) # seconds
thumbnail_url = Column(String(500), nullable=True)
upload_date = Column(String(20), nullable=True)
# File paths
local_path = Column(String(500), nullable=True)
frames_count = Column(Integer, default=0)
features_count = Column(Integer, default=0)
# Status
status = Column(Enum(VideoStatus), default=VideoStatus.PENDING)
error_message = Column(Text, nullable=True)
# Timestamps
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
# Relationships
analyses = relationship("Analysis", back_populates="video", cascade="all, delete-orphan")
def __repr__(self):
return f"<Video {self.youtube_id}: {self.title}>"
class Analysis(Base):
__tablename__ = "analyses"
__table_args__ = (
Index("idx_analyses_video_id", "video_id"),
Index("idx_analyses_status", "status"),
Index("idx_analyses_type", "analysis_type"),
)
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
video_id = Column(UUID(as_uuid=True), ForeignKey("videos.id", ondelete="CASCADE"), nullable=False)
analysis_type = Column(Enum(AnalysisType), default=AnalysisType.FULL)
# Status
status = Column(Enum(AnalysisStatus), default=AnalysisStatus.PENDING)
progress = Column(Float, default=0.0) # 0.0 to 100.0
error_message = Column(Text, nullable=True)
# Results
results = Column(JSON, nullable=True) # Flexible JSON for any analysis type
# Timestamps
created_at = Column(DateTime(timezone=True), server_default=func.now())
completed_at = Column(DateTime(timezone=True), nullable=True)
# Relationships
video = relationship("Video", back_populates="analyses")
def __repr__(self):
return f"<Analysis {self.id}: {self.analysis_type.value} for {self.video_id}>"
class SearchResult(Base):
__tablename__ = "search_results"
__table_args__ = (
Index("idx_search_analysis_id", "analysis_id"),
Index("idx_search_matched_video_id", "matched_video_id"),
)
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
analysis_id = Column(UUID(as_uuid=True), ForeignKey("analyses.id", ondelete="CASCADE"), nullable=False)
matched_video_id = Column(UUID(as_uuid=True), ForeignKey("videos.id"), nullable=False)
# Search metrics
num_matching_frames = Column(Integer, default=0)
avg_similarity = Column(Float, default=0.0)
max_similarity = Column(Float, default=0.0)
rank = Column(Integer, default=0)
# Detailed matches (JSON array of frame-level matches)
frame_matches = Column(JSON, nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
# Relationships
analysis = relationship("Analysis")
matched_video = relationship("Video")
class UserSession(Base):
__tablename__ = "user_sessions"
__table_args__ = (
Index("idx_sessions_session_key", "session_key", unique=True),
Index("idx_sessions_expires", "expires_at"),
)
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
session_key = Column(String(100), unique=True, nullable=False, index=True)
ip_address = Column(String(45), nullable=True)
user_agent = Column(String(500), nullable=True)
query_count = Column(Integer, default=0)
expires_at = Column(DateTime(timezone=True), nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
# Import relationship
from sqlalchemy.orm import relationship # noqa: E402
Video.analyses = relationship("Analysis", back_populates="video", cascade="all, delete-orphan")
Analysis.video = relationship("Video", back_populates="analyses")