Luxx/luxx/models.py

114 lines
4.8 KiB
Python

"""ORM model definitions"""
from datetime import datetime
from typing import Optional, List
from sqlalchemy import String, Integer, Boolean, Float, Text, DateTime, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from luxx.database import Base
class Project(Base):
"""Project model"""
__tablename__ = "projects"
id: Mapped[str] = mapped_column(String(64), primary_key=True)
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), nullable=False)
name: Mapped[str] = mapped_column(String(255), nullable=False)
description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
user: Mapped["User"] = relationship("User", backref="projects")
class User(Base):
"""User model"""
__tablename__ = "users"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
username: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
email: Mapped[Optional[str]] = mapped_column(String(120), unique=True, nullable=True)
password_hash: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
role: Mapped[str] = mapped_column(String(20), default="user")
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
# Relationships
conversations: Mapped[List["Conversation"]] = relationship(
"Conversation", back_populates="user", cascade="all, delete-orphan"
)
def to_dict(self):
return {
"id": self.id,
"username": self.username,
"email": self.email,
"role": self.role,
"is_active": self.is_active,
"created_at": self.created_at.isoformat() if self.created_at else None
}
class Conversation(Base):
"""Conversation model"""
__tablename__ = "conversations"
id: Mapped[str] = mapped_column(String(64), primary_key=True)
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), nullable=False)
project_id: Mapped[Optional[str]] = mapped_column(String(64), ForeignKey("projects.id"), nullable=True)
title: Mapped[str] = mapped_column(String(255), nullable=False)
model: Mapped[str] = mapped_column(String(64), nullable=False, default="deepseek-chat")
system_prompt: Mapped[str] = mapped_column(Text, nullable=False, default="You are a helpful assistant.")
temperature: Mapped[float] = mapped_column(Float, default=0.7)
max_tokens: Mapped[int] = mapped_column(Integer, default=2000)
thinking_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
user: Mapped["User"] = relationship("User", back_populates="conversations")
messages: Mapped[List["Message"]] = relationship(
"Message", back_populates="conversation", cascade="all, delete-orphan"
)
def to_dict(self):
return {
"id": self.id,
"user_id": self.user_id,
"project_id": self.project_id,
"title": self.title,
"model": self.model,
"system_prompt": self.system_prompt,
"temperature": self.temperature,
"max_tokens": self.max_tokens,
"thinking_enabled": self.thinking_enabled,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None
}
class Message(Base):
"""Message model"""
__tablename__ = "messages"
id: Mapped[str] = mapped_column(String(64), primary_key=True)
conversation_id: Mapped[str] = mapped_column(String(64), ForeignKey("conversations.id"), nullable=False)
role: Mapped[str] = mapped_column(String(16), nullable=False)
content: Mapped[str] = mapped_column(Text, nullable=False)
token_count: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
# Relationships
conversation: Mapped["Conversation"] = relationship("Conversation", back_populates="messages")
def to_dict(self):
return {
"id": self.id,
"conversation_id": self.conversation_id,
"role": self.role,
"content": self.content,
"token_count": self.token_count,
"created_at": self.created_at.isoformat() if self.created_at else None
}