MaiBot/src/common/database/database_model.py

311 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from typing import Optional
from sqlalchemy import Column, Float, Enum as SQLEnum, DateTime
from sqlmodel import SQLModel, Field, LargeBinary
from enum import Enum
from datetime import datetime
class ModelUser(str, Enum):
SYSTEM = "system"
PLUGIN = "plugin"
class ImageType(str, Enum):
EMOJI = "emoji"
IMAGE = "image"
class Messages(SQLModel, table=True):
__tablename__ = "mai_messages" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 消息元数据
message_id: str = Field(index=True, max_length=255) # 消息id
timestamp: datetime = Field(sa_column=Column(DateTime)) # 消息时间,单位为秒
platform: str = Field(index=True, max_length=100) # 顶层平台字段
# 消息发送者信息
user_id: str = Field(index=True, max_length=255) # 发送者用户id
user_nickname: str = Field(index=True, max_length=255) # 发送者昵称
user_cardname: Optional[str] = Field(default=None, max_length=255, nullable=True) # 发送者备注名
# 群聊信息(如果有)
group_id: Optional[str] = Field(index=True, default=None, max_length=255, nullable=True) # 群组id
group_name: Optional[str] = Field(default=None, max_length=255, nullable=True) # 群组名称
# 被提及/at字段
is_mentioned: bool = Field(default=False) # 被提及
is_at: bool = Field(default=False) # 被at
# 消息内部元数据
session_id: str = Field(index=True, max_length=255) # 聊天会话id
reply_to: Optional[str] = Field(default=None, max_length=255, nullable=True) # 回复的消息id
is_emoji: bool = Field(default=False) # 是否为表情包消息
is_picture: bool = Field(default=False) # 是否为图片消息
is_command: bool = Field(default=False) # 是否为命令
is_notify: bool = Field(default=False) # 是否为通知消息
# 消息内容
raw_content: bytes = Field(sa_column=Column(LargeBinary)) # msgpack后的原始消息内容
processed_plain_text: Optional[str] = Field(default=None) # 平面化处理后的纯文本消息
display_message: Optional[str] = Field(default=None) # 显示的消息内容被放入Prompt
# 其他配置
additional_config: Optional[str] = Field(default=None) # 额外配置JSON格式存储
class ModelUsage(SQLModel, table=True):
__tablename__ = "llm_usage" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 模型相关信息
model_name: str = Field(index=True, max_length=255) # 模型实际名称(供应商名称)
model_assign_name: Optional[str] = Field(index=True, default=None, max_length=255) # 模型分配名称(用户自定义名称)
model_api_provider_name: str = Field(index=True, max_length=255) # 模型API供应商名称
# 请求相关信息
endpoint: Optional[str] = Field(default=None, max_length=255, nullable=True) # 模型API的具体endpoint
user_type: ModelUser = Field(sa_column=Column(SQLEnum(ModelUser)), default=ModelUser.SYSTEM) # 模型使用者类型
request_type: str = Field(max_length=50) # 内部请求类型,记录哪种模块使用了此模型
time_cost: float = Field(sa_column=Column(Float)) # 本次请求耗时,单位秒
timestamp: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime, index=True)) # 请求时间戳
# Token使用情况
prompt_tokens: int # 提示词令牌数
completion_tokens: int # 完成词令牌数
total_tokens: int # 总令牌数
cost: float # 本次请求的费用,单位元
class Images(SQLModel, table=True):
"""用于同时存储表情包和图片的数据库模型。"""
__tablename__ = "images" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 元信息
image_hash: str = Field(index=True, max_length=255) # 图片哈希使用sha256哈希值亦作为图片唯一ID
description: str # 图片的描述
full_path: str = Field(max_length=1024) # 文件的完整路径 (包括文件名)
image_type: ImageType = Field(sa_column=Column(SQLEnum(ImageType)), default=ImageType.EMOJI)
"""图片类型,例如 'emoji''image'"""
emotion: Optional[str] = Field(default=None, nullable=True) # 表情包的情感标签,逗号分隔
query_count: int = Field(default=0) # 被查询次数
is_registered: bool = Field(default=False) # 是否已经注册
is_banned: bool = Field(default=False) # 被手动禁用
no_file_flag: bool = Field(default=False) # 文件不存在标记如果为True表示文件已经不存在仅保留描述字段
record_time: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 记录时间(数据库记录被创建的时间)
register_time: Optional[datetime] = Field(
default=None, sa_column=Column(DateTime, nullable=True)
) # 注册时间(被注册为可用表情包的时间)
last_used_time: Optional[datetime] = Field(default=None, sa_column=Column(DateTime, nullable=True)) # 上次使用时间
vlm_processed: bool = Field(default=False) # 是否已经过VLM处理
class ActionRecord(SQLModel, table=True):
"""存储动作记录"""
__tablename__ = "action_records" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 元信息
action_id: str = Field(index=True, max_length=255) # 动作ID
timestamp: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime, index=True)) # 记录时间戳
session_id: str = Field(index=True, max_length=255) # 对应的 ChatSession session_id
# 调用信息
action_name: str = Field(index=True, max_length=255) # 动作名称
action_reasoning: Optional[str] = Field(default=None) # 动作推理过程
action_data: Optional[str] = Field(default=None) # 动作数据JSON格式存储
action_builtin_prompt: Optional[str] = Field(default=None) # 内置动作提示
action_display_prompt: Optional[str] = Field(default=None) # 最终输入到Prompt的内容
class CommandRecord(SQLModel, table=True):
"""记录命令执行情况"""
__tablename__ = "command_records" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 元信息
timestamp: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime, index=True)) # 记录时间戳
session_id: str = Field(index=True, max_length=255) # 对应的 ChatSession session_id
# 调用信息
command_name: str = Field(index=True, max_length=255) # 命令名称
command_data: Optional[str] = Field(default=None) # 命令数据JSON格式存储
command_result: Optional[str] = Field(default=None) # 命令执行结果
class OnlineTime(SQLModel, table=True):
"""
用于存储在线时长记录的模型。
"""
__tablename__ = "online_time" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
timestamp: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime, index=True)) # 时间戳
duration_minutes: int = Field() # 时长,单位秒
start_timestamp: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime)) # 上线时间
end_timestamp: datetime = Field(sa_column=Column(DateTime)) # 下线时间
class Expression(SQLModel, table=True):
"""用于存储表达方式的模型"""
__tablename__ = "expressions" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
situation: str = Field(index=True, max_length=255, primary_key=True) # 情景
style: str = Field(index=True, max_length=255, primary_key=True) # 风格
context: str # 上下文
up_content: str
content_list: str # 内容列表JSON格式存储
count: int = Field(default=0) # 使用次数
last_active_time: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 上次使用时间
create_time: datetime = Field(default_factory=datetime.now, sa_column=Column(DateTime)) # 创建时间
session_id: Optional[str] = Field(default=None, max_length=255, nullable=True) # 会话ID区分是否为全局表达方式
class Jargon(SQLModel, table=True):
"""存黑话的模型"""
__tablename__ = "jargons" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
content: str = Field(index=True, max_length=255, primary_key=True) # 黑话内容
raw_content: Optional[str] = Field(default=None, nullable=True) # 原始内容,未处理的黑话内容
meaning: str # 黑话含义
session_id: Optional[str] = Field(default=None, max_length=255, nullable=True) # 会话ID区分是否为全局黑话
count: int = Field(default=0) # 使用次数
is_jargon: Optional[bool] = Field(default=True) # 是否为黑话False表示为白话
is_complete: bool = Field(default=False) # 是否为已经完成全部推断count > 100后不再推断
inference_with_context: Optional[str] = Field(default=None, nullable=True) # 带上下文的推断结果JSON格式
inference_with_content_only: Optional[str] = Field(default=None, nullable=True) # 只基于词条的推断结果JSON格式
class ChatHistory(SQLModel, table=True):
"""存储聊天历史记录的模型"""
__tablename__ = "chat_history" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 元信息
session_id: str = Field(index=True, max_length=255) # 聊天会话ID
start_timestamp: datetime = Field(sa_column=Column(DateTime, index=True)) # 聊天开始时间
end_timestamp: datetime = Field(sa_column=Column(DateTime, index=True)) # 聊天结束时间
query_count: int = Field(default=0) # 被检索次数
query_forget_count: int = Field(default=0) # 被遗忘检查的次数
# 历史消息内容
original_messages: str # 对话原文
participants: str # 参与者列表JSON格式存储
theme: str # 对话主题:这段对话的主要内容,一个简短的标题
keywords: str # 关键词这段对话的关键词JSON格式存储
summary: str # 概括:对这段话的平文本概括
class ThinkingQuestion(SQLModel, table=True):
"""存储思考型问题的模型"""
__tablename__ = "thinking_questions" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
# 问答对
question: str # 问题内容
context: Optional[str] = Field(default=None, nullable=True) # 上下文
found_answer: bool = Field(default=False) # 是否找到答案
answer: Optional[str] = Field(default=None, nullable=True) # 问题答案
thinking_steps: Optional[str] = Field(default=None, nullable=True) # 思考步骤JSON格式存储
created_timestamp: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 创建时间
updated_timestamp: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 最后更新时间
class BinaryData(SQLModel, table=True):
"""存储二进制数据的模型"""
__tablename__ = "binary_data" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
data_hash: str = Field(index=True, max_length=255) # 数据哈希使用sha256哈希值亦作为数据唯一ID
full_path: str = Field(max_length=1024) # 文件的完整路径 (包括文件名)
class PersonInfo(SQLModel, table=True):
"""存储个人信息的模型"""
__tablename__ = "person_info" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
is_known: bool = Field(default=False) # 是否为已知人
person_id: str = Field(unique=True, index=True, max_length=255) # 人员ID
person_name: Optional[str] = Field(default=None, max_length=255, nullable=True) # 人员名称
name_reason: Optional[str] = Field(default=None, nullable=True) # 名称原因
# 身份元数据
platform: str = Field(index=True, max_length=100) # 平台名称
user_id: str = Field(index=True, max_length=255) # 用户ID
user_nickname: str = Field(index=True, max_length=255) # 用户昵称
group_nickname: Optional[str] = Field(
default=None, nullable=True
) # 群昵称 (JSON, [{"group_id": str, "group_nick_name": str}])
# 印象
memory_points: Optional[str] = Field(default=None, nullable=True) # 记忆要点JSON格式存储
# 认识次数和时间
know_counts: int = Field(default=0) # 认识次数
first_known_time: Optional[datetime] = Field(
default=None, sa_column=Column(DateTime, nullable=True)
) # 首次认识时间
last_known_time: Optional[datetime] = Field(default=None, sa_column=Column(DateTime, nullable=True)) # 最后认识时间
class ChatSession(SQLModel, table=True):
"""存储聊天会话的模型"""
__tablename__ = "chat_sessions" # type: ignore
id: Optional[int] = Field(default=None, primary_key=True) # 自增主键
session_id: str = Field(unique=True, index=True, max_length=255) # 聊天会话ID
created_timestamp: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 创建时间
last_active_timestamp: datetime = Field(
default_factory=datetime.now, sa_column=Column(DateTime, index=True)
) # 最后活跃时间
# 身份元数据
user_id: Optional[str] = Field(index=True, max_length=255, nullable=True) # 用户ID
group_id: Optional[str] = Field(index=True, default=None, max_length=255, nullable=True) # 群组id
platform: str = Field(index=True, max_length=100) # 会话所在平台