18 KiB
18 KiB
LeAudit Platform — 系统现状总览
最后更新:2026-04-28
一、目标架构
┌─ API ───────────────────────────────────────────────────────────┐
│ AuditController (/audit) RuleController (/rule-sets) │
│ DocumentController (/upload) │
│ POST /run 触发评查 GET / 规则集列表 │
│ POST /upload 上传建档/可选自动评查 │
│ GET /run/:id 查询状态 GET /{type}/versions 版本列表 │
│ GET /result/:id 查询结果 GET /versions/:id/content 正文│
│ POST /{type}/validate 校验 │
│ POST /{type}/versions 创建 │
│ POST /{type}/publish 发布 │
│ POST /{type}/rollback 回滚 │
│ GET /bindings 绑定列表 │
│ POST /{type}/bindings 创建绑定│
│ PUT /bindings/{id} 更新绑定│
│ DELETE /bindings/{id} 删除绑定│
├─ Service ───────────────────────────────────────────────────────┤
│ AuditServiceImpl RuleServiceImpl + OssServiceImpl│
├─ Bridge ────────────────────────────────────────────────────────┤
│ FileSourceResolver RuleVersionResolver RulesLoader │
│ AuditCtxBuilder AuditServiceFactory NativeRunner │
│ StorageAdapter ResultAdapter RuleValidator │
│ tasks.py (dispatch_leaudit_task) │
├─ leaudit (不改) ────────────────────────────────────────────────│
│ AuditCtx → AuditService.audit() → OCR/Normalize/Extract/ │
│ Evaluate/Rescue → 填充 ctx.normalized_doc/extraction/ │
│ evaluation/fallback_tasks/timing/extraction_errors │
├─ 存储 ──────────────────────────────────────────────────────────┤
│ OSS (MinIO) PostgreSQL │
│ bdocs/{region}/{type}/{doc_id}/ leaudit_documents │
│ rules/{rule_type}/{version_no}/ leaudit_document_files │
│ artifacts/{region}/{run_id}/ leaudit_audit_runs │
│ leaudit_rule_sets │
│ leaudit_rule_versions │
│ leaudit_rule_type_bindings │
│ leaudit_rule_results │
│ leaudit_field_results │
│ leaudit_run_metrics │
│ leaudit_run_errors │
│ leaudit_rescue_outcomes │
│ leaudit_artifacts │
└─────────────────────────────────────────────────────────────────┘
二、两条核心数据流
流 A:规则生命周期
编辑 YAML
→ POST /rule-sets/{type}/validate → RuleValidator (YAML语法 + DSL语义)
→ POST /rule-sets/{type}/versions → 上传 OSS + INSERT leaudit_rule_versions
→ POST /rule-sets/{type}/publish → UPDATE leaudit_rule_sets.current_version_id
→ POST /rule-sets/{type}/bindings → INSERT leaudit_rule_type_bindings
→ 新 run 自动绑定新版本到对应文档类型
流 B:评查执行
POST /audit/run { documentId }
→ AuditServiceImpl.Run()
1. 查 leaudit_documents + leaudit_document_files
2. 查 leaudit_rule_type_bindings → rule_set_id + rule_version_id
3. INSERT leaudit_audit_runs (rule_version_id, rule_source_oss_url, sha256)
4. FileSourceResolver → 下载文档 bytes
5. dispatch_leaudit_task()
┌─ RuleVersionResolver → OSS 下载规则 YAML → SHA256 校验
├─ RulesLoader → RulesFile
├─ NativeRunner.run() → AuditCtx → AuditService.audit()
└─ NativeRunner.persist_result()
├─ save_ocr_result() → leaudit_artifacts
├─ save_extraction_result() → leaudit_field_results
├─ save_evaluation_results() → leaudit_rule_results + 分数
├─ save_run_errors() → leaudit_run_errors
├─ save_rescue_outcomes() → leaudit_rescue_outcomes
├─ save_run_metrics() → leaudit_run_metrics
└─ finalize_run() → 终态 (result_status/finished_at)
三、模块完成度
M1:OSS 基础设施 — 100%
| 文件 | 状态 | 说明 |
|---|---|---|
fastapi_common/fastapi_common_storage/oss_client.py |
已完成 | 上传/下载/Presign/ObjectExists |
fastapi_common/fastapi_common_storage/oss_path_utils.py |
已完成 | BuildBusinessDocKey/ArtifactKey/RuleYamlKey |
fastapi_admin/config/_settings.py |
已完成 | OSS_ENDPOINT/ACCESS_KEY/SECRET_KEY/BUCKET/REGION/USE_SSL/PRESIGN_EXPIRE |
fastapi_admin/config/__init__.pyi |
已完成 | 类型声明 |
M2:规则管理后端 — 100%
| 文件 | 状态 | 说明 |
|---|---|---|
controllers/ruleController.py |
已完成 | 11 个端点(含绑定管理) |
services/ruleService.py |
已完成 | IRuleService 接口 |
services/impl/ruleServiceImpl.py |
已完成 | 规则 CRUD + 绑定 CRUD |
leaudit_bridge/ruleValidator.py |
已完成 | YAML 语法 + DSL 语义校验 |
domian/Dto/ruleVersionCreateDto.py |
已完成 | 创建版本 DTO |
domian/Dto/ruleValidateDto.py |
已完成 | 校验 DTO |
domian/Dto/rulePublishDto.py |
已完成 | 发布/回滚 DTO |
domian/Dto/ruleBindingDto.py |
已完成 | 绑定 DTO |
domian/vo/ruleVo.py |
已完成 | RuleSetVO/VersionVO/ContentVO/ValidationVO/BindingVO |
M3:执行链与持久化 — ~95%
| 文件 | 状态 | 说明 |
|---|---|---|
leaudit_bridge/auditCtxBuilder.py |
已完成 | 构建原生 AuditCtx |
leaudit_bridge/auditServiceFactory.py |
已完成 | 创建 AuditService |
leaudit_bridge/nativeRunner.py |
已完成 | 原生执行入口 + persist_result |
leaudit_bridge/fileSourceResolver.py |
已完成 | 文档来源解析(接 OSS) |
leaudit_bridge/ruleVersionResolver.py |
已完成 | 规则版本解析(含 SHA256) |
leaudit_bridge/storage_adapter.py |
已完成 | 全部持久化方法(已修双重 finalize) |
leaudit_bridge/tasks.py |
已完成 | 任务入口 + 失败处理 |
leaudit_bridge/pipeline.py |
待退役 | 旧管线(已被 nativeRunner 替代) |
leaudit_bridge/client_factory.py |
90% | OCR/LLM/VLM 客户端工厂 |
M4:全流程联调 — ~25%
| 项目 | 状态 |
|---|---|
| 上传入口梳理 | 已完成 |
| 上传后自动触发评查 | 已完成最小链路(POST /upload + autoRun) |
| 结果查询展示 | 已补运行/规则/字段/errors/rescue/metrics/artifacts 查询 |
| 联调样例准备 | 待做 |
| E2E 验证 | 待做 |
四、持久化执行顺序与终态
persist_result() 严格按以下顺序执行,finalize_run 在最后是唯一的终态写入者:
save_ocr_result()
save_extraction_result()
save_evaluation_results() ← 只写分数/计数,不写 finished_at
save_run_errors()
save_rescue_outcomes()
save_run_metrics()
finalize_run() ← 唯一写 result_status / finished_at / rescue_applied / phase
终态来源(直接从 AuditCtx 读取,不另存平行状态):
| 平台表 | 来源 |
|---|---|
leaudit_run_metrics |
ctx.timing |
leaudit_run_errors |
ctx.extraction_errors + ctx.extraction.all_errors |
leaudit_rescue_outcomes |
ctx.fallback_tasks |
leaudit_audit_runs.result_status |
综合 ctx.fallback_tasks + ctx.evaluation 推导 |
leaudit_audit_runs.finished_at |
finalize_run 写入 now() |
leaudit_audit_runs.rescue_applied |
bool(ctx.fallback_tasks) |
四点五、最新补充:上传建档入口
当前仓库已补最小上传入口:
POST /upload (multipart/form-data)
file
typeId / typeCode
bizDocumentId?
region=default
fileRole=primary
createdBy?
autoRun=false
执行链:
Upload
-> DocumentServiceImpl.Upload()
-> upsert leaudit_documents
-> 旧 active 文件失效
-> 上传原始文件到 OSS:
bdocs/{region}/{type_code}/{document_id}/v{n}/{file_role}.{ext}
-> INSERT leaudit_document_files
-> autoRun=true 时直接调用 AuditServiceImpl.Run()
四点六、最新补充:结果查询视图
当前 GetRunStatus() / GetResult() 已不再只返回 run 主表摘要。
GetRunStatus()当前已返回:documentFileIdresultStatusruleSetId/ruleVersionId/ruleTypeIdrescueAppliedskippedCount
GetResult()当前已可聚合查询:leaudit_rule_resultsleaudit_field_resultsleaudit_run_errorsleaudit_rescue_outcomesleaudit_run_metricsleaudit_artifacts
四点七、关键关系图:DocumentType -> Binding -> RuleSet -> RuleVersion
这一段是当前规则执行链里最关键的一层路由关系。
很多时候容易把这四张表混在一起,但它们职责其实完全不同:
leaudit_document_types:定义“系统里有哪些文档类型”leaudit_rule_type_bindings:定义“某个文档类型该用哪套规则集”leaudit_rule_sets:定义“某类规则集合本身”leaudit_rule_versions:定义“某套规则的具体版本快照”
关系图
┌────────────────────────────┐
│ leaudit_document_types │
│----------------------------│
│ id │
│ code │ <- 文档类型编码,如 contract.entrust
│ name │
│ extraction_mode │
│ is_enabled │
└──────────────┬─────────────┘
│ 1:N
│
▼
┌────────────────────────────┐
│ leaudit_rule_type_bindings │
│----------------------------│
│ id │
│ doc_type_id │ -> leaudit_document_types.id
│ doc_type_code │ -> 冗余编码,便于快速排查
│ rule_set_id │ -> leaudit_rule_sets.id
│ binding_mode │ -> explicit / wildcard / fallback
│ priority │ -> 多条命中时按优先级选
│ is_active │
│ region │ -> default / mz / yf / ...
└──────────────┬─────────────┘
│ N:1
│
▼
┌────────────────────────────┐
│ leaudit_rule_sets │
│----------------------------│
│ id │
│ rule_type │ <- 与 DSL metadata.type_id 对齐
│ rule_name │
│ current_version_id │ -> 当前生效版本
│ status │
└──────────────┬─────────────┘
│ 1:N
│
▼
┌────────────────────────────┐
│ leaudit_rule_versions │
│----------------------------│
│ id │
│ rule_set_id │ -> leaudit_rule_sets.id
│ version_no │
│ status │
│ oss_url │ -> rules/.../rules.yaml
│ file_sha256 │
│ metadata_type_id │
│ published_at │
└────────────────────────────┘
执行时怎么走
真正运行评查时,不是直接“拿一个 rule_type 去找 YAML”,而是按下面这条链走:
leaudit_documents.type_id
-> leaudit_document_types.id
-> leaudit_rule_type_bindings.doc_type_id
-> leaudit_rule_type_bindings.rule_set_id
-> leaudit_rule_sets.current_version_id
-> leaudit_rule_versions.id
-> leaudit_rule_versions.oss_url
-> 下载对应 rules.yaml
-> NativeRunner / AuditService.audit(ctx)
每张表到底解决什么问题
1. leaudit_document_types
它解决的是:
“这份文档属于什么类型?”
例如:
id = 2
code = contract.entrust
name = 通用委托合同
那一条 leaudit_documents 记录里如果:
type_id = 2
就表示这份文档被平台认定为“通用委托合同”。
它本质上是平台的“文档分类字典表”。
2. leaudit_rule_type_bindings
它解决的是:
“这种文档类型,应该使用哪套规则集?”
例如:
doc_type_id = 2
rule_set_id = 22
region = default
binding_mode = explicit
priority = 100
意思就是:
- 文档类型
2(通用委托合同) - 在
default区域 - 显式绑定到规则集
22
这张表本质上是“规则路由表”。
它不能省略,因为后续扩展会依赖它支持:
- 同一种文档类型在不同地区走不同规则
- 同一种文档类型绑定多套规则并通过优先级决策
- fallback / wildcard 兜底规则
3. leaudit_rule_sets
它解决的是:
“系统里存在什么规则集合?”
例如:
id = 22
rule_type = contract.entrust
rule_name = 通用委托合同
current_version_id = 2
这表示:
- 系统里有一套“通用委托合同”规则集
- 当前生效版本是
2
注意:
rule_set表示“规则集合”的稳定身份- 它不是某个具体 YAML 版本文件
4. leaudit_rule_versions
它解决的是:
“这套规则当前/历史具体长什么样?”
例如:
id = 2
rule_set_id = 22
version_no = 2.0
oss_url = rules/contract.entrust/2.0/rules.yaml
status = published
这表示:
- 规则集
22 - 的
2.0版本 - 对应 OSS 上某个
rules.yaml
这层是规则版本治理的核心,支持:
- 发布
- 回滚
- 历史追溯
- 运行时精确复盘
为什么一定要拆成四层
如果不拆,后面会遇到很多问题:
- 文档类型和规则类型耦合死,无法独立演进
- 没法优雅支持一类文档多套规则
- 没法支持地区差异
- 没法做发布 / 回滚 / 历史 run 溯源
拆成四层以后,结构会更稳定:
document_type负责“分类”binding负责“路由”rule_set负责“规则身份”rule_version负责“规则版本快照”
当前初始化策略
基于当前数据库里已有的 leaudit_rule_sets,当前最合理的初始化策略是:
rule_set.rule_type -> document_type.code
rule_set.rule_name -> document_type.name
document_type.id -> binding.doc_type_id
rule_set.id -> binding.rule_set_id
rule_set.current_version_id -> 当前执行版本
也就是说,先用现有 rule_set 反向补齐:
leaudit_document_typesleaudit_rule_type_bindings
这是当前最稳、也最方便后续扩展的做法。
五、数据库表关系
leaudit_document_types
└── leaudit_rule_type_bindings (doc_type_id → rule_set_id)
└── leaudit_rule_sets (current_version_id)
└── leaudit_rule_versions (oss_url, sha256)
└── leaudit_audit_runs (rule_version_id, rule_source_oss_url)
├── leaudit_rule_results
├── leaudit_field_results
├── leaudit_run_metrics
├── leaudit_run_errors
├── leaudit_rescue_outcomes
└── leaudit_artifacts
六、关键设计原则
- leaudit 核心不改 — 所有定制在 bridge 层,leaudit 保持纯 Python 包
- 只读 AuditCtx — 执行完只从 ctx 上读取,不自己模拟 stage
- 规则版本溯源 — 每个 run 绑定具体
rule_version_id,老 run 不受新发布影响 - OSS 真源 + DB 索引 — YAML 正文存 OSS,元数据索引存 PostgreSQL
- 终态单点写入 —
finalize_run是 run 主表终态的唯一写入者 - 独立 session 提交 — 每个
save_*独立会话,按"先子表后主表"顺序保证最终一致性
七、已知待补项
| 缺口 | 优先级 |
|---|---|
run_metrics.llm_call_count / vlm_call_count 仍为空 |
P1(可从 RescueTask 汇总) |
ctx.timing 缺 normalize/rescue 独立 key |
P2(等 leaudit 原生补) |
| 文档状态更新逻辑分散在两处 | P1(应收敛到 StorageAdapter) |
| Celery 异步化 | P2(当前同步可跑通,生产需异步) |
_TYPE_ID_RULES_MAP 硬编码兜底 |
P2(等 bindings 全覆盖后移除) |
| M4 E2E 联调 | P0(下个里程碑) |