自用笔记初稿。内层 anti_fraud 里「规则怎么用 Feature 判出结论」。
前置:03-Risk 决策三层模块(总图)· 01-Risk 架构总览 · 02-Holmes 平台业务全景 · 04-Risk Feature 取数链路
一句话:Feature 给变量;内层规则 DAG 用表达式判命中;输出 CheckResult(Pass/Reject/Challenge)给外层工作流 Goto。
0. 本文在架构里讲哪一块(模块)
总图见 03-Risk 决策三层模块:
相对 04-Risk Feature 取数链路(燃料从哪来):本篇 = 判据怎么利用这些燃料。
一、外层 / 策略树 / 内层执行 DAG —— 什么关系
| ① 外层工作流 DAG | ② 策略语义树 | ③ 内层执行 DAG | |
|---|---|---|---|
| 在哪 | credit_risk_engine | Holmes / 配置(给人看的分类) | risk-antifraud(进了 anti_fraud 之后) |
| 问什么 | 下一步跑哪个工作流节点? | 规则怎么分层分类? | 房间里节点怎么串、怎么跳? |
| 长什么样 | Root→anti_fraud→challenge… | Scene→Group→L1→L2→L3→Feature | Start→Group→Condition→Output→END |
| 配置 | insert 到 db | Holmes 配置 | 配置(落 DB,加载到内容) |
| 何时结束 | 走到 END / return | 不「跑完」,是静态说明书 | Output 吐 CheckResult → 回外层 |
L3 是什么
L3 = Level 3 规则 = 一条「如果…就拦/就过」的具体判断式。
策略树上分三层只是为了好管:L1/L2 是文件夹,只有 L3 里写了真正会算的表达式。
kredit / 某支付场景(示意)
用户发起一笔 SPL 支付,外层工作流进到 anti_fraud。策略里有一个 Group「高危交易拦截」,树长这样:
Scene: 支付反欺诈
└─ Group: 高危交易拦截组
├─ L1 账户风险
│ └─ L2 设备异常
│ └─ L3-A 新设备且异地 ← 叶子,真规则
│ 表达式: is_new_device == true && ip_city_distance > 100
│ 命中动作: Reject
└─ L1 名单风险
└─ L2 黑名单
└─ L3-B 命中欺诈黑名单 ← 另一条叶子
表达式: hit_fraud_blocklist == true
命中动作: Reject| 层 | 角色 | 例子里是什么 | 会不会「算 true/false」 |
|---|---|---|---|
| L1 | 大类文件夹 | 账户风险 / 名单风险 | 否 |
| L2 | 中类文件夹 | 设备异常 / 黑名单 | 否 |
| L3 | 具体条款 | 新设备且异地 / 命中黑名单 | 会 |
| Feature | 条款里的变量 | is_new_device、ip_city_distance | 变量取值,见 Feature 笔记 |
这一笔请求实际发生什么
假设 Feature 取完:
is_new_device = true
ip_city_distance = 350
hit_fraud_blocklist = false- 内层执行 DAG 跑到 Group 节点「高危交易拦截」
- Group 内部依次(或按配置)评估多条 L3:
- L3-A:
true && 350 > 100→ 命中 - L3-B:
false→ 未命中
- L3-A:
- 组结论按策略汇总(示例:有 Reject 叶子命中 → 组结论 Reject)
- 记下 命中了 L3-A → 监控/日志里的
hit_l3_group(或同类 label) - Output 给出
CheckResult=Reject→ 回外层 → 可能return_reject
Group 节点(执行 DAG 上的一个框)
├── 跑 L3-A ──命中──► hit_l3 = L3-A
├── 跑 L3-B ──未命中
└── 组结论 Reject- L3 = 策略树最底下那条可执行表达式(条款)
- Group 节点 = 内层 DAG 上的容器,一次请求里把组内多条 L3 拿出来算
二、Group 与 L3
Group = 一组 L3 规则的打包执行单元(可复用)。
跑完一组后,关键产出(值班高频):
| 产出 | 是什么 |
|---|---|
| 组结论 | 这一组整体 Pass / Reject / Challenge |
X_HitL3Group / hit_l3 | 命中了哪条 L3 叶子(监控 hit_l3_group) |
| 原因码 / 工单模板等 | 给运营、工单、下游用的附属信息 |
监控串法(与 08-Risk 值班指南 一致):
某 scene 拒绝率↑
→ hit_l3_group topk
→ 哪条 L3 变多
→ 该 L3 依赖的 Feature 是否超时/缺数/漂移注意 sceneId 两层:查反欺诈命中用内层 anti_fraud_<数字> 的 scene,不是外层入口号(见 Holmes 全景)。
三、Watson / Moriarty(规则引擎)
Watson/Moriarty 不是内层 DAF 上单独的节点,而是 Group 节点内部,用来算 L3 表达式的引擎
输入:规则表达式 + 一堆变量值(Feature 等)
输出:命中 / 未命中(以及组级汇总)| Watson | Moriarty | |
|---|---|---|
| 关系 | 旧 | 新(替换,不是并行分工) |
| 切换 | context 标志位 USE_MORIARTY 等 | 同上;可有 shadow 对比 |
| 形态 | vendor 库,在 engine 进程内 | 同 |
位置:
credit_risk_engine
└─ risk-antifraud
└─ Watson / Moriarty不是 feature_core 注册表里的 executor;也不是 Unicorn(Unicorn 更多在 Feature 外调 / 自定义函数场景)。
策略配置会预编译进缓存(规则表达式 → 可执行对象),避免每次请求重新 parse。
四、Condition / Process / Output(知道存在即可)
| 节点 | 干什么 |
|---|---|
| Condition | 拉 Feature、塞环境,供内层 DAG 边的 expr 跳转 |
| Process Feature | 算中间量,写入 ProcessFeatureMap(可跨 scene 用) |
| Output | 挑选要吐给外层 / 回填响应的字段 |
主结论通常仍由 Group(L3) 决定;Condition 更多管「组与组之间怎么走」。
五、和 Feature 笔记的接口
规则要变量时的调用链(可点进对应笔记/小节):
- L3 表达式 里的名字(如
is_new_device) - → Group 节点 内 FeatureHandler.GetFeatures 要值
- → 04-Risk Feature 取数链路
- → 值回到规则环境
- → Watson / Moriarty 求值
总图:03-Risk 决策三层模块(内层判 + 特征侧挂)。
| 出问题的感觉 | 更可能在 |
|---|---|
| 特征值错 / 超时 / 缺数 | 04-Risk Feature 取数链路 |
| 值对但该拒没拒 / 命中规则变了 | [[#L3 是什么(用一笔支付讲清楚) |
| 命中了但外层走错分支 | 外层 Goto / CheckResult(01-Risk 架构总览 > 4.1 两层 DAG) |
相关
- 01-Risk 架构总览 > 4.1 两层 DAG · 3.3 risk-antifraud 的规则引擎
- 02-Holmes 平台业务全景 > 四、策略层级模型
- 04-Risk Feature 取数链路
- 08-Risk 值班指南(hit_l3_group)
- hub:KB B-002 / B-004