695 lines
33 KiB
Python
695 lines
33 KiB
Python
"""SQLAlchemy数据库模型定义
|
||
|
||
本文件只包含纯模型定义,使用SQLAlchemy 2.0的Mapped类型注解风格。
|
||
引擎和会话管理已移至core/engine.py和core/session.py。
|
||
|
||
支持的数据库类型:
|
||
- SQLite: 使用 Text 类型
|
||
- PostgreSQL: 使用 Text 类型(PostgreSQL 的 Text 类型性能与 VARCHAR 相当)
|
||
|
||
所有模型使用统一的类型注解风格:
|
||
field_name: Mapped[PyType] = mapped_column(Type, ...)
|
||
|
||
这样IDE/Pylance能正确推断实例属性类型。
|
||
"""
|
||
|
||
import datetime
|
||
import time
|
||
|
||
from sqlalchemy import Boolean, DateTime, Float, Index, Integer, String, Text
|
||
from sqlalchemy.ext.declarative import declarative_base
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
# 创建基类
|
||
Base = declarative_base()
|
||
|
||
|
||
# 数据库兼容的字段类型辅助函数
|
||
def get_string_field(max_length=255, **kwargs):
|
||
"""
|
||
根据数据库类型返回合适的字符串字段类型
|
||
|
||
对于需要索引的字段:
|
||
- PostgreSQL: 可以使用 Text,但为了兼容性使用 VARCHAR
|
||
- SQLite: 可以使用 Text,无长度限制
|
||
|
||
Args:
|
||
max_length: 最大长度
|
||
**kwargs: 传递给 String/Text 的额外参数
|
||
|
||
Returns:
|
||
SQLAlchemy 类型
|
||
"""
|
||
from src.config.config import global_config
|
||
|
||
assert global_config is not None
|
||
db_type = global_config.database.database_type
|
||
|
||
# PostgreSQL 可以使用 Text,但为了跨数据库迁移兼容性,使用 VARCHAR
|
||
if db_type == "postgresql":
|
||
return String(max_length, **kwargs)
|
||
# SQLite 使用 Text(无长度限制)
|
||
else:
|
||
return Text(**kwargs)
|
||
|
||
|
||
class ChatStreams(Base):
|
||
"""聊天流模型"""
|
||
|
||
__tablename__ = "chat_streams"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
stream_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, unique=True, index=True)
|
||
create_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
group_platform: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
group_id: Mapped[str | None] = mapped_column(get_string_field(100), nullable=True, index=True)
|
||
group_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
last_active_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
user_platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
user_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
user_nickname: Mapped[str] = mapped_column(Text, nullable=False)
|
||
user_cardname: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
energy_value: Mapped[float | None] = mapped_column(Float, nullable=True, default=5.0)
|
||
sleep_pressure: Mapped[float | None] = mapped_column(Float, nullable=True, default=0.0)
|
||
focus_energy: Mapped[float | None] = mapped_column(Float, nullable=True, default=0.5)
|
||
# 动态兴趣度系统字段
|
||
base_interest_energy: Mapped[float | None] = mapped_column(Float, nullable=True, default=0.5)
|
||
message_interest_total: Mapped[float | None] = mapped_column(Float, nullable=True, default=0.0)
|
||
message_count: Mapped[int | None] = mapped_column(Integer, nullable=True, default=0)
|
||
action_count: Mapped[int | None] = mapped_column(Integer, nullable=True, default=0)
|
||
reply_count: Mapped[int | None] = mapped_column(Integer, nullable=True, default=0)
|
||
last_interaction_time: Mapped[float | None] = mapped_column(Float, nullable=True, default=None)
|
||
consecutive_no_reply: Mapped[int | None] = mapped_column(Integer, nullable=True, default=0)
|
||
# 消息打断系统字段
|
||
interruption_count: Mapped[int | None] = mapped_column(Integer, nullable=True, default=0)
|
||
# 聊天流印象字段
|
||
stream_impression_text: Mapped[str | None] = mapped_column(Text, nullable=True) # 对聊天流的主观印象描述
|
||
stream_chat_style: Mapped[str | None] = mapped_column(Text, nullable=True) # 聊天流的总体风格
|
||
stream_topic_keywords: Mapped[str | None] = mapped_column(Text, nullable=True) # 话题关键词,逗号分隔
|
||
stream_interest_score: Mapped[float | None] = mapped_column(Float, nullable=True, default=0.5) # 对聊天流的兴趣程度(0-1)
|
||
|
||
__table_args__ = (
|
||
Index("idx_chatstreams_stream_id", "stream_id"),
|
||
Index("idx_chatstreams_user_id", "user_id"),
|
||
Index("idx_chatstreams_group_id", "group_id"),
|
||
)
|
||
|
||
|
||
class LLMUsage(Base):
|
||
"""LLM使用记录模型"""
|
||
|
||
__tablename__ = "llm_usage"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
model_name: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
model_assign_name: Mapped[str] = mapped_column(get_string_field(100), index=True)
|
||
model_api_provider: Mapped[str] = mapped_column(get_string_field(100), index=True)
|
||
user_id: Mapped[str] = mapped_column(get_string_field(50), nullable=False, index=True)
|
||
request_type: Mapped[str] = mapped_column(get_string_field(50), nullable=False, index=True)
|
||
endpoint: Mapped[str] = mapped_column(Text, nullable=False)
|
||
prompt_tokens: Mapped[int] = mapped_column(Integer, nullable=False)
|
||
completion_tokens: Mapped[int] = mapped_column(Integer, nullable=False)
|
||
time_cost: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
total_tokens: Mapped[int] = mapped_column(Integer, nullable=False)
|
||
cost: Mapped[float] = mapped_column(Float, nullable=False)
|
||
status: Mapped[str] = mapped_column(Text, nullable=False)
|
||
timestamp: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, index=True, default=datetime.datetime.now)
|
||
|
||
__table_args__ = (
|
||
Index("idx_llmusage_model_name", "model_name"),
|
||
Index("idx_llmusage_model_assign_name", "model_assign_name"),
|
||
Index("idx_llmusage_model_api_provider", "model_api_provider"),
|
||
Index("idx_llmusage_time_cost", "time_cost"),
|
||
Index("idx_llmusage_user_id", "user_id"),
|
||
Index("idx_llmusage_request_type", "request_type"),
|
||
Index("idx_llmusage_timestamp", "timestamp"),
|
||
)
|
||
|
||
|
||
class Emoji(Base):
|
||
"""表情包模型"""
|
||
|
||
__tablename__ = "emoji"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
full_path: Mapped[str] = mapped_column(get_string_field(500), nullable=False, unique=True, index=True)
|
||
format: Mapped[str] = mapped_column(Text, nullable=False)
|
||
emoji_hash: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
description: Mapped[str] = mapped_column(Text, nullable=False)
|
||
query_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
is_registered: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
is_banned: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
emotion: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
record_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
register_time: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
usage_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
last_used_time: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
|
||
__table_args__ = (
|
||
Index("idx_emoji_full_path", "full_path"),
|
||
Index("idx_emoji_hash", "emoji_hash"),
|
||
)
|
||
|
||
|
||
class Messages(Base):
|
||
"""消息模型"""
|
||
|
||
__tablename__ = "messages"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
message_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
chat_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
reply_to: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
interest_value: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
key_words: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
key_words_lite: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
is_mentioned: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||
|
||
# 从 chat_info 扁平化而来的字段
|
||
chat_info_stream_id: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_user_platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_user_id: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_user_nickname: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_user_cardname: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_info_group_platform: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_info_group_id: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_info_group_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_info_create_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
chat_info_last_active_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
|
||
# 从顶层 user_info 扁平化而来的字段
|
||
user_platform: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
user_id: Mapped[str | None] = mapped_column(get_string_field(100), nullable=True, index=True)
|
||
user_nickname: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
user_cardname: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
|
||
processed_plain_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
display_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
memorized_times: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
priority_mode: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
priority_info: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
additional_config: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
is_emoji: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
is_picid: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
is_command: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
is_notify: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
is_public_notice: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
notice_type: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
||
|
||
# 兴趣度系统字段
|
||
actions: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
should_reply: Mapped[bool | None] = mapped_column(Boolean, nullable=True, default=False)
|
||
should_act: Mapped[bool | None] = mapped_column(Boolean, nullable=True, default=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_messages_message_id", "message_id"),
|
||
Index("idx_messages_chat_id", "chat_id"),
|
||
Index("idx_messages_time", "time"),
|
||
Index("idx_messages_user_id", "user_id"),
|
||
Index("idx_messages_should_reply", "should_reply"),
|
||
Index("idx_messages_should_act", "should_act"),
|
||
)
|
||
|
||
|
||
class ActionRecords(Base):
|
||
"""动作记录模型"""
|
||
|
||
__tablename__ = "action_records"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
action_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
action_name: Mapped[str] = mapped_column(Text, nullable=False)
|
||
action_data: Mapped[str] = mapped_column(Text, nullable=False)
|
||
action_done: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
action_build_into_prompt: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
action_prompt_display: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
chat_info_stream_id: Mapped[str] = mapped_column(Text, nullable=False)
|
||
chat_info_platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_actionrecords_action_id", "action_id"),
|
||
Index("idx_actionrecords_chat_id", "chat_id"),
|
||
Index("idx_actionrecords_time", "time"),
|
||
)
|
||
|
||
|
||
class Images(Base):
|
||
"""图像信息模型"""
|
||
|
||
__tablename__ = "images"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
image_id: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
||
emoji_hash: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
path: Mapped[str] = mapped_column(get_string_field(500), nullable=False, unique=True)
|
||
count: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
||
timestamp: Mapped[float] = mapped_column(Float, nullable=False)
|
||
type: Mapped[str] = mapped_column(Text, nullable=False)
|
||
vlm_processed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_images_emoji_hash", "emoji_hash"),
|
||
Index("idx_images_path", "path"),
|
||
)
|
||
|
||
|
||
class ImageDescriptions(Base):
|
||
"""图像描述信息模型"""
|
||
|
||
__tablename__ = "image_descriptions"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
type: Mapped[str] = mapped_column(Text, nullable=False)
|
||
image_description_hash: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
description: Mapped[str] = mapped_column(Text, nullable=False)
|
||
timestamp: Mapped[float] = mapped_column(Float, nullable=False)
|
||
|
||
__table_args__ = (Index("idx_imagedesc_hash", "image_description_hash"),)
|
||
|
||
|
||
class Videos(Base):
|
||
"""视频信息模型"""
|
||
|
||
__tablename__ = "videos"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
video_id: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
||
video_hash: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True, unique=True)
|
||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
count: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
||
timestamp: Mapped[float] = mapped_column(Float, nullable=False)
|
||
vlm_processed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
|
||
# 视频特有属性
|
||
duration: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
frame_count: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||
fps: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
resolution: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
file_size: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||
|
||
__table_args__ = (
|
||
Index("idx_videos_video_hash", "video_hash"),
|
||
Index("idx_videos_timestamp", "timestamp"),
|
||
)
|
||
|
||
|
||
class OnlineTime(Base):
|
||
"""在线时长记录模型"""
|
||
|
||
__tablename__ = "online_time"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
timestamp: Mapped[str] = mapped_column(Text, nullable=False, default=str(datetime.datetime.now))
|
||
duration: Mapped[int] = mapped_column(Integer, nullable=False)
|
||
start_timestamp: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
end_timestamp: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, index=True)
|
||
|
||
__table_args__ = (Index("idx_onlinetime_end_timestamp", "end_timestamp"),)
|
||
|
||
|
||
class PersonInfo(Base):
|
||
"""人物信息模型"""
|
||
|
||
__tablename__ = "person_info"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
person_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, unique=True, index=True)
|
||
person_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
name_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
platform: Mapped[str] = mapped_column(Text, nullable=False)
|
||
user_id: Mapped[str] = mapped_column(get_string_field(50), nullable=False, index=True)
|
||
nickname: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
impression: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
short_impression: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
points: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
forgotten_points: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
info_list: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
know_times: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
know_since: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
last_know: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
attitude: Mapped[int | None] = mapped_column(Integer, nullable=True, default=50)
|
||
|
||
__table_args__ = (
|
||
Index("idx_personinfo_person_id", "person_id"),
|
||
Index("idx_personinfo_user_id", "user_id"),
|
||
)
|
||
|
||
|
||
class BotPersonalityInterests(Base):
|
||
"""机器人人格兴趣标签模型"""
|
||
|
||
__tablename__ = "bot_personality_interests"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
personality_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
personality_description: Mapped[str] = mapped_column(Text, nullable=False)
|
||
interest_tags: Mapped[str] = mapped_column(Text, nullable=False)
|
||
embedding_model: Mapped[str] = mapped_column(get_string_field(100), nullable=False, default="text-embedding-ada-002")
|
||
version: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
||
last_updated: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now, index=True)
|
||
|
||
__table_args__ = (
|
||
Index("idx_botpersonality_personality_id", "personality_id"),
|
||
Index("idx_botpersonality_version", "version"),
|
||
Index("idx_botpersonality_last_updated", "last_updated"),
|
||
)
|
||
|
||
|
||
class Memory(Base):
|
||
"""记忆模型"""
|
||
|
||
__tablename__ = "memory"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
memory_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
chat_id: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
memory_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
keywords: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
create_time: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
last_view_time: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
|
||
__table_args__ = (Index("idx_memory_memory_id", "memory_id"),)
|
||
|
||
|
||
class Expression(Base):
|
||
"""表达风格模型"""
|
||
|
||
__tablename__ = "expression"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
situation: Mapped[str] = mapped_column(Text, nullable=False)
|
||
style: Mapped[str] = mapped_column(Text, nullable=False)
|
||
count: Mapped[float] = mapped_column(Float, nullable=False)
|
||
last_active_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
chat_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
type: Mapped[str] = mapped_column(Text, nullable=False)
|
||
create_date: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
|
||
__table_args__ = (Index("idx_expression_chat_id", "chat_id"),)
|
||
|
||
|
||
class ThinkingLog(Base):
|
||
"""思考日志模型"""
|
||
|
||
__tablename__ = "thinking_logs"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
chat_id: Mapped[str] = mapped_column(get_string_field(64), nullable=False, index=True)
|
||
trigger_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
response_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
trigger_info_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
response_info_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
timing_results_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_history_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_history_in_thinking_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
chat_history_after_response_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
heartflow_data_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
reasoning_data_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
|
||
__table_args__ = (Index("idx_thinkinglog_chat_id", "chat_id"),)
|
||
|
||
|
||
class GraphNodes(Base):
|
||
"""记忆图节点模型"""
|
||
|
||
__tablename__ = "graph_nodes"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
concept: Mapped[str] = mapped_column(get_string_field(255), nullable=False, unique=True, index=True)
|
||
memory_items: Mapped[str] = mapped_column(Text, nullable=False)
|
||
hash: Mapped[str] = mapped_column(Text, nullable=False)
|
||
weight: Mapped[float] = mapped_column(Float, nullable=False, default=1.0)
|
||
created_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
last_modified: Mapped[float] = mapped_column(Float, nullable=False)
|
||
|
||
__table_args__ = (Index("idx_graphnodes_concept", "concept"),)
|
||
|
||
|
||
class GraphEdges(Base):
|
||
"""记忆图边模型"""
|
||
|
||
__tablename__ = "graph_edges"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
source: Mapped[str] = mapped_column(get_string_field(255), nullable=False, index=True)
|
||
target: Mapped[str] = mapped_column(get_string_field(255), nullable=False, index=True)
|
||
strength: Mapped[int] = mapped_column(Integer, nullable=False)
|
||
hash: Mapped[str] = mapped_column(Text, nullable=False)
|
||
created_time: Mapped[float] = mapped_column(Float, nullable=False)
|
||
last_modified: Mapped[float] = mapped_column(Float, nullable=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_graphedges_source", "source"),
|
||
Index("idx_graphedges_target", "target"),
|
||
)
|
||
|
||
|
||
class Schedule(Base):
|
||
"""日程模型"""
|
||
|
||
__tablename__ = "schedule"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
date: Mapped[str] = mapped_column(get_string_field(10), nullable=False, unique=True, index=True)
|
||
schedule_data: Mapped[str] = mapped_column(Text, nullable=False)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now, onupdate=datetime.datetime.now)
|
||
|
||
__table_args__ = (Index("idx_schedule_date", "date"),)
|
||
|
||
|
||
class MaiZoneScheduleStatus(Base):
|
||
"""麦麦空间日程处理状态模型"""
|
||
|
||
__tablename__ = "maizone_schedule_status"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
datetime_hour: Mapped[str] = mapped_column(get_string_field(13), nullable=False, unique=True, index=True)
|
||
activity: Mapped[str] = mapped_column(Text, nullable=False)
|
||
is_processed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
processed_at: Mapped[datetime.datetime | None] = mapped_column(DateTime, nullable=True)
|
||
story_content: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
send_success: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now, onupdate=datetime.datetime.now)
|
||
|
||
__table_args__ = (
|
||
Index("idx_maizone_datetime_hour", "datetime_hour"),
|
||
Index("idx_maizone_is_processed", "is_processed"),
|
||
)
|
||
|
||
|
||
class BanUser(Base):
|
||
"""被禁用用户模型
|
||
|
||
使用 SQLAlchemy 2.0 类型标注写法,方便静态类型检查器识别实际字段类型,
|
||
避免在业务代码中对属性赋值时报 `Column[...]` 不可赋值的告警。
|
||
"""
|
||
|
||
__tablename__ = "ban_users"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
platform: Mapped[str] = mapped_column(get_string_field(50), nullable=False) # 使用有限长度,以便创建索引
|
||
user_id: Mapped[str] = mapped_column(get_string_field(50), nullable=False, index=True)
|
||
violation_num: Mapped[int] = mapped_column(Integer, nullable=False, default=0, index=True)
|
||
reason: Mapped[str] = mapped_column(Text, nullable=False)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
|
||
__table_args__ = (
|
||
Index("idx_violation_num", "violation_num"),
|
||
Index("idx_banuser_user_id", "user_id"),
|
||
Index("idx_banuser_platform", "platform"),
|
||
Index("idx_banuser_platform_user_id", "platform", "user_id"),
|
||
)
|
||
|
||
|
||
class AntiInjectionStats(Base):
|
||
"""反注入系统统计模型"""
|
||
|
||
__tablename__ = "anti_injection_stats"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
total_messages: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""总处理消息数"""
|
||
|
||
detected_injections: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""检测到的注入攻击数"""
|
||
|
||
blocked_messages: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""被阻止的消息数"""
|
||
|
||
shielded_messages: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""被加盾的消息数"""
|
||
|
||
processing_time_total: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
|
||
"""总处理时间"""
|
||
|
||
total_process_time: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
|
||
"""累计总处理时间"""
|
||
|
||
last_process_time: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
|
||
"""最近一次处理时间"""
|
||
|
||
error_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""错误计数"""
|
||
|
||
start_time: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
"""统计开始时间"""
|
||
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
"""记录创建时间"""
|
||
|
||
updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now, onupdate=datetime.datetime.now)
|
||
"""记录更新时间"""
|
||
|
||
__table_args__ = (
|
||
Index("idx_anti_injection_stats_created_at", "created_at"),
|
||
Index("idx_anti_injection_stats_updated_at", "updated_at"),
|
||
)
|
||
|
||
|
||
class CacheEntries(Base):
|
||
"""工具缓存条目模型"""
|
||
|
||
__tablename__ = "cache_entries"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
cache_key: Mapped[str] = mapped_column(get_string_field(500), nullable=False, unique=True, index=True)
|
||
"""缓存键,包含工具名、参数和代码哈希"""
|
||
|
||
cache_value: Mapped[str] = mapped_column(Text, nullable=False)
|
||
"""缓存的数据,JSON格式"""
|
||
|
||
expires_at: Mapped[float] = mapped_column(Float, nullable=False, index=True)
|
||
"""过期时间戳"""
|
||
|
||
tool_name: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
"""工具名称"""
|
||
|
||
created_at: Mapped[float] = mapped_column(Float, nullable=False, default=lambda: time.time())
|
||
"""创建时间戳"""
|
||
|
||
last_accessed: Mapped[float] = mapped_column(Float, nullable=False, default=lambda: time.time())
|
||
"""最后访问时间戳"""
|
||
|
||
access_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
"""访问次数"""
|
||
|
||
__table_args__ = (
|
||
Index("idx_cache_entries_key", "cache_key"),
|
||
Index("idx_cache_entries_expires_at", "expires_at"),
|
||
Index("idx_cache_entries_tool_name", "tool_name"),
|
||
Index("idx_cache_entries_created_at", "created_at"),
|
||
)
|
||
|
||
|
||
class MonthlyPlan(Base):
|
||
"""月度计划模型"""
|
||
|
||
__tablename__ = "monthly_plans"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
plan_text: Mapped[str] = mapped_column(Text, nullable=False)
|
||
target_month: Mapped[str] = mapped_column(String(7), nullable=False, index=True)
|
||
status: Mapped[str] = mapped_column(get_string_field(20), nullable=False, default="active", index=True)
|
||
usage_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||
last_used_date: Mapped[str | None] = mapped_column(String(10), nullable=True, index=True)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, default=datetime.datetime.now)
|
||
is_deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, index=True)
|
||
|
||
__table_args__ = (
|
||
Index("idx_monthlyplan_target_month_status", "target_month", "status"),
|
||
Index("idx_monthlyplan_last_used_date", "last_used_date"),
|
||
Index("idx_monthlyplan_usage_count", "usage_count"),
|
||
)
|
||
|
||
|
||
class PermissionNodes(Base):
|
||
"""权限节点模型"""
|
||
|
||
__tablename__ = "permission_nodes"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
node_name: Mapped[str] = mapped_column(get_string_field(255), nullable=False, unique=True, index=True)
|
||
description: Mapped[str] = mapped_column(Text, nullable=False)
|
||
plugin_name: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
default_granted: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_permission_plugin", "plugin_name"),
|
||
Index("idx_permission_node", "node_name"),
|
||
)
|
||
|
||
|
||
class UserPermissions(Base):
|
||
"""用户权限模型"""
|
||
|
||
__tablename__ = "user_permissions"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
platform: Mapped[str] = mapped_column(get_string_field(50), nullable=False, index=True)
|
||
user_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, index=True)
|
||
permission_node: Mapped[str] = mapped_column(get_string_field(255), nullable=False, index=True)
|
||
granted: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||
granted_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||
granted_by: Mapped[str | None] = mapped_column(get_string_field(100), nullable=True)
|
||
|
||
__table_args__ = (
|
||
Index("idx_user_platform_id", "platform", "user_id"),
|
||
Index("idx_user_permission", "platform", "user_id", "permission_node"),
|
||
Index("idx_permission_granted", "permission_node", "granted"),
|
||
)
|
||
|
||
|
||
class UserRelationships(Base):
|
||
"""用户关系模型 - 存储用户与bot的关系数据
|
||
|
||
核心字段:
|
||
- relationship_text: 当前印象描述(用于兼容旧系统,逐步迁移到 impression_text)
|
||
- impression_text: 长期印象(新字段,自然叙事风格)
|
||
- preference_keywords: 用户偏好关键词
|
||
- relationship_score: 好感度分数(0-1)
|
||
- key_facts: 关键信息JSON(生日、职业、理想等)
|
||
- relationship_stage: 关系阶段(stranger/acquaintance/friend/close_friend/bestie)
|
||
"""
|
||
|
||
__tablename__ = "user_relationships"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
user_id: Mapped[str] = mapped_column(get_string_field(100), nullable=False, unique=True, index=True)
|
||
user_name: Mapped[str | None] = mapped_column(get_string_field(100), nullable=True)
|
||
user_aliases: Mapped[str | None] = mapped_column(Text, nullable=True) # 用户别名,逗号分隔
|
||
|
||
# 印象相关(新旧兼容)
|
||
relationship_text: Mapped[str | None] = mapped_column(Text, nullable=True) # 旧字段,保持兼容
|
||
impression_text: Mapped[str | None] = mapped_column(Text, nullable=True) # 新字段:长期印象(自然叙事)
|
||
|
||
# 用户信息
|
||
preference_keywords: Mapped[str | None] = mapped_column(Text, nullable=True) # 用户偏好关键词,逗号分隔
|
||
key_facts: Mapped[str | None] = mapped_column(Text, nullable=True) # 关键信息JSON(生日、职业等)
|
||
|
||
# 关系状态
|
||
relationship_score: Mapped[float] = mapped_column(Float, nullable=False, default=0.3) # 好感度(0-1)
|
||
relationship_stage: Mapped[str | None] = mapped_column(get_string_field(50), nullable=True, default="stranger") # 关系阶段
|
||
|
||
# 时间记录
|
||
first_met_time: Mapped[float | None] = mapped_column(Float, nullable=True) # 首次认识时间戳
|
||
last_impression_update: Mapped[float | None] = mapped_column(Float, nullable=True) # 上次更新印象时间
|
||
last_updated: Mapped[float] = mapped_column(Float, nullable=False, default=time.time)
|
||
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||
|
||
__table_args__ = (
|
||
Index("idx_user_relationship_id", "user_id"),
|
||
Index("idx_relationship_score", "relationship_score"),
|
||
Index("idx_relationship_updated", "last_updated"),
|
||
Index("idx_relationship_stage", "relationship_stage"),
|
||
)
|