Files
X-Financial/document/development/risk-rule-explainable-flow/CONCEPT.md
caoxiaozhu 7989f3a159 feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL
校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计,
优化 agent 运行和编排执行链路,清理旧开发文档,前端新增
系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈
对话框和工作台日期选择器,优化报销创建和审批详情交互,
补充单元测试覆盖。
2026-05-30 15:46:51 +08:00

19 KiB
Raw Blame History

风险规则可解释流程判断改造方案

功能一句话

把风险规则从“自然语言生成一段 JSON”升级为“自然语言、字段本体、可执行 JSON DSL、流程判断图、测试命中路径、版本修改”一致闭环让业务用户能看懂规则怎么判断让系统按同一套逻辑执行。

背景与问题

当前风险规则已经具备自然语言创建、JSON 风险规则、风险评分、详情页流程图、仿真测试和上线启用能力,但仍有几个关键缺口:

  • 规则解释不够稳定。用户输入复杂业务规则后,系统可能把“城市是否一致、日期是否越界、是否存在合理说明”解释成“是否出现关键词”,这会导致业务语义失真。
  • 流程图容易变成展示装饰。如果流程图不严格从可执行 JSON DSL 派生,就会出现“页面看起来是 A后端实际执行是 B”的问题。
  • 测试结果缺少路径解释。用户上传票据和输入意图后,需要知道系统识别到了哪些字段、走过哪些判断节点、为什么命中或未命中。
  • 规则修改缺少版本化闭环。已上线规则不能直接覆盖,应创建修订版本,旧版本继续生效,新版本测试通过后再替换。
  • 常见费控规则需要模板化扩展。预算、票据、差旅、招待、采购/AP、企业卡等规则应进入规则模板库但仍必须走同一套解释和执行链路。

目标与非目标

目标

  • [G1] 自然语言规则经过 Hermes 语义理解后,生成结构稳定、可校验、可执行的 JSON DSL。
  • [G2] 流程判断图必须由 JSON DSL 派生,不能直接由自然语言单独生成。
  • [G3] 详情页展示“文字流程解释 + 流程图 + 使用字段 + 风险分数 + 规则状态”,让业务用户能确认系统理解是否正确。
  • [G4] 测试规则时展示本次样例或票据仿真的字段识别结果、判断路径、命中节点和最终结论。
  • [G5] 用户觉得规则不合理时,通过“创建修订版本”修改,线上版本保持稳定。
  • [G6] 常见费控规则模板库可以复用同一套 DSL、流程图和测试机制。

非目标

  • [NG1] 本期不做流程图编辑器,不允许拖拽、改节点、缩放编辑或在线画图。
  • [NG2] 本期不让大模型作为风险命中裁判。Hermes 只负责理解、生成、解释和辅助解析,最终命中由规则执行器决定。
  • [NG3] 本期不把所有复杂政策一次性建成完整专家系统,先保证规则表达、解释和执行一致。
  • [NG4] 本期不直接覆盖已上线规则,所有线上修改都走修订版本。

用户与场景

  • 财务规则制定者:创建风险规则,查看系统理解是否正确,修改草稿规则。
  • 高级财务人员 / admin审核、上线、下线、启用、停用、删除未发布规则。
  • 普通报销用户:在真实业务命中风险时看到简明原因,可反馈误判或漏判。
  • 系统执行链路:报销、费用申请、预算占用、票据识别、采购/AP 等场景只加载已上线且已启用的规则。

核心场景:

  1. 新建规则:输入规则标题、费用业务环节、费用领域、是否需要附件、自然语言规则。
  2. 生成规则Hermes 结合字段本体输出 JSON DSL、业务说明、风险评分、流程模型和 SVG。
  3. 查看详情:用户确认“系统理解的字段、判断条件、例外说明、命中动作”是否正确。
  4. 仿真测试:用户上传附件并输入测试意图,系统统一识别字段,再由执行器判断当前规则。
  5. 修改规则:未上线规则直接编辑;已上线规则创建修订版本,测试通过后发布替换。

功能能力

C1. 自然语言输入能力

新建风险规则表单应包含:

  • 规则标题。
  • 业务环节:费用申请、报销、预算控制、付款/采购等。
  • 费用领域:差旅、住宿、交通、招待、办公、培训、会议、软件服务、通讯、福利、预算、发票、采购/AP、通用。
  • 是否需要附件:需要时测试弹窗开放附件上传;不需要时隐藏上传入口。
  • 自然语言规则描述。

风险等级不允许用户手动选择,由评分模型输出风险分数和等级。

C2. 语义理解与字段本体映射

Hermes 需要输出一份中间语义计划,而不是直接写死 JSON

  • 规则意图:判断什么业务风险。
  • 适用范围:业务环节、费用领域、费用科目、单据类型。
  • 所需字段:中文解释、英文字段名、来源、是否必填。
  • 票据字段OCR 或文档智能识别得到的城市、日期、金额、销售方、发票号等。
  • 判断步骤:按顺序表达条件、分支、例外说明和命中动作。
  • 例外条件:例如延期、改签、跨城办事、临时任务等说明。
  • 风险动作:提醒、人工复核、要求补充说明、退回修改、禁止提交。

字段展示统一为:

申报目的地[claim.destination_city]
明细发生地点[item.location_city]
交通票行程城市[receipt.transport_route_cities]
住宿发票城市[receipt.hotel_city]
出差开始日期[trip.start_date]
出差结束日期[trip.end_date]
报销事由[claim.reason]

C3. 可执行 JSON DSL

JSON DSL 应表达规则执行逻辑,而不是保存自然语言摘要。建议基本结构:

{
  "rule_id": "risk.travel.city_mismatch",
  "version": "v1",
  "scope": {
    "business_stage": "reimbursement",
    "expense_types": ["travel", "lodging"]
  },
  "required_fields": [
    {
      "label": "申报目的地",
      "field": "claim.destination_city",
      "source": "claim",
      "required": true
    }
  ],
  "conditions": {
    "all": [
      {
        "op": "in_scope",
        "field": "expense.type",
        "values": ["travel", "lodging"]
      },
      {
        "op": "any_present",
        "fields": [
          "receipt.transport_route_cities",
          "receipt.hotel_city",
          "item.location_city"
        ]
      },
      {
        "op": "none_match",
        "left_fields": [
          "receipt.transport_route_cities",
          "receipt.hotel_city"
        ],
        "right_fields": [
          "claim.destination_city",
          "item.location_city",
          "trip.route_cities"
        ],
        "matcher": "city_equivalent"
      },
      {
        "op": "not_contains_any",
        "field": "claim.reason",
        "values": ["延期", "改签", "跨城办事", "临时任务", "绕行"]
      }
    ]
  },
  "action": {
    "risk_level": "high",
    "risk_score": 76,
    "decision": "review_required",
    "message": "票据城市与申报目的地或行程城市不一致,且未说明合理原因。"
  }
}

核心要求:

  • 城市、日期、金额、人员、供应商等字段必须使用专门比较算子,不能退化成“关键词出现”。
  • 复杂规则允许多层条件组合:allanynotbranchexistsrangecomparesemantic_contains
  • 例外说明可以使用语义包含,但只能影响“是否进入复核/降级/豁免”,不能替代结构化字段判断。
  • DSL 生成后必须通过 schema 校验和执行器 dry-run。

C4. 流程判断图

流程图不是编辑器,也不是自然语言插图。流程图必须由 JSON DSL 转换成 flow_model,再生成 SVG。

建议 flow_model

{
  "nodes": [
    {
      "id": "start",
      "type": "start",
      "title": "开始",
      "description": "进入差旅住宿报销风险检查"
    },
    {
      "id": "scope",
      "type": "decision",
      "title": "是否属于差旅住宿报销",
      "fields": ["expense.type", "claim.business_stage"]
    },
    {
      "id": "city_match",
      "type": "decision",
      "title": "票据城市是否匹配申报或行程城市",
      "fields": [
        "receipt.hotel_city",
        "receipt.transport_route_cities",
        "claim.destination_city",
        "trip.route_cities"
      ]
    },
    {
      "id": "hit",
      "type": "risk",
      "title": "命中高风险",
      "description": "要求补充行程说明或退回修改"
    }
  ],
  "edges": [
    { "from": "start", "to": "scope", "label": "开始检查" },
    { "from": "scope", "to": "end_pass", "label": "否" },
    { "from": "scope", "to": "city_match", "label": "是" },
    { "from": "city_match", "to": "end_pass", "label": "是" },
    { "from": "city_match", "to": "hit", "label": "否" }
  ]
}

流程图展示要求:

  • 详情页左侧为文字流程解释,右侧为“流程图”。
  • 判断分支用“是 / 否 / 通过 / 不通过 / 缺失 / 存在”等明确标签。
  • 风险命中框使用风险等级颜色:低风险蓝色,中风险橙色,高风险红色,极高风险深红色。
  • 普通节点保持 SaaS 白底、细边框、低饱和样式,不能整张图都染成风险色。
  • 图只做展示,不响应拖拽、编辑、缩放和节点点击。
  • 节点数量超过 8 个时,需要自动压缩文字、合并说明节点或分页展示,避免图过大。

C5. 测试命中路径

测试规则弹窗应展示三类信息:

  1. 输入与识别结果

    • 用户自然语言测试意图。
    • 上传附件清单。
    • OCR / 文档智能识别字段。
    • Hermes 辅助规范化后的结构化字段。
  2. 规则执行结果

    • 是否进入适用范围。
    • 每个判断节点的输入值、比较方式、判断结果。
    • 命中的风险动作。
    • 未命中的原因。
  3. 流程图路径高亮

    • 使用同一个 flow_model
    • 本次执行走过的节点和边由执行器输出 trace
    • 前端按 trace 高亮路径。

执行 trace 示例:

{
  "trace_id": "run_001",
  "matched": true,
  "risk_level": "high",
  "risk_score": 76,
  "steps": [
    {
      "node_id": "scope",
      "result": true,
      "inputs": {
        "expense.type": "住宿费",
        "claim.business_stage": "reimbursement"
      }
    },
    {
      "node_id": "city_match",
      "result": false,
      "inputs": {
        "receipt.hotel_city": "北京",
        "claim.destination_city": "上海",
        "trip.route_cities": ["武汉", "上海"]
      }
    }
  ]
}

C6. 规则修改与版本化

规则修改分三种:

  • 未上线规则:允许创建者或 admin 直接编辑,保存后重新生成 DSL、流程图、评分和说明。
  • 已上线规则:不允许直接覆盖,必须点击“创建修订版本”。
  • 业务用户反馈:只能提交误判/漏判反馈,由管理员决定是否创建修订版本。

已上线规则修改流程:

线上版本 active
  ↓
创建修订版本 draft_revision
  ↓
编辑自然语言 / 参数 / 附件要求
  ↓
重新生成 JSON DSL + 流程图 + 评分
  ↓
仿真测试通过
  ↓
发布新版本
  ↓
旧版本归档,新版本 active

版本记录必须包含:

  • 修改人。
  • 修改原因。
  • 修改前后自然语言差异。
  • 修改前后 DSL 差异。
  • 测试报告。
  • 发布时间。
  • 是否替换线上版本。

方案设计

总体链路

自然语言规则
  ↓
字段本体召回与业务域约束
  ↓
Hermes 生成语义计划 semantic_plan
  ↓
语义计划校验与补全
  ↓
生成 JSON DSL
  ↓
Schema 校验 + 执行器 dry-run
  ↓
风险评分 risk_score / risk_level
  ↓
DSL 转 flow_model
  ↓
flow_model 转 flow_diagram_svg
  ↓
详情展示 + 仿真测试 + 上线执行

前端设计

涉及入口:

  • AuditRuleDialogs.vue:新建风险规则表单,后续增加修订版本编辑入口。
  • AuditJsonRiskRuleDetail.vue:详情页展示基本信息、测试状态、流程解释、流程图、操作按钮。
  • RiskRuleFlowDiagram.vue:只负责展示 SVG 或由 flow_model 派生的静态图,不做编辑。
  • RiskRuleTestDialog.vue:仿真测试窗口,展示输入识别、执行路径、测试报告。
  • auditViewRiskRuleModel.js / auditViewModel.js:规则详情视图模型、列表字段和状态映射。

详情页建议结构:

Topbar规则标题、状态、风险分数、风险等级、上线/启用状态

基本信息:费用领域、业务环节、附件要求、创建人、上线时间、最后操作、测试状态

判断流程:
  左侧:文字流程解释
  右侧:流程图

测试与版本:
  最近测试报告
  修订版本 / 历史版本
  操作按钮

修改规则界面建议采用左右布局:

  • 左侧:自然语言规则编辑、规则标题、费用领域、附件要求。
  • 右侧:系统解释预览,包括字段、本体映射、流程解释、风险分数。
  • 底部:重新生成、保存草稿、测试规则、提交上线。

后端设计

已有相关模块应优先复用:

  • risk_rule_generation.py:规则生成主流程。
  • risk_rule_generation_prompt.pyHermes 提示词。
  • risk_rule_generation_ontology.py:字段本体和费用领域约束。
  • risk_rule_generation_semantics.py:自然语言语义解释。
  • risk_rule_generation_interpreter.py:解释结果到 DSL。
  • risk_rule_scoring.py:风险评分。
  • risk_rule_flow_diagram.py:流程图 SVG 生成。
  • risk_rule_manifest_normalizer.py:规则 manifest 规范化。
  • risk_rule_template_executor.py:规则执行器。
  • agent_asset_risk_rule_testing.py:规则测试、删除、发布、启用。
  • agent_asset_risk_rule_simulation.py:仿真测试对话。

后端需要补齐的能力:

  • 生成 semantic_plan 并持久化到 config_json 或版本内容中。
  • 生成并持久化 flow_model,再生成 flow_diagram_svg
  • 执行器输出 trace,用于测试解释和流程图高亮。
  • 支持创建修订版本,避免直接覆盖 active 版本。
  • 支持从常见模板创建规则,模板也走同一套生成和校验链路。

接口设计

建议新增或调整:

POST /agent-assets/risk-rules/generate
  根据自然语言创建生成任务,返回生成中资产。

POST /agent-assets/{asset_id}/risk-rules/regenerate
  对草稿或修订版本重新生成 DSL、评分和流程图。

POST /agent-assets/{asset_id}/risk-rules/revisions
  基于已上线规则创建修订版本。

PATCH /agent-assets/{asset_id}/risk-rules/draft
  保存未上线规则或修订版本的编辑内容。

POST /agent-assets/{asset_id}/risk-rule-tests/simulate
  独立仿真测试返回字段识别、执行结果、trace。

GET /agent-assets/{asset_id}/risk-rule-tests/latest
  返回最近测试摘要。

POST /agent-assets/{asset_id}/publish
  发布通过测试的规则版本。

数据设计

建议在风险规则版本内容或 config_json 中保留:

{
  "source_text": "用户输入的自然语言规则",
  "semantic_plan": {},
  "dsl": {},
  "flow_model": {},
  "flow_diagram_svg": "<svg>...</svg>",
  "flow_explanation": [],
  "risk_score": 76,
  "risk_level": "high",
  "required_attachment": true,
  "required_fields": [],
  "last_operation": {
    "action": "publish",
    "actor": "admin",
    "at": "2026-05-30T10:00:00+08:00"
  }
}

测试记录保留:

{
  "test_type": "simulation",
  "input_text": "我去北京出差 3 天,上传武汉到上海车票",
  "attachments": [],
  "recognized_fields": {},
  "normalized_fields": {},
  "execution_result": {},
  "trace": {},
  "passed": true,
  "tester": "admin",
  "tested_at": "2026-05-30T10:10:00+08:00"
}

算法与公式

风险评分

风险评分由模型辅助判断,但必须结构化输出。建议使用可解释加权模型:


score = \min(100, base + \sum_{i=1}^{n} w_i x_i + c + e)

变量说明:

  • $base$:业务领域基础风险分。预算、发票、付款类通常高于普通提示类。
  • $x_i$:风险因子是否存在或强度,例如金额影响、附件缺失、字段冲突、越权、历史重复。
  • $w_i$:风险因子权重。
  • $c$:复杂度修正,例如多字段交叉、跨单据、跨时间窗口、跨附件识别。
  • $e$:例外说明修正。存在合理说明时可降低,但不能直接清零。

等级映射:

  • 0-30低风险。
  • 31-60中风险。
  • 61-80高风险。
  • 81-100极高风险。

流程复杂度控制

为了避免流程图过大,建议定义流程复杂度:


complexity = node_count + 0.5 \times edge_count + branch_count

处理规则:

  • complexity <= 12:单图展示。
  • 12 < complexity <= 20:合并说明节点,保留关键判断。
  • complexity > 20:详情页展示主流程,测试弹窗展示完整 trace。

测试方案

单元测试

  • 语义计划生成:复杂差旅城市规则不能退化为关键词判断。
  • DSL schema 校验:缺字段、非法算子、空 action 必须失败。
  • 执行器:城市匹配、日期范围、金额阈值、附件缺失、例外说明。
  • 流程转换:同一 DSL 生成稳定的 flow_model 和 SVG。
  • 风险评分:低/中/高/极高边界分数。

接口测试

  • 新建规则返回生成中资产。
  • 生成完成后包含 dslflow_modelflow_diagram_svgrisk_score
  • 仿真测试返回 recognized_fieldsnormalized_fieldstrace
  • 未测试通过的规则不能发布。
  • 已上线规则创建修订版本,不覆盖线上版本。

前端测试

  • 新建弹窗不再选择风险等级。
  • 详情页展示风险分数、流程解释、流程图。
  • 流程图不可点击、不可拖拽、无工具栏。
  • 测试弹窗显示字段识别结果和判断路径。
  • 已上线规则只能创建修订版本修改。

容器验证

后续开发验证默认在 Docker 容器内执行:

docker exec x-financial-main sh -lc "cd /app/server && pytest <target> --timeout=60"
docker exec x-financial-main sh -lc "cd /app/web && npm run build"

指标与验收

  • [A1] 新建复杂差旅规则后,详情页流程解释不能出现“检查是否包含风险关键词”这类错误表达。
  • [A2] 详情页流程图与 JSON DSL 条件数量、分支方向、命中动作一致。
  • [A3] 仿真测试能显示票据识别字段,并说明为什么命中或未命中。
  • [A4] 同一条测试样例的执行 trace 可以高亮流程图路径。
  • [A5] 已上线规则修改时不会改变当前线上执行结果,只有发布修订版本后才替换。
  • [A6] 低、中、高、极高风险都能由评分模型产出,不应默认集中在中高风险。
  • [A7] 前端构建通过,后端定向测试 60s 内完成。

风险与开放问题

  • LLM 语义理解仍可能出错,因此必须有 schema 校验、执行器 dry-run、详情解释和仿真测试兜底。
  • 字段本体不完整会限制规则表达,需要持续扩展费用、票据、预算、采购/AP 字段。
  • 复杂规则可能产生过大的流程图,需要主流程和完整 trace 分层展示。
  • 老规则没有 semantic_planflow_model,需要兼容展示并允许重新生成。
  • 常见规则模板要避免写成定制逻辑。模板只能提供默认文本、字段和 DSL 样例,最终仍走通用生成链路。