Files
Video-Tree-TRM5/research-wiki/designs/2026-07-14-task-type-strategy-design.md
T

13 KiB
Raw Blame History

id, title, type, created, status
id title type created status
task-type-strategy 出题管线 TaskTypeStrategy 拆分设计(Clean Architecture design 2026-07-14 approved

出题管线 TaskTypeStrategy 拆分设计

1. 目标

借鉴 Clean Architecture 思想,将出题管线从 5 个粗粒度 Family 替换为 12 个题型级别的 TaskTypeStrategy,实现题型独立的出题策略。第一个特化实现为 ActionRecognitionStrategy(含 6 个失败子模式靶向出题)。

设计驱动

问题 数据来源
v2-360 全部 30 道 AR 题 100% 单帧可答 research-wiki/findings/2026-07-14-question-quality-gap-analysis.md
12/12 题型存在 CRITICAL 或 HIGH 差距 同上
同一 task_type 跨 family 随机选择导致行为不确定 app/question_gen/families.py — AR 同时在 RETRIEVAL 和 VISUAL
5 个 prompt 模板零题型分支 store/prompts/question_gen/*.md

2. 架构

2.1 替换关系

之前:pipeline → get_family_for_slot() → QuestionFamilySpec5 个,随机选择)
之后:pipeline → get_strategy(task_type) → TaskTypeStrategy12 个,确定性查找)

2.2 类层次

TaskTypeStrategy (Protocol)
    │
    ├── BaseTaskTypeStrategy (类)
    │     └── 封装现有 family 行为,确定性绑定一个 QuestionFamilySpec
    │     └── select_sub_pattern → None
    │     └── extra_gates → []
    │     └── 11 个题型用此类
    │
    └── ActionRecognitionStrategy (类)
          └── 自包含采样/prompt/SubPattern
          └── 仍提供 strategy_name / skill_target / leak_probe_templategate/store 合约)
          └── 6 个 SubPattern + maintenance_pool

2.3 接口定义

class TaskTypeStrategy(Protocol):
    """题型出题策略 — pipeline 的唯一接口。"""

    @property
    def task_type(self) -> str: ...

    # ── 采样 ──
    @property
    def sampling_level(self) -> int: ...
    @property
    def sampling_constraint(self) -> SamplingConstraint: ...

    # ── Prompt ──
    @property
    def prompt_template(self) -> str: ...
    def select_sub_pattern(self, rng: Random) -> SubPattern | None: ...
    def build_prompt_context(self, material: MaterialContext, sub_pattern: SubPattern | None) -> dict: ...

    # ── Gate / Store 合约 ──
    @property
    def strategy_name(self) -> str:
        """策略标识名,写入 store family 字段(如 "RETRIEVAL"、"ACTION_RECOGNITION")。"""
    @property
    def skill_target(self) -> str:
        """目标失败机制编号,写入 store(如 "M1"、"AR")。"""
    @property
    def leak_probe_template(self) -> str:
        """泄漏检测 prompt 模板文件名,供 leak_test gate 使用。"""

    def extra_gates(self, candidate: CandidateQuestion) -> list[GateResult]:
        """题型专属的额外验证(base 返回空列表)。"""

strategy_name / skill_target / leak_probe_template 替代了 pipeline 中对 slot.family.name / slot.family.skill_target / slot.family.leak_profile.probe_template 的访问,确保 gate 和 store 合约不破坏。

3. SubPattern 数据结构

@dataclass(frozen=True)
class SubPattern:
    """出题子模式 — 靶向特定失败机制。"""
    name: str
    weight: float
    sampling_level_override: int | None
    constraint_override: SamplingConstraint | None
    instruction: str                # 核心指令(1-3 句话)
    positive_examples: list[dict]   # VME 原题 few-shot
    negative_examples: list[dict]   # 反面示例
    distractor_rules: str           # 干扰项构造规则

4. ActionRecognitionStrategy 的 6 个 SubPattern

来源:22 道错题双分类器仲裁分析。

SubPattern 权重 采样 错题# 失败机制
premature_evidence_anchoring 0.20 L1 #3,4,12,17 找到一个证据就停搜,未验证全部选项
temporal_reasoning_failure 0.20 L1 #8,9,15,16 事件排序错误 / 无法定位第 N 次事件
semantic_rigidity 0.15 L2 #1,2,22 要求字面匹配,拒绝同义词释义
fine_grained_visual_action 0.15 L2 #6,13,14,18 识别"做了什么"但分不清"怎么做的"
cross_segment_entity_tracking 0.15 L1 #7,19,20 单段正确但无法跨段合并
evidence_gap_confabulation 0.15 L2 #5,10,11,21 缺证据时编造因果链

ActionRecognitionStrategy 的 gate/store 合约值

字段 说明
strategy_name "ACTION_RECOGNITION" store 的 family 字段
skill_target "M1_AR" 继承自 RETRIEVAL 的 M1 + AR 后缀区分
leak_probe_template "gate_leak_retrieval.md" 复用 RETRIEVAL 的泄漏检测模板
sampling_level(默认) 2 L2 事件级(从 L3 提升,有意变更)
sampling_constraint(默认) min_subtitles=3, min_l3_nodes=5, require_frames=True, cross_l2_span=True 加强约束(有意变更)

SubPattern 可通过 sampling_level_override / constraint_override 进一步覆盖默认值。

4.1 能力保持机制

capability_maintenance 不是生成子模式,而是采样来源:从 Video-MME AR 的 41 道正确题中采样,直接进训练集。通过 batch_correct_ratio 控制混合比例。

训练 batch 组成:
  ├── 错误题来源: 6 个 SubPattern 生成的新题
  └── 正确题来源: maintenance_pool (41 道已验证正确的 VME 原题)

5. pipeline 集成

5.1 调用链变更

之前: slot.family → sample_material_v2(family_spec=...) → generate_one_v2(family_spec=...)
                  → run_gates(family_spec=...) → store.record_item(family=slot.family.name)

之后: strategy = get_strategy(slot.task_type)
      sub_pattern = strategy.select_sub_pattern(rng)
      level = sub_pattern.sampling_level_override or strategy.sampling_level
      constraint = sub_pattern.constraint_override or strategy.sampling_constraint
      material = sample_material_v2(level=level, constraint=constraint, ...)
      prompt_ctx = strategy.build_prompt_context(material, sub_pattern)
      candidate = generate_one_v2(prompt_ctx=prompt_ctx, ...)
      report = run_gates(candidate, leak_template=strategy.leak_probe_template, ...)
      extra = strategy.extra_gates(candidate)
      store.record_item(..., family=strategy.strategy_name, skill_target=strategy.skill_target,
                        sub_pattern=sub_pattern.name if sub_pattern else None)

5.2 接口影响面

文件 变更 影响范围
sampler_v2.py sample_material_v2 签名:family_speclevel: int + constraint: SamplingConstraint 函数签名 + 内部 constraint = family_spec.sampling
pipeline_v2.py _process_one_slotslot.familystrategySlotAssignment.family 字段移除 _assign_slots / _process_one_slot / _process_wrapper
generator_v2.py generate_one_v2 签名:新增 prompt_ctx: dict 参数,替代内部读 family_spec.prompt_template _build_v2_prompt / generate_one_v2
gates.py run_gates 签名:family_specleak_template: str _run_leak_test 参数变更
run_store.py record_item 新增 `sub_pattern: str None` 参数

5.3 不变的部分

后处理(postprocess)、四门 gate 内部逻辑、去重(embedding)、重量抽检(heavy_check)、on_accept 回调、progress 断点续跑 — 全部不动。

6. Strategy 注册

_STRATEGY_REGISTRY: dict[str, TaskTypeStrategy] = {}

def get_strategy(task_type: str) -> TaskTypeStrategy:
    if task_type in _STRATEGY_REGISTRY:
        return _STRATEGY_REGISTRY[task_type]
    return _build_default_strategy(task_type)

6.1 BaseTaskTypeStrategy family 消歧绑定表

消除多 family 随机性。每个 task_type 确定性绑定一个 family。

task_type 旧合法 families 新绑定 被移除行为 理由
Action Recognition RETRIEVAL, VISUAL 特化策略 不走 family 完全自包含
Object Recognition RETRIEVAL RETRIEVAL 唯一
Object Reasoning RETRIEVAL, REASONING REASONING RETRIEVAL 的 L3 单帧 + 禁推理 prompt 需要推理;RETRIEVAL 产出识别题是已知 bug
Action Reasoning REASONING REASONING 唯一
Attribute Perception RETRIEVAL, VISUAL VISUAL RETRIEVAL 的 require_frames=False 属性感知需要帧
OCR Problems RETRIEVAL, VISUAL VISUAL RETRIEVAL 的 require_frames=False OCR 需要帧
Counting Problem ENUMERATION, VISUAL ENUMERATION VISUAL 的 L3 单帧采样 计数需要跨帧
Information Synopsis REASONING, ENUMERATION REASONING ENUMERATION 的 cross_l2_span=False 综述需要跨段
Temporal Reasoning ENUMERATION ENUMERATION 唯一
Temporal Perception ENUMERATION ENUMERATION 唯一
Spatial Reasoning SPATIAL SPATIAL 唯一
Spatial Perception SPATIAL SPATIAL 唯一

6.2 多归属题型约束变化明细

确定性绑定会改变多归属题型的采样约束,这是有意的行为变更(旧行为是随机混合,本身就是不可控的)。

task_type 旧约束(随机选择) 新约束(确定绑定) 变化
Object Reasoning RETRIEVAL(L3,no-frame,no-cross) 或 REASONING(L2,no-frame,cross) REASONING 固定 不再退化为 L3 识别题
Attribute Perception RETRIEVAL(no-frame) 或 VISUAL(frame) VISUAL 固定 始终要求帧
OCR Problems RETRIEVAL(no-frame) 或 VISUAL(frame) VISUAL 固定 始终要求帧
Counting Problem ENUMERATION(no-frame) 或 VISUAL(frame) ENUMERATION 固定 不再混入 VISUAL 的 L3 采样
Information Synopsis REASONING(cross) 或 ENUMERATION(no-cross) REASONING 固定 始终跨段

7. 文件结构

操作 文件 职责
新建 app/question_gen/strategy.py Protocol + SubPattern + BaseTaskTypeStrategy + 注册表
新建 app/question_gen/strategy_action_recognition.py ActionRecognitionStrategy 实现 + 6 个 SubPattern 定义
修改 app/question_gen/pipeline_v2.py _process_one_slot / _assign_slots 改为通过 strategy
修改 app/question_gen/sampler_v2.py 签名 family_speclevel + constraint
修改 app/question_gen/generator_v2.py 签名 family_specprompt_ctx
修改 app/question_gen/gates.py run_gates 签名 family_specleak_template
修改 app/question_gen/run_store.py record_item 新增 sub_pattern 参数 + DDL 加列
不动 app/question_gen/families.py 保留,BaseTaskTypeStrategy 内部使用
不动 app/question_gen/postprocess.py 后处理不变

8. 非功能性需求

维度 设计
持久化 不变 — on_accept 逐题回调。SubPattern 名写入 store 的 sub_pattern 列以便追溯
幂等性 不变 — 同 seed → 同 slot 分配。strategy 查找确定性,sub_pattern 选择由 rng 控制
断点续跑 不变 — progress 机制在 pipeline 层,strategy 无状态
原子性 不变 — 逐题落库
store 迁移 question_gen_items 表新增 sub_pattern TEXT 列,默认 NULLBaseTaskTypeStrategy 写 NULL

9. 行为保真检查清单

# 行为 状态 说明
1 12 种 task_type 列表 保留 pipeline 不变
2 slot round-robin 视频 保留 pipeline 不变
3 family 加权随机选择 有意变更 消除不确定性 → 确定性绑定。详见 §6.2
4 _TASK_TYPE_TO_LEVEL 映射 有意变更 BaseTaskTypeStrategy 从绑定 family 读取原值(唯一归属题型数值不变);AR 特化策略从 L3→L2(有意提升);多归属题型因消歧而变化(详见 §6.2)
5 SamplingConstraint 约束 有意变更 同 #4 逻辑:唯一归属不变,多归属因消歧变化,AR 有意加强
6 重出循环 + 换视频 保留
7 后处理洗牌 + verbatim 保留
8 四门 gate 保留 leak_test 通过 strategy.leak_probe_template 获取模板
9 embedding 去重 保留
10 重量抽检 保留
11 on_accept 回调 保留
12 progress 断点续跑 保留
13 reject_reason 传入重出 保留
14 QuestionGenStore 记录 保留 family → strategy_name;新增 sub_pattern 列

10. 渐进替换路径

Phase 1 (当前): ActionRecognitionStrategy 特化 + 11 个 BaseTaskTypeStrategy
Phase 2 (按需): 逐个替换表现差的题型为特化策略
Phase N (最终): 12 个特化策略,families.py 可移除