补充LSFX Mock第二期稳定随机命中设计文档

This commit is contained in:
wkc
2026-03-20 16:56:44 +08:00
parent 1d89e9e77a
commit 782e41c0f0
2 changed files with 275 additions and 0 deletions

View File

@@ -0,0 +1,253 @@
# 兰溪流水 Mock 第二期稳定随机命中设计
## 1. 背景
当前仓库已经具备两条基础能力:
- `lsfx-mock-server` 已支持按 `logId` 稳定随机命中第一期规则子集,并通过 Mock 流水为主工程提供可重复联调输入。
- 主工程第二期真实规则已在 [`docs/plans/backend/2026-03-20-bank-tag-real-rule-phase2-backend-implementation.md`](/Users/wkc/Desktop/ccdi/ccdi/docs/plans/backend/2026-03-20-bank-tag-real-rule-phase2-backend-implementation.md) 中明确范围,但 `lsfx-mock-server` 尚未补齐第二期命中输入与配套基线。
本次目标不是重写主工程打标逻辑,而是在保留第一期稳定随机命中方案的前提下,为第二期补齐可联调、可重复、可命中真实 SQL 的输入数据。
## 2. 目标
- 保留现有第一期 `logId -> 稳定随机规则子集` 行为不变。
- 为第二期规则新增稳定随机命中计划。
- 让“拉取本行信息 / 获取流水列表 -> 入库到本地 -> 执行重打标”后,最终标签结果中可以查到抽中的第二期规则命中。
- 对依赖采购、资产等外部事实表的规则,补最小且幂等的本地数据库基线。
## 3. 非目标
- 不新增主工程打标补丁逻辑。
- 不把采购类、资产类规则伪造成纯银行流水规则。
- 不引入“指定特殊 `logId` 固定命中全部第二期规则”的双轨模式。
- 不扩展第二期范围外的新规则。
## 4. 方案对比
### 4.1 方案 A稳定随机命中 + 第二期基线编排
保留现有 `FileService -> StatementService -> 缓存分页` 主链路;对可由银行流水驱动的第二期规则继续通过 Mock 流水样本触发;对依赖采购、资产等外部事实表的规则,通过本地数据库最小基线补齐真实 SQL 输入。
优点:
- 与主工程真实 SQL 数据来源一致。
- 能同时覆盖“Mock 取数正确”和“真实规则可命中”。
- 保持现有第一期链路结构不变,扩展成本最低。
缺点:
- 需要同时维护流水样本和数据库基线两类输入。
### 4.2 方案 B只改 Mock 流水
只扩充 `lsfx-mock-server` 返回的流水数据,不补采购、资产等业务表。
缺点:
- 第二期中存在真实依赖 `ccdi_purchase_transaction``ccdi_asset_info` 的规则,最终会出现 Mock 看似有数据、真实 SQL 仍然无法命中的偏差。
### 4.3 方案 C只补数据库基线
Mock 仅返回普通流水,把第二期命中主要交给数据库灌数。
缺点:
- 无法证明“兰溪本地接口获取流水列表并入库”的链路本身正确。
- 偏离本次验收口径。
## 5. 推荐方案
采用方案 A。
原因:
- 第二期联调必须同时证明两件事Mock 取数入库链路没问题,真实 SQL 也确实能命中。
- 采购类和资产类规则本来就不是纯流水规则,直接补最小事实基线才符合真实业务口径。
- 继续使用“同一 `logId` 稳定随机命中一部分规则”可以复用现有测试与排障习惯。
## 6. 模块边界与数据流
### 6.1 `FileService`
继续负责生成并持久化规则命中计划。
在现有字段基础上新增两组规则计划:
- `phase2_statement_hit_rules`
- `phase2_baseline_hit_rules`
职责边界:
- 只负责决定“这个 `logId` 抽中了哪些第二期规则”。
- 不直接构造流水明细,也不直接写数据库业务基线。
### 6.2 `StatementService` 与 `statement_rule_samples.py`
继续负责把命中计划转成最小流水样本,并与噪声流水合并后返回。
职责边界:
- 只生成能通过 `ccdi_bank_statement` 真实入库后触发的第二期样本。
- 不为采购、资产等外部事实规则伪造流水替代。
### 6.3 第二期基线服务
`lsfx-mock-server/services/` 下新增一个轻量服务,负责根据 `phase2_baseline_hit_rules` 幂等写入本地 MySQL 最小事实数据。
职责边界:
- 只补真实 SQL 所需输入。
- 不直接写标签结果表,不参与打标逻辑计算。
### 6.4 主工程
主工程 `CcdiFileUploadServiceImpl -> CcdiBankStatement -> CcdiBankTagServiceImpl` 链路保持不变。
验收以真实链路为准:
1. 拉取本行信息或通过兰溪接口获取流水。
2. 流水成功入库到 `ccdi_bank_statement`
3. 执行项目重打标。
4.`ccdi_bank_statement_tag_result` 或结果接口中看到抽中的第二期规则命中。
## 7. 第二期规则分层
### 7.1 流水样本直接驱动
以下规则以 `ccdi_bank_statement` 为核心输入,使用 Mock 流水样本驱动:
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
- `MULTI_PARTY_GAMBLING_TRANSFER`
- `MONTHLY_FIXED_INCOME`
- `FIXED_COUNTERPARTY_TRANSFER`
- `SALARY_QUICK_TRANSFER`
- `SALARY_UNUSED`
要求:
- 样本必须落在同一个真实员工域或其亲属域上。
- 时间窗口、金额区间、对手方稳定性等聚合条件必须在同一对象范围内闭环。
- 互斥规则不得使用同一员工样本组。
### 7.2 数据库基线驱动
以下规则需要外部事实表配合:
- `HOUSE_REGISTRATION_MISMATCH`
- `PROPERTY_FEE_REGISTRATION_MISMATCH`
- `TAX_ASSET_REGISTRATION_MISMATCH`
- `SUPPLIER_CONCENTRATION`
处理方式:
- 三条资产不匹配规则:
- Mock 生成对应交易流水。
- 基线服务在 `ccdi_asset_info` 中补“故意缺失或不匹配”的最小资产事实。
- `SUPPLIER_CONCENTRATION`
- 直接补 `ccdi_purchase_transaction` 聚合命中基线。
- 不伪造银行流水替代。
## 8. 第二期样本设计
### 8.1 `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
- 选择一个真实员工及其亲属身份证范围。
- 亲属收入基线维持低收入事实。
- 生成大额累计转入或转出流水,确保超过低收入亲属的大额交易阈值。
### 8.2 `MULTI_PARTY_GAMBLING_TRANSFER`
- 同一员工对象、同一天、多名不同对手方。
- 每笔金额落在 `MULTI_PARTY_AMT_MIN ~ MULTI_PARTY_AMT_MAX` 区间。
- 命中依赖“多人 + 多次 + 同日 + 区间金额”,不依赖敏感词。
### 8.3 `MONTHLY_FIXED_INCOME`
- 为同一员工构造连续 3 至 4 个月的固定收入转入。
- 排除工资代发主体和工资关键词。
- 每月金额稳定高于 `MONTHLY_FIXED_INCOME`
### 8.4 `FIXED_COUNTERPARTY_TRANSFER`
- 为同一员工与固定对手方构造季度稳定转入。
- 每季累计金额落在 `FIXED_COUNTERPARTY_TRANSFER_MIN ~ FIXED_COUNTERPARTY_TRANSFER_MAX` 区间。
### 8.5 `SALARY_QUICK_TRANSFER`
- 先生成可识别工资入账。
- 再在 24 小时内生成大额转出,满足比例条件。
### 8.6 `SALARY_UNUSED`
- 先生成工资入账。
- 后续 30 天不生成可计入“工资使用”的消费或转账支出。
-`SALARY_QUICK_TRANSFER` 不共用同一员工对象。
### 8.7 资产不匹配三条规则
- `HOUSE_REGISTRATION_MISMATCH`:生成购房交易流水,但不提供可匹配房产登记。
- `PROPERTY_FEE_REGISTRATION_MISMATCH`:生成物业缴费流水,但不提供对应房产登记。
- `TAX_ASSET_REGISTRATION_MISMATCH`:生成大额纳税流水,但不提供与税费相符的资产登记。
### 8.8 `SUPPLIER_CONCENTRATION`
- 为同一申请人写入多笔采购记录。
- 使单一供应商采购额占比显著超过 70%。
- 使用固定业务主键和稳定供应商集合,确保可重复验证。
## 9. 实现落点
- Modify: `lsfx-mock-server/services/file_service.py`
- Modify: `lsfx-mock-server/services/statement_service.py`
- Modify: `lsfx-mock-server/services/statement_rule_samples.py`
- Add: `lsfx-mock-server/services/phase2_baseline_service.py`
- Add/Modify: `lsfx-mock-server/tests/test_file_service.py`
- Add/Modify: `lsfx-mock-server/tests/test_statement_service.py`
- Add/Modify: `lsfx-mock-server/tests/integration/test_full_workflow.py`
- Add: `sql/migration/2026-03-20-lsfx-mock-phase2-hit-baseline.sql`
## 10. 幂等策略
- 规则命中计划继续由 `logId` 决定,不新增第二随机源。
- 流水样本继续由 `StatementService` 缓存,同一 `logId` 重复分页读取结果一致。
- 采购基线使用固定业务主键,按固定主键删后重建。
- 资产基线使用固定特征组合,确保可精确清理与重建。
- 所有基线写入都必须只作用于本次选中的员工域,避免污染无关人员。
## 11. 验证设计
### 11.1 Mock 单元测试
- 第二期规则池抽样稳定性。
- 第二期流水样本只装配被抽中的规则。
- 第二期数据库基线写入的幂等性。
### 11.2 Mock 集成测试
- `getJZFileOrZjrcuFile -> getBSByLogId` 同一 `logId` 下结果稳定。
- 抽中第二期规则时,流水样本与基线写入同步成立。
### 11.3 主工程端到端验证
- 拉取本行信息后流水成功入库。
- 执行项目重打标后,第二期目标规则出现在结果中。
- 明细型规则可通过流水详情接口回查。
- 对象型规则可在标签结果表中看到正确 `objectType/objectKey/reasonDetail`
## 12. 风险与边界
- 不为了联调成功去修改主工程真实 SQL。
- 不把 `SUPPLIER_CONCENTRATION` 伪造成纯流水命中。
- 不引入兜底、补丁或兼容性双轨逻辑。
- 若第二期真实 SQL 与现有基线字段口径不一致,按验证失败暴露,不在 Mock 侧偷偷修正业务规则。
## 13. 结论
本方案采用“保留第一期稳定随机命中方案 + 为第二期补齐稳定随机命中计划、最小流水样本和幂等数据库基线”的最短路径实现。
这样可以同时保证:
- 兰溪本地接口能够正确返回并入库存量流水;
- 第二期新增模型所需输入事实完整;
- 主工程重打标后能够命中新增模型的真实规则结果。

View File

@@ -0,0 +1,22 @@
# LSFX Mock 第二期稳定随机命中设计记录
## 本次变更
- 新增第二期联调设计文档:
- `docs/design/2026-03-20-lsfx-mock-phase2-random-hit-design.md`
## 设计收敛结果
- 明确保留第一期 `logId` 稳定随机命中方案,不引入第二套命中模式。
- 明确第二期规则按“流水样本驱动”和“数据库基线驱动”两层处理。
- 明确验收口径为“兰溪本地接口取数并入库后,执行重打标,最终标签结果中可查到抽中的第二期规则命中”。
## 关键边界
- 不修改主工程真实打标逻辑。
- 不把采购类、资产类规则伪造成纯流水规则。
- 不新增兼容性或补丁式方案。
## 后续动作
- 待用户审核设计文档后,再进入实施计划编写。