docs(wiki): add three-round analysis findings and Spec-1/2/3 designs

This commit is contained in:
2026-07-11 07:45:51 -04:00
parent 658e62054e
commit a79c2ec753
11 changed files with 528 additions and 2 deletions
@@ -0,0 +1,83 @@
# Spec-2:建树批量并行入口
- **日期**: 2026-07-11
- **状态**: 已批准(用户确认两层参数推荐方案)
- **系列**: Spec-1/2/3 三件套之一,见 [2026-07-11-agent-runtime-fixes-design.md]、[2026-07-11-question-gen-v2-design.md]
## 1. 问题
TRM5 只有单视频建树(`app/tree/video_builder.py`,内部 Semaphore(16) 限 VLM/LLM 调用)与修复/迁移工具,**没有多视频批量构建入口**——批量建树只能视频间串行,非 API 阶段(ffmpeg 帧提取、图像编码、IO)与 API 阶段无法跨视频重叠,太慢。
## 2. 并发语义调研结论(项目惯例)
| 位置 | 并行单元 | 惯例 |
|------|---------|------|
| `app/harness/inference.py` | 题目 | 一个 `asyncio.Semaphore` + `gather`,任务级 |
| `tools/repair_trees.py` | 视频 | 视频级 Semaphore + gather + progress.json + 熔断阈值随并发缩放 |
| `app/tree/video_builder.py` | API 调用 | Semaphore 作为参数在协程链中显式传递 |
建树是唯一任务内部本身有大并发的场景 → **视频级与 API 级信号量必须分开**,否则 16×16=256 API 并发打爆端点与熔断器。
## 3. 设计
### 入口形态(遵循项目结构规范)
- `tools/build_trees.py`:独立工具(不被其他模块 import),复刻 `repair_trees.py` 的编排模式
- `scripts/build_trees.sh`:自包含实验记录,写死参数、零参数复现(GPU 卡号除外)
### 两层并发参数
```mermaid
graph LR
subgraph tools/build_trees.py
V[视频级 Semaphore<br/>video_concurrency=16] --> B1[VideoTreeBuilder 视频A]
V --> B2[VideoTreeBuilder 视频B]
V --> B3[...]
end
B1 --> API[全局共享 Semaphore<br/>api_concurrency=16]
B2 --> API
B3 --> API
API --> E[VLM/LLM 端点]
```
| 参数 | 默认 | 语义 |
|------|------|------|
| `--video-concurrency` | 16 | 同时在建的视频数;吞吐提升来自非 API 阶段跨视频重叠 |
| `--api-concurrency` | 16 | 全局在途 VLM/LLM 调用上限,跨所有视频共享**一个** Semaphore 实例——端点压力与今天单视频建树完全一致 |
熔断阈值按 repair_trees 惯例缩放:`max(cfg_threshold, api_concurrency * 2)`
### builder 改动(唯一的存量修改)
`VideoTreeBuilder` 的内部 Semaphore 改为**可注入参数**(构造器可选传入外部 Semaphore;不传则自建,单视频调用行为零变化)。builder 内部协程链本就显式传递 Semaphore,改动面极小。
### 断点续跑
- 视频级:`progress.json`(复用 repair_trees 的 `save_progress` 模式);tree.json 存在且完整性校验通过的视频自动跳过
- 视频内:现有段级恢复(核心算法 #3)不动
### 输入输出
- 输入:`--videos-dir`(视频文件 + 可选同名 SRT
- 输出:`store/videos/<video_id>/tree.json`;帧持久化沿用现有 cache 机制
## 4. 风险与观测
- 16 路并行 ffmpeg/cv2 解码可能压满 CPU/磁盘 → 实现时输出速率日志(视频/分钟,复刻 repair_trees),观测后再调 video_concurrency
- 日志遵循"禁止缓存、立即输出"CLAUDE.md §2.1
## 5. 不做什么(YAGNI
- 不做分布式/多机;不做动态并发自适应
- 不改单视频建树算法(核心算法 #1/#2/#3 保真,仅信号量注入)
## 6. 验证
1. 单测:Semaphore 注入后单视频行为不变(默认自建路径)
2. 集成:3-4 个短视频小批量构建,验证跨视频并行、progress 跳过、全局 API 信号量生效(遥测里在途调用数 ≤ api_concurrency
3. 中断-恢复测试:构建中 Ctrl+C 后重跑,已完成视频跳过、未完成视频从段级断点续跑
## 7. 被否方案
- **单一视频级 Semaphorerepair_trees 原样照搬)**:建树内部并发大,总 API 并发 = 视频数 × 内部并发,不可控
- **仅共享全局 API Semaphore、视频数不限**:任意多视频同时提帧会压垮磁盘 IO/CPU