docs: add fix-double-finalize-and-bindings-api implementation plan
This commit is contained in:
@@ -0,0 +1,610 @@
|
||||
# 原生 AuditCtx 接入重构方案
|
||||
|
||||
## 1. 目标
|
||||
|
||||
基于对 `/home/wren-dev/Porject/leaudit/src` 源码的核对,确认当前 `leaudit` 的正式执行模型应视为:
|
||||
|
||||
- `AuditCtx`
|
||||
- `AuditServices`
|
||||
- `AuditConfig`
|
||||
- `AuditService.audit(ctx)`
|
||||
|
||||
因此,`leaudit-platform` 后续不应继续由平台自己手写主流程编排,而应重构为:
|
||||
|
||||
```text
|
||||
平台层
|
||||
→ Bridge 适配层
|
||||
→ build AuditServices
|
||||
→ build AuditConfig
|
||||
→ build AuditCtx
|
||||
→ call AuditService.audit(ctx)
|
||||
→ persist ctx outputs
|
||||
→ 返回 run / result
|
||||
```
|
||||
|
||||
本文档用于说明:
|
||||
|
||||
- 为什么要重构
|
||||
- 重构后的目标架构
|
||||
- 现有文件怎么迁移
|
||||
- 建议新增哪些文件
|
||||
- 如何分阶段实施,避免一次性推翻现有代码
|
||||
|
||||
---
|
||||
|
||||
## 2. 关键结论
|
||||
|
||||
## 2.1 必须使用原生 CTX
|
||||
|
||||
这一点已经可以下明确结论:
|
||||
|
||||
- 后续应使用 `leaudit.services.audit_ctx.AuditCtx`
|
||||
- 后续应通过 `leaudit.services.audit_service.AuditService.audit(ctx)` 执行主流程
|
||||
- 不建议平台继续手工串接:
|
||||
- OCR
|
||||
- Extract
|
||||
- Phase
|
||||
- Evaluate
|
||||
- Rescue
|
||||
- Persist
|
||||
|
||||
## 2.2 但 Bridge 不能取消
|
||||
|
||||
Bridge 仍然是必须保留的正式边界层。
|
||||
|
||||
Bridge 的职责应改为:
|
||||
|
||||
- 平台对象 -> 原生 `AuditCtx`
|
||||
- 原生 `ctx` -> 平台数据库结果
|
||||
|
||||
也就是说:
|
||||
|
||||
- **不要自己编排**
|
||||
- **但要自己适配**
|
||||
|
||||
---
|
||||
|
||||
## 3. 当前实现与目标实现的差异
|
||||
|
||||
## 3.1 当前实现(过渡态)
|
||||
|
||||
当前 `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py` 的角色,是平台侧自编排器:
|
||||
|
||||
```text
|
||||
file_path + rules_file
|
||||
→ OCR
|
||||
→ Extraction
|
||||
→ Phase detection
|
||||
→ Evaluation
|
||||
→ Save results
|
||||
```
|
||||
|
||||
特点:
|
||||
|
||||
- 直接调用 engine / extraction / evaluation 低层函数
|
||||
- 部分阶段逻辑由平台维护
|
||||
- rescue / finalize 语义未完整对齐原生服务层
|
||||
- 结果写入与运行编排耦合较高
|
||||
|
||||
## 3.2 目标实现(正式态)
|
||||
|
||||
目标应改成:
|
||||
|
||||
```text
|
||||
document + file + rule version
|
||||
→ build AuditServices
|
||||
→ build AuditConfig
|
||||
→ build AuditCtx
|
||||
→ await AuditService.audit(ctx)
|
||||
→ persist final ctx
|
||||
```
|
||||
|
||||
特点:
|
||||
|
||||
- 主流程交给 `leaudit` 原生编排器
|
||||
- Bridge 只负责适配与持久化
|
||||
- 平台不再复制 `leaudit` 的阶段编排语义
|
||||
- 后续升级风险更小
|
||||
|
||||
---
|
||||
|
||||
## 4. 目标架构图
|
||||
|
||||
```text
|
||||
┌────────────────────────────────────────────┐
|
||||
│ 平台层 │
|
||||
│ Controller / Service / ORM / API / DB │
|
||||
│ 文档上传、规则管理、任务触发、结果查询 │
|
||||
└──────────────────┬─────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────────┐
|
||||
│ Bridge 适配层 │
|
||||
│ │
|
||||
│ 1. resolve document file │
|
||||
│ 2. resolve rule version │
|
||||
│ 3. download doc / yaml to local temp │
|
||||
│ 4. build AuditServices / AuditConfig │
|
||||
│ 5. build AuditCtx │
|
||||
│ 6. call AuditService.audit(ctx) │
|
||||
│ 7. persist ctx outputs to leaudit_* │
|
||||
└──────────────────┬─────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────────┐
|
||||
│ leaudit 原生服务层 │
|
||||
│ AuditCtx / AuditServices / AuditService │
|
||||
│ normalization / extraction / evaluation │
|
||||
│ rescue / finalize │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Bridge 重构后的职责边界
|
||||
|
||||
## 5.1 Bridge 负责的事情
|
||||
|
||||
- 从平台数据库找到本次执行的文档与文件版本
|
||||
- 从平台规则表找到当前生效规则版本
|
||||
- 从 OSS 下载文档文件与规则文件到本地临时路径
|
||||
- 构造 `AuditServices`
|
||||
- 构造 `AuditConfig`
|
||||
- 构造原生 `AuditCtx`
|
||||
- 调用 `AuditService.audit(ctx)`
|
||||
- 将最终 `ctx` 中的结果持久化到 `leaudit_*`
|
||||
|
||||
### 5.1.1 当前已落地到代码的链路
|
||||
|
||||
当前项目已经完成第一批骨架接入:
|
||||
|
||||
- 文档文件:
|
||||
- `auditServiceImpl.py` 中从 `LeauditDocumentFile` 解析文件来源
|
||||
- `fileSourceResolver.py` 已支持 `localPath` 和 `ossUrl`
|
||||
- `tasks.py` 执行前统一写入本地临时文档文件
|
||||
- 规则文件:
|
||||
- `auditServiceImpl.py` 创建 `LeauditAuditRun` 时锁定 `ruleVersionId` / `ruleSourceOssUrl`
|
||||
- `ruleVersionResolver.py` 按 `run_id` 解析规则版本来源
|
||||
- `tasks.py` 已支持 `OSS URL -> 本地临时 YAML -> RulesLoader -> NativeRunner`
|
||||
|
||||
因此当前 bridge 的真实职责已经不只是“理论适配层”,而是运行期真正负责把平台侧 DB/OSS 语义转换成 `leaudit` 原生可消费的本地文件输入。
|
||||
|
||||
## 5.2 Bridge 不再负责的事情
|
||||
|
||||
- 不再手工定义 7 个 stage 的顺序
|
||||
- 不再自己负责 phase 判定与 rescue 调度的业务语义
|
||||
- 不再自己维护与原生服务层重复的一套编排逻辑
|
||||
|
||||
## 5.3 平台层不应直接做的事情
|
||||
|
||||
- 不直接构造 `AuditCtx`
|
||||
- 不直接调用 `AuditService.audit(ctx)`
|
||||
- 不直接 import `leaudit.services.*`
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议新增的核心文件
|
||||
|
||||
## 6.1 `audit_ctx_builder.py`
|
||||
|
||||
建议新增:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/audit_ctx_builder.py`
|
||||
|
||||
职责:
|
||||
|
||||
- 把平台运行对象组装成原生 `AuditCtx`
|
||||
|
||||
建议输入:
|
||||
|
||||
- `run_id`
|
||||
- `document_id`
|
||||
- `document_file_id`
|
||||
- `rule_version_id`
|
||||
- `local_file_path`
|
||||
- `rules_file`
|
||||
- `services`
|
||||
- `audit_config`
|
||||
|
||||
建议输出:
|
||||
|
||||
- `AuditCtx`
|
||||
|
||||
建议职责细分:
|
||||
|
||||
- `build_services(...)`
|
||||
- `build_config(...)`
|
||||
- `build_ctx(...)`
|
||||
|
||||
---
|
||||
|
||||
## 6.2 `audit_service_factory.py`
|
||||
|
||||
建议新增:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/audit_service_factory.py`
|
||||
|
||||
职责:
|
||||
|
||||
- 构造原生 `AuditService` 及其依赖服务
|
||||
|
||||
建议内部负责:
|
||||
|
||||
- `DocNormalizationService`
|
||||
- `ExtractionService`
|
||||
- `EvaluationService`
|
||||
- `RescueService`
|
||||
- `AuditServices`
|
||||
- `AuditService`
|
||||
|
||||
目标是让平台不直接感知 `leaudit` 服务装配细节。
|
||||
|
||||
---
|
||||
|
||||
## 6.3 `file_source_resolver.py`
|
||||
|
||||
建议新增:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/file_source_resolver.py`
|
||||
|
||||
职责:
|
||||
|
||||
- 根据 `document_file_id` 找到文件真源
|
||||
- 必要时从 OSS 下载到本地临时路径
|
||||
|
||||
说明:
|
||||
|
||||
当前 `ctx_builder.py` 有一部分类似职责,但建议拆得更明确:
|
||||
|
||||
- 文档文件解析
|
||||
- 规则文件解析
|
||||
- 原生 ctx 组装
|
||||
|
||||
不要混在一个“万能 builder”里。
|
||||
|
||||
---
|
||||
|
||||
## 6.4 `rule_version_resolver.py`
|
||||
|
||||
建议新增:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/rule_version_resolver.py`
|
||||
|
||||
职责:
|
||||
|
||||
- 根据 `document.type_id` / `binding` 找到当前生效规则版本
|
||||
- 从 OSS 下载 `rules.yaml`
|
||||
- 解析为 `RulesFile`
|
||||
|
||||
说明:
|
||||
|
||||
当前 `rules_loader.py` 偏向本地路径加载器;后续建议保留它做“底层 YAML 解析器”,但把“版本解析 + 规则定位”职责上移到 resolver。
|
||||
|
||||
---
|
||||
|
||||
## 7. 现有文件的重构策略
|
||||
|
||||
## 7.1 `pipeline.py`
|
||||
|
||||
文件:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py`
|
||||
|
||||
### 当前问题
|
||||
|
||||
- 现在是平台自编排器
|
||||
- 直接串低层 stage
|
||||
|
||||
### 目标定位
|
||||
|
||||
重构后应退化为“薄包装器”。
|
||||
|
||||
建议最终形态:
|
||||
|
||||
```python
|
||||
ctx = build_audit_ctx(...)
|
||||
ctx = await audit_service.audit(ctx)
|
||||
return ctx
|
||||
```
|
||||
|
||||
也就是说:
|
||||
|
||||
- 保留 `pipeline.py` 文件名可以
|
||||
- 但不再保留其“自定义主编排器”角色
|
||||
|
||||
### 建议处理方式
|
||||
|
||||
- 第一阶段:保留现有 `LauditPipeline`,但新增原生 `AuditCtxPipeline`
|
||||
- 第二阶段:调用方切换到新实现
|
||||
- 第三阶段:删除或降级旧自编排逻辑
|
||||
|
||||
---
|
||||
|
||||
## 7.2 `tasks.py`
|
||||
|
||||
文件:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/tasks.py`
|
||||
|
||||
### 当前问题
|
||||
|
||||
- 现在既负责任务分发,又负责规则路径解析,又直接触发旧 pipeline
|
||||
- 仍依赖 `LEAUDIT_RULES_DIR` 与 `_TYPE_ID_RULES_MAP`
|
||||
|
||||
### 重构目标
|
||||
|
||||
把它变成真正的“任务入口层”:
|
||||
|
||||
- 创建执行上下文
|
||||
- 调 bridge 执行服务
|
||||
- 更新 run 状态
|
||||
|
||||
### 建议改造
|
||||
|
||||
- `dispatch_leaudit_task()` 只做任务分发
|
||||
- `leaudit_process_document()` 只做:
|
||||
- resolve run inputs
|
||||
- call bridge runner
|
||||
- update run status
|
||||
|
||||
不要在这里继续放太多规则解析与 pipeline 内部细节。
|
||||
|
||||
---
|
||||
|
||||
## 7.3 `ctx_builder.py`
|
||||
|
||||
文件:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/ctx_builder.py`
|
||||
|
||||
### 当前问题
|
||||
|
||||
- 当前 `ExecutionContext` 不是原生 `AuditCtx`
|
||||
- 更像平台内部轻量执行输入对象
|
||||
|
||||
### 重构目标
|
||||
|
||||
有两种方案:
|
||||
|
||||
#### 方案 A:保留并改名
|
||||
|
||||
- 保留文件,但改成“平台预上下文 builder”
|
||||
- 只负责收集文档/文件/规则/本地路径
|
||||
|
||||
#### 方案 B:拆分
|
||||
|
||||
推荐拆分成:
|
||||
|
||||
- `file_source_resolver.py`
|
||||
- `rule_version_resolver.py`
|
||||
- `audit_ctx_builder.py`
|
||||
|
||||
我更建议方案 B,更清晰。
|
||||
|
||||
---
|
||||
|
||||
## 7.4 `rules_loader.py`
|
||||
|
||||
文件:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/rules_loader.py`
|
||||
|
||||
### 当前问题
|
||||
|
||||
- 更偏“本地 YAML 加载器”
|
||||
- 还没有真正承担“规则版本解析器”职责
|
||||
|
||||
### 重构目标
|
||||
|
||||
让它只做一件事:
|
||||
|
||||
- 输入本地路径 / YAML 文本
|
||||
- 输出 `RulesFile`
|
||||
|
||||
而以下职责交给 resolver:
|
||||
|
||||
- 查绑定表
|
||||
- 查规则版本
|
||||
- 查 OSS 路径
|
||||
- 下载本地临时文件
|
||||
|
||||
---
|
||||
|
||||
## 7.5 `storage_adapter.py`
|
||||
|
||||
文件:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/storage_adapter.py`
|
||||
|
||||
### 当前问题
|
||||
|
||||
- 结果写入还依赖“按 `document_id` 查最新 run”
|
||||
- 与当前平台自编排写法耦合较深
|
||||
|
||||
### 重构目标
|
||||
|
||||
让它变成“最终 ctx 持久化器”。
|
||||
|
||||
建议接口风格:
|
||||
|
||||
- `persist_run_start(...)`
|
||||
- `persist_ctx_outputs(run_id, ctx, meta)`
|
||||
- `persist_failure(run_id, err)`
|
||||
|
||||
其中 `persist_ctx_outputs()` 从原生 `ctx` 中读取:
|
||||
|
||||
- `normalized_doc`
|
||||
- `extraction`
|
||||
- `phase`
|
||||
- `evaluation`
|
||||
- `fallback_tasks`
|
||||
- `timing`
|
||||
|
||||
统一落表。
|
||||
|
||||
---
|
||||
|
||||
## 8. 目标执行链路
|
||||
|
||||
重构后的理想执行链如下:
|
||||
|
||||
```text
|
||||
AuditServiceImpl.Run()
|
||||
→ 创建 leaudit_audit_runs
|
||||
→ dispatch_leaudit_task(run_id, ...)
|
||||
→ bridge runner
|
||||
→ resolve document file
|
||||
→ resolve rule version
|
||||
→ build AuditServices
|
||||
→ build AuditConfig
|
||||
→ build AuditCtx
|
||||
→ await AuditService.audit(ctx)
|
||||
→ persist ctx outputs
|
||||
→ 返回 run_id
|
||||
```
|
||||
|
||||
这里的关键点是:
|
||||
|
||||
- 平台仍然围绕 run 管理
|
||||
- 引擎仍然围绕 ctx 管理
|
||||
- bridge 负责把两者接起来
|
||||
|
||||
---
|
||||
|
||||
## 9. 推荐实施步骤
|
||||
|
||||
## 阶段 1:并行引入原生 CTX 路线
|
||||
|
||||
目标:
|
||||
|
||||
- 不马上删旧 `pipeline.py`
|
||||
- 先把原生接入链做出来
|
||||
|
||||
建议动作:
|
||||
|
||||
- 新增 `audit_ctx_builder.py`
|
||||
- 新增 `audit_service_factory.py`
|
||||
- 新增一个新的 bridge runner
|
||||
|
||||
例如:
|
||||
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/native_runner.py`
|
||||
|
||||
职责:
|
||||
|
||||
- 一次性跑通原生 CTX 执行
|
||||
|
||||
---
|
||||
|
||||
## 阶段 2:让任务入口切到 native runner
|
||||
|
||||
目标:
|
||||
|
||||
- `tasks.py` 不再调用旧自编排 pipeline
|
||||
- 改成调用原生 ctx 路线
|
||||
|
||||
建议动作:
|
||||
|
||||
- 改 `dispatch_leaudit_task()`
|
||||
- 改 `leaudit_process_document()`
|
||||
- 保留旧 pipeline 作为 fallback 一小段时间
|
||||
|
||||
---
|
||||
|
||||
## 阶段 3:让结果持久化围绕最终 ctx 收口
|
||||
|
||||
目标:
|
||||
|
||||
- `storage_adapter.py` 从“阶段中途写”转成“最终 ctx 聚合写”
|
||||
|
||||
建议动作:
|
||||
|
||||
- 显式传 `run_id`
|
||||
- 从 ctx 中统一提取产物与汇总
|
||||
|
||||
---
|
||||
|
||||
## 阶段 4:删除旧自编排主链
|
||||
|
||||
目标:
|
||||
|
||||
- 彻底避免出现两套主流程语义
|
||||
|
||||
建议动作:
|
||||
|
||||
- 删除旧 `LauditPipeline.run()` 中的核心编排
|
||||
- 或保留文件但只做代理包装
|
||||
|
||||
---
|
||||
|
||||
## 10. 风险与注意事项
|
||||
|
||||
## 10.1 不要一次性重写全部文件
|
||||
|
||||
建议采用“双轨过渡”:
|
||||
|
||||
- 旧 pipeline 先保留
|
||||
- 新 native runner 并行引入
|
||||
- 验证结果一致后再切换
|
||||
|
||||
## 10.2 不要把平台字段直接塞进原生 CTX
|
||||
|
||||
例如:
|
||||
|
||||
- `run_id`
|
||||
- `trigger_user_id`
|
||||
- `biz_document_id`
|
||||
|
||||
这些属于平台字段,不应该污染 `AuditCtx` 本身。
|
||||
|
||||
建议放在:
|
||||
|
||||
- bridge 层本地元数据对象
|
||||
- 或持久化上下文对象
|
||||
|
||||
## 10.3 不要让平台业务代码直接 import `leaudit.services.*`
|
||||
|
||||
这条边界必须守住。
|
||||
|
||||
即使未来 100% 使用原生 `AuditCtx`,也应该只允许 `leaudit_bridge/` 感知这些类型。
|
||||
|
||||
## 10.4 规则与文件都要先落成本地路径
|
||||
|
||||
原生 `AuditCtx` 依旧是文件路径驱动:
|
||||
|
||||
- 文档文件要落地成本地路径
|
||||
- 规则文件也要落地成本地 YAML 路径
|
||||
|
||||
不要试图让 `leaudit` 直接理解 OSS / DB。
|
||||
|
||||
---
|
||||
|
||||
## 11. 与现有文档的关系
|
||||
|
||||
本方案是以下文档的进一步收敛:
|
||||
|
||||
- `docs/规则编辑/yaml规则在线编辑设计.md`
|
||||
- `docs/规则编辑/跑通全流程所需准备项.md`
|
||||
- `docs/规则编辑/开发任务拆解清单.md`
|
||||
- `docs/规则编辑/为什么仍然需要Bridge适配层.md`
|
||||
|
||||
它的核心新增点是:
|
||||
|
||||
- 不再停留在“Bridge 保留 / 自编排废弃”的原则层
|
||||
- 而是把“如何迁移到原生 AuditCtx 模式”具体化
|
||||
|
||||
---
|
||||
|
||||
## 12. 最终结论
|
||||
|
||||
当前项目的 Bridge 应该正式转向下面这条路线:
|
||||
|
||||
- **平台负责 run / OSS / DB / 权限 / API**
|
||||
- **Bridge 负责 AuditCtx 接入适配**
|
||||
- **`leaudit` 原生服务层负责评查执行**
|
||||
|
||||
所以重构的最终方向不是“继续完善旧 pipeline”,而是:
|
||||
|
||||
> **用原生 `AuditCtx + AuditService.audit(ctx)` 替代平台自编排主链,并把 Bridge 重塑为适配层。**
|
||||
|
||||
这是当前项目最稳、最可维护、最符合 `leaudit` 演进方向的接入方案。
|
||||
Reference in New Issue
Block a user