From ef402c46a28abbbe08198e11071ae0ab04efef97 Mon Sep 17 00:00:00 2001 From: iomgaa Date: Sat, 11 Jul 2026 07:54:48 -0400 Subject: [PATCH] docs(designs): apply Codex review fixes to Spec-1/2/3 --- .../2026-07-11-agent-runtime-fixes-design.md | 7 ++-- .../2026-07-11-batch-tree-build-design.md | 12 ++++++- .../2026-07-11-question-gen-v2-design.md | 36 +++++++++++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/research-wiki/designs/2026-07-11-agent-runtime-fixes-design.md b/research-wiki/designs/2026-07-11-agent-runtime-fixes-design.md index f5b2375..6312580 100644 --- a/research-wiki/designs/2026-07-11-agent-runtime-fixes-design.md +++ b/research-wiki/designs/2026-07-11-agent-runtime-fixes-design.md @@ -33,19 +33,20 @@ |------|-----|------| | 重试次数 | 2 | 第 3 次失败才整题终止(stop_reason=error 不变) | | 退避 | 20s / 40s | 用户指定 | -| 异常范围 | 全部 Exception | 这一层防的是穿透 GovernedLLMClient 内部重试栈的异常(SSL 等),统一兜底不分型 | +| 可重试异常 | 显式类型元组:`ssl.SSLError`、`TimeoutError`、`ConnectionError`、`OSError`、openai SDK 传输类异常(`APIConnectionError`/`APITimeoutError`) | 遵循 CLAUDE.md P5(不做全 Exception 兜底);`asyncio.CancelledError` 绝不吞;其余未知异常 fail-fast 整题终止(现状行为) | | 上下文 | 原样保留 | messages 不回滚,重试即重发 | -| 遥测 | 中间失败记入 error 字段 | 保持调用链可追溯 | +| 遥测 | 失败尝试的 error 记录由 `GovernedLLMClient` 内部负责(已有);AgentLoop 侧只以 loguru 记录步级重试事件(不注入 TelemetryRecorder) | AgentLoop 无遥测端口,不越层补写 | ### B 摘要附带实体原文 -`summarize_node` 输出末尾由**确定性代码**(非 LLM)追加节点 card 的字段原文: +在 **dispatcher 侧**(`SearchToolDispatcher._handle_view_node`)由确定性代码(非 LLM)在摘要结果末尾追加节点 card 的字段原文: ``` [实体] [画面文字] ``` +- **调用链改动**(Codex 审查修正):`summarize_node` 只收 `raw_text: str`、无结构化 card 访问,且 `_node_full_text` 递归收值不保留字段名——因此在 `TreeEnvironment` 新增结构化字段提取方法(如 `node_entity_fields(node_id) -> dict[str, str]`),dispatcher 调用它并把区块拼接到 summarize_node 返回值之后;summarize_node 本体不改 - 摘要后追加 → LLM 无法吞掉;字段为空则不加对应区块 - 对 anchor / 非 anchor 两种模式一致生效 diff --git a/research-wiki/designs/2026-07-11-batch-tree-build-design.md b/research-wiki/designs/2026-07-11-batch-tree-build-design.md index ebe39da..bdddf84 100644 --- a/research-wiki/designs/2026-07-11-batch-tree-build-design.md +++ b/research-wiki/designs/2026-07-11-batch-tree-build-design.md @@ -47,9 +47,19 @@ graph LR 熔断阈值按 repair_trees 惯例缩放:`max(cfg_threshold, api_concurrency * 2)`。 +**配置归属(D7 规则,Codex 审查补充)**: + +| 参数 | 归属 | 理由 | +|------|------|------| +| `api_concurrency` | 工程配置 `.env`(`TREE_BUILD_API_CONCURRENCY=16`) | 端点保护参数,少变、随部署环境定 | +| `video_concurrency` | sh 脚本写死(默认 16)+ CLI 单次覆盖 | 单机吞吐参数,随硬件观测调整,不进科研 YAML(不会被实验扫动) | + ### builder 改动(唯一的存量修改) -`VideoTreeBuilder` 的内部 Semaphore 改为**可注入参数**(构造器可选传入外部 Semaphore;不传则自建,单视频调用行为零变化)。builder 内部协程链本就显式传递 Semaphore,改动面极小。 +两处(Codex 审查修正后): + +1. **公开异步入口**:现有 `build()` 是同步壳(内部 `asyncio.run(self._build_async(...))`),在异步批量编排里调用会触发"事件循环嵌套"运行时错误。将 `_build_async` 提升为公开 `build_async()` 供批量工具调用;同步 `build()` 保留原样(内部改为调 `build_async`),单视频调用方零影响。 +2. **Semaphore 注入**:内部 Semaphore 改为构造器可选参数(不传则自建,行为零变化)。builder 内部协程链本就显式传递 Semaphore,改动面极小。 ### 断点续跑 diff --git a/research-wiki/designs/2026-07-11-question-gen-v2-design.md b/research-wiki/designs/2026-07-11-question-gen-v2-design.md index 5c89b9c..56c8fe0 100644 --- a/research-wiki/designs/2026-07-11-question-gen-v2-design.md +++ b/research-wiki/designs/2026-07-11-question-gen-v2-design.md @@ -43,6 +43,18 @@ graph LR | 视觉族 | 状态演化多帧、实例消歧数字 | 证据仅在帧内、不在任何 card 文本;多时刻真实读数做干扰项 | M4 视觉验证 | 15% | | 空间族 | 参照系空间 | spatial_layout 字段 + 时间锚;摄像机/被摄者双参照系 | T5 空间 | 10% | +**题族 × task_type 兼容矩阵**(Codex 审查补充;✓=合法组合,采样器按此分配双标签,保证 12 类各 20 题的硬约束可满足): + +| 题族 | 合法 task_type | +|------|---------------| +| 检索族 | Object Recognition、Object Reasoning、Action Recognition、Attribute Perception、OCR Problems | +| 推理族 | Action Reasoning、Object Reasoning、Information Synopsis | +| 枚举族 | Counting Problem、Temporal Reasoning、Temporal Perception、Information Synopsis | +| 视觉族 | Attribute Perception、Counting Problem、OCR Problems、Action Recognition | +| 空间族 | Spatial Perception、Spatial Reasoning | + +每个 task_type 至少落入一个题族;Spatial 两类仅由空间族供给。**"不出 T1 类素材题"是素材形态禁用**(不采瞬时动作/记分牌瞬时数值/无对白因果类素材),不删除任何 Video-MME task_type。 + ### 2.2 确定性后处理(零 LLM 成本,通用硬约束) 1. **选项 shuffle** + 答案字母重映射(修复 v1 答案 57% 在 A 的偏斜) @@ -77,8 +89,15 @@ graph LR | 项 | 决策 | |----|------| | 旧 240 题 | 原地保留 `store/questions/generated/`(infer_gen240 run 引用它,保可复现) | -| 新题集 | `store/questions/generated-v2/`,workspace 以 `--questions generated-v2` 指向 | +| 新题集 | `store/questions/generated-v2/`,布局与 v1 一致:`{video_id}.json` 平铺(无子目录)。CLI 示例:生成 `python tools/generate_questions.py generate --output-dir store/questions/generated-v2 ...`;推理 `python main.py --mode infer --questions generated-v2 --run-id gen240v2` | | 题目元数据新增 | `skill_target`、`source_nodes`(已有)、`gate_report`(四门判定)、`difficulty_steps`(抽检题) | + +**元数据承载方式(Codex 审查修正)**:现有 `GeneratedQuestion`(`core/types.py`)为固定 8 字段,`load_benchmark` 丢弃未知 JSON 字段,池快照只存固定字段。约定: + +| 字段 | 承载 | 进训练链路 | +|------|------|-----------| +| `skill_target`、`difficulty_steps` | 扩展 `GeneratedQuestion` 为可选字段(默认 None,benchmark 题不受影响);loader/pools 同步保留 | 是(diagnose 可按 skill_target 聚合报表) | +| `gate_report` | 只存在于题目 JSON(溯源用)与生成期 SQLite;loader **不加载**(体积大且训练不需要) | 否 | | 规模 | 默认 240 题;**task_type 均匀(20/类)为硬约束**(进化循环分层需要),**族配比为软目标(±5%)**——采样器按"族 × task_type 兼容矩阵"(如枚举族→Counting/Temporal 类)分配每题的双标签;YAML 可扫 | ## 4. 配置归属(D7 规则) @@ -86,9 +105,20 @@ graph LR - **科研配置**(per-experiment YAML):族配比、门阈值(n-gram 窗口、多真判定温度)、抽检率、重出上限、规模 - **工程配置**(`.env`):LLM/VLM 端点、超时、熔断——沿用现有 -## 5. 运行时数据 +## 5. 运行时数据与治理 -每题的门判定记录(哪门拒、拒因文本、重出轮次、最终状态)落 SQLite。表结构在设计批准后走 `structured-logging` skill 单独设计(本 spec 只约定:记录必须逐题可追溯、可聚合出各门拦截率报表)。 +- 每题的门判定记录(哪门拒、拒因文本、重出轮次、最终状态)落 SQLite。表结构在设计批准后走 `structured-logging` skill 单独设计(本 spec 只约定:记录必须逐题可追溯、可聚合出各门拦截率报表) +- **质量门 LLM 调用治理(Codex 审查补充)**:轻量四门与生成器的全部 LLM/VLM 调用必须经 `GovernedLLMClient`/`GovernedVLMClient` + `TelemetryRecorder`(CLAUDE.md §4.8/§4.9),严禁裸调 SDK;门执行器通过依赖注入接收客户端实例,session_id 用生成批次 id、parent_call_id 链接到题目生成调用 + +## 5.5 核心接口概要(Codex 审查补充,完整签名留给 plan) + +| 类型/函数 | 职责 | +|----------|------| +| `QuestionFamilySpec` | 题族声明:采样约束、prompt 模板、泄漏门捷径画像、合法 task_type 集合 | +| `CandidateQuestion` | 生成器输出:题面 + 双标签 + source_nodes + 构造验证材料(未过门) | +| `GateReport` | 四门判定结果:每门 pass/reject + 拒因文本 | +| `run_gates(candidate, deps) -> GateReport` | 门执行器(依赖注入 LLM/树环境) | +| `generate_one` 迁移 | v1 签名(只收 task_type)废弃,v2 收 `(family_spec, task_type, slot_seed)` 返回 `CandidateQuestion` | ## 6. 不做什么(YAGNI)