image-rag-pipeline / app /models /database.py
axit612's picture
Add Image-to-Image RAG Pipeline - FastAPI project
0c44b7d verified
Raw
History Blame Contribute Delete
3.35 kB
"""
Database Models & Setup
Defines SQLAlchemy ORM models for storing image records and generation history.
Uses async SQLite via aiosqlite for non-blocking database operations.
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import Column, String, Text, DateTime, Integer, Float
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
"""Base class for all ORM models."""
pass
class ImageRecord(Base):
"""
Stores metadata for every image in the system (uploaded or generated).
Each record is linked to a ChromaDB embedding via its ID.
"""
__tablename__ = "image_records"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
filename = Column(String, nullable=False) # Stored filename on disk
original_name = Column(String, nullable=True) # Original upload filename
description = Column(Text, nullable=True) # Vision model description
prompt = Column(Text, nullable=True) # User-provided prompt
generated_prompt = Column(Text, nullable=True) # Final engineered prompt
image_url = Column(String, nullable=True) # URL path to access image
source = Column(String, default="uploaded") # 'uploaded' or 'generated'
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
class GenerationHistory(Base):
"""
Stores the full pipeline history for each generation request.
Captures every stage: user input → vision → RAG → prompt → output.
"""
__tablename__ = "generation_history"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_input = Column(Text, nullable=False) # Original user text/prompt
input_type = Column(String, default="text") # 'text' or 'image'
vision_output = Column(Text, nullable=True) # Vision model description
retrieved_context = Column(Text, nullable=True) # RAG-retrieved similar descriptions
final_prompt = Column(Text, nullable=True) # Engineered prompt sent to generator
generated_image_url = Column(String, nullable=True) # URL of generated image
similarity_score = Column(Float, nullable=True) # Best match score from RAG
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
# --- Database Engine & Session Factory ---
_engine = None
_session_factory = None
async def init_db(database_url: str) -> None:
"""
Initialize the async database engine and create all tables.
Called once during application startup.
"""
global _engine, _session_factory
_engine = create_async_engine(database_url, echo=False)
_session_factory = async_sessionmaker(_engine, class_=AsyncSession, expire_on_commit=False)
# Create tables if they don't exist
async with _engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
def get_session_factory() -> async_sessionmaker[AsyncSession]:
"""
Returns the async session factory.
Must be called after init_db().
"""
if _session_factory is None:
raise RuntimeError("Database not initialized. Call init_db() first.")
return _session_factory