| from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, DateTime, Text, Float, Boolean, JSON, UniqueConstraint |
| from sqlalchemy.ext.declarative import declarative_base |
| from sqlalchemy.orm import sessionmaker, relationship |
| from datetime import datetime, UTC |
|
|
| |
| Base = declarative_base() |
|
|
| |
| class User(Base): |
| __tablename__ = 'users' |
| |
| user_id = Column(Integer, primary_key=True, autoincrement=True) |
| username = Column(String, nullable=False) |
| email = Column(String, unique=True, nullable=False) |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| |
| chats = relationship("Chat", back_populates="user", cascade="all, delete-orphan") |
| usage_records = relationship("ModelUsage", back_populates="user") |
| deep_analysis_reports = relationship("DeepAnalysisReport", back_populates="user", cascade="all, delete-orphan") |
| template_preferences = relationship("UserTemplatePreference", back_populates="user", cascade="all, delete-orphan") |
|
|
| |
| class Chat(Base): |
| __tablename__ = 'chats' |
| |
| chat_id = Column(Integer, primary_key=True, autoincrement=True) |
| user_id = Column(Integer, ForeignKey('users.user_id', ondelete="CASCADE"), nullable=True) |
| title = Column(String, default='New Chat') |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| |
| user = relationship("User", back_populates="chats") |
| messages = relationship("Message", back_populates="chat", cascade="all, delete-orphan") |
| usage_records = relationship("ModelUsage", back_populates="chat") |
|
|
| |
| class Message(Base): |
| __tablename__ = 'messages' |
| |
| message_id = Column(Integer, primary_key=True, autoincrement=True) |
| chat_id = Column(Integer, ForeignKey('chats.chat_id', ondelete="CASCADE"), nullable=False) |
| sender = Column(String, nullable=False) |
| content = Column(Text, nullable=False) |
| timestamp = Column(DateTime, default=lambda: datetime.now(UTC)) |
| |
| chat = relationship("Chat", back_populates="messages") |
| feedback = relationship("MessageFeedback", back_populates="message", uselist=False, cascade="all, delete-orphan") |
|
|
| |
| class ModelUsage(Base): |
| """Tracks AI model usage metrics for analytics and billing purposes.""" |
| __tablename__ = 'model_usage' |
| |
| usage_id = Column(Integer, primary_key=True) |
| user_id = Column(Integer, ForeignKey('users.user_id', ondelete="SET NULL"), nullable=True) |
| chat_id = Column(Integer, ForeignKey('chats.chat_id', ondelete="SET NULL"), nullable=True) |
| model_name = Column(String(100), nullable=False) |
| provider = Column(String(50), nullable=False) |
| prompt_tokens = Column(Integer, default=0) |
| completion_tokens = Column(Integer, default=0) |
| total_tokens = Column(Integer, default=0) |
| query_size = Column(Integer, default=0) |
| response_size = Column(Integer, default=0) |
| cost = Column(Float, default=0.0) |
| timestamp = Column(DateTime, default=lambda: datetime.now(UTC)) |
| is_streaming = Column(Boolean, default=False) |
| request_time_ms = Column(Integer, default=0) |
| |
| user = relationship("User", back_populates="usage_records") |
| chat = relationship("Chat", back_populates="usage_records") |
|
|
| |
| class CodeExecution(Base): |
| """Tracks code execution attempts and results for analysis and debugging.""" |
| __tablename__ = 'code_executions' |
| |
| execution_id = Column(Integer, primary_key=True, autoincrement=True) |
| message_id = Column(Integer, ForeignKey('messages.message_id', ondelete="CASCADE"), nullable=True) |
| chat_id = Column(Integer, ForeignKey('chats.chat_id', ondelete="CASCADE"), nullable=True) |
| user_id = Column(Integer, ForeignKey('users.user_id', ondelete="SET NULL"), nullable=True) |
| |
| |
| initial_code = Column(Text, nullable=True) |
| latest_code = Column(Text, nullable=True) |
| |
| |
| is_successful = Column(Boolean, default=False) |
| output = Column(Text, nullable=True) |
| |
| |
| model_provider = Column(String(50), nullable=True) |
| model_name = Column(String(100), nullable=True) |
| model_temperature = Column(Float, nullable=True) |
| model_max_tokens = Column(Integer, nullable=True) |
| |
| |
| failed_agents = Column(Text, nullable=True) |
| error_messages = Column(Text, nullable=True) |
| |
| |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) |
| |
| class MessageFeedback(Base): |
| """Tracks user feedback and model settings for each message.""" |
| __tablename__ = 'message_feedback' |
| |
| feedback_id = Column(Integer, primary_key=True, autoincrement=True) |
| message_id = Column(Integer, ForeignKey('messages.message_id', ondelete="CASCADE"), nullable=False) |
| |
| |
| rating = Column(Integer, nullable=True) |
| |
| |
| model_name = Column(String(100), nullable=True) |
| model_provider = Column(String(50), nullable=True) |
| temperature = Column(Float, nullable=True) |
| max_tokens = Column(Integer, nullable=True) |
|
|
| |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) |
| |
| |
| message = relationship("Message", back_populates="feedback") |
|
|
| class DeepAnalysisReport(Base): |
| """Stores deep analysis reports with comprehensive analysis data and metadata.""" |
| __tablename__ = 'deep_analysis_reports' |
| |
| report_id = Column(Integer, primary_key=True, autoincrement=True) |
| report_uuid = Column(String(100), unique=True, nullable=False) |
| user_id = Column(Integer, ForeignKey('users.user_id', ondelete="CASCADE"), nullable=True) |
| |
| |
| goal = Column(Text, nullable=False) |
| status = Column(String(20), nullable=False, default='pending') |
| |
| |
| start_time = Column(DateTime, default=lambda: datetime.now(UTC)) |
| end_time = Column(DateTime, nullable=True) |
| duration_seconds = Column(Integer, nullable=True) |
| |
| |
| deep_questions = Column(Text, nullable=True) |
| deep_plan = Column(Text, nullable=True) |
| summaries = Column(JSON, nullable=True) |
| analysis_code = Column(Text, nullable=True) |
| plotly_figures = Column(JSON, nullable=True) |
| synthesis = Column(JSON, nullable=True) |
| final_conclusion = Column(Text, nullable=True) |
| |
| |
| html_report = Column(Text, nullable=True) |
| report_summary = Column(Text, nullable=True) |
| |
| |
| progress_percentage = Column(Integer, default=0) |
| steps_completed = Column(JSON, nullable=True) |
| error_message = Column(Text, nullable=True) |
| |
| |
| model_provider = Column(String(50), nullable=True) |
| model_name = Column(String(100), nullable=True) |
| total_tokens_used = Column(Integer, default=0) |
| estimated_cost = Column(Float, default=0.0) |
| credits_consumed = Column(Integer, default=0) |
| |
| |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) |
| |
| |
| user = relationship("User", back_populates="deep_analysis_reports") |
| |
| class AgentTemplate(Base): |
| """Stores predefined agent templates that users can enable/disable.""" |
| __tablename__ = 'agent_templates' |
| |
| template_id = Column(Integer, primary_key=True, autoincrement=True) |
| |
| |
| template_name = Column(String(100), nullable=False, unique=True) |
| display_name = Column(String(200), nullable=True) |
| description = Column(Text, nullable=False) |
| prompt_template = Column(Text, nullable=False) |
| |
| |
| icon_url = Column(String(500), nullable=True) |
| |
| |
| category = Column(String(50), nullable=True) |
| is_premium_only = Column(Boolean, default=False) |
| |
| |
| variant_type = Column(String(20), default='individual') |
| base_agent = Column(String(100), nullable=True) |
| |
| |
| is_active = Column(Boolean, default=True) |
| |
| |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) |
| |
| |
| user_preferences = relationship("UserTemplatePreference", back_populates="template", cascade="all, delete-orphan") |
|
|
| class UserTemplatePreference(Base): |
| """Tracks user preferences and usage for agent templates.""" |
| __tablename__ = 'user_template_preferences' |
| |
| preference_id = Column(Integer, primary_key=True, autoincrement=True) |
| user_id = Column(Integer, ForeignKey('users.user_id', ondelete="CASCADE"), nullable=False) |
| template_id = Column(Integer, ForeignKey('agent_templates.template_id', ondelete="CASCADE"), nullable=False) |
| |
| |
| is_enabled = Column(Boolean, default=True) |
| |
| |
| usage_count = Column(Integer, default=0) |
| last_used_at = Column(DateTime, nullable=True) |
| |
| |
| created_at = Column(DateTime, default=lambda: datetime.now(UTC)) |
| updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)) |
| |
| |
| user = relationship("User", back_populates="template_preferences") |
| template = relationship("AgentTemplate", back_populates="user_preferences") |
| |
| |
| __table_args__ = ( |
| UniqueConstraint('user_id', 'template_id', name='unique_user_template_preference'), |
| ) |
| |
| |