feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL 校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计, 优化 agent 运行和编排执行链路,清理旧开发文档,前端新增 系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈 对话框和工作台日期选择器,优化报销创建和审批详情交互, 补充单元测试覆盖。
This commit is contained in:
@@ -11,7 +11,12 @@ from app.core.agent_enums import AgentName, AgentPermissionLevel, AgentRunStatus
|
||||
from app.core.logging import get_logger
|
||||
from app.models.agent_run import AgentRun, AgentToolCall, SemanticParseLog
|
||||
from app.repositories.agent_run import AgentRunRepository
|
||||
from app.schemas.agent_run import AgentRunRead, AgentToolCallRead, SemanticParseRead
|
||||
from app.schemas.agent_run import (
|
||||
AgentRunRead,
|
||||
AgentRunStatsRead,
|
||||
AgentToolCallRead,
|
||||
SemanticParseRead,
|
||||
)
|
||||
from app.services.agent_foundation import AgentFoundationService
|
||||
from app.services.knowledge_ingest_log import enrich_knowledge_ingest_route_json
|
||||
|
||||
@@ -47,6 +52,86 @@ class AgentRunService:
|
||||
return None
|
||||
return self._serialize_run(run, enrich_knowledge_ingest=True)
|
||||
|
||||
def summarize_runs(
|
||||
self,
|
||||
*,
|
||||
agent: str | None = None,
|
||||
status: str | None = None,
|
||||
source: str | None = None,
|
||||
limit: int = 200,
|
||||
) -> AgentRunStatsRead:
|
||||
self._ensure_ready()
|
||||
self._reconcile_stale_knowledge_index_runs()
|
||||
runs = self.repository.list(agent=agent, status=status, source=source, limit=limit)
|
||||
agents: dict[str, int] = {}
|
||||
statuses: dict[str, int] = {}
|
||||
tool_statuses: dict[str, int] = {}
|
||||
tool_call_count = 0
|
||||
failed_tool_call_count = 0
|
||||
llm_call_count = 0
|
||||
failed_llm_call_count = 0
|
||||
model_fallback_count = 0
|
||||
model_guardrail_count = 0
|
||||
recent_errors: list[dict[str, Any]] = []
|
||||
|
||||
for run in runs:
|
||||
agents[run.agent] = agents.get(run.agent, 0) + 1
|
||||
statuses[run.status] = statuses.get(run.status, 0) + 1
|
||||
ontology_json = run.ontology_json or {}
|
||||
if ontology_json.get("parse_strategy") == "rule_fallback":
|
||||
model_fallback_count += 1
|
||||
model_summary = ontology_json.get("model_invocation_summary")
|
||||
if isinstance(model_summary, dict) and model_summary.get("model_guardrail_reason"):
|
||||
model_guardrail_count += 1
|
||||
if run.status == AgentRunStatus.FAILED.value and run.error_message:
|
||||
recent_errors.append(
|
||||
{
|
||||
"run_id": run.run_id,
|
||||
"agent": run.agent,
|
||||
"stage": (run.route_json or {}).get("stage"),
|
||||
"message": run.error_message,
|
||||
}
|
||||
)
|
||||
|
||||
for tool_call in run.tool_calls:
|
||||
tool_call_count += 1
|
||||
tool_statuses[tool_call.status] = tool_statuses.get(tool_call.status, 0) + 1
|
||||
failed = tool_call.status == "failed"
|
||||
if failed:
|
||||
failed_tool_call_count += 1
|
||||
if tool_call.tool_type == "llm":
|
||||
llm_call_count += 1
|
||||
if failed:
|
||||
failed_llm_call_count += 1
|
||||
if tool_call.error_message:
|
||||
recent_errors.append(
|
||||
{
|
||||
"run_id": run.run_id,
|
||||
"agent": run.agent,
|
||||
"tool_name": tool_call.tool_name,
|
||||
"tool_type": tool_call.tool_type,
|
||||
"message": tool_call.error_message,
|
||||
}
|
||||
)
|
||||
|
||||
return AgentRunStatsRead(
|
||||
window_limit=limit,
|
||||
total_runs=len(runs),
|
||||
succeeded_runs=statuses.get(AgentRunStatus.SUCCEEDED.value, 0),
|
||||
blocked_runs=statuses.get(AgentRunStatus.BLOCKED.value, 0),
|
||||
failed_runs=statuses.get(AgentRunStatus.FAILED.value, 0),
|
||||
tool_call_count=tool_call_count,
|
||||
failed_tool_call_count=failed_tool_call_count,
|
||||
llm_call_count=llm_call_count,
|
||||
failed_llm_call_count=failed_llm_call_count,
|
||||
model_fallback_count=model_fallback_count,
|
||||
model_guardrail_count=model_guardrail_count,
|
||||
agents=agents,
|
||||
statuses=statuses,
|
||||
tool_statuses=tool_statuses,
|
||||
recent_errors=recent_errors[:10],
|
||||
)
|
||||
|
||||
def create_run(
|
||||
self,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user