DriftLedger/docs/账单识别及账户分类设计.md
fengmengqi 6767dd538a feat: 领域/组件/服务三层目录重构 + 微信无障碍绕过方案 + 新 UI 组件体系 + 账本增删改增强
### 架构重构:三层分层目录化
  - domain 拆分为 8 个子目录(core/pipeline/rules/finance/stats/taxonomy/transaction/platform)
  - components 拆分为 6 个子目录(form/ui/layout/account/category/stats/transaction)
  - services 拆分为 5 个子目录(automation/data/ocr/security),accessibilityParser 从 automationPipeline 提取
  - 新增 ruleConfig.ts — 规则配置唯一数据源(关键词/方向/OCR 模式),与业务逻辑解耦

  ### 微信账单抓取:节点混淆绕过(核心突破)
  - BillingAccessibilityService 重命名为 SelectToSpeakService,完整伪装为系统服务
  - 同时伪装包名+类名为 com.google.android.accessibility.selecttospeak,规避微信 8.0.52+ 白名单校验
  - Config Plugin 重写:8 个 kt 文件整体复制+package 正则替换+Manifest/import 联动
  - 支付宝/微信无障碍文本解析器全面增强(方向推断/账单分类提取/付款方式提取/容错)
  - 补充文档 accessibility-wechat-guide.md(伪装原理、踩坑全记录)

  ### 新 UI 组件体系
  - Toast:全局轻量 toast(Context Provider + 入场动画 + 操作按钮 + 自动消失)
  - ErrorBoundary:React class 错误边界(降级 UI + 重试)
  - EmptyState / ConfirmDialog / SegmentedControl / Skeleton / TimePicker
  - BottomSheet 重写:SafeAreaProvider 修复、手势下滑关闭、键盘响应式避让
  - FormModal 重构:拆出 FormFields 子组件(TextField/SelectField/DropdownField)
  - 新增 PeriodSwitcher、RangeStatsCard 独立组件

  ### 新 Hooks & 工具
  - useBottomInset — 统一底部安全区留白
  - useKeyboardAvoiding — 键盘高度响应式 hook(替代 translateY 方案)
  - sanitize.ts — 日志脱敏工具提取

  ### 账本增删改增强
  - 写锁增加代际计数器(lockGeneration),reset 后旧链 pending 任务自动跳过 set
  - 新增 restoreTransaction — 撤销删除(重新追加 raw 文本到 mobile.bean)
  - 删除交易时清除去重缓存(buildTxKeyFromRaw 重建去重键),支持「删了重记」
  - editTransaction/deleteTransaction 改用 dr-id 精确定位交易块(避免同名交易定位错误)
  - appendTransactionsBatch 改从存储直接读取,避免 zustand state 不一致

  ### OCR 原生模块增强
  - 异步 initEngine 增加 CountDownLatch 等待(最多 15s),解决竞态导致的「引擎未就绪」
  - setModelDir 增加去重判断 + file:// 前缀剥离,避免冗余 reload
  - 推理链路增加分阶段耗时日志(det 推理/det 后处理/rec 识别)
  - 图片缩放策略重命名(scaleDownForOcr → capLongEdge)

  ### OCR 模型按需下载
  - 移除了启动时自动下载 ~30MB OCR 模型的逻辑
  - 改为首次使用 OCR 时才触发下载

  ### 设置页重设计
  - ScrollView → SectionList 分组卡片布局(iOS 风格分组圆角行+右侧箭头)
  - 移除 Card 组件包装,直接使用独立分组头+底部关于卡片

  ### 首页优化
  - ScrollView → FlatList(ListHeaderComponent 承载净资产卡片+待办条)
  - 日期/金额格式化增加 locale 感知(zh/en)

  ### 通知管道增强
  - NotificationChannel MD5 去重改为批量淘汰(80% 阈值),替代逐个删除
  - 增加 debug 日志输出(过滤原因/包名)

  ### ESLint
  - 新增 eslint.config.mjs(typescript-eslint + react-hooks + react-native 规则集)
  - package.json 新增 lint/lint:fix 脚本,引入 5 个 devDependencies

  ### 文档
  - accessibility-wechat-guide.md — 微信无障碍伪装完整方案
  - modal-keyboard-guide.md — 弹窗键盘避让方案
  - ocr-pipeline-guide.md — OCR 三层层级管线
  - OCR及文本模型测试 / 账单元识别及账户分类设计 / 账户分类模型测试
2026-07-28 20:57:37 +08:00

156 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 账单识别与 Beancount 账户分类:合并 vs 解耦架构对比文档
在双式记账Beancount / DriftLedger离线移动客户端开发中**“原始账单识别Bill Recognition”** 与 **“Beancount 账户分类Account Classification”** 是两个核心处理阶段。
本文档深度对比分析将这两个阶段进行 **合并(单步一体求值)****解耦(双阶段责任链)** 的架构差异,并结合 DriftLedger 源码实现,分别涵盖 **传统规则渠道Rule-based****大模型/AI 渠道LLM/VLM** 的表现。
---
## 目录
1. [架构定义与处理模式](#一-架构定义与处理模式)
2. [传统规则渠道Rule-based Channel对比](#二-传统规则渠道-rule-based-channel-对比)
3. [大模型/AI 渠道AI/LLM Channel对比](#三-大模型ai-渠道-aillm-channel-对比)
4. [多维性能与工程指标全景对比表](#四-多维性能与工程指标全景对比表)
5. [DriftLedger (浮记) 混合架构落地推荐](#五-driftledger-浮记-混合架构落地推荐)
---
## 一、 架构定义与处理模式
在多通道系统架构中,无论采用合并还是解耦,**多通道原始内容采集Ingestion Adapters** 始终是前置的:
- **通道 1拍照/图库 OCR**(获取账单图像或 OCR Markdown 文本)
- **通道 2无障碍服务 UI 节点提取**(解析微信/支付宝支付成功页的 node 文本,参见 [accessibilityParser.ts](file:///C:/Users/fmq/Documents/work/DriftLedger/src/services/automation/accessibilityParser.ts)
- **通道 3短信与系统通知监控**(解析银行/支付软件推送通知字符串)
合并与解耦的核心区别,在于拿到**账单原始内容 (Raw Bill Text)** 之后,**“事实字段识别”** 与 **“Beancount 账户分配”** 是在单次操作中完成,还是拆分为多个阶段:
```text
========================================================================================
【多通道多源输入】
(通道A: 拍照OCR文本 / 通道B: 无障碍UI节点文本 / 通道C: 短信通知文本)
【合并架构 (Merged Mode / 一体化文本求值)】
单次求值 (AI Prompt 或 规则引擎):
输入: 账单原始内容 + 用户 Beancount 动态账户列表
输出: 直接一步得到【Beancount 交易草稿 TransactionDraft】(含时间、金额、商户、资金账户、支出账户)
========================================================================================
========================================================================================
【多通道多源输入】
(通道A: 拍照OCR文本 / 通道B: 无障碍UI节点文本 / 通道C: 短信通知文本)
【解耦架构 (Decoupled Mode / 责任链流水线)】
阶段 1事实识别: 仅识别事实输出无账户关联的【ImportedEvent】(时间、金额、商户、备注)
阶段 2账户分类: 送入 BillPipeline由规则引擎 RuleEngine 或轻量 AI 匹配 Beancount 账户
========================================================================================
```
---
## 二、 传统规则渠道Rule-based Channel对比
在规则匹配渠道下,账户名均来自用户动态配置的规则库 (`Rule[]`),绝非代码硬编码:
### 1. 动态规则合并模式Single-Pass Rule Evaluation / 一体化动态匹配)
- **处理逻辑**
拿到多通道的原始内容后,解析器直接调用用户配置的动态规则库 `Rule[]`。一条规则同时包含了**事实判定条件**与**双向账户分配**
```typescript
// 用户在 APP 中配置的动态规则对象(非代码硬编码)
const rule: Rule = {
id: "rule-101",
counterpartyContains: "星巴克",
sourceAccount: "Assets:Alipay:Balance", // 动态资金来源账户
categoryAccount: "Expenses:Food:Coffee", // 动态分类支出账户
narration: "星巴克咖啡"
};
// 单次求值:一步构造出带有账户的完整 TransactionDraft 草稿
if (matches(rawText, rule)) {
return createDraftDirectly(rawText, rule.sourceAccount, rule.categoryAccount);
}
```
- **特点**
单次求值即产生最终 `TransactionDraft`。如果入口预填了 `sourceAccount` / `categoryAccount`(参考 DriftLedger 代码 [billPipeline.ts:L169-L180](file:///C:/Users/fmq/Documents/work/DriftLedger/src/domain/pipeline/billPipeline.ts#L169-L180)),流水线直接接受该草稿。
### 2. 规则解耦模式Two-Stage Evaluation / 责任链流水线匹配)
- **处理逻辑**
1. **阶段 1 (事实化)**:所有通道(通知、无障碍、短信、账单 CSV统一输出仅包含事实的 `ImportedEvent`(无账户关联)。
2. **阶段 2 (责任链评估)**`BillPipeline` 依次执行:转账识别 ➔ 批次去重 ➔ 历史去重 ➔ 送入 `RuleEngine` 匹配规则库中的账户。
- **特点**
解析器只需关心文本事实提取,账户分配归口给 `BillPipeline``RuleEngine` 统一调度。在分配账户前可先过滤重复事件,避免无效计算。
---
## 三、 大模型/AI 渠道AI/LLM Channel对比
利用大语言模型LLM或多模态视觉模型VLM处理多通道获取的原始内容
### 1. AI 文本级合并模式(单次 LLM 提示词一步直出草稿)
- **处理逻辑**
多通道(拍照 OCR / 无障碍节点文本 / 短信通知)提取到**账单原始内容字符串**后,**在单次 LLM 请求中**将“账单原始内容”与“用户本地 Beancount 候选账户列表”一同作为 Prompt 提交给大模型(如 `glm-4-flash-250414``Qwen2.5-7B-Instruct`)。
- **流程**
```text
[多通道原始内容文本] + [用户动态账户列表] ───(单次 LLM 求值)───> [Beancount TransactionDraft]
```
- **优势**
- **通道统一**:不管是图片 OCR、微信支付成功的节点文本、还是银行扣款短信都使用同一种“文本级合并 Prompt”直接返回填充好 `sourceAccount``categoryAccount` 的 JSON 草稿。
- **响应极快**:纯文本大模型(如 `glm-4-flash-250414`)处理文本合并请求耗时仅 **~2.2 秒**。
- **劣势**
- **Token 开销**:每次请求都需携带用户账户列表。
- **确定性风险**:可能偶发生成不存在的账户名。
### 2. AI 解耦模式(内容识别提取事实 ➔ 独立分类器)
- **处理逻辑**
1. **阶段 1事实识别**:模型仅负责解析多通道原始内容,输出不含账户的 `ImportedEvent`(时间、金额、商户、备注)。
2. **阶段 2账户分类**:优先走本地 `RuleEngine`;若未命中,再调用轻量 LLM耗时 ~2.2 秒)或向量 Embedding 模型(如 `bge-m3`,耗时 **0.3 秒**)在单独的 Prompt / 向量空间中挑选账户。
- **优势**
- **绝对确定性**:已知商户 100% 走本地规则引擎0 延迟、0 错误率)。
- **离线优先 (Offline-first)**:本地识别出事实后,断网状态下本地规则引擎依然能完成账户分类。
---
## 四、 多维性能与工程指标全景对比表
| 评估维度 | **规则合并模式 (单次一体匹配)** | **规则解耦模式 (责任链流水线)** | **AI 文本级合并模式 (单次LLM求值)** | **AI 解耦模式 (双阶段链式)** |
| :--- | :--- | :--- | :--- | :--- |
| **原始内容来源** | 多通道 (OCR/无障碍/短信) | 多通道 (OCR/无障碍/短信) | 多通道 (OCR/无障碍/短信) | 多通道 (OCR/无障碍/短信) |
| **识别与分类点** | 文本解析时同步求值 | 分两阶段:解析事实 ➔ 匹配账户 | **单次 LLM 同时提取事实+账户** | 分两阶段:提取事实 ➔ LLM/向量选账户 |
| **响应延迟 (Latency)** | **< 1ms** | **< 1ms** | **~2.2s** (`glm-4-flash-250414`) | **~4.3s** (OCR + 分类) |
| **API 调用次数** | 0 | 0 | **1 次** | 1 ~ 2 |
| **断网/离线鲁棒性** | 完全支持 | 完全支持 | 不支持 (需在线 LLM) | **半支持** (文本提取后离线规则分类) |
| **准确率与确定性** | **100%** | **100%** | ( 95% Prompt 引导) | **100%** (已知规则优先覆写) |
| **代码可维护性** | 良好 | **极佳** (领域分层极清) | 优秀 (通道无缝复用 Prompt) | **极佳** (管道可随意组装) |
---
## 五、 DriftLedger (浮记) 混合架构落地推荐
结合多通道采集OCR / 无障碍 / 短信通知 DriftLedger 的代码实现 [billPipeline.ts](file:///C:/Users/fmq/Documents/work/DriftLedger/src/domain/pipeline/billPipeline.ts#L169-L180)推荐采取 **多通道输入 AI 文本级合并直出 本地流水线预填覆写”** 的最佳落地架构
```text
【通道 A: 拍照 OCR 文本】 【通道 B: 无障碍 UI 文本】 【通道 C: 短信通知文本】
│ │ │
└────────────────────────────┼────────────────────────────┘
【AI 文本级合并求值 (glm-4-flash-250414)】
单次 LLM 传入多通道文本 + 用户 Beancount 动态账户列表
2.2 秒内一步生成带预填账户的 `ImportedEvent` (含 sourceAccount/categoryAccount)
【领域核心层 / BillPipeline 责任链】
┌────────────────────────────────┴────────────────────────────────┐
▼ ▼
【1: 本地规则覆写 (RuleEngine)】 【2: 多通道去重 (Dedup)】
若匹配到用户定义的 100% 精确 Rule 规则, 自动过滤历史账本已存在的重复交易,
本地规则强行覆写 AI 预测的账户,保障零差错。 避免多次拍照或无障碍重复记账。
```
### 总结:
1. **多通道采集OCR / 无障碍 / 短信)** 是解耦的前置适配层
2. **AI 合并模式** 指的是在获取到账单文本后**用单次 LLM 请求同时完成事实提取与账户选择**2.2 秒极速返回)。
3. **架构落地**多通道文本输入 AI 文本级合并一步预填 本地流水线校验覆写