from __future__ import annotations from datetime import datetime from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func from sqlalchemy.orm import Mapped, mapped_column from app.models.base import Base class QuestionInsightCleanedQuestion(Base): """用户问题清洗后的持久化结果。 每个原始消息至少写入一条记录。没有有效问题的消息会写入 accepted=0 的占位记录,使增量清洗无需重复读取已经处理过的聊天原文。 """ __tablename__ = "sys_question_insight_cleaned_question" __table_args__ = ( UniqueConstraint( "message_id", "cleaner_version", "part_index", name="uq_question_insight_message_version_part", ), ) id: Mapped[int] = mapped_column( BigInteger().with_variant(Integer, "sqlite"), primary_key=True, autoincrement=True, ) message_id: Mapped[int] = mapped_column( ForeignKey("sys_chat_message.id", ondelete="CASCADE"), nullable=False, ) session_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False) user_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False) part_index: Mapped[int] = mapped_column(Integer, nullable=False) cleaner_version: Mapped[str] = mapped_column(String(20), nullable=False) source_hash: Mapped[str] = mapped_column(String(64), nullable=False) cleaned_text: Mapped[str] = mapped_column(Text, nullable=False, default="") normalized_text: Mapped[str] = mapped_column(Text, nullable=False, default="") category: Mapped[str] = mapped_column(String(50), nullable=False, default="other") tokens_json: Mapped[str] = mapped_column(Text, nullable=False, default="[]") accepted: Mapped[int] = mapped_column(Integer, nullable=False, default=1) filtered_reason: Mapped[str | None] = mapped_column(String(100), nullable=True) source_created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=func.now(), onupdate=func.now(), nullable=False, )