docs: sync OCR architecture wording and close G1 R9 R10
This commit is contained in:
@@ -58,7 +58,7 @@
|
||||
| `Permit{release, settle(actual_tokens:int)}`(ports.py:495-504) | 库 `Permit.settle(actual_usage)`(ARCH §7.3) | 语义同;settle 参数类型 int vs usage 需 M2 定稿 | 库内部端口,业务不触及 |
|
||||
| `ConcurrencyLimiter`(ports.py:508-529,含 `mark_progress`/`progress_age_s`/`source_stats`) | 库限流端口(ARCH §7.3 同款契约) | 对等(§7.3 已列 mark_progress/progress_age) | 无 |
|
||||
| `ProviderGate` + `ProviderGateDecision`(epoch/is_probe/probe_owner)(ports.py:406-491) | 库熔断端口 + epoch fencing(ARCH §7.4) | 状态机对等;probe TTL 见 §9-G5 | 无 |
|
||||
| `TableLocator.locate(image)`(ports.py:577-580) | 业务端口保留,内部改调 `OcrLayoutPort.parse_layout` | 库返回 elements 全量;项目只取首个 table bbox | `table_locator.py` 改写取数逻辑 |
|
||||
| `TableLocator.locate(image)`(ports.py:577-580) | 业务端口保留,内部改调 `OcrLayoutPort.parse_layout` | 库返回 elements 全量(para_blocks 提取,与 tables 列表 bbox 逐一相等——M3 设计 §1.2 35 样本取证);项目 shim 约 5 行: 取首个 type=="table" 元素 + `int()` 四元组 | `table_locator.py` 改写取数逻辑 |
|
||||
| 错误三分类 + `OcrResultInvalidError` + `ExtractionParseError` | 库四分类(ARCH §6.1) | Transient/SourceDead/RequestRejected 一一对应;`OcrResultInvalidError` 与 `ExtractionParseError` 合并进 `ResultInvalidError` | worker `_TERMINAL`/重试分支改 except 库异常 |
|
||||
|
||||
**ProviderUnavailableError 的专门论述**(errors.py:140-180): 这是项目独有的 **scope 级不可用**语义——不是"某次调用失败",而是"整个 VLM/OCR 作用域暂时无源可用,任务应延期且**不消耗业务失败预算**"。它携带 `scope`、7 种受控 `reason`(network_error/timeout/rate_limited/source_dead/circuit_open/retry_exhausted/stalled)、`retry_after_s`(读共享熔断门取全 scope 最早恢复时刻,governance.py:182-198)、`reasons`(per-source 失败原因字典)。消费点 `workers/tracking.py:406-428`:捕获后 `finish_deferred_attempt`(FAILED 但不计失败预算)并 `raise Retry(defer=retry_after_s 派生)`——**arq 级延期重投**。ARCHITECTURE §6.1 的承接:`CircuitOpenError`/`AllSourcesExhausted` 覆盖了"发生了什么",但**未定义结构化字段**(retry_after_s/reason/per-source reasons),而 tracking.py 的延期时长直接依赖 `retry_after_s`。承接方案:库两异常须携带 `retry_after_s`(熔断后端最早恢复时刻)与逐源原因;项目侧留 10 行翻译 shim 把库异常包成 `ProviderUnavailableError`(或 tracking.py 直接改 except 库异常)。字段缺失则该行为不可复现 → **⚠️ 架构缺口 G1**。
|
||||
@@ -147,6 +147,8 @@ stack = ExtractionProviderStack(
|
||||
| 换源重试失败跨源累计,`fails > max_attempts` → retry_exhausted(governance.py:255-260) | 重试预算是全局的不是 per-source | **保留**(M2 设计明确计数口径) |
|
||||
| 整圈 gate 全拒 → circuit_open 快失败;配额满则 poll+jitter 重探(governance.py:210-214, 283-285) | 区分"全熔断"与"配额满" | **保留**(映射 CircuitOpenError vs wait,G1) |
|
||||
| MonkeyOCR 两段协议(POST /parse → GET ZIP)+ bbox 有限性/顺序/退化校验(invokers.py:489-552, 427-479) | 数值防御 | **保留**(下沉库,ARCH §7.10 已承诺;首表选取留业务) |
|
||||
| `success!=true` 拒绝不带 status_code,gate 走"本地拒绝"分支不记成功(invokers.py:514-519 + governance.py:228-236) | 熔断口径 | **有意修复**(M3): 库附 status_code=200,按"响应即健康"记成功——200 响应确证服务活着 |
|
||||
| OCR 路径共用 `_translate_429`(insufficient_quota→SourceDead、Retry-After 解析) | 429 细分 | **有意放弃**(M3): MonkeyOCR 无鉴权无计费,429 语义不存在,防御性归 Transient |
|
||||
| 无响应缓存 | 相同图+指令重复付费 | **替换**:迁移后净增缓存(风险见 §8) |
|
||||
| judge 同步裸 SDK 零治理(judge.py:34-52) | 反面教材 | **修复**(§4) |
|
||||
|
||||
@@ -171,7 +173,7 @@ stack = ExtractionProviderStack(
|
||||
| R4 | 六道闸+契约 5 条、服务器时钟窗口、settle 落 acquire 窗口、transient 按 est 保守结算 | M2 | §7.3 大体覆盖 |
|
||||
| R5 | RequestRejected 二分(真实响应记成功/本地拒绝释放探针);换源重试跨源计数口径 | M2 | 须进 M2 设计 |
|
||||
| R6 | OCR ZIP 协议 + bbox 数值防御下沉;OCR Usage=0;glm 白名单预留 | M3 | §7.10 已覆盖 |
|
||||
| **G1** | ⚠️ `CircuitOpenError`/`AllSourcesExhausted` 未定义结构化字段:须携 `retry_after_s`(全 scope 最早恢复时刻,读熔断后端)、reason(circuit_open/retry_exhausted/stalled)、per-source reasons——否则 tracking.py:406-428 的"延期重投不耗失败预算"不可复现(§3) | M2 | **架构缺口**,修订 §6.1 |
|
||||
| **G1** | ✅ 已闭(M3 核实): 库 `GatewayUnavailableError` 一族自 M1 起携 `scope/reason/retry_after_s/per_source_reasons`(errors.py:74-105),chat/embedding/OCR 三循环抛出点均已填充且有契约测试钉住;项目侧仅剩约 10 行翻译 shim(库异常 → ProviderUnavailableError)或 tracking.py 直接 except 库异常 | M2 | 已闭 |
|
||||
| **G2** | ⚠️ `est_tokens`(TPM 预扣常量 + usage 缺失兜底,config.py:55)不在 ARCH §7.7 SourceConfig 字段清单;§7.3 `try_acquire(source, est_tokens)` 的 est 来源未定义 | M2 | **架构缺口**,修订 §7.7 |
|
||||
| **G3** | ⚠️ §4.3 层序图文矛盾:图示 熔断→限流→重试(重试最内),但理由要求"每次重试重新过限流闸"且熔断/限流是 per-source 的、选源在重试循环内(governance.py:120-167 实践为每次尝试执行 选源→冷却备忘→permit→熔断门)。洋葱不澄清"逐次准入"机制则多源语义无法成立 | M2 | **架构缺口**,澄清 §4.3/§4.4 |
|
||||
| **G4** | ⚠️ per-scope 韧性配置命名(`{SCOPE}__RETRY__*`/`BREAKER__*`/`BACKPRESSURE__*`/`SELECTOR`/`GLOBAL__*`)未进 ARCH §9,现文只有平铺 `LLM_*` 键;CHSAnalyzer 的 VLM/OCR 两 scope 参数各异,平铺键无法表达 | M2 | **架构缺口**,修订 §9 |
|
||||
|
||||
Reference in New Issue
Block a user