Download backend/app/db/database.py from Rixhot/ZARAI: direct link, hf CLI and curl.
- Browser
- Download file 6.5 kB
-
https://huggingface.co/spaces/Rixhot/ZARAI/resolve/main/backend/app/db/database.py
- Command line
-
hf download hf://spaces/Rixhot/ZARAI/backend/app/db/database.py
-
curl -L -o database.py https://huggingface.co/spaces/Rixhot/ZARAI/resolve/main/backend/app/db/database.py
6.5 kB
| """ | |
| JARVIS β Database Layer | |
| Async SQLAlchemy with SQLite. | |
| Tables: sessions, conversations, embeddings_meta | |
| """ | |
| from datetime import datetime | |
| from typing import Optional, List | |
| from sqlalchemy import ( | |
| Column, String, Text, DateTime, Integer, | |
| ForeignKey, Index, event | |
| ) | |
| from sqlalchemy.ext.asyncio import ( | |
| AsyncSession, create_async_engine, async_sessionmaker | |
| ) | |
| from sqlalchemy.orm import DeclarativeBase, relationship | |
| from sqlalchemy.future import select | |
| from loguru import logger | |
| from app.core.config import settings | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Engine & session factory | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| engine = create_async_engine( | |
| settings.DATABASE_URL, | |
| echo=settings.DEBUG, | |
| connect_args={"check_same_thread": False}, | |
| ) | |
| AsyncSessionLocal = async_sessionmaker( | |
| engine, | |
| class_=AsyncSession, | |
| expire_on_commit=False, | |
| ) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Base model | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| class Base(DeclarativeBase): | |
| pass | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # ORM Models | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| class Session(Base): | |
| """A chat session (conversation thread).""" | |
| __tablename__ = "sessions" | |
| id = Column(String(36), primary_key=True) # UUID | |
| title = Column(String(200), default="New Chat") | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| messages = relationship("Message", back_populates="session", cascade="all, delete-orphan") | |
| class Message(Base): | |
| """A single message in a session.""" | |
| __tablename__ = "messages" | |
| id = Column(Integer, primary_key=True, autoincrement=True) | |
| session_id = Column(String(36), ForeignKey("sessions.id"), nullable=False) | |
| role = Column(String(20), nullable=False) # "user" | "assistant" | "system" | |
| content = Column(Text, nullable=False) | |
| modality = Column(String(20), default="text") # text | image | voice | tool | |
| metadata_ = Column("metadata", Text, default="{}") # JSON string | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| session = relationship("Session", back_populates="messages") | |
| __table_args__ = ( | |
| Index("ix_messages_session_id", "session_id"), | |
| Index("ix_messages_created_at", "created_at"), | |
| ) | |
| class EmbeddingMeta(Base): | |
| """Metadata for stored FAISS embeddings.""" | |
| __tablename__ = "embeddings_meta" | |
| id = Column(Integer, primary_key=True, autoincrement=True) | |
| faiss_id = Column(Integer, unique=True, nullable=False) # index in FAISS | |
| session_id = Column(String(36), nullable=True) | |
| text = Column(Text, nullable=False) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Init | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| async def init_db(): | |
| """Create all tables if they don't exist.""" | |
| async with engine.begin() as conn: | |
| await conn.run_sync(Base.metadata.create_all) | |
| logger.info("Database tables created/verified.") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Dependency | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| async def get_db() -> AsyncSession: | |
| """FastAPI dependency β yields an async DB session.""" | |
| async with AsyncSessionLocal() as session: | |
| try: | |
| yield session | |
| await session.commit() | |
| except Exception: | |
| await session.rollback() | |
| raise | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Helper CRUD functions | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| async def create_session(db: AsyncSession, session_id: str, title: str = "New Chat") -> Session: | |
| sess = Session(id=session_id, title=title) | |
| db.add(sess) | |
| await db.flush() | |
| return sess | |
| async def get_session(db: AsyncSession, session_id: str) -> Optional[Session]: | |
| result = await db.execute(select(Session).where(Session.id == session_id)) | |
| return result.scalar_one_or_none() | |
| async def list_sessions(db: AsyncSession, limit: int = 50) -> List[Session]: | |
| result = await db.execute( | |
| select(Session).order_by(Session.updated_at.desc()).limit(limit) | |
| ) | |
| return result.scalars().all() | |
| async def add_message( | |
| db: AsyncSession, | |
| session_id: str, | |
| role: str, | |
| content: str, | |
| modality: str = "text", | |
| metadata: str = "{}", | |
| ) -> Message: | |
| msg = Message( | |
| session_id=session_id, | |
| role=role, | |
| content=content, | |
| modality=modality, | |
| metadata_=metadata, | |
| ) | |
| db.add(msg) | |
| await db.flush() | |
| # Update session timestamp | |
| sess = await get_session(db, session_id) | |
| if sess: | |
| sess.updated_at = datetime.utcnow() | |
| return msg | |
| async def get_messages( | |
| db: AsyncSession, | |
| session_id: str, | |
| limit: int = 50, | |
| ) -> List[Message]: | |
| result = await db.execute( | |
| select(Message) | |
| .where(Message.session_id == session_id) | |
| .order_by(Message.created_at.asc()) | |
| .limit(limit) | |
| ) | |
| return result.scalars().all() | |
| async def add_embedding_meta( | |
| db: AsyncSession, | |
| faiss_id: int, | |
| text: str, | |
| session_id: Optional[str] = None, | |
| ) -> EmbeddingMeta: | |
| em = EmbeddingMeta(faiss_id=faiss_id, text=text, session_id=session_id) | |
| db.add(em) | |
| await db.flush() | |
| return em | |