Files

230 lines
7.0 KiB
Python
Raw Permalink Normal View History

# =============================================================================
# 企微IT智能服务台 — 分诊会话模型
# =============================================================================
# 说明:对应数据库 triage_sessions 表
# 存储 AI 分诊的完整会话记录,包括分诊步骤、收集的上下文、路由结果等。
# =============================================================================
import uuid
from datetime import datetime
from typing import Any, Dict, List, Optional
from sqlalchemy import DateTime, Float, Index, Integer, JSON, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class TriageSession(Base):
"""分诊会话模型 — 对应 triage_sessions 表。
存储员工发起的 AI 分诊全流程数据,从发起分诊到最终路由。
Attributes:
id: 分诊会话IDUUID
conversation_id: 关联的企微会话ID
user_id: 员工企微UserID
user_name: 员工姓名
user_dept: 员工部门
user_level: 员工IT技能等级
device_info: 设备信息
request_title: 问题标题
request_content: 问题原文
source: 来源渠道(wecom_h5 / api / other
problem_type: AI识别的问题类型(硬件/软件/网络/安全/账号/其他)
problem_category: AI识别的问题分类
confidence: AI置信度(0.0-1.0
urgency: 紧急度(high/medium/low
suggested_route: AI建议路由(ai_self/human/auto_approval
matched_knowledge: 匹配到的知识条目
match_score: 知识匹配分数
context_tags: 上下文标签列表(JSON数组)
triage_steps: 分诊步骤数据(JSON数组)
collected_context: 已收集的上下文列表(JSON数组)
status: 分诊状态(pending/triaging/routed/skipped/timeout
route_action: 最终路由动作(ai_self/human/auto_approval/skip
route_note: 路由备注
operator_id: 操作坐席ID
operated_at: 操作时间
created_at: 创建时间
updated_at: 更新时间
"""
__tablename__ = "triage_sessions"
# 主键
id: Mapped[str] = mapped_column(
String(36),
primary_key=True,
default=lambda: str(uuid.uuid4()),
)
# 会话关联
conversation_id: Mapped[str] = mapped_column(
String(36),
nullable=False,
comment="关联的企微会话ID",
)
# 用户信息
user_id: Mapped[str] = mapped_column(
String(100),
nullable=False,
comment="员工企微UserID",
)
user_name: Mapped[Optional[str]] = mapped_column(
String(100),
nullable=True,
comment="员工姓名",
)
user_dept: Mapped[Optional[str]] = mapped_column(
String(100),
nullable=True,
comment="员工部门",
)
user_level: Mapped[Optional[str]] = mapped_column(
String(20),
nullable=True,
comment="员工IT技能等级",
)
device_info: Mapped[Optional[str]] = mapped_column(
String(200),
nullable=True,
comment="设备信息",
)
# 问题描述
request_title: Mapped[str] = mapped_column(
String(200),
nullable=False,
comment="问题标题",
)
request_content: Mapped[str] = mapped_column(
Text,
nullable=False,
comment="问题原文",
)
source: Mapped[str] = mapped_column(
String(50),
nullable=False,
default="wecom_h5",
comment="来源渠道",
)
# AI 分诊分析结果
problem_type: Mapped[Optional[str]] = mapped_column(
String(50),
nullable=True,
comment="问题类型:硬件/软件/网络/安全/账号/其他",
)
problem_category: Mapped[Optional[str]] = mapped_column(
String(100),
nullable=True,
comment="问题分类",
)
confidence: Mapped[Optional[float]] = mapped_column(
Float,
nullable=True,
comment="AI置信度(0.0-1.0",
)
urgency: Mapped[str] = mapped_column(
String(20),
nullable=False,
default="medium",
comment="紧急度:high/medium/low",
)
suggested_route: Mapped[Optional[str]] = mapped_column(
String(50),
nullable=True,
comment="AI建议路由:ai_self/human/auto_approval",
)
matched_knowledge: Mapped[Optional[str]] = mapped_column(
String(500),
nullable=True,
comment="匹配到的知识条目",
)
match_score: Mapped[Optional[float]] = mapped_column(
Float,
nullable=True,
comment="知识匹配分数",
)
context_tags: Mapped[List[str]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="上下文标签列表",
)
# 分诊步骤数据
triage_steps: Mapped[List[Dict[str, Any]]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="分诊步骤数据:[{question, options:[{label, probability}]}]",
)
collected_context: Mapped[List[str]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="已收集的上下文列表",
)
# 状态与路由
status: Mapped[str] = mapped_column(
String(30),
nullable=False,
default="pending",
comment="分诊状态:pending/triaging/routed/skipped/timeout",
)
route_action: Mapped[Optional[str]] = mapped_column(
String(50),
nullable=True,
comment="最终路由动作:ai_self/human/auto_approval/skip",
)
route_note: Mapped[Optional[str]] = mapped_column(
Text,
nullable=True,
comment="路由备注",
)
operator_id: Mapped[Optional[str]] = mapped_column(
String(100),
nullable=True,
comment="操作坐席ID",
)
operated_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="操作时间",
)
# 时间戳
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
comment="创建时间",
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
onupdate=datetime.now,
comment="更新时间",
)
# 索引
__table_args__ = (
Index("idx_triage_status", "status"),
Index("idx_triage_urgency", "urgency"),
Index("idx_triage_conversation", "conversation_id"),
Index("idx_triage_created", "created_at"),
Index("idx_triage_user", "user_id"),
)
def __repr__(self) -> str:
"""分诊会话对象的字符串表示。"""
return (
f"<TriageSession(id={self.id}, user={self.user_id}, "
f"status={self.status}, urgency={self.urgency})>"
)