返回 AIPA 笔记
AIPA Day 67

类型学比对引擎升级 I — structuring/layering 的阈值、可解释与证据对齐

类型学比对引擎升级 I — structuring/layering 的阈值、可解释与证据对齐

2026-08-20
structuringlayeringexplainable-rules

日期: 2026-08-20 阶段: Phase 3 - AML 调查 Copilot 标签: #structuring #layering #explainable-rules

核心问题

Day 64-66 把证据汇集这条「进水口」和它的成本闸都修好了。今天进 pipeline 的②段——类型学比对:拿到一份证据 dossier,怎么判它是 structuring、layering,还是 normal?为什么这一段在 2026 的合规落地里坚持用确定性规则引擎而非 LLM

P1 已经造了 typology.tsassessCase + V2 的 assessCaseV2),跑出 recall 1.0×3 类型学、FPR 5.6%。今天不是从零造轮子,而是回答三个「为什么这么造」的深问题,并把 structuring/layering 两类的阈值与可解释性讲透:

  1. 阈值怎么定才不被洗钱者反向利用? 结构化的本质是「贴着 $10,000 CTR 门槛下方走」——若检测阈值也写死在 $10,000,洗钱者只要再降一点就躲过。今天用「Searching for Smurfs」(2025) 的实证回答:洗钱者确实知道并贴线,所以规则必须用「贴线带」而非「单点阈值」。
  2. 规则输出怎么和证据 schema 对齐、并带可解释理由? SAR 起草段(③段)要引用每条命中的「触发了哪条规则、具体数值、阈值」。P1 的 RuleExplanation(含 triggers: {label,value,threshold,op,unit})就是为此设计。
  3. 它和 P1 规则基线是什么关系? 不是取代,是「同一引擎、V2 加可解释层」——assessCaseV2assessCase 之上叠加 explanations / muleGraph / arbitration,不改 base 判定

关键内容

A. structuring 阈值:为什么是「贴线带 $8,000-$10,000」而非「单点 $10,000」

美国 BSA 要求现金交易超 $10,000 报 CTR(31 CFR 1010.311,监管)。结构化(smurfing)就是把大额现金拆成多笔单笔 <$10,000 来躲 CTR。若检测规则写「单笔 ≥$10,000 才可疑」,等于只抓不躲申报的笨贼——真正的结构化全在 $10,000 下方。

「Searching for Smurfs: Testing if Money Launderers Know Alert Thresholds」(Journal of Quantitative Criminology, 2025) 用 bunching estimator 实证检验了一个关键假设:洗钱者是否知道并贴着阈值走。核心逻辑——「Knowing a threshold value would be valuable for the money launderer; it would allow them to make transactions just below the threshold, lowering their probability of detection while minimizing their number of transactions and smurfing costs」。结论是阈值附近存在 bunching(金额分布在阈值下方异常堆积),且机密的银行内部告警阈值一旦泄露,洗钱者会贴新阈值走

这条实证直接决定了 typology.ts 的阈值设计——用「带」不用「点」

// src/aml/typology.ts(现有常量)
export const CTR_THRESHOLD_CENTS = 1_000_000  // $10,000 CTR 申报门槛(监管)
const STRUCT_BAND_MIN_CENTS = 800_000          // 贴线带下限 $8,000
// STRUCT-01:≤10 天窗口内 ≥3 笔落在 [$8,000, $10,000) 的现金存款

checkStruct01 的判定不是「金额 ≥ X」,而是「金额 ∈ [$8,000, $10,000) 且 ≥3 笔且 ≤10 天」——这正是 AMLNet (arXiv:2509.11595, 2025-09) 建模结构化时用的「random splits with some transactions just below threshold ($8,500-$9,900)」配方。判定伪代码:

checkStruct01(case):
  band = cashDeposits(case).filter(t => $8,000 ≤ t.amount < $10,000)   // 贴线带
  best = argmax over windows of (txs within [d, d+9 days])             // 滑动 10 天窗
  if len(best) < 3: return null                                        // 笔数门槛
  return RuleHit{ STRUCT-01, score=0.6, evidenceTxIds=best, desc=含具体数值 }

为什么带下限设 $8,000 而非 $0?——精确率。下限以下是日常小额现金(买菜、找零),全算进来会把 normal 阴性案件误报。P1 的 normal 生成器刻意放了一个「现金密集型商户」案件(3 笔 $8,200-$9,800 营业款),它触发 STRUCT-01——这是保留的真实感 FP,正是 5.6% FPR 的来源。带下限是 precision/recall 的调节旋钮。

反直觉洞察①(检测阈值必须和申报阈值脱钩):把检测门槛等同于监管申报门槛($10,000)是新手最常见的错。Smurfs 论文证明洗钱者知道阈值并贴线,所以「单点 $10,000」规则的召回率对结构化趋近 0——真正的结构化交易全部在阈值下方。正确做法是检测阈值(贴线带 $8,000-$10,000 + 笔数 + 窗口)严于低于申报阈值。更狠的现实:连内部机密告警阈值都可能泄露给洗钱者,所以单一固定阈值天然脆弱,必须叠加「多笔 + 短窗 + 渠道」的组合条件,让单维贴线躲不过。

B. layering 阈值:从「金额」转向「资金流拓扑」

structuring 看的是金额分布(贴线、多笔),layering 看的是资金流动结构——外部流入后经多个账户链式快进快出。这是一个图上的路径搜索问题,不是金额阈值问题。checkLayer01 的核心是沿内部转账边做 DFS,找最长合规链:

follow(account, arrivedDay, arrivedCents, visited):       // 链式过账 DFS
  candidates = internalDebits(account).filter(t =>
    t.day ∈ [arrivedDay, arrivedDay+2]      AND            // 停留 ≤2 天(DWELL)
    t.amount ≥ arrivedCents * 0.8           AND            // 转出 ≥80%(FORWARD_RATIO)
    t.counterparty ∉ visited)                              // 防环
  return 最长的 [hop, ...follow(hop.next, ...)]
// 命中条件:链上账户数 ≥3(即 ≥2 跳)+ 链头外部流入 ≥$5,000

三个阈值各自的依据:

阈值依据调松/调紧的后果
每跳停留天数≤2 天「快进快出」是 layering 定义特征;停留久=正常资金沉淀调松→把正常转账误判为过账(FP↑)
每跳转出比例≥80%过账要保留绝大部分本金,留一点当幌子调紧到 100%→漏「留小尾巴」的真案(FN↑)
最小链长≥3 账户(≥2 跳)单跳是普通转账;多跳才是「分层」调到 ≥2 账户→普通 A→B 转账全中(FP↑)
链头流入下限≥$5,000过滤工资等小额合法入账调到 $0→工资入账后正常消费链误判

AMLNet (2025-09) 对 layering 的分层建模口径印证了这套阈值:「low-sophistication: 2-3 layers splitting funds among 2-3 accounts with fixed delays; medium-sophistication: 3-5 layers with randomized delays and unique destinations per layer」。P1 的 genLayeringCase 生成 3-5 个内部账户、每跳停留 0-2 天、整千金额($25k→$24k→$22k),正落在 AMLNet 的「medium」区间。

为什么 layering 用图 DFS 而非 SQL 聚合?——因为「链」是路径属性,不是账户属性。一个账户单看「收一笔、转一笔」毫无可疑;只有把它放进「外部流入→A→B→C→外部流出」这条路径里,每跳都满足「快进快出 ≥80%」,才构成 layering。这是图算法不可被聚合查询替代的本质原因。

反直觉洞察②(layering 的可疑度在边上,不在点上):审查单个账户、单笔交易,layering 看起来完全正常——每笔都是合法的内部转账。可疑信号只存在于交易之间的时序+比例关系(这笔进来 2 天内 80% 又出去了)。所以 layering 检测不能靠「给每笔交易打风险分再求和」——那样每笔都低分、加起来还是低分。必须在资金流图的边上做模式匹配。P1 用 internalDebitsByAccount 建邻接表 + follow DFS,正是把「点的检测」升级成「路径的检测」。这也是为什么纯 LLM 读交易列表容易漏 layering——它擅长读文本,不擅长在隐式图上做路径搜索。

C. 可解释命中:规则输出与证据 schema 的对齐

②段的输出要喂给③段 SAR 起草,所以命中不能只给一句中文描述——必须给结构化、可机读的触发事实,让 SAR 能逐条引用「触发了 STRUCT-01,因为贴线存款 4 笔 ≥ 阈值 3 笔」。这就是 P1 RuleExplanation 的设计:

// src/aml/typology.ts(现有 RuleTrigger / RuleExplanation)
interface RuleTrigger {
  label: string                                  // 「贴线现金存款笔数」
  value: number; threshold?: number              // 实测 4 / 阈值 3
  op?: '>='|'>'|'<'|'<='|'=='                     // 比较算子
  unit: 'count'|'cents'|'days'|'ratio'|'accounts'
}

explainHit(case, hit) 把每条 RuleHit 升级为带 triggers 列表的 RuleExplanation。对 STRUCT-01 它产出四条触发事实:贴线存款笔数(4 ≥ 3)、窗口天跨度(8 ≤ 10)、合计金额、单笔上限(< CTR)。每条都是「value op threshold」三元组——可被 evalChecks 的代码型检查逐条核对(Day 18 的代码型 eval 层),也可被 UI 高亮成证据锚点

三层对齐保证证据可溯源(这是合规审计的硬要求):

RuleHit.evidenceTxIds  ⊆  case.transactions(必须存在 → cited_tx_exist 检查)
RuleExplanation.triggers ← 从 evidenceTxIds 对应的交易重新算(不复述 desc,重新核对)
SarDraft.citedTxIds = dedupe(hits.flatMap(evidenceTxIds))(SAR 只能引用命中证据)

explainHit 的关键纪律——triggers 的 value 是从 evidenceTxIds 对应交易重新计算的,不是复制 RuleHit.description 里的数字。这样若 description 和实际证据脱节(幻觉风险),代码型检查能抓到。这是「确定性引擎」相对 LLM 的核心优势:每个数字都有可重算的来源,审计追问「这个 4 是怎么来的」时,能指到具体 4 笔交易 id。

与 P1 规则基线的关系(不是取代,是分层):

函数产出P3 角色
base 判定assessCasehits + scores + topTypology不变,recall 1.0 的基线
V2 可解释assessCaseV2+ explanations + muleGraph + arbitration②段主输出,喂③段 SAR
代码型核对runCodeCheckscited_tx_exist 等 pass/faileval gate,核对②段自洽

assessCaseV2assessCase 之上只加不改——base 的 scores/topTypology 语义完全保留(唯一例外:多类型学并列时用 arbitration.primary 覆盖 topTypology 打破平手,Day 68 详谈)。这保证 P1 的 recall 1.0 不被 V2 破坏。

设计要点/决策表

要点决策理由
structuring 阈值贴线 [$8,000, $10,000) + ≥3 笔 + ≤10 天,不用单点 $10,000洗钱者知道并贴线(Smurfs 2025),检测须严于申报阈值
带下限 $8,000过滤日常小额现金precision 旋钮;下限太低则日常现金误报
layering 检测资金流图 DFS(停留≤2天/转出≥80%/链长≥3),非金额阈值可疑度在边的时序+比例关系上,不在单点
链头流入下限≥$5,000过滤工资等小额合法入账
命中输出结构化 RuleTrigger{value,threshold,op,unit},非纯文本③段 SAR 要可机读引用;代码型检查要可核对
triggers 来源从 evidenceTxIds 重算,不复制 description防 description 与证据脱节;每个数字可溯源
与 base 关系assessCaseV2 只加可解释层,不改 base 判定保 P1 recall 1.0 不被破坏

对本项目的落地

  • src/aml/typology.ts 的 structuring/layering 阈值已落地且不改CTR_THRESHOLD_CENTS=$10,000、STRUCT_BAND_MIN_CENTS=$8,000、LAYER_DWELL_DAYS=2、LAYER_FORWARD_RATIO=0.8、LAYER_MIN_CHAIN_ACCOUNTS=3、LAYER_MIN_INFLOW_CENTS=$5,000——本日把它们的实证依据(Smurfs 贴线/AMLNet 分层口径)补全为设计文档,供面试与审计追问时引用,而非改代码。
  • explainHit / RuleExplanation 是②→③段的接口:Day 64 pipeline ②段输出 assessCaseV2(case),其 explanations 字段(每条命中的 triggers)是③段 SAR 起草引用证据的来源。P3 的 LLM 起草 prompt 应喂 explanations 的结构化 triggers,不喂原始交易全表——让 LLM 在「已核对的事实」上叙述,降低幻觉。
  • 代码型检查兜底src/aml/evalChecks.tscited_tx_exist / top_typology_consistent 在 CI 核对②段输出自洽——SAR 引用的 txId 必须存在、topTypology 必须与最高分一致。这是确定性引擎相对 LLM 的可审计优势。
  • 降级路径复用(呼应 Day 66):成本极限降级(90%+)时整条 LLM pipeline 退回 assessCaseV2(零成本)+ draftSar(模板)——②段规则引擎本就是降级安全网,recall 1.0 保证降级后仍不漏报。
  • 诚实标注typology.ts 头注已写明「确定性规则引擎(非 LLM)」;本日不引入任何 LLM 进②段。mule_network 的图度量与多类型学叠加仲裁留 Day 68(升级 II)详谈。

参考资料

  1. Sumarliah / van Koningsveld et al. — Searching for Smurfs: Testing if Money Launderers Know Alert Thresholds, Journal of Quantitative Criminology(Springer,arXiv:2309.12704):bunching estimator 检验阈值附近金额堆积;洗钱者知阈值则贴线以降被测概率、减交易数与 smurfing 成本;机密告警阈值泄露后洗钱者贴新阈值——故单点阈值脆弱 (2025)
  2. arXiv:2509.11595 — AMLNet: A Knowledge-Based Multi-Agent Framework to Generate and Detect Realistic Money Laundering Transactions:structuring 配方含 random splits just below threshold ($8,500-$9,900);layering 低复杂度 2-3 层/2-3 账户,中复杂度 3-5 层/随机延迟/每层唯一目的地;检测 F1 0.90(precision 0.84, recall 0.97)(2025-09)
  3. FinCEN — 31 CFR 1010.311 / Form 112:现金交易超 $10,000 须报 CTR(BSA,监管)(持续)
  4. amlwatcher / aiprise — Key AML Typologies 2026 / 10 AML Typologies Every Bank Needs to Know:结构化+smurfing 跨渠道(银行/移动钱包/预付卡/跨境 FinTech)持续高风险,须 holistic cross-channel 分析而非孤立规则;现代监控对每笔 ACH/wire/card/internal 评分 structuring/layering/rapid movement (2026)
  5. 本仓库 src/aml/typology.ts(STRUCT-01/02 + LAYER-01/02 规则、贴线带/DFS 阈值常量、RuleTrigger/RuleExplanation/explainHit/assessCaseV2)、src/aml/generator.ts(genStructuringCase/genLayeringCase 配方、现金密集型商户 FP)、src/aml/evalChecks.ts(cited_tx_exist/top_typology_consistent 核对)(2026-06)

SOTA 检查 (2026-06-11)

  • 「确定性规则引擎做类型学判定 + LLM 只做叙述」是 2026-06 合规落地的主流分工:FIS-Anthropic (2026-05) 与 Co-Investigator (2025-09) 都把「比对已知类型学」放在确定性/可审计的一侧,LLM 负责证据汇集与叙述生成——因为类型学判定要回答审计追问「为何判 structuring」,规则的「value op threshold」可解释性是 LLM 黑箱给不了的。
  • 「检测阈值须严于申报阈值」在 2026 仍是 live 的设计纪律:Smurfs 论文 (2025) 的「launderers know and bunch」结论未被推翻;2026 typology 指南一致强调 cross-channel holistic 分析(单维贴线易躲),印证「贴线带 + 多条件组合」优于「单点阈值」。
  • 图方法在 layering 检测上升温:DELATOR (multi-task GNN on transaction graphs) 等图神经网络方案在大规模交易图上抓 layering 优于规则,但牺牲可解释性——合规场景下 GNN 适合做「召回候选」,最终定性仍回退确定性规则给可审计理由。本项目原型用规则 DFS(可解释)是对的,规模化后可考虑「GNN 召回 + 规则定性」两阶段。
  • 待跟踪:贴线带下限 $8,000 与 layering 的 80%/2天 阈值是 v1 经验值;W2-W3 用更大合成集(或公开 SynthAML/AMLworld)做阈值灵敏度分析,按 precision/recall 曲线回填最优值;mule_network 图度量与叠加仲裁见 Day 68。
  • 过时警示:把检测阈值写死成监管申报阈值($10,000 单点)是 2024 前规则系统的经典缺陷,对结构化召回趋近 0——反直觉洞察①是 live 踩坑点,至今仍有初级 TM 系统犯此错。