from datetime import datetime from sqlalchemy import DateTime, ForeignKey, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db import Base class Conversation(Base): __tablename__ = "conversations" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) title: Mapped[str] = mapped_column(String(255), default="新会话") adp_conversation_id: Mapped[str | None] = mapped_column(String(120)) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) last_message_at: Mapped[datetime | None] = mapped_column(DateTime) messages: Mapped[list["Message"]] = relationship(back_populates="conversation") class Message(Base): __tablename__ = "messages" id: Mapped[int] = mapped_column(primary_key=True) conversation_id: Mapped[int] = mapped_column(ForeignKey("conversations.id"), index=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) question: Mapped[str] = mapped_column(Text) answer: Mapped[str | None] = mapped_column(Text) status: Mapped[str] = mapped_column(String(30), default="pending", index=True) latency_ms: Mapped[int | None] = mapped_column(Integer) token_usage: Mapped[int] = mapped_column(Integer, default=0) pu_usage: Mapped[int] = mapped_column(Integer, default=0) model_conversation_id: Mapped[str | None] = mapped_column(String(120)) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) conversation: Mapped[Conversation] = relationship(back_populates="messages") references: Mapped[list["MessageReference"]] = relationship(back_populates="message") class MessageReference(Base): __tablename__ = "message_references" id: Mapped[int] = mapped_column(primary_key=True) message_id: Mapped[int] = mapped_column(ForeignKey("messages.id"), index=True) document_id: Mapped[int | None] = mapped_column(ForeignKey("documents.id")) source_title: Mapped[str] = mapped_column(String(255)) snippet: Mapped[str | None] = mapped_column(Text) page_no: Mapped[str | None] = mapped_column(String(40)) section: Mapped[str | None] = mapped_column(String(120)) source_url: Mapped[str | None] = mapped_column(String(500)) message: Mapped[Message] = relationship(back_populates="references") class Attachment(Base): __tablename__ = "attachments" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) message_id: Mapped[int | None] = mapped_column(ForeignKey("messages.id")) file_type: Mapped[str] = mapped_column(String(80)) storage_key: Mapped[str] = mapped_column(String(255)) remote_url: Mapped[str | None] = mapped_column(String(1000)) original_name: Mapped[str | None] = mapped_column(String(255)) expire_at: Mapped[datetime | None] = mapped_column(DateTime) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) class Feedback(Base): __tablename__ = "feedback" id: Mapped[int] = mapped_column(primary_key=True) message_id: Mapped[int] = mapped_column(ForeignKey("messages.id"), index=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) rating: Mapped[str] = mapped_column(String(20)) comment: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)