Files
leaudit-platform-backend/docs/规则编辑/原生AuditCtx接入重构方案.md
T

15 KiB
Raw Blame History

原生 AuditCtx 接入重构方案

1. 目标

基于对 /home/wren-dev/Porject/leaudit/src 源码的核对,确认当前 leaudit 的正式执行模型应视为:

  • AuditCtx
  • AuditServices
  • AuditConfig
  • AuditService.audit(ctx)

因此,leaudit-platform 后续不应继续由平台自己手写主流程编排,而应重构为:

平台层
  → 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 的角色,是平台侧自编排器:

file_path + rules_file
  → OCR
  → Extraction
  → Phase detection
  → Evaluation
  → Save results

特点:

  • 直接调用 engine / extraction / evaluation 低层函数
  • 部分阶段逻辑由平台维护
  • rescue / finalize 语义未完整对齐原生服务层
  • 结果写入与运行编排耦合较高

3.2 目标实现(正式态)

目标应改成:

document + file + rule version
  → build AuditServices
  → build AuditConfig
  → build AuditCtx
  → await AuditService.audit(ctx)
  → persist final ctx

特点:

  • 主流程交给 leaudit 原生编排器
  • Bridge 只负责适配与持久化
  • 平台不再复制 leaudit 的阶段编排语义
  • 后续升级风险更小

4. 目标架构图

┌────────────────────────────────────────────┐
│                平台层                      │
│ 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 已支持 localPathossUrl
    • tasks.py 执行前统一写入本地临时文档文件
  • 规则文件:
    • auditServiceImpl.py 创建 LeauditAuditRun 时锁定 ruleVersionId / ruleSourceOssUrl
    • ruleVersionResolver.pyrun_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

目标定位

重构后应退化为“薄包装器”。

建议最终形态:

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. 目标执行链路

重构后的理想执行链如下:

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。


10.5 为什么仍然需要 Bridge 适配层

即使当前方向已经明确为:

  • 使用原生 AuditCtx
  • 使用原生 AuditService.audit(ctx)
  • 不再由平台自己手写 7 阶段主流程编排

也仍然必须保留 Bridge,原因是:

  1. 平台世界和引擎世界不是同一套对象
    • 平台关心:document_idrule_set_idrule_version_idoss_urlrun_id
    • 引擎关心:file_pathRulesFileAuditServicesAuditConfigAuditCtx
  2. 平台层还要处理 OSS 下载、run 状态、结果落库、前端查询
  3. 如果 Controller / Service 直接 import leaudit.services.*,边界会失守,后续升级会把改动扩散到整个平台

因此正确结构不是:

平台层 -> 直接调用 leaudit AuditCtx / AuditService

而是:

平台层 -> Bridge 适配层 -> leaudit AuditCtx / AuditService

Bridge 的固定职责应保持为:

  • 输入适配:文档真源、规则版本、OSS 下载、本地临时路径
  • 运行装配:AuditServicesAuditConfigAuditCtx
  • 输出适配:把 ctx 结果写回 leaudit_*
  • 边界保护:只有 leaudit_bridge/ 感知原生 leaudit 类型

所以这次重构真正要取消的,是“平台自己编排评查主流程”,不是 Bridge 本身。


11. 与现有文档的关系

本方案是以下文档的进一步收敛:

  • docs/规则编辑/统一OSS与规则管理实施计划.md

它的核心新增点是:

  • 不再停留在“Bridge 保留 / 自编排废弃”的原则层
  • 而是把“如何迁移到原生 AuditCtx 模式”具体化

12. 最终结论

当前项目的 Bridge 应该正式转向下面这条路线:

  • 平台负责 run / OSS / DB / 权限 / API
  • Bridge 负责 AuditCtx 接入适配
  • leaudit 原生服务层负责评查执行

所以重构的最终方向不是“继续完善旧 pipeline”,而是:

用原生 AuditCtx + AuditService.audit(ctx) 替代平台自编排主链,并把 Bridge 重塑为适配层。

这是当前项目最稳、最可维护、最符合 leaudit 演进方向的接入方案。