feat: 新增风险规则生成引擎与知识图谱可视化
后端新增风险规则自动生成和模板执行服务,支持从规则资产 批量生成并持久化风险规则文件;知识库入库日志增强图谱 查询和本地 RAG 回退,前端审计页面增加风险规则模型和流 程图组件,知识入库面板拆分为图谱可视化子组件,报销创 建页面增加引导式流程模型,更新知识库索引数据。
This commit is contained in:
@@ -480,6 +480,7 @@ def _build_initial_knowledge_ingest_document(
|
||||
"entity_count": 0,
|
||||
"relation_count": 0,
|
||||
"entities": [],
|
||||
"entity_chunks": [],
|
||||
"relations": [],
|
||||
"events": [
|
||||
{
|
||||
@@ -677,7 +678,7 @@ def _build_ingest_graph(knowledge_ingest: dict[str, Any]) -> dict[str, Any]:
|
||||
documents = [
|
||||
item for item in list(knowledge_ingest.get("documents") or []) if isinstance(item, dict)
|
||||
]
|
||||
entities = _dedupe_text_items(
|
||||
entities = _dedupe_entities(
|
||||
entity for document in documents for entity in list(document.get("entities") or [])
|
||||
)
|
||||
relations = _dedupe_relations(
|
||||
@@ -692,20 +693,52 @@ def _build_ingest_graph(knowledge_ingest: dict[str, Any]) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _dedupe_text_items(items: Any) -> list[str]:
|
||||
deduped: list[str] = []
|
||||
def _dedupe_entities(items: Any) -> list[dict[str, Any]]:
|
||||
deduped: list[dict[str, Any]] = []
|
||||
seen: set[str] = set()
|
||||
for item in items:
|
||||
text = str(item or "").strip()
|
||||
if not text or text in seen:
|
||||
if isinstance(item, dict):
|
||||
name = str(
|
||||
item.get("name")
|
||||
or item.get("entity")
|
||||
or item.get("entity_id")
|
||||
or item.get("title")
|
||||
or item.get("id")
|
||||
or ""
|
||||
).strip()
|
||||
entity = dict(item)
|
||||
else:
|
||||
name = str(item or "").strip()
|
||||
entity = {}
|
||||
if not name or name in seen:
|
||||
continue
|
||||
seen.add(text)
|
||||
deduped.append(text)
|
||||
seen.add(name)
|
||||
entity["name"] = name
|
||||
entity["type"] = str(
|
||||
entity.get("type")
|
||||
or entity.get("entity_type")
|
||||
or entity.get("category")
|
||||
or entity.get("kind")
|
||||
or "实体"
|
||||
).strip()
|
||||
description = str(entity.get("description") or "").strip()
|
||||
descriptions = entity.get("descriptions")
|
||||
if not isinstance(descriptions, list):
|
||||
descriptions = [description] if description else []
|
||||
entity["description"] = description
|
||||
entity["descriptions"] = [
|
||||
str(description_item or "").strip()
|
||||
for description_item in descriptions
|
||||
if str(description_item or "").strip()
|
||||
][:5]
|
||||
if not isinstance(entity.get("properties"), dict):
|
||||
entity["properties"] = {}
|
||||
deduped.append(entity)
|
||||
return deduped
|
||||
|
||||
|
||||
def _dedupe_relations(items: Any) -> list[dict[str, str]]:
|
||||
deduped: list[dict[str, str]] = []
|
||||
def _dedupe_relations(items: Any) -> list[dict[str, Any]]:
|
||||
deduped: list[dict[str, Any]] = []
|
||||
seen: set[tuple[str, str, str]] = set()
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
@@ -717,7 +750,7 @@ def _dedupe_relations(items: Any) -> list[dict[str, str]]:
|
||||
if not source or not target or key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
deduped.append({"source": source, "target": target, "type": relation_type})
|
||||
deduped.append({**item, "source": source, "target": target, "type": relation_type})
|
||||
return deduped
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user