Files
wecom_it_smart_desk/backend/app/schemas/automation.py
T

247 lines
7.4 KiB
Python
Raw Normal View History

# =============================================================================
# 企微IT智能服务台 — 阶段5 自动化闭环 Schema
# =============================================================================
# 说明:定义自动化会话相关接口的 Pydantic 请求/响应模型,以及 ORM → dict
# 序列化辅助函数。所有响应沿用项目 {code, data, message} 约定,
# 此处只描述 data 结构。
# =============================================================================
from __future__ import annotations
from datetime import datetime
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
# --------------------------------------------------------------------------
# 请求模型
# --------------------------------------------------------------------------
class CreateSessionRequest(BaseModel):
"""创建自动化会话请求。"""
conversation_id: Optional[str] = Field(None, description="关联工单ID(弱关联)")
employee_id: str = Field(..., description="发起员工企微 UserID")
description: str = Field(..., description="员工诉求/原始消息")
mode: str = Field("real_exec", description="执行模式:plan_only / real_exec")
class ApprovalDecisionRequest(BaseModel):
"""坐席审批决策请求。"""
decision: str = Field(..., description="approve / reject")
note: Optional[str] = Field(None, description="审批意见")
class ConfirmRequest(BaseModel):
"""员工 H5 二次确认请求。"""
confirmed: bool = Field(..., description="是否确认执行")
note: Optional[str] = Field(None, description="备注")
class TakeoverRequest(BaseModel):
"""转人工接管请求。"""
agent_id: str = Field(..., description="接管坐席ID")
note: Optional[str] = Field(None, description="接管说明")
class ResolveFeedbackRequest(BaseModel):
"""处置结果反馈(员工是否满意)。"""
satisfied: bool = Field(True, description="是否满意")
note: Optional[str] = Field(None, description="反馈备注")
class ScenarioConfigUpdate(BaseModel):
"""场景配置更新请求(管理端)。"""
name: Optional[str] = None
description: Optional[str] = None
enabled: Optional[bool] = None
trigger_conditions: Optional[dict] = None
actions: Optional[list] = None
approval_strategy: Optional[dict] = None
# --------------------------------------------------------------------------
# 响应模型
# --------------------------------------------------------------------------
class IntentResult(BaseModel):
"""意图识别结果。"""
scenario_key: Optional[str] = None
confidence: float = 0.0
raw: str = ""
error: str = ""
class ActionResponse(BaseModel):
"""处置动作响应。"""
id: str
session_id: str
action_index: int
action_type: str
adapter: str
risk_level: str
title: str
description: str
status: str
payload: Optional[dict] = None
result: Optional[dict] = None
error: Optional[str] = None
approved_by: Optional[str] = None
approved_at: Optional[str] = None
class ApprovalTicketResponse(BaseModel):
"""审批单响应。"""
id: str
action_id: str
session_id: str
approver_id: Optional[str] = None
channel: str
status: str
reason: Optional[str] = None
decision_note: Optional[str] = None
decided_at: Optional[str] = None
class SessionResponse(BaseModel):
"""自动化会话响应。"""
id: str
conversation_id: Optional[str] = None
employee_id: str
agent_id: Optional[str] = None
scenario_key: Optional[str] = None
status: str
mode: str
confidence: float
title: str
intent: Optional[dict] = None
current_action_id: Optional[str] = None
auto_close_at: Optional[str] = None
resolved_at: Optional[str] = None
closed_by: Optional[str] = None
meta: Optional[dict] = None
actions: List[ActionResponse] = Field(default_factory=list)
approval: Optional[ApprovalTicketResponse] = None
created_at: Optional[str] = None
updated_at: Optional[str] = None
class ScenarioConfigResponse(BaseModel):
"""场景配置响应。"""
id: str
scenario_key: str
name: str
description: str
enabled: bool
trigger_conditions: Optional[dict] = None
actions: Optional[list] = None
approval_strategy: Optional[dict] = None
current_version_id: Optional[str] = None
class RuleVersionResponse(BaseModel):
"""规则版本响应。"""
id: str
scenario_key: str
version: int
content: Optional[dict] = None
status: str
canary_percent: int
created_by: Optional[str] = None
remark: str
created_at: Optional[str] = None
class AutoMetricsResponse(BaseModel):
"""自动化看板指标响应。"""
total_sessions: int = 0
resolved_sessions: int = 0
handoff_sessions: int = 0
error_sessions: int = 0
auto_executed_actions: int = 0
approval_required_actions: int = 0
by_scenario: Dict[str, int] = Field(default_factory=dict)
# --------------------------------------------------------------------------
# 序列化辅助
# --------------------------------------------------------------------------
def _iso(dt: Optional[datetime]) -> Optional[str]:
"""将 datetime 转为 ISO 字符串(None 透传)。"""
return dt.isoformat() if dt else None
def serialize_action(action: Any) -> ActionResponse:
"""将 AutoAction ORM 对象序列化为响应模型。"""
return ActionResponse(
id=action.id,
session_id=action.session_id,
action_index=action.action_index,
action_type=action.action_type,
adapter=action.adapter,
risk_level=action.risk_level,
title=action.title,
description=action.description,
status=action.status,
payload=action.payload,
result=action.result,
error=action.error,
approved_by=action.approved_by,
approved_at=_iso(action.approved_at),
)
def serialize_approval(ticket: Any) -> ApprovalTicketResponse:
"""将 ApprovalTicket ORM 对象序列化为响应模型。"""
return ApprovalTicketResponse(
id=ticket.id,
action_id=ticket.action_id,
session_id=ticket.session_id,
approver_id=ticket.approver_id,
channel=ticket.channel,
status=ticket.status,
reason=ticket.reason,
decision_note=ticket.decision_note,
decided_at=_iso(ticket.decided_at),
)
def serialize_session(
session: Any,
actions: Optional[List[Any]] = None,
ticket: Optional[Any] = None,
) -> SessionResponse:
"""将 AutoSession ORM 对象序列化为响应模型。"""
return SessionResponse(
id=session.id,
conversation_id=session.conversation_id,
employee_id=session.employee_id,
agent_id=session.agent_id,
scenario_key=session.scenario_key,
status=session.status,
mode=session.mode,
confidence=session.confidence,
title=session.title,
intent=session.intent,
current_action_id=session.current_action_id,
auto_close_at=_iso(session.auto_close_at),
resolved_at=_iso(session.resolved_at),
closed_by=session.closed_by,
meta=session.meta,
actions=[serialize_action(a) for a in (actions or [])],
approval=serialize_approval(ticket) if ticket else None,
created_at=_iso(session.created_at),
updated_at=_iso(session.updated_at),
)