后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL 校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计, 优化 agent 运行和编排执行链路,清理旧开发文档,前端新增 系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈 对话框和工作台日期选择器,优化报销创建和审批详情交互, 补充单元测试覆盖。
340 lines
11 KiB
Python
340 lines
11 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
from app.core.agent_enums import (
|
|
AgentAssetContentType,
|
|
AgentAssetDomain,
|
|
AgentAssetStatus,
|
|
AgentAssetType,
|
|
AgentReviewStatus,
|
|
)
|
|
|
|
|
|
class AgentAssetCreate(BaseModel):
|
|
asset_type: AgentAssetType
|
|
code: str = Field(min_length=1, max_length=100)
|
|
name: str = Field(min_length=1, max_length=200)
|
|
description: str = ""
|
|
domain: AgentAssetDomain
|
|
scenario_json: list[Any] = Field(default_factory=list)
|
|
owner: str = Field(min_length=1, max_length=100)
|
|
reviewer: str | None = Field(default=None, max_length=100)
|
|
status: AgentAssetStatus = AgentAssetStatus.DRAFT
|
|
config_json: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AgentAssetUpdate(BaseModel):
|
|
name: str | None = Field(default=None, min_length=1, max_length=200)
|
|
description: str | None = None
|
|
domain: AgentAssetDomain | None = None
|
|
scenario_json: list[Any] | None = None
|
|
owner: str | None = Field(default=None, min_length=1, max_length=100)
|
|
reviewer: str | None = Field(default=None, max_length=100)
|
|
status: AgentAssetStatus | None = None
|
|
current_version: str | None = Field(default=None, max_length=30)
|
|
published_version: str | None = Field(default=None, max_length=30)
|
|
working_version: str | None = Field(default=None, max_length=30)
|
|
config_json: dict[str, Any] | None = None
|
|
|
|
|
|
class AgentAssetVersionCreate(BaseModel):
|
|
version: str = Field(min_length=1, max_length=30)
|
|
content: Any
|
|
content_type: AgentAssetContentType
|
|
change_note: str | None = None
|
|
created_by: str = Field(min_length=1, max_length=100)
|
|
|
|
|
|
class RuleMarkdownUpdate(BaseModel):
|
|
version: str = Field(min_length=1, max_length=30)
|
|
content: str
|
|
change_note: str | None = None
|
|
created_by: str = Field(min_length=1, max_length=100)
|
|
|
|
|
|
class AgentAssetReviewCreate(BaseModel):
|
|
version: str = Field(min_length=1, max_length=30)
|
|
reviewer: str = Field(min_length=1, max_length=100)
|
|
review_status: AgentReviewStatus
|
|
review_note: str | None = None
|
|
|
|
|
|
class AgentAssetReviewRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: str
|
|
asset_id: str
|
|
version: str
|
|
reviewer: str
|
|
review_status: str
|
|
review_note: str | None
|
|
reviewed_at: datetime | None
|
|
created_at: datetime
|
|
|
|
|
|
class AgentAssetOnlyOfficeConfigRead(BaseModel):
|
|
documentServerUrl: str
|
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AgentAssetOnlyOfficeCallbackRead(BaseModel):
|
|
error: int = 0
|
|
|
|
|
|
class AgentAssetOnlyOfficeCallbackWrite(BaseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
status: int = Field(description="ONLYOFFICE 回调状态码。")
|
|
url: str | None = Field(default=None, description="文档下载地址,状态为 2 或 6 时使用。")
|
|
users: list[str] = Field(default_factory=list, description="当前编辑用户列表。")
|
|
|
|
|
|
class AgentAssetRuleJsonWrite(BaseModel):
|
|
payload: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AgentAssetRuleJsonRead(BaseModel):
|
|
file_name: str
|
|
rule_code: str
|
|
name: str
|
|
description: str = ""
|
|
evaluator: str = ""
|
|
ontology_signal: str | None = None
|
|
flow_diagram_svg: str | None = None
|
|
inputs: dict[str, Any] = Field(default_factory=dict)
|
|
outcomes: dict[str, Any] = Field(default_factory=dict)
|
|
payload: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AgentAssetRiskRuleGenerateRequest(BaseModel):
|
|
business_domain: AgentAssetDomain = AgentAssetDomain.EXPENSE
|
|
business_stage: str | None = Field(
|
|
default="reimbursement",
|
|
pattern="^(expense_application|reimbursement)$",
|
|
max_length=40,
|
|
)
|
|
expense_category: str | None = Field(default=None, max_length=40)
|
|
rule_title: str | None = Field(default=None, max_length=80)
|
|
risk_level: str | None = Field(default=None, pattern="^(low|medium|high|critical)$")
|
|
natural_language: str = Field(min_length=8, max_length=2000)
|
|
requires_attachment: bool = False
|
|
|
|
|
|
class AgentAssetRiskRuleDraftUpdate(BaseModel):
|
|
rule_title: str | None = Field(default=None, min_length=2, max_length=80)
|
|
expense_category: str | None = Field(default=None, max_length=40)
|
|
natural_language: str | None = Field(default=None, min_length=8, max_length=2000)
|
|
requires_attachment: bool | None = None
|
|
|
|
|
|
class AgentAssetRiskRuleRevisionCreate(BaseModel):
|
|
rule_title: str | None = Field(default=None, min_length=2, max_length=80)
|
|
expense_category: str | None = Field(default=None, max_length=40)
|
|
natural_language: str | None = Field(default=None, min_length=8, max_length=2000)
|
|
requires_attachment: bool | None = None
|
|
change_reason: str = Field(min_length=1, max_length=1000)
|
|
|
|
|
|
class AgentAssetRiskRuleRegenerateRequest(BaseModel):
|
|
rule_title: str | None = Field(default=None, min_length=2, max_length=80)
|
|
expense_category: str | None = Field(default=None, max_length=40)
|
|
natural_language: str | None = Field(default=None, min_length=8, max_length=2000)
|
|
requires_attachment: bool | None = None
|
|
|
|
|
|
class AgentAssetRiskRuleSampleCase(BaseModel):
|
|
case_id: str | None = Field(default=None, max_length=60)
|
|
name: str = Field(default="测试样例", min_length=1, max_length=80)
|
|
values: dict[str, Any] = Field(default_factory=dict)
|
|
expected_hit: bool = True
|
|
expected_severity: str | None = Field(default=None, max_length=20)
|
|
note: str | None = None
|
|
|
|
|
|
class AgentAssetRiskRuleSampleTestRequest(BaseModel):
|
|
version: str | None = Field(default=None, max_length=30)
|
|
cases: list[AgentAssetRiskRuleSampleCase] = Field(default_factory=list)
|
|
|
|
|
|
class AgentAssetRiskRuleScenarioTestRequest(BaseModel):
|
|
version: str | None = Field(default=None, max_length=30)
|
|
intent: str = Field(default="", max_length=1000)
|
|
filters: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AgentAssetRiskRuleReportRequest(BaseModel):
|
|
version: str | None = Field(default=None, max_length=30)
|
|
confirm_passed: bool = True
|
|
note: str | None = Field(default=None, max_length=1000)
|
|
|
|
|
|
class AgentAssetRiskRuleSimulationAttachment(BaseModel):
|
|
name: str = Field(default="", max_length=240)
|
|
content_type: str | None = Field(default=None, max_length=120)
|
|
size: int | None = Field(default=None, ge=0)
|
|
note: str | None = Field(default=None, max_length=500)
|
|
ocr_text: str | None = Field(default=None, max_length=20000)
|
|
summary: str | None = Field(default=None, max_length=2000)
|
|
document_type: str | None = Field(default=None, max_length=80)
|
|
document_type_label: str | None = Field(default=None, max_length=120)
|
|
scene_code: str | None = Field(default=None, max_length=80)
|
|
scene_label: str | None = Field(default=None, max_length=120)
|
|
avg_score: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
recognition_status: str | None = Field(default=None, max_length=40)
|
|
document_fields: list[dict[str, Any]] = Field(default_factory=list)
|
|
|
|
|
|
class AgentAssetRiskRuleSimulationRequest(BaseModel):
|
|
version: str | None = Field(default=None, max_length=30)
|
|
message: str = Field(default="", max_length=4000)
|
|
field_values: dict[str, Any] = Field(default_factory=dict)
|
|
attachments: list[AgentAssetRiskRuleSimulationAttachment] = Field(default_factory=list)
|
|
|
|
|
|
class AgentAssetRiskRuleSimulationRead(BaseModel):
|
|
version: str
|
|
ready: bool = True
|
|
stage: str = "executed"
|
|
hit: bool
|
|
severity: str = "none"
|
|
severity_label: str = "未命中"
|
|
summary: str
|
|
blocking_reason: str = ""
|
|
message: str = ""
|
|
field_values: dict[str, Any] = Field(default_factory=dict)
|
|
normalized_fields: dict[str, Any] = Field(default_factory=dict)
|
|
evidence: dict[str, Any] = Field(default_factory=dict)
|
|
trace: dict[str, Any] = Field(default_factory=dict)
|
|
attachments: list[dict[str, Any]] = Field(default_factory=list)
|
|
recognized_fields: list[dict[str, Any]] = Field(default_factory=list)
|
|
missing_fields: list[dict[str, Any]] = Field(default_factory=list)
|
|
recognition_summary: list[dict[str, Any]] = Field(default_factory=list)
|
|
execution_mode: str = "risk_rule_simulation"
|
|
created_at: datetime
|
|
|
|
|
|
class AgentAssetRiskRuleReturnRequest(BaseModel):
|
|
note: str = Field(min_length=1, max_length=1000)
|
|
|
|
|
|
class AgentAssetRiskRuleEnabledUpdate(BaseModel):
|
|
enabled: bool
|
|
|
|
|
|
class AgentAssetRiskRuleLevelUpdate(BaseModel):
|
|
risk_level: str = Field(pattern="^(low|medium|high|critical)$")
|
|
|
|
|
|
class AgentAssetRiskRuleTestRunRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: str
|
|
asset_id: str
|
|
version: str
|
|
test_type: str
|
|
status: str
|
|
passed: bool
|
|
summary: str
|
|
input_json: dict[str, Any] = Field(default_factory=dict)
|
|
result_json: dict[str, Any] = Field(default_factory=dict)
|
|
created_by: str
|
|
created_at: datetime
|
|
|
|
|
|
class AgentAssetRiskRuleLatestTestSummary(BaseModel):
|
|
version: str = ""
|
|
sample: AgentAssetRiskRuleTestRunRead | None = None
|
|
scenario: AgentAssetRiskRuleTestRunRead | None = None
|
|
report: AgentAssetRiskRuleTestRunRead | None = None
|
|
test_passed: bool = False
|
|
|
|
|
|
class AgentAssetVersionTimelineItemRead(BaseModel):
|
|
event_type: str
|
|
version: str
|
|
actor: str
|
|
event_time: datetime
|
|
title: str
|
|
description: str = ""
|
|
note: str | None = None
|
|
source_version: str | None = None
|
|
|
|
|
|
class AgentAssetSpreadsheetDiffCellRead(BaseModel):
|
|
sheet_name: str
|
|
cell: str
|
|
change_type: str
|
|
before_value: Any | None = None
|
|
after_value: Any | None = None
|
|
|
|
|
|
class AgentAssetSpreadsheetDiffSheetRead(BaseModel):
|
|
sheet_name: str
|
|
change_type: str
|
|
|
|
|
|
class AgentAssetSpreadsheetChangeRecordRead(BaseModel):
|
|
id: str
|
|
actor: str
|
|
changed_at: datetime
|
|
summary: str
|
|
sheet_changes: list[AgentAssetSpreadsheetDiffSheetRead] = Field(default_factory=list)
|
|
cell_changes: list[AgentAssetSpreadsheetDiffCellRead] = Field(default_factory=list)
|
|
changed_sheet_count: int = 0
|
|
changed_cell_count: int = 0
|
|
|
|
|
|
class AgentAssetVersionRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: str
|
|
asset_id: str
|
|
version: str
|
|
content: Any
|
|
content_type: str
|
|
change_note: str | None
|
|
created_by: str
|
|
created_at: datetime
|
|
is_current: bool = False
|
|
is_published: bool = False
|
|
is_working: bool = False
|
|
lifecycle_state: str = "history"
|
|
|
|
|
|
class AgentAssetListItem(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: str
|
|
asset_type: str
|
|
code: str
|
|
name: str
|
|
description: str
|
|
domain: str
|
|
scenario_json: list[Any]
|
|
owner: str
|
|
reviewer: str | None
|
|
status: str
|
|
current_version: str | None
|
|
published_version: str | None
|
|
working_version: str | None
|
|
config_json: dict[str, Any]
|
|
change_count: int = 0
|
|
modified_by: str | None = None
|
|
published_by: str | None = None
|
|
published_at: datetime | None = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class AgentAssetRead(AgentAssetListItem):
|
|
current_version_content: Any | None = None
|
|
current_version_content_type: str | None = None
|
|
current_version_change_note: str | None = None
|
|
recent_versions: list[AgentAssetVersionRead] = Field(default_factory=list)
|
|
latest_review: AgentAssetReviewRead | None = None
|
|
latest_test_summary: AgentAssetRiskRuleLatestTestSummary | None = None
|