后端新增风险规则自动生成和模板执行服务,支持从规则资产 批量生成并持久化风险规则文件;知识库入库日志增强图谱 查询和本地 RAG 回退,前端审计页面增加风险规则模型和流 程图组件,知识入库面板拆分为图谱可视化子组件,报销创 建页面增加引导式流程模型,更新知识库索引数据。
99 lines
4.3 KiB
Python
99 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from app.models.agent_asset import AgentAsset
|
|
from app.schemas.agent_asset import AgentAssetRuleJsonRead, AgentAssetRuleJsonWrite
|
|
from app.services.agent_asset_spreadsheet import RISK_RULES_LIBRARY, RULE_LIBRARY_NAMES
|
|
|
|
|
|
class AgentAssetJsonRuleMixin:
|
|
def _resolve_json_risk_rule_document(self, asset: AgentAsset) -> tuple[str, str]:
|
|
config_json = dict(asset.config_json or {})
|
|
detail_mode = str(config_json.get("detail_mode") or "").strip().lower()
|
|
if detail_mode != "json_risk":
|
|
raise ValueError("当前资产不是 JSON 风险规则。")
|
|
|
|
rule_library = str(config_json.get("rule_library") or RISK_RULES_LIBRARY).strip()
|
|
if rule_library not in RULE_LIBRARY_NAMES:
|
|
raise ValueError("规则库目录不合法。")
|
|
|
|
rule_document = config_json.get("rule_document")
|
|
if not isinstance(rule_document, dict):
|
|
raise ValueError("规则资产缺少 rule_document 配置。")
|
|
|
|
file_name = str(rule_document.get("file_name") or "").strip()
|
|
if not file_name:
|
|
raise ValueError("规则资产缺少 JSON 文件名。")
|
|
return rule_library, file_name
|
|
|
|
def read_rule_json(self, asset_id: str) -> AgentAssetRuleJsonRead:
|
|
asset = self.repository.get(asset_id)
|
|
if asset is None:
|
|
raise LookupError("资产不存在。")
|
|
|
|
rule_library, file_name = self._resolve_json_risk_rule_document(asset)
|
|
payload = self.rule_library_manager.read_rule_library_json(
|
|
library=rule_library,
|
|
file_name=file_name,
|
|
)
|
|
return AgentAssetRuleJsonRead(
|
|
file_name=file_name,
|
|
rule_code=str(payload.get("rule_code") or asset.code or ""),
|
|
name=str(payload.get("name") or asset.name or ""),
|
|
description=str(payload.get("description") or asset.description or "").strip(),
|
|
evaluator=str(payload.get("evaluator") or ""),
|
|
ontology_signal=str(payload.get("ontology_signal") or "") or None,
|
|
flow_diagram_svg=str(payload.get("flow_diagram_svg") or "") or None,
|
|
inputs=payload.get("inputs") if isinstance(payload.get("inputs"), dict) else {},
|
|
outcomes=payload.get("outcomes") if isinstance(payload.get("outcomes"), dict) else {},
|
|
payload=payload,
|
|
)
|
|
|
|
def write_rule_json(
|
|
self,
|
|
asset_id: str,
|
|
*,
|
|
body: AgentAssetRuleJsonWrite,
|
|
actor: str,
|
|
request_id: str | None = None,
|
|
) -> AgentAssetRuleJsonRead:
|
|
asset = self.repository.get(asset_id)
|
|
if asset is None:
|
|
raise LookupError("资产不存在。")
|
|
|
|
rule_library, file_name = self._resolve_json_risk_rule_document(asset)
|
|
payload = dict(body.payload or {})
|
|
asset_code = str(asset.code or "").strip()
|
|
if asset_code and str(payload.get("rule_code") or "").strip() not in {"", asset_code}:
|
|
raise ValueError("规则 JSON 的 rule_code 必须与资产编码一致。")
|
|
if asset_code and not str(payload.get("rule_code") or "").strip():
|
|
payload["rule_code"] = asset_code
|
|
|
|
saved = self.rule_library_manager.write_rule_library_json(
|
|
library=rule_library,
|
|
file_name=file_name,
|
|
payload=payload,
|
|
)
|
|
rule_description = str(saved.get("description") or "").strip()
|
|
if rule_description:
|
|
asset.description = rule_description
|
|
rule_name = str(saved.get("name") or "").strip()
|
|
if rule_name:
|
|
asset.name = rule_name
|
|
risk_category = str(saved.get("risk_category") or "").strip()
|
|
if risk_category:
|
|
config_json = dict(asset.config_json or {})
|
|
config_json["risk_category"] = risk_category
|
|
asset.config_json = config_json
|
|
asset.scenario_json = [risk_category]
|
|
self.audit_service.log_action(
|
|
actor=actor,
|
|
action="update_agent_asset_rule_json",
|
|
resource_type=asset.asset_type,
|
|
resource_id=asset.id,
|
|
before_json={"file_name": file_name},
|
|
after_json={"file_name": file_name, "rule_code": saved.get("rule_code")},
|
|
request_id=request_id,
|
|
)
|
|
self.db.commit()
|
|
return self.read_rule_json(asset_id)
|