feat: wire native leaudit upload flow

This commit is contained in:
wren
2026-04-28 16:53:16 +08:00
parent c776af598a
commit e738398eb6
26 changed files with 7364 additions and 5778 deletions
+288 -4
View File
@@ -7,7 +7,9 @@
```
┌─ 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 校验 │
@@ -121,13 +123,13 @@ POST /audit/run { documentId }
| `leaudit_bridge/pipeline.py` | 待退役 | 旧管线(已被 nativeRunner 替代) |
| `leaudit_bridge/client_factory.py` | 90% | OCR/LLM/VLM 客户端工厂 |
### M4:全流程联调 — 0%
### M4:全流程联调 — ~25%
| 项目 | 状态 |
|---|---|
| 上传入口梳理 | 待做 |
| 上传后自动触发评查 | 待做 |
| 结果查询展示 | 待做 |
| 上传入口梳理 | 已完成 |
| 上传后自动触发评查 | 已完成最小链路(`POST /upload` + `autoRun` |
| 结果查询展示 | 已补运行/规则/字段/errors/rescue/metrics/artifacts 查询 |
| 联调样例准备 | 待做 |
| E2E 验证 | 待做 |
@@ -156,6 +158,288 @@ finalize_run() ← 唯一写 result_status / finished_at / rescue_
| `leaudit_audit_runs.finished_at` | `finalize_run` 写入 now() |
| `leaudit_audit_runs.rescue_applied` | `bool(ctx.fallback_tasks)` |
## 四点五、最新补充:上传建档入口
当前仓库已补最小上传入口:
```text
POST /upload (multipart/form-data)
file
typeId / typeCode
bizDocumentId?
region=default
fileRole=primary
createdBy?
autoRun=false
```
执行链:
```text
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()` 当前已返回:
- `documentFileId`
- `resultStatus`
- `ruleSetId` / `ruleVersionId` / `ruleTypeId`
- `rescueApplied`
- `skippedCount`
- `GetResult()` 当前已可聚合查询:
- `leaudit_rule_results`
- `leaudit_field_results`
- `leaudit_run_errors`
- `leaudit_rescue_outcomes`
- `leaudit_run_metrics`
- `leaudit_artifacts`
## 四点七、关键关系图:DocumentType -> Binding -> RuleSet -> RuleVersion
这一段是当前规则执行链里最关键的一层路由关系。
很多时候容易把这四张表混在一起,但它们职责其实完全不同:
- `leaudit_document_types`:定义“系统里有哪些文档类型”
- `leaudit_rule_type_bindings`:定义“某个文档类型该用哪套规则集”
- `leaudit_rule_sets`:定义“某类规则集合本身”
- `leaudit_rule_versions`:定义“某套规则的具体版本快照”
### 关系图
```text
┌────────────────────────────┐
│ 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”,而是按下面这条链走:
```text
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`
它解决的是:
```text
“这份文档属于什么类型?”
```
例如:
```text
id = 2
code = contract.entrust
name = 通用委托合同
```
那一条 `leaudit_documents` 记录里如果:
```text
type_id = 2
```
就表示这份文档被平台认定为“通用委托合同”。
它本质上是平台的“文档分类字典表”。
#### 2. `leaudit_rule_type_bindings`
它解决的是:
```text
“这种文档类型,应该使用哪套规则集?”
```
例如:
```text
doc_type_id = 2
rule_set_id = 22
region = default
binding_mode = explicit
priority = 100
```
意思就是:
- 文档类型 `2`(通用委托合同)
-`default` 区域
- 显式绑定到规则集 `22`
这张表本质上是“规则路由表”。
它不能省略,因为后续扩展会依赖它支持:
- 同一种文档类型在不同地区走不同规则
- 同一种文档类型绑定多套规则并通过优先级决策
- fallback / wildcard 兜底规则
#### 3. `leaudit_rule_sets`
它解决的是:
```text
“系统里存在什么规则集合?”
```
例如:
```text
id = 22
rule_type = contract.entrust
rule_name = 通用委托合同
current_version_id = 2
```
这表示:
- 系统里有一套“通用委托合同”规则集
- 当前生效版本是 `2`
注意:
- `rule_set` 表示“规则集合”的稳定身份
- 它不是某个具体 YAML 版本文件
#### 4. `leaudit_rule_versions`
它解决的是:
```text
“这套规则当前/历史具体长什么样?”
```
例如:
```text
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`,当前最合理的初始化策略是:
```text
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_types`
- `leaudit_rule_type_bindings`
这是当前最稳、也最方便后续扩展的做法。
## 五、数据库表关系
```