- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
264 lines
7.6 KiB
Python
264 lines
7.6 KiB
Python
"""陪练模块数据模型"""
|
||
from datetime import datetime
|
||
from typing import Optional
|
||
from enum import Enum
|
||
|
||
from sqlalchemy import (
|
||
Column,
|
||
String,
|
||
Integer,
|
||
ForeignKey,
|
||
Text,
|
||
JSON,
|
||
Enum as SQLEnum,
|
||
Float,
|
||
Boolean,
|
||
DateTime,
|
||
func,
|
||
)
|
||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||
|
||
from app.models.base import BaseModel, SoftDeleteMixin, AuditMixin
|
||
|
||
|
||
class TrainingSceneStatus(str, Enum):
|
||
"""陪练场景状态枚举"""
|
||
|
||
DRAFT = "draft" # 草稿
|
||
ACTIVE = "active" # 已激活
|
||
INACTIVE = "inactive" # 已停用
|
||
|
||
|
||
class TrainingSessionStatus(str, Enum):
|
||
"""陪练会话状态枚举"""
|
||
|
||
CREATED = "created" # 已创建
|
||
IN_PROGRESS = "in_progress" # 进行中
|
||
COMPLETED = "completed" # 已完成
|
||
CANCELLED = "cancelled" # 已取消
|
||
ERROR = "error" # 异常结束
|
||
|
||
|
||
class MessageType(str, Enum):
|
||
"""消息类型枚举"""
|
||
|
||
TEXT = "text" # 文本消息
|
||
VOICE = "voice" # 语音消息
|
||
SYSTEM = "system" # 系统消息
|
||
|
||
|
||
class MessageRole(str, Enum):
|
||
"""消息角色枚举"""
|
||
|
||
USER = "user" # 用户
|
||
ASSISTANT = "assistant" # AI助手
|
||
SYSTEM = "system" # 系统
|
||
|
||
|
||
class TrainingScene(BaseModel, SoftDeleteMixin, AuditMixin):
|
||
"""
|
||
陪练场景模型
|
||
定义不同的陪练场景,如面试训练、演讲训练等
|
||
"""
|
||
|
||
__tablename__ = "training_scenes"
|
||
__allow_unmapped__ = True
|
||
|
||
# 基础信息
|
||
name: Mapped[str] = mapped_column(String(100), nullable=False, comment="场景名称")
|
||
description: Mapped[Optional[str]] = mapped_column(
|
||
Text, nullable=True, comment="场景描述"
|
||
)
|
||
category: Mapped[str] = mapped_column(String(50), nullable=False, comment="场景分类")
|
||
|
||
# 配置信息
|
||
ai_config: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="AI配置(如Coze Bot ID等)"
|
||
)
|
||
prompt_template: Mapped[Optional[str]] = mapped_column(
|
||
Text, nullable=True, comment="提示词模板"
|
||
)
|
||
evaluation_criteria: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="评估标准"
|
||
)
|
||
|
||
# 状态和权限
|
||
status: Mapped[TrainingSceneStatus] = mapped_column(
|
||
SQLEnum(TrainingSceneStatus),
|
||
default=TrainingSceneStatus.DRAFT,
|
||
nullable=False,
|
||
comment="场景状态",
|
||
)
|
||
is_public: Mapped[bool] = mapped_column(
|
||
Boolean, default=True, nullable=False, comment="是否公开"
|
||
)
|
||
required_level: Mapped[Optional[int]] = mapped_column(
|
||
Integer, nullable=True, comment="所需用户等级"
|
||
)
|
||
|
||
# 关联
|
||
sessions: Mapped[list["TrainingSession"]] = relationship(
|
||
"TrainingSession", back_populates="scene", cascade="all, delete-orphan"
|
||
)
|
||
|
||
|
||
class TrainingSession(BaseModel, AuditMixin):
|
||
"""
|
||
陪练会话模型
|
||
记录每次陪练会话的信息
|
||
"""
|
||
|
||
__tablename__ = "training_sessions"
|
||
__allow_unmapped__ = True
|
||
|
||
# 基础信息
|
||
user_id: Mapped[int] = mapped_column(
|
||
Integer, nullable=False, index=True, comment="用户ID"
|
||
)
|
||
scene_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("training_scenes.id"), nullable=False, comment="场景ID"
|
||
)
|
||
|
||
# 会话信息
|
||
coze_conversation_id: Mapped[Optional[str]] = mapped_column(
|
||
String(100), nullable=True, comment="Coze会话ID"
|
||
)
|
||
start_time: Mapped[datetime] = mapped_column(
|
||
DateTime, server_default=func.now(), nullable=False, comment="开始时间(北京时间)"
|
||
)
|
||
end_time: Mapped[Optional[datetime]] = mapped_column(
|
||
DateTime, nullable=True, comment="结束时间(北京时间)"
|
||
)
|
||
duration_seconds: Mapped[Optional[int]] = mapped_column(
|
||
Integer, nullable=True, comment="持续时长(秒)"
|
||
)
|
||
|
||
# 状态和配置
|
||
status: Mapped[TrainingSessionStatus] = mapped_column(
|
||
SQLEnum(TrainingSessionStatus),
|
||
default=TrainingSessionStatus.CREATED,
|
||
nullable=False,
|
||
comment="会话状态",
|
||
)
|
||
session_config: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="会话配置"
|
||
)
|
||
|
||
# 评估信息
|
||
total_score: Mapped[Optional[float]] = mapped_column(
|
||
Float, nullable=True, comment="总分"
|
||
)
|
||
evaluation_result: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="评估结果详情"
|
||
)
|
||
|
||
# 关联
|
||
scene: Mapped["TrainingScene"] = relationship(
|
||
"TrainingScene", back_populates="sessions"
|
||
)
|
||
messages: Mapped[list["TrainingMessage"]] = relationship(
|
||
"TrainingMessage",
|
||
back_populates="session",
|
||
cascade="all, delete-orphan",
|
||
order_by="TrainingMessage.created_at",
|
||
)
|
||
report: Mapped[Optional["TrainingReport"]] = relationship(
|
||
"TrainingReport", back_populates="session", uselist=False
|
||
)
|
||
|
||
|
||
class TrainingMessage(BaseModel):
|
||
"""
|
||
陪练消息模型
|
||
记录会话中的每条消息
|
||
"""
|
||
|
||
__tablename__ = "training_messages"
|
||
__allow_unmapped__ = True
|
||
|
||
# 基础信息
|
||
session_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("training_sessions.id"), nullable=False, comment="会话ID"
|
||
)
|
||
|
||
# 消息内容
|
||
role: Mapped[MessageRole] = mapped_column(
|
||
SQLEnum(MessageRole), nullable=False, comment="消息角色"
|
||
)
|
||
type: Mapped[MessageType] = mapped_column(
|
||
SQLEnum(MessageType), nullable=False, comment="消息类型"
|
||
)
|
||
content: Mapped[str] = mapped_column(Text, nullable=False, comment="消息内容")
|
||
|
||
# 语音消息相关
|
||
voice_url: Mapped[Optional[str]] = mapped_column(
|
||
String(500), nullable=True, comment="语音文件URL"
|
||
)
|
||
voice_duration: Mapped[Optional[float]] = mapped_column(
|
||
Float, nullable=True, comment="语音时长(秒)"
|
||
)
|
||
|
||
# 元数据
|
||
message_metadata: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="消息元数据"
|
||
)
|
||
coze_message_id: Mapped[Optional[str]] = mapped_column(
|
||
String(100), nullable=True, comment="Coze消息ID"
|
||
)
|
||
|
||
# 关联
|
||
session: Mapped["TrainingSession"] = relationship(
|
||
"TrainingSession", back_populates="messages"
|
||
)
|
||
|
||
|
||
class TrainingReport(BaseModel, AuditMixin):
|
||
"""
|
||
陪练报告模型
|
||
存储陪练会话的分析报告
|
||
"""
|
||
|
||
__tablename__ = "training_reports"
|
||
__allow_unmapped__ = True
|
||
|
||
# 基础信息
|
||
session_id: Mapped[int] = mapped_column(
|
||
Integer,
|
||
ForeignKey("training_sessions.id"),
|
||
unique=True,
|
||
nullable=False,
|
||
comment="会话ID",
|
||
)
|
||
user_id: Mapped[int] = mapped_column(
|
||
Integer, nullable=False, index=True, comment="用户ID"
|
||
)
|
||
|
||
# 评分信息
|
||
overall_score: Mapped[float] = mapped_column(Float, nullable=False, comment="总体得分")
|
||
dimension_scores: Mapped[dict] = mapped_column(
|
||
JSON, nullable=False, comment="各维度得分"
|
||
)
|
||
|
||
# 分析内容
|
||
strengths: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="优势点")
|
||
weaknesses: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="待改进点")
|
||
suggestions: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="改进建议")
|
||
|
||
# 详细内容
|
||
detailed_analysis: Mapped[Optional[str]] = mapped_column(
|
||
Text, nullable=True, comment="详细分析"
|
||
)
|
||
transcript: Mapped[Optional[str]] = mapped_column(
|
||
Text, nullable=True, comment="对话文本记录"
|
||
)
|
||
|
||
# 统计信息
|
||
statistics: Mapped[Optional[dict]] = mapped_column(
|
||
JSON, nullable=True, comment="统计数据"
|
||
)
|
||
|
||
# 关联
|
||
session: Mapped["TrainingSession"] = relationship(
|
||
"TrainingSession", back_populates="report"
|
||
)
|