Files

19 KiB
Raw Permalink Blame History

Video-Tree-TRM5 架构设计

版本 v1 · 状态 提案 · 读者 工程团队

本文分两部分。Part 1「架构」与具体技术栈无关,只描述边界、依赖方向、接缝与核心算法——它是长期承诺,预期能跨越多次技术选型而不变。Part 2「韧性与运维」描述 LLM 调用治理与可观测规范——它随实现演进,但当前约束所有实现必须满足。


§1 核心定位

项目目标:在层次化视频树上构建可自我进化的搜索 Agent + 可训练的递归检索器,实现长视频理解。目标会议 EMNLP 2026。

系统类比——自进化循环对标 PyTorch 训练:

PyTorch 本项目 代码位置
DataLoader 出题 question_gen app/question_gen/loader.py
model.forward() 推理 inference app/harness/inference.py + core/agent/loop.py
loss.backward() 诊断 diagnose core/evolution/diagnose.py
optimizer.step() 进化 evolve core/evolution/evolve.py
nn.Parameter Skills + Prompts(版本化) store/skills/, store/prompts/
training loop 外层循环 runner app/harness/runner.py
checkpoint Store 版本快照 app/harness/workspace.py

只有 inference 是 agent-controlledLLM 自主调工具),其余三步是 code-controlled workflow。

三大模块

模块 目录 一句话定义
建树 app/tree/ 离线预处理——VLM 生成三层 TreeIndex(L1段落→L2片段→L3帧),支持字幕注入和后增强
训练 app/harness/ + core/ 自进化循环(推理→诊断→进化)+ RecursiveRetriever 参数训练
新题构建 app/question_gen/ 生成 Video-MME 风格训练题,原始 benchmark 作 held-out 泛化评测

§2 分层架构(Clean Architecture

2.1 四层依赖规则

flowchart TB
    subgraph 外部实现层
        AD_LLM["adapters/llm.py\nGovernedLLMClient"]
        AD_VLM["adapters/vlm.py"]
        AD_EMB["adapters/embedding.py"]
        AD_CACHE["adapters/redis_cache.py"]
        AD_TEL["adapters/telemetry.py"]
        AD_OCR["adapters/ocr.py"]
        AD_ASR["adapters/asr.py"]
    end

    subgraph 应用层
        TREE["app/tree/\n建树模块"]
        HARNESS["app/harness/\n训练循环"]
        QGEN["app/question_gen/\n新题构建"]
        SEARCH["app/search/\nAgent 装配"]
        RET["app/retriever/\n可训练检索器"]
        PORTS["app/ports.py"]
    end

    subgraph 可提取内核
        AGENT["core/agent/\nAgentLoop 引擎"]
        EVO["core/evolution/\n诊断+进化引擎"]
        CPROTO["core/*/protocols.py"]
    end

    AD_LLM & AD_VLM & AD_EMB & AD_CACHE & AD_TEL -->|实现| CPROTO & PORTS
    HARNESS --> AGENT & EVO
    SEARCH --> AGENT
    TREE & RET & QGEN --> PORTS
    AGENT & EVO -->|定义| CPROTO

依赖只能向内,源码 import 方向严格单向。内层不认识外层:core/ 不知道自己被哪个 app/ 模块组合,app/ 不知道 Protocol 背后是哪个 adapter。判据:任意一个 core/ 模块,搬到没有 adapters 的环境里,用假实现替换 Protocol 即可原样运行

2.2 模块交互全景

flowchart TD
    CLI["main.py CLI"] --> RUNNER["app/harness/runner.py\n训练循环编排"]
    CLI --> BUILD["app/tree/video_builder.py\n建树"]
    CLI --> QGEN["app/question_gen/loader.py\n新题构建"]
    CLI --> TRAIN_RET["app/retriever/train.py\n检索器训练"]

    RUNNER --> INF["app/harness/inference.py\n推理 step"]
    RUNNER --> DIAG["core/evolution/diagnose.py\n诊断"]
    RUNNER --> EVOL["core/evolution/evolve.py\n进化"]
    RUNNER --> BATCH["app/harness/batching.py\nmini-batch"]
    RUNNER --> GATE["core/evolution/gate.py\nCE-Gate"]
    RUNNER --> WS["app/harness/workspace.py\nStore + Workspace"]

    INF --> LOOP["core/agent/loop.py\nAgentLoop"]
    LOOP --> SEARCH["app/search/\nprompt + skills"]
    LOOP --> LLM["adapters/llm.py\nGovernedLLMClient"]

    BUILD --> VLM["adapters/vlm.py"]
    BUILD --> EMB["adapters/embedding.py"]

2.3 目录结构

project_root/
├── core/                    # 可提取内核(不依赖 app/、adapters/
│   ├── protocols.py         # 共享端口:LLMProvider, VLMProvider, TelemetryRecorder
│   ├── agent/               # 【可提取包】AgentLoop 引擎
│   │   ├── loop.py          # Thinking+JSON 推理循环,pluggy hook
│   │   ├── types.py         # Step, LoopResult
│   │   └── protocols.py     # Agent 专属:ToolDispatcher, AgentLoopSpec
│   ├── evolution/           # 【可提取包】诊断+进化引擎
│   │   ├── diagnose.py      # 两阶段诊断管线
│   │   ├── evolve.py        # patch/rewrite 进化
│   │   ├── gate.py          # CE-Gate e-process
│   │   ├── validate.py      # 块顺序验证
│   │   ├── types.py         # DiagnosisResult, EvolutionRecord, ...
│   │   └── protocols.py     # Evolution 专属:SkillStore, PromptStore, RunLog
│   └── types.py             # 跨模块共享类型
│
├── app/                     # 应用层(组合 core + adapters,领域特化)
│   ├── tree/                # 模块1:建树
│   │   ├── index.py         # TreeIndex 数据结构(L1/L2/L3Node + Card
│   │   ├── video_builder.py # VideoTreeBuilderL2 轴心 + asyncio 并发)
│   │   ├── config.py        # TreeConfig 配置 dataclass
│   │   ├── subtitle.py      # SRT 解析 + Voronoi 字幕分配
│   │   ├── verify.py        # 交叉校验(entities/visible_text
│   │   ├── environment.py   # 树环境语义搜索(分块 embedding + 祖先去重)
│   │   └── repair/          # 后修复管线
│   │       ├── detector.py  # 缺陷检测(空字段/缺帧/时间间隙)
│   │       ├── regenerator.py # VLM 重描述 + 自底向上级联修复
│   │       └── supplement.py  # Q&A 反向补全
│   ├── harness/             # 模块2:训练 harness
│   │   ├── runner.py        # 训练循环编排(对标 Trainer)
│   │   ├── inference.py     # 推理 step
│   │   ├── batching.py      # mini-batch 构建
│   │   ├── pools.py         # 三池切分(数据加载已移至 question_gen/loader.py
│   │   ├── gate_ladder.py   # 信息阶梯
│   │   ├── momentum.py      # 慢速动量
│   │   ├── config.py        # RunConfig
│   │   ├── log.py           # HarnessLog (SQLite)
│   │   └── workspace.py     # Store + Workspace 版本管理
│   ├── question_gen/        # 模块3:出题(加载 + 采样 + 未来 LLM 生成)
│   │   └── loader.py        # benchmark 加载、分层采样
│   ├── search/              # 搜索 Agent 装配
│   │   ├── prompt.py        # PromptManagerprompt 加载与拼装)
│   │   ├── skills.py        # SkillRegistry + discover_skills
│   │   ├── summarizer.py    # 两轮 LLM 摘要(view_node / search_similar 用)
│   │   ├── vision.py        # observe_frameVLM 两轮 + OCR 注入)
│   │   └── tools.py         # SearchToolDispatcher(实现 ToolDispatcher
│   ├── retriever/           # 可训练检索器
│   │   ├── recursive.py     # RecursiveRetriever (CrossAttention+ACT)
│   │   ├── losses.py        # NavigationLoss + ACTLoss
│   │   └── train.py         # 两阶段训练入口
│   └── ports.py             # 应用层特有端口
│
├── adapters/                # 外部实现层
│   ├── llm.py               # GovernedLLMClient(四层治理栈)
│   ├── streaming.py          # 流式三层看门狗(TTFT/inter_token/total
│   ├── breaker.py            # CircuitBreaker(内存级熔断器)
│   ├── vlm.py               # VLM 客户端
│   ├── embedding.py         # Embedding 服务实现
│   ├── redis_cache.py       # Redis 响应缓存
│   ├── ocr.py               # MonkeyOCR 客户端
│   ├── asr.py               # ASR (Whisper) 客户端
│   └── telemetry.py         # SQLite 遥测记录实现
│
├── config/                  # 声明性配置(YAML,禁止 .py
├── store/                   # 版本化资源(skills/prompts/questions/videos
├── workspaces/              # 实验工作区
├── prompts/                 # 诊断 prompt(不参与进化,是评估标尺)
├── tests/                   # 测试
├── data/                    # 数据(不提交 Git)
├── logs/                    # 日志(不提交 Git
├── results/                 # 实验结果
├── main.py                  # CLI 入口
└── research-wiki/           # 单一事实源

2.4 依赖方向硬性规则

可依赖 禁止依赖
core/ 标准库、typing、pluggy、json_repair app/adapters/、任何框架
app/ core/、标准库 adapters/(只通过 Protocol
adapters/ core/app/ports.py、第三方库 app/ 内部模块

2.5 可提取内核

core/agent/core/evolution/ 是两个独立可提取包,只依赖 Protocol 接口。将它们连同 core/types.py 复制到另一个项目,提供 Protocol 实现即可运行——这是验证依赖方向是否守住的判据。


§3 接缝清单(Protocol 端口)

只在真正易变、需替换或需造测试替身处引入接口,其余写直白的领域函数。

3.1 核心端口(core/ 内,可提取)

共享端口(core/protocols.py,跨子包):

Protocol 关键方法 职责
LLMProvider chat() LLM 文本调用(全异步)
VLMProvider chat_with_images() VLM 图文调用(全异步)
TelemetryRecorder record_llm_call() LLM 调用遥测

Agent 专属端口(core/agent/protocols.py):

Protocol 关键方法 职责
ToolDispatcher dispatch(tool_name, args, context) Agent 工具调度
AgentLoopSpec before_step/after_tool/after_step/on_finish pluggy 生命周期 hook

Evolution 专属端口(core/evolution/protocols.py):

core/ 侧 Protocol 只读——core/ 返回结果 dataclass,写入由 app/harness/ 编排层执行。写方法保留在 app/ 侧的实现类中。

Protocol 关键方法 职责
SkillStore read_skill(), list_skill_files() 版本化技能读取(只读)
PromptStore read_prompt(), list_prompt_files() 版本化提示词读取(只读)
RunLog get_predictions(), get_traces() 实验日志查询(只读)

3.2 应用层端口(app/ports.py

Protocol 关键方法 职责 当前实现
EmbeddingProvider embed(texts) 文本嵌入 adapters/embedding.py
TreeCache get(), set() 树索引缓存 adapters/redis_cache.py
ASRProvider transcribe(audio_path) 语音识别 adapters/asr.py
OCRProvider transcribe_frames(frame_paths: list[Path]) -> str 帧文字转录 adapters/ocr.py

判据:这块代码会不会被换实现、或需要在测试里替换成假的?不会,就别抽象。

3.3 当前实现映射

Protocol adapter 实现 说明
LLMProvider adapters/llm.py GovernedLLMClient OpenAI 兼容 API,内置治理栈(§5)
VLMProvider adapters/vlm.py Qwen VL 等 OpenAI 兼容 VLM API
ToolDispatcher app/search/tools.py SearchToolDispatcher 搜索 Agent 工具分发(view_node / search_similar / observe_frame / submit_answer / read_skill
SkillStore / PromptStore app/harness/workspace.py 文件系统版本化存储(store/skills/v{N}/
RunLog app/harness/log.py HarnessLog SQLite 持久化
TelemetryRecorder adapters/telemetry.py SQLite telemetry.db
EmbeddingProvider adapters/embedding.py localsentence-transformers/ remote 双后端
TreeCache adapters/redis_cache.py Redis 键值缓存
ASRProvider adapters/asr.py Groq Whisper API
OCRProvider adapters/ocr.py MonkeyOCR 自建端点

§4 Agent 遥测规范

每次 LLM/VLM 调用必须经过 TelemetryRecorder 记录以下字段:

字段 类型 说明
call_id str UUID,本次调用唯一标识
parent_call_id str? 父调用(agent step → LLM call 链路)
session_id str epoch/step/question 关联 ID
model_name str 使用的模型名
provider str API 端点标识
messages str (JSON) 原始输入
response str 原始输出
thinking str thinking/reasoning 内容
prompt_tokens int 输入 token 数
completion_tokens int 输出 token 数
latency_ms int 延迟毫秒
ttft_ms float? 首 token 延迟(流式测量)
max_inter_token_ms float? 最大 token 间隔(流式测量)
cache_hit bool 是否命中 Redis 缓存
error str? 异常信息(正常为 null

存储SQLite telemetry.dbllm_calls 表。adapters/telemetry.py 实现 TelemetryRecorder Protocoladapters/llm.pyGovernedLLMClient 在每次调用后自动写入。


§5 LLM 调用韧性

所有 LLM/VLM 调用必须经过 GovernedLLMClientadapters/llm.py)治理,禁止裸调 OpenAI SDK。治理栈包含四层:

机制 说明
1 熔断器 连续 N 失败 → 短路 M 秒 → 探针恢复(adapters/breaker.py
2 Redis 响应缓存 content-addressedhash(model + messages) → response
3 流式三层看门狗 TTFT / inter_token / total 超时保护(adapters/streaming.py
4 指数退避重试 max_retriesbase_delaymax_delay(可配置)

流式三层看门狗GovernedLLMClient 内部始终使用 stream=True 消费 SSE,通过 stream_with_liveness_timeouts() 实现三层超时保护——TTFT(首 token,含 thinking token)、inter_tokentoken 间隔)、total(总时长)。thinking token 刷新看门狗但不计入 content,确保长时间思考不会被误判为连接挂死。

熔断参数(LLM_CIRCUIT_BREAKER_THRESHOLDLLM_CIRCUIT_BREAKER_COOLDOWN)、超时(LLM_TIMEOUTLLM_TTFT_TIMEOUTLLM_INTER_TOKEN_TIMEOUT)通过 .env 工程配置管理。

治理流程伪代码

chat(messages) →
  if breaker.is_open: raise CircuitOpen     # 层1: 熔断
  call_id = uuid4()
  if cache.get(model, messages):            # 层2: 缓存
    telemetry.record(..., cache_hit=True)
    return cached
  retry loop:                                # 层4: 重试
    stream = httpx.stream(POST, stream=True)
    guarded = stream_with_liveness_timeouts( # 层3: 三层看门狗
      sse_deltas, ttft, inter_token, total)
    content, thinking, ttft_ms = consume(guarded)
    breaker.record_success()
    cache.set(model, messages, response)
    telemetry.record(...)
    return response
  except transient → backoff + breaker.record_failure()
  except 401/403 → breaker.force_open(); raise

§6 核心算法保真清单

迁移时逐一比对参考代码,不可简化。建树 4 项 + 训练 9 项 = 13 项:

# 算法 参考文件 核心逻辑
1 L2 轴心建树策略 reference/video_tree_trm/video_tree_builder.py L2 先行→L3 向下→L1 向上,asyncio 链式并发
2 VLM 批量帧描述 + JSON fallback reference/video_tree_trm/video_tree_builder.py _L3_BATCH_SIZE=5 批量调用,解析失败逐帧 fallback
3 断点续跑机制 reference/video_tree_trm/video_tree_builder.py progress.json + L1 中间 JSON,按段恢复
4 RecursiveRetriever reference/docs/architecture.md §5 Cross-Attention 选择器 + ACT halt + z 状态累积
5 CE-Gate e-process TRM4 core/harness/eprocess.py 截断 Beta 混合、四出口门控
6 信息阶梯 TRM4 core/harness/gate_ladder.py 冷启动 2:1、gamma-EMA、反泄漏
7 块顺序验证 TRM4 core/harness/validate.py 基线缓存、INFRA 护栏、配对翻转
8 诊断瀑布 TRM4 core/harness/diagnose.py 错误归因级联、缺陷 vs 失误、D1-D5
9 进化 patch 引擎 TRM4 core/harness/evolve.py + patch.py 保护跨度、rank-and-clip、附录/动量
10 Mini-batch 构建 TRM4 core/harness/batching.py FFD + round-robin + 正确率混合
11 Agent Loop TRM4 core/loop.py Thinking+JSON、json_repair、pluggy hook
12 树环境语义搜索 TRM4 core/tree/environment.py 分块 embedding、祖先去重、锚定验证
13 训练循环编排 TRM4 core/harness/runner.py 三级嵌套、慢更新10步、断点续训

TRM4/home/iomgaa/Projects/Video-Tree-TRM4/reference/home/iomgaa/Projects/Video-Tree-TRM5/reference/


§7 配置管理(双模式)

系统配置分两套,按用途隔离:

模式 载体 适用
工程配置 pydantic-settings + .env 系统运行所需、少变或敏感(API 密钥、Redis URL、LLM 超时等)
科研实验配置 per-experiment YAML + harness run 快照 会在实验中反复扫动/对比的参数(gate 阈值、batch 大小、评估口径等)

D7 归属判定规则(防串台,强制遵守):某参数是否会在科研实验中被反复扫动/对比?

  • → 科研配置(per-experiment YAML + harness run 快照,保证可复现)。
  • (系统运行所需、少变、或敏感)→ 工程配置(pydantic-settings + .env)。

CLI args 仅用于单次临时覆盖,不作为任何配置的常驻来源。两类载体之外,严禁在代码中散落硬编码默认值;缺失关键配置应直接报错而非兜底。

参数归属示例

参数 归属 理由
SEARCH_LLM_API_KEY 工程 .env 敏感,不变
LLM_TIMEOUT 工程 .env 系统运行所需,少变
gate_e_confirm 科研 YAML CE-Gate 阈值,实验中反复调优
batch_size 科研 YAML mini-batch 大小,实验中反复扫动
embed.model_name 科研 YAML 嵌入模型选型,实验中对比
REDIS_URL 工程 .env 基础设施地址,少变

附:横切原则

  • 溯源:每条推理链(Agent 看了哪些节点、如何汇总出答案)都带来源。遥测(§4)记录全部 LLM 调用,Store 版本化记录 skill/prompt 变更历史。
  • 可复现:每次 harness run 冻结当前 config/ YAML + Store 版本快照(app/harness/workspace.py),结果可重算。
  • 安全/合规API 密钥走 .env,不提交 Git;Redis 缓存中不存敏感信息的明文。