conversation.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. """
  2. 对话模型
  3. """
  4. from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey, Index
  5. from sqlalchemy.orm import relationship
  6. from sqlalchemy.sql import func
  7. from app.core.database import Base
  8. class Conversation(Base):
  9. """对话会话表"""
  10. __tablename__ = "conversations"
  11. id = Column(Integer, primary_key=True, index=True)
  12. user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
  13. character_id = Column(Integer, ForeignKey("characters.id", ondelete="CASCADE"), nullable=False)
  14. title = Column(String(200)) # 对话标题
  15. created_at = Column(DateTime(timezone=True), server_default=func.now())
  16. updated_at = Column(DateTime(timezone=True), onupdate=func.now())
  17. # 唯一约束:每个用户与角色只有一个对话
  18. __table_args__ = (
  19. Index("idx_user_character", "user_id", "character_id", unique=True),
  20. )
  21. # 关系
  22. user = relationship("User", back_populates="conversations")
  23. character = relationship("Character", back_populates="conversations")
  24. messages = relationship("Message", back_populates="conversation", cascade="all, delete-orphan")
  25. user_activity = relationship("UserActivity", back_populates="conversation", uselist=False, cascade="all, delete-orphan")
  26. class Message(Base):
  27. """消息表"""
  28. __tablename__ = "messages"
  29. id = Column(Integer, primary_key=True, index=True)
  30. conversation_id = Column(Integer, ForeignKey("conversations.id", ondelete="CASCADE"), nullable=False, index=True)
  31. role = Column(String(20), nullable=False) # user | assistant | system
  32. content = Column(Text, nullable=False)
  33. # 统计信息
  34. tokens_used = Column(Integer, default=0)
  35. is_proactive = Column(Boolean, default=False) # 是否为AI主动发送
  36. created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True)
  37. # 关系
  38. conversation = relationship("Conversation", back_populates="messages")
  39. class UserActivity(Base):
  40. """用户活跃状态表(用于主动消息检测)"""
  41. __tablename__ = "user_activity"
  42. id = Column(Integer, primary_key=True, index=True)
  43. conversation_id = Column(Integer, ForeignKey("conversations.id", ondelete="CASCADE"), unique=True, nullable=False)
  44. last_message_at = Column(DateTime(timezone=True), nullable=False)
  45. last_check_at = Column(DateTime(timezone=True)) # 上次检查主动消息的时间
  46. next_proactive_at = Column(DateTime(timezone=True), index=True) # 计划的下次主动消息时间
  47. # 关系
  48. conversation = relationship("Conversation", back_populates="user_activity")