Files
Video-Tree-TRM5/research-wiki/designs/2026-07-11-batch-tree-build-design.md

4.6 KiB
Raw Permalink Blame History

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 卡号除外)

两层并发参数

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)

配置归属(D7 规则,Codex 审查补充)

参数 归属 理由
api_concurrency 工程配置 .envTREE_BUILD_API_CONCURRENCY=16 端点保护参数,少变、随部署环境定
video_concurrency sh 脚本写死(默认 16)+ CLI 单次覆盖 单机吞吐参数,随硬件观测调整,不进科研 YAML(不会被实验扫动)

builder 改动(唯一的存量修改)

两处(Codex 审查修正后):

  1. 公开异步入口:现有 build() 是同步壳(内部 asyncio.run(self._build_async(...))),在异步批量编排里调用会触发"事件循环嵌套"运行时错误。将 _build_async 提升为公开 build_async() 供批量工具调用;同步 build() 保留原样(内部改为调 build_async),单视频调用方零影响。
  2. 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