Spaces:
Sleeping
Sleeping
| """ | |
| SQLModel ORM table definitions and the SQLAlchemy engine singleton. | |
| Tables | |
| ------ | |
| User β accounts (email, hashed password, role, active flag). | |
| Job β file processing jobs with full status/step/retry/error tracking. | |
| UsageLog β one row per LLM/Whisper/embed API call (tokens, latency, model). | |
| QueryHistory β one row per RAG query (answer, citations, RAGAS scores). | |
| Engine | |
| ------ | |
| get_engine() returns a module-level singleton so the connection pool is shared | |
| across all Celery tasks and FastAPI requests in the same process. | |
| """ | |
| import enum | |
| import uuid | |
| from datetime import datetime | |
| from typing import Optional | |
| from sqlmodel import Field, SQLModel, create_engine, Session | |
| from sqlalchemy import text | |
| # ββ Enums ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class UserRole(str, enum.Enum): | |
| admin = "admin" | |
| user = "user" | |
| class JobStatus(str, enum.Enum): | |
| pending = "PENDING" | |
| processing = "PROCESSING" | |
| completed = "COMPLETED" | |
| failed = "FAILED" | |
| failed_permanent = "FAILED_PERMANENT" | |
| class ErrorType(str, enum.Enum): | |
| rate_limit = "RATE_LIMIT" | |
| invalid_input = "INVALID_INPUT" | |
| unknown = "UNKNOWN" | |
| # ββ Tables βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class User(SQLModel, table=True): | |
| __tablename__ = "users" | |
| id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) | |
| email: str = Field(unique=True, index=True) | |
| hashed_password: str | |
| role: UserRole = Field(default=UserRole.user) | |
| is_active: bool = Field(default=True) | |
| created_at: datetime = Field(default_factory=datetime.utcnow) | |
| last_active_at: Optional[datetime] = Field(default=None) | |
| class Job(SQLModel, table=True): | |
| __tablename__ = "jobs" | |
| id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) | |
| user_id: uuid.UUID = Field(foreign_key="users.id", index=True) | |
| filename: str | |
| file_type: str | |
| file_path: str | |
| file_size_bytes: int | |
| status: JobStatus = Field(default=JobStatus.pending) | |
| step: Optional[str] = Field(default=None) | |
| retry_count: int = Field(default=0) | |
| error_type: Optional[ErrorType] = Field(default=None) | |
| error_message: Optional[str] = Field(default=None) | |
| result: Optional[str] = Field(default=None) | |
| chunk_count: Optional[int] = Field(default=None) | |
| created_at: datetime = Field(default_factory=datetime.utcnow) | |
| updated_at: datetime = Field(default_factory=datetime.utcnow) | |
| class UsageLog(SQLModel, table=True): | |
| __tablename__ = "usage_logs" | |
| id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) | |
| user_id: Optional[uuid.UUID] = Field(default=None, foreign_key="users.id", index=True) | |
| job_id: Optional[uuid.UUID] = Field(default=None, foreign_key="jobs.id", index=True) | |
| endpoint: str | |
| model: str | |
| prompt_tokens: int | |
| completion_tokens: int | |
| total_tokens: int | |
| latency_ms: int | |
| query_text: Optional[str] = Field(default=None) | |
| llm_response_preview: Optional[str] = Field(default=None) | |
| created_at: datetime = Field(default_factory=datetime.utcnow) | |
| class QueryHistory(SQLModel, table=True): | |
| __tablename__ = "query_history" | |
| id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) | |
| user_id: uuid.UUID = Field(foreign_key="users.id", index=True) | |
| question: str | |
| answer: str | |
| citations: str | |
| job_ids_queried: str | |
| chunk_count_retrieved: int | |
| avg_similarity_score: float | |
| confidence_gate_passed: bool | |
| prompt_tokens: int | |
| completion_tokens: int | |
| latency_ms: int | |
| ragas_scores: Optional[str] = Field(default=None) | |
| ragas_computed_at: Optional[datetime] = Field(default=None) | |
| created_at: datetime = Field(default_factory=datetime.utcnow) | |
| # ββ Engine helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _engine = None | |
| def get_engine(): | |
| global _engine | |
| if _engine is None: | |
| from app.config import settings | |
| _engine = create_engine( | |
| settings.DATABASE_URL, | |
| echo=False, | |
| pool_size=10, | |
| max_overflow=20, | |
| pool_pre_ping=True, | |
| ) | |
| return _engine | |
| def create_db_and_tables(): | |
| SQLModel.metadata.create_all(get_engine()) | |