docs: reorganize backend project documentation
This commit is contained in:
@@ -2,6 +2,15 @@
|
||||
|
||||
本目录包含 `leaudit-platform` 项目的核心架构设计文档。
|
||||
|
||||
## 阅读顺序
|
||||
|
||||
1. `docs/HANDOFF.md`
|
||||
2. `document_schema_design.md`
|
||||
3. `dsl_rule_schema_design.md`
|
||||
4. `bridge_directory_design.md`
|
||||
5. `processing_logic.md`
|
||||
6. `docs/规则编辑/README.md`
|
||||
|
||||
## 文档索引
|
||||
|
||||
| 文档 | 内容 | 状态 |
|
||||
@@ -12,6 +21,30 @@
|
||||
| [bridge_directory_design.md](bridge_directory_design.md) | Bridge 桥接层目录与职责设计 | ✅ 已落地 |
|
||||
| [infrastructure_redesign.md](infrastructure_redesign.md) | 基础设施重设计 — OSS/队列/缓存/区域隔离 | 📋 设计蓝图 |
|
||||
|
||||
## 当前运行参数口径
|
||||
|
||||
- 并发与重试参数不再单独保留为独立说明文档
|
||||
- 当前约定统一如下:
|
||||
- 重试参数使用 `*_RETRY_MAX_ATTEMPTS`
|
||||
- 退避参数使用 `*_RETRY_BACKOFF_BASE_SECONDS`
|
||||
- 统一按指数退避计算等待时间
|
||||
- 当前主要链路包括:
|
||||
- LLM
|
||||
- VLM
|
||||
- OCR
|
||||
- signature probe
|
||||
- 相关代码位置:
|
||||
- `fastapi_admin/config/_settings.py`
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/client_factory.py`
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/resilient_clients.py`
|
||||
- `fastapi_modules/fastapi_leaudit/leaudit_bridge/ocr_bridge.py`
|
||||
|
||||
## 当前边界
|
||||
|
||||
- 当前“系统现状、已完成事项、剩余阻塞”统一看 `docs/HANDOFF.md`
|
||||
- 本目录只保留相对稳定的后端架构、表结构、处理链路设计
|
||||
- 原 `SYSTEM_OVERVIEW.md` 的阶段性现状内容已收口到 `docs/HANDOFF.md` 与本文件
|
||||
|
||||
## 快览
|
||||
|
||||
```
|
||||
|
||||
@@ -1,497 +0,0 @@
|
||||
# LeAudit Platform — 系统现状总览
|
||||
|
||||
> 最后更新:2026-04-28
|
||||
|
||||
## 一、目标架构
|
||||
|
||||
补充文档:
|
||||
|
||||
- 并发与重试参数:`docs/leaudit/并发与重试参数说明.md`
|
||||
|
||||
```
|
||||
┌─ 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)` |
|
||||
|
||||
## 四点五、最新补充:上传建档入口
|
||||
|
||||
当前仓库已补最小上传入口:
|
||||
|
||||
```text
|
||||
POST /upload (multipart/form-data)
|
||||
file
|
||||
typeId / typeCode
|
||||
region=default
|
||||
fileRole=primary
|
||||
createdBy?
|
||||
autoRun=false
|
||||
speed=normal|urgent
|
||||
```
|
||||
|
||||
执行链:
|
||||
|
||||
```text
|
||||
Upload
|
||||
-> DocumentServiceImpl.Upload()
|
||||
-> create leaudit_documents
|
||||
-> 旧 active 文件失效
|
||||
-> 上传原始文件到 OSS:
|
||||
bdocs/{region}/{type_code}/{document_id}/v{n}/{file_role}.{ext}
|
||||
-> INSERT leaudit_document_files
|
||||
-> autoRun=true 时直接调用 AuditServiceImpl.Run()
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `leaudit_documents` 现阶段是平台内部文档主表,不再依赖旧系统 `documents.id`
|
||||
- 每次前端上传都会新建一条 `leaudit_documents`
|
||||
- `speed`
|
||||
- `normal` -> `leaudit.normal`
|
||||
- `urgent` -> `leaudit.urgent`
|
||||
|
||||
## 四点六、最新补充:结果查询视图
|
||||
|
||||
当前 `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`
|
||||
|
||||
建议联调方式:
|
||||
|
||||
- 上传后从 `run.runId` 轮询 `GET /audit/run/{runId}`
|
||||
- 完成后调用 `GET /audit/result/{runId}`
|
||||
- worker 日志里会明确打印:
|
||||
- 已投递到哪个队列
|
||||
- worker 实际消费的是 `urgent` 还是 `normal`
|
||||
|
||||
## 四点七、关键关系图: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`
|
||||
|
||||
这是当前最稳、也最方便后续扩展的做法。
|
||||
|
||||
## 五、数据库表关系
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
## 六、关键设计原则
|
||||
|
||||
1. **leaudit 核心不改** — 所有定制在 bridge 层,leaudit 保持纯 Python 包
|
||||
2. **只读 AuditCtx** — 执行完只从 ctx 上读取,不自己模拟 stage
|
||||
3. **规则版本溯源** — 每个 run 绑定具体 `rule_version_id`,老 run 不受新发布影响
|
||||
4. **OSS 真源 + DB 索引** — YAML 正文存 OSS,元数据索引存 PostgreSQL
|
||||
5. **终态单点写入** — `finalize_run` 是 run 主表终态的唯一写入者
|
||||
6. **独立 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(下个里程碑) |
|
||||
@@ -1,149 +0,0 @@
|
||||
# LeAudit 并发与重试参数说明
|
||||
|
||||
这份文档记录当前 `leaudit-platform` 已经落地的并发与重试参数,避免后面再忘。
|
||||
|
||||
---
|
||||
|
||||
## 1. 为什么没有用 `RETRY_BACKOFF_SECONDS = [1, 2, 4]`
|
||||
|
||||
这次我没有把退避时间设计成数组,而是改成了:
|
||||
|
||||
- `*_RETRY_MAX_ATTEMPTS`
|
||||
- `*_RETRY_BACKOFF_BASE_SECONDS`
|
||||
|
||||
原因很简单:
|
||||
|
||||
- 配置更短,更容易看懂
|
||||
- 不用每次都手写 `[1, 2, 4]`
|
||||
- 代码统一按“指数退避”算等待时间
|
||||
|
||||
计算方式:
|
||||
|
||||
```text
|
||||
第 1 次重试等待 = base
|
||||
第 2 次重试等待 = base * 2
|
||||
第 3 次重试等待 = base * 4
|
||||
...
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```toml
|
||||
LLM_RETRY_MAX_ATTEMPTS = 3
|
||||
LLM_RETRY_BACKOFF_BASE_SECONDS = 1
|
||||
```
|
||||
|
||||
表示:
|
||||
|
||||
- 第 1 次请求失败后,等 `1s`
|
||||
- 第 2 次再失败后,等 `2s`
|
||||
- 总共最多尝试 `3` 次
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前已正式化的参数
|
||||
|
||||
当前 `app.toml` 中已启用:
|
||||
|
||||
```toml
|
||||
[LEAUDIT]
|
||||
LLM_MAX_CONCURRENCY = 5
|
||||
VLM_MAX_CONCURRENCY = 3
|
||||
|
||||
LLM_REQUEST_TIMEOUT = 120
|
||||
LLM_RETRY_MAX_ATTEMPTS = 3
|
||||
LLM_RETRY_BACKOFF_BASE_SECONDS = 1
|
||||
|
||||
VLM_REQUEST_TIMEOUT = 45
|
||||
VLM_RETRY_MAX_ATTEMPTS = 2
|
||||
VLM_RETRY_BACKOFF_BASE_SECONDS = 1
|
||||
|
||||
OCR_VLM_CONCURRENCY = 32
|
||||
OCR_RETRY_MAX_ATTEMPTS = 3
|
||||
OCR_RETRY_BACKOFF_BASE_SECONDS = 1
|
||||
|
||||
SIGNATURE_PROBE_CONCURRENCY = 2
|
||||
SIGNATURE_PROBE_TIMEOUT = 20
|
||||
SIGNATURE_PROBE_RETRY_MAX_ATTEMPTS = 2
|
||||
SIGNATURE_PROBE_RETRY_BACKOFF_BASE_SECONDS = 0.5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 各链路当前策略
|
||||
|
||||
### 3.1 LLM
|
||||
|
||||
- 客户端:`ResilientOpenAICompatibleClient`
|
||||
- 超时:`LLM_REQUEST_TIMEOUT`
|
||||
- 最大尝试次数:`LLM_RETRY_MAX_ATTEMPTS`
|
||||
- 退避基数:`LLM_RETRY_BACKOFF_BASE_SECONDS`
|
||||
- 重试条件:
|
||||
- 超时
|
||||
- 连接错误
|
||||
- `5xx`
|
||||
- `408`
|
||||
- `429`
|
||||
|
||||
### 3.2 VLM
|
||||
|
||||
- 客户端:`ResilientQwenVLMClient`
|
||||
- 超时:`VLM_REQUEST_TIMEOUT`
|
||||
- 最大尝试次数:`VLM_RETRY_MAX_ATTEMPTS`
|
||||
- 退避基数:`VLM_RETRY_BACKOFF_BASE_SECONDS`
|
||||
- 重试条件:
|
||||
- 超时
|
||||
- 连接错误
|
||||
- `5xx`
|
||||
- `408`
|
||||
- `429`
|
||||
|
||||
### 3.3 OCR
|
||||
|
||||
- 客户端:`ResilientChandraOCRClient`
|
||||
- OCR HTTP 超时:沿用 `[OCR].TIMEOUT`
|
||||
- 最大尝试次数:`OCR_RETRY_MAX_ATTEMPTS`
|
||||
- 退避基数:`OCR_RETRY_BACKOFF_BASE_SECONDS`
|
||||
- 重试条件:
|
||||
- 超时
|
||||
- 连接错误
|
||||
- `5xx`
|
||||
- `408`
|
||||
- `429`
|
||||
|
||||
### 3.4 Signature Probe
|
||||
|
||||
这是 DOCX 签名候选补识别,不是主 OCR。
|
||||
|
||||
- 并发:`SIGNATURE_PROBE_CONCURRENCY`
|
||||
- 单次超时:`SIGNATURE_PROBE_TIMEOUT`
|
||||
- 最大尝试次数:`SIGNATURE_PROBE_RETRY_MAX_ATTEMPTS`
|
||||
- 退避基数:`SIGNATURE_PROBE_RETRY_BACKOFF_BASE_SECONDS`
|
||||
- 第 1 次失败后,会用 fresh VLM client 再试
|
||||
|
||||
---
|
||||
|
||||
## 4. 为什么把 signature probe 调小
|
||||
|
||||
之前这里容易长时间卡住,根因是:
|
||||
|
||||
- 它是补探测
|
||||
- 但单次超时太长
|
||||
- 且失败后还会再试一次
|
||||
|
||||
所以现在把它收成:
|
||||
|
||||
- `SIGNATURE_PROBE_CONCURRENCY = 2`
|
||||
- `SIGNATURE_PROBE_TIMEOUT = 20`
|
||||
|
||||
这样它仍然能补识别,但不会把整条 OCR 长尾拖得太夸张。
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前代码位置
|
||||
|
||||
- 配置定义:`fastapi_admin/config/_settings.py`
|
||||
- 客户端工厂:`fastapi_modules/fastapi_leaudit/leaudit_bridge/client_factory.py`
|
||||
- 重试封装:`fastapi_modules/fastapi_leaudit/leaudit_bridge/resilient_clients.py`
|
||||
- signature probe:`fastapi_modules/fastapi_leaudit/leaudit_bridge/ocr_bridge.py`
|
||||
|
||||
Reference in New Issue
Block a user