diff --git a/research-wiki/designs/2026-07-15-question-gen-v2-grounded-contrastive-design.md b/research-wiki/designs/2026-07-15-question-gen-v2-grounded-contrastive-design.md new file mode 100644 index 0000000..c39bde5 --- /dev/null +++ b/research-wiki/designs/2026-07-15-question-gen-v2-grounded-contrastive-design.md @@ -0,0 +1,165 @@ +--- +id: question-gen-v2-grounded-contrastive +title: question-gen v2 — AR grounded-contrastive 重构(双模式生成 + 独立 VLM grounding + 生成端对抗) +type: design +created: 2026-07-15 +status: draft +--- + +# question-gen v2:AR grounded-contrastive 重构 + +## 1. 目标与范围 + +Phase A(grounded selector)落地后,双独立评审(Claude 三 agent + Codex)判定新题"未真正过关":negative-space 减少但 grounding 不可审计(selector 用生成器自己的 VLM 自评=循环自证)、8/12 仍可被结构性 shortcut 秒杀(逐槽多数投票 / 最模糊-子串项 / 字幕泄答案)、4/12 双正解歧义。根因诊断见 [2026-07-15-question-gen-v2-diagnosis-and-strategy.md](四层病灶 + 六篇文献回挖)。 + +v2 从**四层**对症重构,用户锁定三个治本方向: + +| 决策 | 选定 | +|------|------| +| 题型 | **双模式对称对比(决策 C)**:可翻转子模式→镜像对+双向 AND;不可翻转→4 选对比集+重去偏 | +| grounding | **独立 VLM(MiniMax-M3)打分**(CLIP 跨模态 embedding 无法服务,退回独立 judge,仍断循环自证) | +| 对抗位置 | **轻量代理内联 + 完整 agent 后置第二道网** | + +**范围铁律**:v2 只重构 **Action Recognition** 路径;11 个非 AR 题型走现有 `generate-v2` **零改动**(路径隔离)。代价:题库出现"AR 新格式 + 非 AR 旧格式"混格,评测/训练侧须兼容两种。 + +### 路径归属 + +| 改动 | 位置 | 生效范围 | +|------|------|---------| +| 双模式生成 | 新建 `app/question_gen/contrastive_gen.py` | 仅 AR(strategy 声明开关分流) | +| 独立 VLM grounding | 改 `distractor_selector.py` `_score_options` + 装配加第二 VLM | 仅 AR selector 调用点 | +| 内联对抗探针 | 新建 `app/question_gen/adversarial_probes.py` | 仅 AR | +| 门收紧 + NLI + 歧义门 | `gate_multi_true.md` 收紧 + 新 gate | multi_true 公共(收紧,用户批准);NLI/歧义门仅 AR | +| pair 契约 | `core/types.py` `GeneratedQuestion` + harness/loader | 公共类型(新字段默认值兼容非 AR) | +| 后置双向评分 | 改造 `adversarial_filter.py` | filter 层,`filter_task_types` 默认 AR | + +## 2. Prior-Version Audit(v2 替换/改造的既有行为) + +| 既有行为 | v2 处置 | +|---------|---------| +| `distractor_selector` VLM 自评选负项 | **改造**:打分器换独立 MiniMax-M3;区间选择/退火/hard-fail 落库**保留** | +| `adversarial_filter` 翻转门(事后生成镜像 Q) | **改造**:镜像在生成期已产出,翻转门→对 pair 做双向 AND 评分(不再事后生成) | +| `adversarial_filter` 作弊门(后置试答) | **保留**,定位为后置第二道网 | +| `adversarial_filter` 补生成迭代 / 两份 JSON | **保留** | +| `gate_multi_true` 松绑 rubric | **反向收紧**(precision over recall,撤销 Phase A 松绑) | +| on_accept 逐题追加 / progress 断点 / verdicts 表续跑 / 原子写 | **保留**,pair 需原子成对落盘(见 §7) | +| 4 选项 + 字母答案契约 | **扩展**:加 pair 语义;单题仍 4 选,pair 双向 AND 评分 | +| 11 非 AR generate-v2 全流程 | **零改动** | + +未发现隐式删除。唯一有意行为变更:AR 出题机制整体重构;multi_true 全局收紧(有意,用户批准)。 + +## 3. 架构与数据流 + +```mermaid +flowchart TD + S[采样素材 + 选 sub_pattern] --> F{sub_pattern 可翻转?} + F -->|temporal/cross_segment| PAIR[生成镜像对 P+Q
同视频翻转轴, 选项 bag-of-words 匹配] + F -->|semantic/fine_grained/evidence_gap/premature| SET[生成 4 选对比集
单维反事实, 等信息量] + PAIR --> GRD[独立 VLM MiniMax-M3
对真实帧打视觉可信度分 → 区间选负项] + SET --> GRD + GRD --> PROXY[内联轻量对抗探针
text-only 盲答 + MiniMax 快解] + PROXY -->|被秒杀| RE[回灌失败模式重生] + RE --> GRD + PROXY -->|存活| GATE[门: key_verify + multi_true收紧
+ NLI禁蕴含 + leak + MiniMax歧义门] + GATE -->|失败| RE + GATE -->|通过| ACC[on_accept 落盘
pair 原子成对写] + ACC -.批次后置.-> NET2[完整 agent 作弊门第二道网
pair 双向 AND 评对 + 补生成迭代] + NET2 --> FINAL[accepted_questions_final.json] +``` + +## 4. 组件设计 + +### 4.1 双模式生成(`contrastive_gen.py`,仅 AR) + +`SubPattern` 已有 `supports_flip`/`flip_axis`(Phase B Task 1)。生成分流: + +**A. 可翻转(temporal→before/after, cross_segment→first/last)— 镜像对** +- VLM 生成题 P(正解 + 干扰项)后,**同素材翻转 flip_axis** 生成镜像 Q(正解天然相反); +- 选项尽量 **bag-of-words 匹配**(Vinoground:正负选项同词不同序 → 长度/具体度线索结构上消失); +- 产出 (P, Q) 共享 `pair_id`,评分双向 AND。 + +**B. 不可翻转(其余 4 个)— 4 选对比集** +- VLM 生成正解 + 3 个**单维反事实**(各改一维、互不重叠 → 防逐槽多数投票); +- 硬约束(写进 prompt + 后置校验):**等信息量/等长**、**禁蕴含**(正解非任一干扰项子串、反之亦然)、**动词/事件结构**上反事实(非名词替换,VITATECS 警示名词替换易解)。 + +### 4.2 独立 VLM grounding(改 `distractor_selector.py`) + +- **装配拆分**:`InfraSettings` 新增读 `M3_VL_LLM_*`;adapter 产出**第二个 `GovernedVLMClient`**(scorer_vlm=MiniMax-M3)。生成用主 VLM(qwen),打分用 scorer_vlm。 +- `build_grounded_options` 增 `scorer_vlm` 形参;`_score_options` 用 scorer_vlm。区间选择 `[s_correct-δ_high, s_correct-δ_low]` / 退火 / hard-fail 落库**逻辑不变**。 +- **早期风险校验**:MiniMax-M3 打分粒度未知(Phase A 观测到 qwen 自评是 1.0/0.1 粗档)。实现第一步抽验 scorer 打分是否够细;过粗则记录为已知局限并考虑候选池扩容补偿。 + +### 4.3 内联轻量对抗探针(`adversarial_probes.py`,仅 AR) + +生成候选通过 grounding 后、进正式门前,跑两个**便宜**探针(都不跑完整树搜索 agent): +- **text-only 盲答探针**:去掉视频/帧,只把 question+options 喂一个 LLM 盲选;答对(对 pair 是双向都对)→ 判"不看视频可解"→ 拒,回灌"该题能被纯文本解,请增强对视觉的依赖"重生。 +- **MiniMax 快解探针**:MiniMax-M3 在**不深搜**(只给采样帧+题)设定下试答;秒解 → 拒,回灌失败模式。 + +探针结果记 run_store 观测(供调参)。 + +### 4.4 门控收紧 + 独立歧义门 + +| 门 | v2 处置 | +|----|--------| +| key_verify | 保留 | +| multi_true | **收紧**:撤销 Phase A 松绑,回到"≥2 选项在题干限定下都完全为真→fail",且取向 precision over recall(宁杀错) | +| NLI 禁蕴含门(新,仅 AR) | 用 NLI 模型(如 Sentence-BERT / 现有文本 embed 近似)判正解与各干扰项**互不蕴含**;存在蕴含→fail(杀子串/最模糊项) | +| MiniMax 歧义门(新,仅 AR) | MiniMax-M3 独立判:是否有干扰项其实**也正确/语义等价于正解**;有→fail(独立于生成器的"错误性/wrongness"核验) | +| leak_test | 保留 | + +### 4.5 完整 agent 后置第二道网(改造 `adversarial_filter.py`) + +- **作弊者门**:定位为后置第二道网(非唯一裁判)。完整树搜索 agent 试答;对 pair 做**双向 AND**(P、Q 都答对=太简单→剔)。 +- **翻转门**:镜像已在生成期产出,**不再事后生成**;直接对 (P,Q) 做双向评对(reuse judge_flip:答案随问题翻转=有效,否则剔)。 +- 补生成迭代 / 难度报告 / 两份 JSON / verdicts 续跑:**保留**。 + +## 5. 契约改动(评测/训练适配) + +- `core/types.py::GeneratedQuestion` 新增:`pair_id: str | None`、`question_role: str`("single"|"pair_original"|"pair_mirror",默认 "single")、`flip_axis: str | None`。默认值保证 11 非 AR + 现有构造点不变。 +- **harness/eval 评分**:`question_role=="single"` 照常 MCQ;pair(同 `pair_id` 的 original+mirror)按**双向 AND**——两题都判对,pair 才计 1 分,否则 0。correctness 信号按 **pair 粒度**喂诊断/进化。 +- **loader/batching**:pair 作为**一个不可拆单元**进 batch(original 与 mirror 同批,避免跨批割裂)。 +- **AgentLoop 本身不改**:仍一次答一道 MCQ;pair 语义只在评分/聚合层。 +- **loader 读回**:`load_benchmark` 补 `pair_id`/`question_role`/`flip_axis`(`.get` 向后兼容旧 JSON)。 + +## 6. 错误处理 + +- grounding hard-fail(凑不齐 grounded 干扰项)→ 重出(reuse 现有机制); +- 镜像生成失败(造不出合法翻转对)→ 该 slot 退回 4 选对比集模式或重出(不产半个 pair); +- scorer VLM / 探针 VLM 异常 → slot 级隔离(对齐 Phase A C3 修复:宽异常→重出,不崩整批); +- NLI/歧义门模型不可用 → 明确报错(不静默跳过,防漏过歧义题)。 + +## 7. 非功能性需求 + +| 维度 | 设计 | +|------|------| +| **持久化** | on_accept 逐题追加;**pair 原子成对写**——P、Q 同时落盘或都不落(tmp 缓冲一对再 os.replace),崩溃不留半个 pair。selector/探针观测随题落 run_store | +| **幂等性** | 同 seed→同 slot;镜像由 flip_axis 确定性构造;VLM 非确定性为既有属性,不新增 | +| **断点续跑** | progress(slot→status);pair 以"整对完成"为 accepted 单位;后置 verdicts 表按 (question_id/hash/stage) 续跑 | +| **原子性** | 逐 slot / 逐 pair 落盘;final JSON 全量 tmp+os.replace;pair 半写检测(读回时校验成对完整,缺半剔除并重生) | + +## 8. 测试策略 + +- 单元:双模式分流(flippable→pair、非 flippable→4 选);bag-of-words 匹配校验;NLI 禁蕴含判定;text-only 探针与快解探针(mock VLM);pair 原子写/半写检测;双向 AND 评分。 +- 集成:AR 端到端(mock 主 VLM + mock scorer VLM + mock 探针)→ 验证 pair 成对落盘、非 flippable 走 4 选、门收紧生效;后置双向评对。 +- 回归:11 非 AR 题型 generate-v2 行为**字节级不变**(现有测试全绿);harness/loader 对混格题库(AR pair + 非 AR single)评分正确。 +- Agent 类测试产出 MD(§4.6 规范)。 + +## 9. 分期实现(一个设计,writing-plans 分阶段) + +1. **契约 + 双模式生成骨架**(GeneratedQuestion 新字段 + contrastive_gen 分流 + pair 落盘); +2. **独立 VLM grounding**(装配第二 VLM + selector 换 scorer + 粒度校验); +3. **内联对抗 + 门收紧 + NLI/歧义门**; +4. **后置双向评分 + 补生成**(改造 adversarial_filter); +5. **harness/eval/loader/batching 混格适配**。 + +## 10. 风险与回退 + +| 风险 | 回退 | +|------|------| +| MiniMax-M3 打分过粗/不准 | 扩候选池补偿;或记录为已知局限,后置 agent 门兜底 | +| 网关无 NLI 模型 | 用现有文本 embed 近似蕴含判定;或 LLM few-shot 判蕴含 | +| 混格题库拖累训练 | 分期 5 先验证评分正确性;必要时 AR pair 与非 AR 分池训练 | +| 双模式产量低(4 选非 flippable 侧 hard-fail 高) | 早停 + 补生成迭代兜底(reuse Phase B) | + +## 11. 核心算法保真 + +v2 局限于 question_gen 层,不迁移 `research-wiki/ARCHITECTURE.md §6` 的 12 项核心算法。作弊门复用既有 `run_inference`(AgentLoop 完整树搜索)未改内部。保真校验不适用。