This commit is contained in:
liubiren 2026-08-09 23:58:25 +08:00
parent 483b7dc7ea
commit 72dae054f1
2 changed files with 56 additions and 115 deletions

View File

@ -22,15 +22,14 @@ from application.states.models import (
Run, Run,
Message, Message,
deps_to_object, deps_to_object,
usage_to_object, usage_validate_python,
usage_limits_to_object, usage_limits_to_object,
) )
class VerificationCodeTable(SQLModel, table=True): class VerificationCodeRecord(SQLModel, table=True, table_name="verification_code"):
""" """
验证码 验证码记录
""" """
email: str = Field(..., primary_key=True, description="邮箱") email: str = Field(..., primary_key=True, description="邮箱")
@ -56,9 +55,9 @@ class VerificationCodeTable(SQLModel, table=True):
) )
class UserTable(SQLModel, table=True): class UserRecord(SQLModel, table=True, table_name="user"):
""" """
用户 用户记录
""" """
id: str = Field( id: str = Field(
@ -69,9 +68,9 @@ class UserTable(SQLModel, table=True):
email: str = Field(..., index=True, description="邮箱") email: str = Field(..., index=True, description="邮箱")
class ConversationTable(SQLModel, table=True): class ConversationRecord(SQLModel, table=True, table_name="conversation"):
""" """
会话 会话记录
""" """
id: str = Field( id: str = Field(
@ -81,6 +80,9 @@ class ConversationTable(SQLModel, table=True):
) )
user_id: str = Field(..., index=True, description="用户唯一标识") user_id: str = Field(..., index=True, description="用户唯一标识")
description: str = Field(default="新会话", description="会话描述") description: str = Field(default="新会话", description="会话描述")
usage: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="会话使用量"
)
is_deleted: bool = Field( is_deleted: bool = Field(
default=False, default=False,
index=True, index=True,
@ -91,53 +93,9 @@ class ConversationTable(SQLModel, table=True):
) )
class TaskTable(SQLModel, table=True): class MessageRecord(SQLModel, table=True, table_name="message"):
""" """
任务表 消息记录
"""
id: str = Field(
default_factory=lambda: str(uuid7()),
primary_key=True,
description="任务唯一标识",
)
conversation_id: str = Field(..., index=True, description="会话唯一标识")
type: TaskType = Field(default=TaskType.CHAT, description="任务类型")
status: TaskStatus = Field(default=TaskStatus.NONE, description="任务状态")
deps: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="任务依赖项"
)
usage: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="任务使用量"
)
usage_limits: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="任务使用量限制"
)
class RunTable(SQLModel, table=True):
"""
运行表
"""
id: str = Field(
default_factory=lambda: str(uuid7()),
primary_key=True,
description="运行唯一标识",
)
task_id: str = Field(..., index=True, description="任务唯一标识")
status: RunStatus = Field(default=RunStatus.RUNNING, description="运行状态")
usage: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="运行使用量"
)
usage_limits: dict[str, Any] = Field(
default_factory=dict, sa_type=JSON, description="运行使用量限制"
)
class MessageTable(SQLModel, table=True):
"""
消息表
""" """
id: str = Field( id: str = Field(
@ -145,15 +103,12 @@ class MessageTable(SQLModel, table=True):
primary_key=True, primary_key=True,
description="消息唯一标识", description="消息唯一标识",
) )
run_id: str = Field(..., index=True, description="运行唯一标识") conversation_id: str = Field(..., index=True, description="会话唯一标识")
type: MessageType = Field(default=MessageType.USER_PROMPT, description="消息类型") type: MessageType = Field(..., description="消息类型")
title: str = Field(default="", description="消息标题") title: str = Field(default="", description="消息标题")
content: str = Field(default="", description="消息内容") content: str = Field(default="", description="消息内容")
class DatabaseState(rx.State): class DatabaseState(rx.State):
""" """
数据库状态 数据库状态
@ -166,19 +121,19 @@ class DatabaseState(rx.State):
:return: 验证码 :return: 验证码
""" """
async with rx.asession() as session: async with rx.asession() as session:
# 先将该邮箱有效、未核验的验证码记录设置为无效 # 先将该邮箱有效、未核验的验证码记录设置为无效
await session.exec( await session.exec(
update(VerificationCodeTable) update(VerificationCodeRecord)
.where( .where(
VerificationCodeTable.email == email, # type: ignore VerificationCodeRecord.email == email, # type: ignore
VerificationCodeTable.is_valid == True, # type: ignore VerificationCodeRecord.is_valid == True, # type: ignore
VerificationCodeTable.is_verified == False, # type: ignore VerificationCodeRecord.is_verified == False, # type: ignore
) )
.values(is_valid=False) .values(is_valid=False)
) )
await session.flush() await session.flush()
# 创建验证码记录 # 创建验证码记录
record = VerificationCodeTable( record = VerificationCodeRecord(
email=email, email=email,
) )
session.add(record) session.add(record)
@ -196,14 +151,13 @@ class DatabaseState(rx.State):
:return: 是否核验成功True 表示核验成功False 表示核验失败根据邮箱和验证码未查询到有效且未核验的记录或失效 :return: 是否核验成功True 表示核验成功False 表示核验失败根据邮箱和验证码未查询到有效且未核验的记录或失效
""" """
async with rx.asession() as session: async with rx.asession() as session:
# 查询该邮箱验证码且有效、未核验、过期时间大于当前时间的验证码记录
result = await session.exec( result = await session.exec(
select(VerificationCodeTable).where( select(VerificationCodeRecord).where(
VerificationCodeTable.email == email, VerificationCodeRecord.email == email,
VerificationCodeTable.verification_code == verification_code, VerificationCodeRecord.verification_code == verification_code,
VerificationCodeTable.is_valid == True, VerificationCodeRecord.is_valid == True,
VerificationCodeTable.is_verified == False, VerificationCodeRecord.is_verified == False,
VerificationCodeTable.expired_at > datetime.now(), VerificationCodeRecord.expired_at > datetime.now(),
) )
) )
record = result.first() record = result.first()
@ -222,13 +176,13 @@ class DatabaseState(rx.State):
""" """
async with rx.asession() as session: async with rx.asession() as session:
result = await session.exec( result = await session.exec(
select(UserTable).where(UserTable.email == email) select(UserRecord).where(UserRecord.email == email)
) )
record = result.first() record = result.first()
# 若用户记录已存在则返回用户唯一标识,否则先创建用户记录再返回用户唯一标识 # 若用户记录已存在则返回用户唯一标识,否则先创建用户记录再返回用户唯一标识
if record: if record:
return record.id return record.id
record = UserTable(email=email) record = UserRecord(email=email)
session.add(record) session.add(record)
await session.commit() await session.commit()
await session.refresh(record) await session.refresh(record)
@ -240,56 +194,42 @@ class DatabaseState(rx.State):
:param user_id: 用户唯一标识 :param user_id: 用户唯一标识
:return: 当前用户的会话字典 :return: 当前用户的会话字典
""" """
records: dict[str, Conversation] = {} conversations: dict[str, Conversation] = {}
async with rx.asession() as session: async with rx.asession() as session:
result = await session.exec( result = await session.exec(
select(ConversationTable, RunTable, MessageTable) select(ConversationRecord, MessageRecord)
.outerjoin(RunTable, RunTable.conversation_id == ConversationTable.id) # type: ignore .outerjoin(MessageRecord, MessageRecord.conversation_id == ConversationRecord.id) # type: ignore
.outerjoin(MessageTable, MessageTable.run_id == RunTable.id) # type: ignore
.where( .where(
ConversationTable.user_id == user_id, ConversationRecord.user_id == user_id,
ConversationTable.is_deleted == False, ConversationRecord.is_deleted == False,
)
.order_by(
ConversationTable.id, TaskTable.id, RunTable.id, MessageTable.id
) )
.order_by(ConversationRecord.id, MessageRecord.id)
) )
for ( for (
conversation_result, conversation_record,
run_result, message_record,
message_result,
) in result.all(): ) in result.all():
conversation_record = records.setdefault( conversation = conversations.setdefault(
conversation_result.id, conversation_record.id,
Conversation( Conversation(
id=conversation_result.id, id=conversation_record.id,
description=conversation_result.description, description=conversation_record.description,
created_at=conversation_result.created_at, usage=usage_validate_python(conversation_record.usage),
created_at=conversation_record.created_at,
), ),
) )
if not run_result: if not message_record:
continue continue
run_record = conversation_record.runs.setdefault( conversation.messages.setdefault(
run_result.id, message_record.id,
Run(
id=run_result.id,
status=run_result.status,
usage=usage_to_object(run_result.usage),
usage_limits=usage_limits_to_object(run_result.usage_limits),
),
)
if not message_result:
continue
run_record.messages.setdefault(
message_result.id,
Message( Message(
id=message_result.id, id=message_record.id,
type=message_result.type, type=message_record.type,
title=message_result.title, title=message_record.title,
content=message_result.content, content=message_record.content,
), ),
) )
return records return conversations
async def create_conversation_record(self, user_id: str) -> dict[str, Conversation]: async def create_conversation_record(self, user_id: str) -> dict[str, Conversation]:
""" """
@ -298,7 +238,7 @@ class DatabaseState(rx.State):
:return: 会话实例 :return: 会话实例
""" """
async with rx.asession() as session: async with rx.asession() as session:
record = ConversationTable(user_id=user_id) record = ConversationRecord(user_id=user_id)
session.add(record) session.add(record)
await session.commit() await session.commit()
await session.refresh(record) await session.refresh(record)

View File

@ -31,8 +31,8 @@ class Message(BaseModel):
type: MessageType = Field(..., description="消息类型") type: MessageType = Field(..., description="消息类型")
title: str = Field(default="", description="消息标题") title: str = Field(default="", description="消息标题")
content: str = Field(default="", description="消息内容") content: str = Field(default="", description="消息内容")
is_component_expanded: bool = Field( is_expanded: bool = Field(
default=True, description="展开组件True 表示展开False 表示折叠" default=True, description="展开True 表示展开False 表示折叠"
) )
@ -106,8 +106,9 @@ class Conversation(BaseModel):
""" """
id: str = Field(default_factory=lambda: str(uuid7()), description="会话唯一标识") id: str = Field(default_factory=lambda: str(uuid7()), description="会话唯一标识")
runs: dict[str, Run] = Field(default_factory=dict, description="运行字典")
description: str = Field(default="新会话", description="会话描述") description: str = Field(default="新会话", description="会话描述")
usage: RunUsage = Field(default=RunUsage(), description="会话使用量")
messages: dict[str, Message] = Field(default_factory=dict, description="运行字典")
created_at: datetime = Field(..., description="会话创建日期时间") created_at: datetime = Field(..., description="会话创建日期时间")
@ -146,7 +147,7 @@ def deps_to_dict(deps: Deps | None) -> dict[str, Any]:
UsageAdapter = TypeAdapter(RunUsage) UsageAdapter = TypeAdapter(RunUsage)
def usage_to_object(usage: dict[str, Any]) -> RunUsage: def usage_validate_python(usage: dict[str, Any]) -> RunUsage:
""" """
Usage 转为对象 Usage 转为对象
""" """