docs: add Plan B — ActionRecognitionStrategy implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -165,6 +165,11 @@
|
|||||||
"id": "plan:task-type-strategy-framework",
|
"id": "plan:task-type-strategy-framework",
|
||||||
"label": "TaskTypeStrategy 框架实现计划 (Plan A)",
|
"label": "TaskTypeStrategy 框架实现计划 (Plan A)",
|
||||||
"type": "plan"
|
"type": "plan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "plan:action-recognition-strategy",
|
||||||
|
"label": "ActionRecognitionStrategy 特化实现计划 (Plan B)",
|
||||||
|
"type": "plan"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [
|
"links": [
|
||||||
@@ -300,6 +305,13 @@
|
|||||||
"relation": "implements",
|
"relation": "implements",
|
||||||
"evidence": "Plan A 实现设计中的框架层(Protocol + Base + pipeline 集成)",
|
"evidence": "Plan A 实现设计中的框架层(Protocol + Base + pipeline 集成)",
|
||||||
"added": "2026-07-14T09:15:22.951263+00:00"
|
"added": "2026-07-14T09:15:22.951263+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "plan:action-recognition-strategy",
|
||||||
|
"target": "design:task-type-strategy",
|
||||||
|
"relation": "implements",
|
||||||
|
"evidence": "Plan B implements design §4: ActionRecognitionStrategy with 6 SubPatterns",
|
||||||
|
"added": "2026-07-14T10:34:27.079088+00:00"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Research Wiki 索引
|
# Research Wiki 索引
|
||||||
|
|
||||||
> 自动生成,更新时间:2026-07-14 09:15 UTC
|
> 自动生成,更新时间:2026-07-14 10:34 UTC
|
||||||
|
|
||||||
## design (25)
|
## design (25)
|
||||||
- [2026-07-06-core-agent-adapters-llm-design](designs/2026-07-06-core-agent-adapters-llm-design.md) `design:2026-07-06-core-agent-adapters-llm-design`
|
- [2026-07-06-core-agent-adapters-llm-design](designs/2026-07-06-core-agent-adapters-llm-design.md) `design:2026-07-06-core-agent-adapters-llm-design`
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
- [Harness 评估: Spec-1 修复验证 (infer_spec1check)](findings/eval-spec1check.md) `finding:eval-spec1check`
|
- [Harness 评估: Spec-1 修复验证 (infer_spec1check)](findings/eval-spec1check.md) `finding:eval-spec1check`
|
||||||
- [Harness 评估: Spec-2 批量并行建树](findings/eval-spec2-batch-tree-build.md) `finding:eval-spec2-batch-tree-build`
|
- [Harness 评估: Spec-2 批量并行建树](findings/eval-spec2-batch-tree-build.md) `finding:eval-spec2-batch-tree-build`
|
||||||
|
|
||||||
## plan (28)
|
## plan (30)
|
||||||
- [2026-07-06-core-agent-adapters-llm](plans/2026-07-06-core-agent-adapters-llm.md) `plan:2026-07-06-core-agent-adapters-llm`
|
- [2026-07-06-core-agent-adapters-llm](plans/2026-07-06-core-agent-adapters-llm.md) `plan:2026-07-06-core-agent-adapters-llm`
|
||||||
- [2026-07-07-app-harness](plans/2026-07-07-app-harness.md) `plan:2026-07-07-app-harness`
|
- [2026-07-07-app-harness](plans/2026-07-07-app-harness.md) `plan:2026-07-07-app-harness`
|
||||||
- [2026-07-07-core-evolution](plans/2026-07-07-core-evolution.md) `plan:2026-07-07-core-evolution`
|
- [2026-07-07-core-evolution](plans/2026-07-07-core-evolution.md) `plan:2026-07-07-core-evolution`
|
||||||
@@ -48,9 +48,11 @@
|
|||||||
- [2026-07-11-agent-runtime-fixes](plans/2026-07-11-agent-runtime-fixes.md) `plan:2026-07-11-agent-runtime-fixes`
|
- [2026-07-11-agent-runtime-fixes](plans/2026-07-11-agent-runtime-fixes.md) `plan:2026-07-11-agent-runtime-fixes`
|
||||||
- [2026-07-11-batch-tree-build](plans/2026-07-11-batch-tree-build.md) `plan:2026-07-11-batch-tree-build`
|
- [2026-07-11-batch-tree-build](plans/2026-07-11-batch-tree-build.md) `plan:2026-07-11-batch-tree-build`
|
||||||
- [2026-07-12-per-category-pool-strategy](plans/2026-07-12-per-category-pool-strategy.md) `plan:2026-07-12-per-category-pool-strategy`
|
- [2026-07-12-per-category-pool-strategy](plans/2026-07-12-per-category-pool-strategy.md) `plan:2026-07-12-per-category-pool-strategy`
|
||||||
|
- [2026-07-14-action-recognition-strategy](plans/2026-07-14-action-recognition-strategy.md) `plan:2026-07-14-action-recognition-strategy`
|
||||||
- [2026-07-14-action-recognition-training](plans/2026-07-14-action-recognition-training.md) `plan:2026-07-14-action-recognition-training`
|
- [2026-07-14-action-recognition-training](plans/2026-07-14-action-recognition-training.md) `plan:2026-07-14-action-recognition-training`
|
||||||
- [2026-07-14-task-type-strategy-framework](plans/2026-07-14-task-type-strategy-framework.md) `plan:2026-07-14-task-type-strategy-framework`
|
- [2026-07-14-task-type-strategy-framework](plans/2026-07-14-task-type-strategy-framework.md) `plan:2026-07-14-task-type-strategy-framework`
|
||||||
- [Action Recognition 单题型首次训练实验计划](plans/action-recognition-training.md) `plan:action-recognition-training`
|
- [Action Recognition 单题型首次训练实验计划](plans/action-recognition-training.md) `plan:action-recognition-training`
|
||||||
|
- [ActionRecognitionStrategy 特化实现计划 (Plan B)](plans/action-recognition-strategy.md) `plan:action-recognition-strategy`
|
||||||
- [app/harness/ 训练循环编排层实现计划](plans/app-harness.md) `plan:app-harness`
|
- [app/harness/ 训练循环编排层实现计划](plans/app-harness.md) `plan:app-harness`
|
||||||
- [app/search/ 搜索 Agent 装配层实现计划](plans/2026-07-07-search-module.md) `plan:2026-07-07-search-module`
|
- [app/search/ 搜索 Agent 装配层实现计划](plans/2026-07-07-search-module.md) `plan:2026-07-07-search-module`
|
||||||
- [core/agent/ + adapters/llm 基础设施实现计划](plans/core-agent-adapters-llm.md) `plan:core-agent-adapters-llm`
|
- [core/agent/ + adapters/llm 基础设施实现计划](plans/core-agent-adapters-llm.md) `plan:core-agent-adapters-llm`
|
||||||
|
|||||||
@@ -76,3 +76,6 @@
|
|||||||
- [2026-07-14 09:15 UTC] 新增 plan: TaskTypeStrategy 框架实现计划 (Plan A) (plan:task-type-strategy-framework)
|
- [2026-07-14 09:15 UTC] 新增 plan: TaskTypeStrategy 框架实现计划 (Plan A) (plan:task-type-strategy-framework)
|
||||||
- [2026-07-14 09:15 UTC] 新增边: plan:task-type-strategy-framework --implements--> design:task-type-strategy
|
- [2026-07-14 09:15 UTC] 新增边: plan:task-type-strategy-framework --implements--> design:task-type-strategy
|
||||||
- [2026-07-14 09:15 UTC] 重建索引: 64 篇页面
|
- [2026-07-14 09:15 UTC] 重建索引: 64 篇页面
|
||||||
|
- [2026-07-14 10:34 UTC] 新增 plan: ActionRecognitionStrategy 特化实现计划 (Plan B) (plan:action-recognition-strategy)
|
||||||
|
- [2026-07-14 10:34 UTC] 新增边: plan:action-recognition-strategy --implements--> design:task-type-strategy
|
||||||
|
- [2026-07-14 10:34 UTC] 重建索引: 66 篇页面
|
||||||
|
|||||||
@@ -0,0 +1,774 @@
|
|||||||
|
# ActionRecognitionStrategy 特化实现计划 (Plan B)
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** 实现 ActionRecognitionStrategy 特化策略(6 个 SubPattern + AR 专属 prompt),替换 Plan A 中 AR 的临时 VISUAL_FAMILY 绑定,使 AR 出题靶向 22 道错题的 6 种失败子模式。
|
||||||
|
|
||||||
|
**Architecture:** 新建 `strategy_action_recognition.py`(ActionRecognitionStrategy 类 + 6 个 SubPattern 定义),新建 `action_recognition.md` prompt 模板,在 `strategy.py` 的模块初始化中注册。Pipeline 无需改动 —— Plan A 已接好全部 sub_pattern 接口(`instruction`、`sampling_level_override`、`constraint_override`)。
|
||||||
|
|
||||||
|
**Tech Stack:** Python 3.11, pytest, Protocol (typing)
|
||||||
|
|
||||||
|
**关联设计:** `research-wiki/designs/2026-07-14-task-type-strategy-design.md` §4
|
||||||
|
|
||||||
|
**范围:** 仅 Plan B(ActionRecognitionStrategy 特化)。不改 pipeline、sampler、generator、gates、store。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: AR 专属 prompt 模板
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `store/prompts/question_gen/action_recognition.md`
|
||||||
|
|
||||||
|
- [ ] **Step 1: 创建 AR 专属 prompt 模板**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
You are a question generator for video understanding benchmarks, specializing in **Action Recognition**.
|
||||||
|
|
||||||
|
Your task: Generate a multiple-choice question that tests whether the answerer can accurately recognize, distinguish, and reason about **actions and behaviors** observed across multiple segments of the video.
|
||||||
|
|
||||||
|
## Action Recognition Guidelines
|
||||||
|
|
||||||
|
- The question MUST require watching multiple segments or the full video — single-frame-answerable questions are failures.
|
||||||
|
- Focus on **dynamic actions**: what someone does, how they do it, the sequence of actions, or which action is absent.
|
||||||
|
- The correct answer must be grounded in observable behavior (body movements, interactions, operations), NOT in static visual attributes or text/OCR.
|
||||||
|
- Questions should target action details that require temporal tracking: order of events, manner of execution, repetition counts, or cross-segment entity behavior.
|
||||||
|
|
||||||
|
## Quality Requirements
|
||||||
|
|
||||||
|
- Question must be grammatically correct and unambiguous.
|
||||||
|
- All four options must be parallel in structure and length.
|
||||||
|
- The correct answer must not be identifiable from linguistic cues alone.
|
||||||
|
- Each option must begin with "A. ", "B. ", "C. ", or "D. ".
|
||||||
|
|
||||||
|
## Prohibited Patterns
|
||||||
|
|
||||||
|
- Do NOT generate questions answerable from a single frame or screenshot — if pausing the video at one moment gives the answer, the question is too easy.
|
||||||
|
- Do NOT generate OCR/text-reading questions disguised as action recognition — reading jersey numbers, scoreboards, or on-screen text is NOT action recognition.
|
||||||
|
- Do NOT fabricate actions not observable in the provided material.
|
||||||
|
- Do NOT construct options where the correct answer is obvious from common sense or world knowledge alone.
|
||||||
|
- Do NOT write questions where multiple options could reasonably be correct.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
Respond with ONLY a valid JSON object. No additional text.
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: 验证模板可加载**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM python -c "
|
||||||
|
from app.question_gen.generator_v2 import _load_prompt_template
|
||||||
|
content = _load_prompt_template('action_recognition.md')
|
||||||
|
assert 'Action Recognition' in content
|
||||||
|
print('OK: action_recognition.md loaded successfully')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:打印 OK 消息,无异常。
|
||||||
|
|
||||||
|
- [ ] **Step 3: 提交**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add store/prompts/question_gen/action_recognition.md
|
||||||
|
git commit -m "feat(question_gen): add Action Recognition specialized prompt template"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: ActionRecognitionStrategy 类 + 6 个 SubPattern
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `app/question_gen/strategy_action_recognition.py`
|
||||||
|
- Test: `tests/unit/test_strategy_action_recognition.py`
|
||||||
|
|
||||||
|
- [ ] **Step 1: 写失败测试**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# tests/unit/test_strategy_action_recognition.py
|
||||||
|
"""ActionRecognitionStrategy 单元测试。"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from app.question_gen.strategy_action_recognition import (
|
||||||
|
AR_SUB_PATTERNS,
|
||||||
|
ActionRecognitionStrategy,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestActionRecognitionStrategy:
|
||||||
|
"""ActionRecognitionStrategy 属性和行为。"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def strategy(self) -> ActionRecognitionStrategy:
|
||||||
|
"""创建策略实例。"""
|
||||||
|
return ActionRecognitionStrategy()
|
||||||
|
|
||||||
|
def test_task_type(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""task_type 固定为 Action Recognition。"""
|
||||||
|
assert strategy.task_type == "Action Recognition"
|
||||||
|
|
||||||
|
def test_strategy_name(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""strategy_name 为 ACTION_RECOGNITION。"""
|
||||||
|
assert strategy.strategy_name == "ACTION_RECOGNITION"
|
||||||
|
|
||||||
|
def test_skill_target(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""skill_target 为 M1_AR。"""
|
||||||
|
assert strategy.skill_target == "M1_AR"
|
||||||
|
|
||||||
|
def test_sampling_level(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""默认采样层级为 L2。"""
|
||||||
|
assert strategy.sampling_level == 2
|
||||||
|
|
||||||
|
def test_sampling_constraint(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""采样约束加强:min_subtitles=3, min_l3_nodes=5, require_frames=True, cross_l2_span=True。"""
|
||||||
|
c = strategy.sampling_constraint
|
||||||
|
assert c.min_subtitles == 3
|
||||||
|
assert c.min_l3_nodes == 5
|
||||||
|
assert c.require_frames is True
|
||||||
|
assert c.cross_l2_span is True
|
||||||
|
|
||||||
|
def test_prompt_template(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""使用 AR 专属 prompt 模板。"""
|
||||||
|
assert strategy.prompt_template == "action_recognition.md"
|
||||||
|
|
||||||
|
def test_leak_probe_template(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""复用 RETRIEVAL 的泄漏检测模板。"""
|
||||||
|
assert strategy.leak_probe_template == "gate_leak_retrieval.md"
|
||||||
|
|
||||||
|
def test_extra_gates_empty(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""当前版本无额外 gate。"""
|
||||||
|
assert strategy.extra_gates(None) == []
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubPatternSelection:
|
||||||
|
"""select_sub_pattern 行为。"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def strategy(self) -> ActionRecognitionStrategy:
|
||||||
|
return ActionRecognitionStrategy()
|
||||||
|
|
||||||
|
def test_returns_sub_pattern(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""select_sub_pattern 返回 SubPattern 而非 None。"""
|
||||||
|
rng = random.Random(42)
|
||||||
|
sp = strategy.select_sub_pattern(rng)
|
||||||
|
assert sp is not None
|
||||||
|
assert sp.name in [p.name for p in AR_SUB_PATTERNS]
|
||||||
|
|
||||||
|
def test_deterministic_with_same_seed(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""相同 seed 返回相同 SubPattern。"""
|
||||||
|
sp1 = strategy.select_sub_pattern(random.Random(42))
|
||||||
|
sp2 = strategy.select_sub_pattern(random.Random(42))
|
||||||
|
assert sp1.name == sp2.name
|
||||||
|
|
||||||
|
def test_distribution_covers_all_patterns(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""足够多次采样应覆盖全部 6 个子模式。"""
|
||||||
|
rng = random.Random(123)
|
||||||
|
names = {strategy.select_sub_pattern(rng).name for _ in range(200)}
|
||||||
|
assert len(names) == 6
|
||||||
|
|
||||||
|
def test_sub_pattern_has_instruction(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""每个 SubPattern 都有非空 instruction。"""
|
||||||
|
for sp in AR_SUB_PATTERNS:
|
||||||
|
assert sp.instruction.strip(), f"{sp.name} 的 instruction 为空"
|
||||||
|
|
||||||
|
def test_sub_pattern_has_distractor_rules(self, strategy: ActionRecognitionStrategy) -> None:
|
||||||
|
"""每个 SubPattern 都有非空 distractor_rules。"""
|
||||||
|
for sp in AR_SUB_PATTERNS:
|
||||||
|
assert sp.distractor_rules.strip(), f"{sp.name} 的 distractor_rules 为空"
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubPatternOverrides:
|
||||||
|
"""SubPattern 的 sampling 覆盖。"""
|
||||||
|
|
||||||
|
def test_l1_patterns_override_level(self) -> None:
|
||||||
|
"""L1 子模式覆盖默认的 L2 采样层级。"""
|
||||||
|
l1_names = {"premature_evidence_anchoring", "temporal_reasoning_failure", "cross_segment_entity_tracking"}
|
||||||
|
for sp in AR_SUB_PATTERNS:
|
||||||
|
if sp.name in l1_names:
|
||||||
|
assert sp.sampling_level_override == 1, f"{sp.name} 应覆盖为 L1"
|
||||||
|
else:
|
||||||
|
assert sp.sampling_level_override is None, f"{sp.name} 不应覆盖采样层级"
|
||||||
|
|
||||||
|
def test_weights_sum_to_one(self) -> None:
|
||||||
|
"""权重总和为 1.0。"""
|
||||||
|
total = sum(sp.weight for sp in AR_SUB_PATTERNS)
|
||||||
|
assert abs(total - 1.0) < 1e-9
|
||||||
|
|
||||||
|
def test_individual_weights_match_design(self) -> None:
|
||||||
|
"""每个子模式权重与设计文档一致。"""
|
||||||
|
expected = {
|
||||||
|
"premature_evidence_anchoring": 0.20,
|
||||||
|
"temporal_reasoning_failure": 0.20,
|
||||||
|
"semantic_rigidity": 0.15,
|
||||||
|
"fine_grained_visual_action": 0.15,
|
||||||
|
"cross_segment_entity_tracking": 0.15,
|
||||||
|
"evidence_gap_confabulation": 0.15,
|
||||||
|
}
|
||||||
|
for sp in AR_SUB_PATTERNS:
|
||||||
|
assert abs(sp.weight - expected[sp.name]) < 1e-9, f"{sp.name} 权重不匹配"
|
||||||
|
|
||||||
|
def test_all_six_patterns_defined(self) -> None:
|
||||||
|
"""定义了 6 个子模式。"""
|
||||||
|
assert len(AR_SUB_PATTERNS) == 6
|
||||||
|
expected_names = {
|
||||||
|
"premature_evidence_anchoring",
|
||||||
|
"temporal_reasoning_failure",
|
||||||
|
"semantic_rigidity",
|
||||||
|
"fine_grained_visual_action",
|
||||||
|
"cross_segment_entity_tracking",
|
||||||
|
"evidence_gap_confabulation",
|
||||||
|
}
|
||||||
|
actual_names = {sp.name for sp in AR_SUB_PATTERNS}
|
||||||
|
assert actual_names == expected_names
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: 运行测试验证失败**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM pytest tests/unit/test_strategy_action_recognition.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:ImportError — `app.question_gen.strategy_action_recognition` 不存在。
|
||||||
|
|
||||||
|
- [ ] **Step 3: 实现 strategy_action_recognition.py**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/question_gen/strategy_action_recognition.py
|
||||||
|
"""Action Recognition 特化出题策略 — 靶向 6 种失败子模式。
|
||||||
|
|
||||||
|
来源:22 道 VME AR 错题双分类器仲裁分析。
|
||||||
|
每个 SubPattern 定义独立的 instruction、采样覆盖、干扰项构造规则,
|
||||||
|
由 pipeline 在出题时注入到 prompt 的 Special Focus 区段。
|
||||||
|
|
||||||
|
设计文档: research-wiki/designs/2026-07-14-task-type-strategy-design.md §4
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
from app.question_gen.families import SamplingConstraint
|
||||||
|
from app.question_gen.strategy import SubPattern
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 默认采样约束(设计文档 §4 定义)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_AR_DEFAULT_CONSTRAINT = SamplingConstraint(
|
||||||
|
min_subtitles=3,
|
||||||
|
min_l3_nodes=5,
|
||||||
|
require_frames=True,
|
||||||
|
cross_l2_span=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 6 个 SubPattern 定义
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_SP_PREMATURE_EVIDENCE_ANCHORING = SubPattern(
|
||||||
|
name="premature_evidence_anchoring",
|
||||||
|
weight=0.20,
|
||||||
|
sampling_level_override=1,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question where the correct answer requires verifying evidence across "
|
||||||
|
"ALL options before committing — not just finding one matching piece of evidence. "
|
||||||
|
"The video must contain a plausible-looking but incorrect match that appears early "
|
||||||
|
"or prominently, while the true answer is confirmed only by cross-referencing "
|
||||||
|
"multiple segments. The question should punish an agent that stops searching after "
|
||||||
|
"the first evidence match."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "Which of the following tasks did the heroine not complete while her baby was sleeping?",
|
||||||
|
"answer": "D. Doing laundry",
|
||||||
|
"why": "Requires checking all 4 options against all segments; stopping at first match misses the negation.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Which acrobatic skill is absent from this video?",
|
||||||
|
"answer": "D. Somersault",
|
||||||
|
"why": "Must verify every option against every segment to confirm absence.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "What color jersey does the player wear?",
|
||||||
|
"why": "Single-frame answerable, no need to verify across segments.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"Place the most visually salient or early-appearing action as a distractor (not the answer). "
|
||||||
|
"Make one distractor partially correct (happens in a different segment or by a different person). "
|
||||||
|
"The correct answer should require exhaustive verification across segments."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_SP_TEMPORAL_REASONING_FAILURE = SubPattern(
|
||||||
|
name="temporal_reasoning_failure",
|
||||||
|
weight=0.20,
|
||||||
|
sampling_level_override=1,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question that requires precise temporal ordering or locating the Nth "
|
||||||
|
"occurrence of an event. The video must contain the same or similar action happening "
|
||||||
|
"multiple times, and the question must specify a temporal anchor (e.g., 'after X happens', "
|
||||||
|
"'the second time', 'at the beginning'). The correct answer depends on getting the "
|
||||||
|
"sequence order right."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "In the video after feeding the ducks, what did the male protagonist do after riding his bike?",
|
||||||
|
"answer": "A. Went jogging in the park",
|
||||||
|
"why": "Requires precise temporal chain: feeding → biking → next action.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "What happened to the team on the counterattack after Sabonis' first steal?",
|
||||||
|
"answer": "D. They scored a three-pointer",
|
||||||
|
"why": "Must locate the FIRST steal (not second) and track what follows.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "What does the person do in the video?",
|
||||||
|
"why": "No temporal anchor, any observation suffices.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"Include actions that genuinely occur in the video but at a different time point. "
|
||||||
|
"One distractor should be what happens before the anchored moment. "
|
||||||
|
"Another should be what happens after the Nth+1 occurrence (off-by-one trap)."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_SP_SEMANTIC_RIGIDITY = SubPattern(
|
||||||
|
name="semantic_rigidity",
|
||||||
|
weight=0.15,
|
||||||
|
sampling_level_override=None,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question where the correct answer option uses a synonym, paraphrase, or "
|
||||||
|
"semantic equivalent of what is shown in the video — NOT the exact words from subtitles. "
|
||||||
|
"The agent must recognize that a rephrased description matches the observed action. "
|
||||||
|
"Include a distractor that uses near-verbatim subtitle wording but describes a "
|
||||||
|
"different or incorrect action."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "What are the magic tricks about?",
|
||||||
|
"answer": "B. Sleight of hand with everyday objects",
|
||||||
|
"why": "Video shows card and coin manipulation; correct answer paraphrases rather than quoting subtitles.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "According to the narrator, what is the main topic?",
|
||||||
|
"why": "Invites verbatim subtitle matching, not semantic understanding.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"One distractor must reuse exact subtitle phrasing but apply it to the wrong action/context. "
|
||||||
|
"Another distractor should use a semantically related but distinct action verb "
|
||||||
|
"(e.g., 'cutting' vs 'slicing' vs 'chopping' when only one is correct). "
|
||||||
|
"The correct answer must be a valid semantic equivalent, not a stretch."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_SP_FINE_GRAINED_VISUAL_ACTION = SubPattern(
|
||||||
|
name="fine_grained_visual_action",
|
||||||
|
weight=0.15,
|
||||||
|
sampling_level_override=None,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question that distinguishes between visually similar actions — "
|
||||||
|
"the MANNER of how something is done, not just WHAT is done. "
|
||||||
|
"The video must show a specific technique, method, or style of performing an action, "
|
||||||
|
"and the question must test whether the agent can differentiate it from similar alternatives. "
|
||||||
|
"Frames are essential — the answer cannot come from subtitles alone."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "How does the chef prepare the garlic in this recipe?",
|
||||||
|
"answer": "C. Crushes it with the flat side of a knife",
|
||||||
|
"why": "All options are valid garlic preparations; only visual observation distinguishes.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "What does the man with a laughing face do at the beginning of the video?",
|
||||||
|
"answer": "C. Clasps his hands together and bows",
|
||||||
|
"why": "Specific gesture detail requires frame-level observation.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "Does the person cook in the video?",
|
||||||
|
"why": "Binary yes/no, no manner distinction needed.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"All four options must describe the same general category of action "
|
||||||
|
"(e.g., all are ways of cutting, all are types of greetings). "
|
||||||
|
"Distractors must be visually plausible alternatives that could occur in the same context. "
|
||||||
|
"The distinction must be observable only from frames, not from subtitles."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_SP_CROSS_SEGMENT_ENTITY_TRACKING = SubPattern(
|
||||||
|
name="cross_segment_entity_tracking",
|
||||||
|
weight=0.15,
|
||||||
|
sampling_level_override=1,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question that requires tracking a specific entity (person, object, or group) "
|
||||||
|
"across multiple video segments and merging observations. The correct answer depends on "
|
||||||
|
"information from at least two separate segments — a single segment gives only a partial "
|
||||||
|
"or misleading picture. The entity must appear in different contexts or states across segments."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "In the video, what happened in the car when the heroine came home from shopping?",
|
||||||
|
"answer": "D. The car wouldn't start and she had to call for help",
|
||||||
|
"why": "Must track heroine across shopping segment → car segment → resolution.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "What is the person wearing?",
|
||||||
|
"why": "Single-segment observation, no cross-segment tracking needed.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"One distractor should be correct for the entity in a DIFFERENT segment (right entity, wrong time). "
|
||||||
|
"Another distractor should be correct for a DIFFERENT entity in the same segment (right time, wrong entity). "
|
||||||
|
"The correct answer must require merging observations from multiple segments."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_SP_EVIDENCE_GAP_CONFABULATION = SubPattern(
|
||||||
|
name="evidence_gap_confabulation",
|
||||||
|
weight=0.15,
|
||||||
|
sampling_level_override=None,
|
||||||
|
constraint_override=None,
|
||||||
|
instruction=(
|
||||||
|
"Generate a question about an action where the video evidence is INCOMPLETE — "
|
||||||
|
"the full causal chain is not directly shown. The correct answer is the one that "
|
||||||
|
"stays faithful to what IS observable, while distractors fill in the gap with "
|
||||||
|
"plausible but unsupported causal narratives. The agent must resist inventing "
|
||||||
|
"explanations for unobserved transitions."
|
||||||
|
),
|
||||||
|
positive_examples=[
|
||||||
|
{
|
||||||
|
"question": "How were the Sawtooth ranges formed?",
|
||||||
|
"answer": "D. The video describes geological uplift but does not show the formation process",
|
||||||
|
"why": "Video describes result but not process; agent must not confabulate mechanism.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
negative_examples=[
|
||||||
|
{
|
||||||
|
"question": "Why did the person leave the room?",
|
||||||
|
"why": "If the reason is explicitly stated in dialogue, no evidence gap exists.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
distractor_rules=(
|
||||||
|
"Distractors must be plausible causal narratives that COULD explain the outcome but "
|
||||||
|
"are NOT supported by the video evidence. Each distractor should fill the evidence gap "
|
||||||
|
"with a different invented mechanism. The correct answer must be the one that "
|
||||||
|
"either: (a) states only what is directly observable, or (b) acknowledges the limitation."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# 导出 tuple(不可变,按名称排序供测试)
|
||||||
|
AR_SUB_PATTERNS: tuple[SubPattern, ...] = (
|
||||||
|
_SP_PREMATURE_EVIDENCE_ANCHORING,
|
||||||
|
_SP_TEMPORAL_REASONING_FAILURE,
|
||||||
|
_SP_SEMANTIC_RIGIDITY,
|
||||||
|
_SP_FINE_GRAINED_VISUAL_ACTION,
|
||||||
|
_SP_CROSS_SEGMENT_ENTITY_TRACKING,
|
||||||
|
_SP_EVIDENCE_GAP_CONFABULATION,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Strategy 实现
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class ActionRecognitionStrategy:
|
||||||
|
"""Action Recognition 特化出题策略。
|
||||||
|
|
||||||
|
自包含 —— 不依赖 QuestionFamilySpec,直接定义采样约束、prompt、gate 合约。
|
||||||
|
6 个 SubPattern 按权重随机选择,各自可覆盖默认采样层级。
|
||||||
|
|
||||||
|
设计文档: research-wiki/designs/2026-07-14-task-type-strategy-design.md §4
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def task_type(self) -> str:
|
||||||
|
"""固定为 Action Recognition。"""
|
||||||
|
return "Action Recognition"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sampling_level(self) -> int:
|
||||||
|
"""默认 L2 事件级(从 L3 提升,有意变更)。"""
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sampling_constraint(self) -> SamplingConstraint:
|
||||||
|
"""加强约束:要求字幕、帧、跨段。"""
|
||||||
|
return _AR_DEFAULT_CONSTRAINT
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prompt_template(self) -> str:
|
||||||
|
"""AR 专属 prompt 模板。"""
|
||||||
|
return "action_recognition.md"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def strategy_name(self) -> str:
|
||||||
|
"""store 的 family 字段。"""
|
||||||
|
return "ACTION_RECOGNITION"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def skill_target(self) -> str:
|
||||||
|
"""M1_AR — 继承 RETRIEVAL 的 M1 + AR 后缀区分。"""
|
||||||
|
return "M1_AR"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def leak_probe_template(self) -> str:
|
||||||
|
"""复用 RETRIEVAL 的泄漏检测模板。"""
|
||||||
|
return "gate_leak_retrieval.md"
|
||||||
|
|
||||||
|
def select_sub_pattern(self, rng: random.Random) -> SubPattern:
|
||||||
|
"""按权重随机选择一个子模式。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
rng: 可控随机数生成器。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
选中的 SubPattern 实例。
|
||||||
|
"""
|
||||||
|
names = [sp.name for sp in AR_SUB_PATTERNS]
|
||||||
|
weights = [sp.weight for sp in AR_SUB_PATTERNS]
|
||||||
|
chosen_name = rng.choices(names, weights=weights, k=1)[0]
|
||||||
|
return next(sp for sp in AR_SUB_PATTERNS if sp.name == chosen_name)
|
||||||
|
|
||||||
|
def build_prompt_context(self, material: Any, sub_pattern: SubPattern | None) -> dict:
|
||||||
|
"""返回 AR 的 prompt 上下文。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
material: 采样素材上下文。
|
||||||
|
sub_pattern: 选中的子模式(AR 策略下始终非 None)。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
上下文字典。
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"family_name": "ACTION_RECOGNITION",
|
||||||
|
"prompt_template": "action_recognition.md",
|
||||||
|
"sub_pattern": sub_pattern.name if sub_pattern else None,
|
||||||
|
}
|
||||||
|
|
||||||
|
def extra_gates(self, candidate: Any) -> list:
|
||||||
|
"""当前版本无额外 gate,预留接口。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
candidate: 候选题目。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
空列表。
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: 运行测试验证通过**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM pytest tests/unit/test_strategy_action_recognition.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:全部 PASS
|
||||||
|
|
||||||
|
- [ ] **Step 5: 格式和 lint 检查**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM ruff format app/question_gen/strategy_action_recognition.py tests/unit/test_strategy_action_recognition.py
|
||||||
|
conda run -n Video-Tree-TRM ruff check app/question_gen/strategy_action_recognition.py tests/unit/test_strategy_action_recognition.py
|
||||||
|
conda run -n Video-Tree-TRM radon cc app/question_gen/strategy_action_recognition.py -n C -s
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:零 error,无 C 级以上复杂度。
|
||||||
|
|
||||||
|
- [ ] **Step 6: 提交**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add app/question_gen/strategy_action_recognition.py tests/unit/test_strategy_action_recognition.py
|
||||||
|
git commit -m "feat(question_gen): add ActionRecognitionStrategy with 6 SubPatterns"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: 注册 AR 策略 + 移除临时绑定
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `app/question_gen/strategy.py:107`
|
||||||
|
- Test: `tests/unit/test_strategy.py`(追加测试)
|
||||||
|
|
||||||
|
- [ ] **Step 1: 写测试 — AR 注册后 get_strategy 返回特化策略**
|
||||||
|
|
||||||
|
在 `tests/unit/test_strategy.py` 末尾追加:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class TestActionRecognitionRegistration:
|
||||||
|
"""AR 策略注册后 get_strategy 返回特化实例。"""
|
||||||
|
|
||||||
|
def test_get_strategy_returns_ar_strategy(self):
|
||||||
|
"""get_strategy('Action Recognition') 返回 ActionRecognitionStrategy。"""
|
||||||
|
from app.question_gen.strategy_action_recognition import ActionRecognitionStrategy
|
||||||
|
|
||||||
|
s = get_strategy("Action Recognition")
|
||||||
|
assert isinstance(s, ActionRecognitionStrategy)
|
||||||
|
assert s.task_type == "Action Recognition"
|
||||||
|
assert s.strategy_name == "ACTION_RECOGNITION"
|
||||||
|
|
||||||
|
def test_ar_not_base_strategy(self):
|
||||||
|
"""get_strategy('Action Recognition') 不再返回 BaseTaskTypeStrategy。"""
|
||||||
|
s = get_strategy("Action Recognition")
|
||||||
|
assert not isinstance(s, BaseTaskTypeStrategy)
|
||||||
|
|
||||||
|
def test_other_types_still_base(self):
|
||||||
|
"""其他题型仍返回 BaseTaskTypeStrategy。"""
|
||||||
|
for tt in ("Object Recognition", "Temporal Reasoning", "Spatial Reasoning"):
|
||||||
|
s = get_strategy(tt)
|
||||||
|
assert isinstance(s, BaseTaskTypeStrategy), f"{tt} 应该是 BaseTaskTypeStrategy"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: 运行测试验证失败**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM pytest tests/unit/test_strategy.py::TestActionRecognitionRegistration -v
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:`test_get_strategy_returns_ar_strategy` FAIL(返回 BaseTaskTypeStrategy)。
|
||||||
|
|
||||||
|
- [ ] **Step 3: 在 get_strategy 中添加延迟注册**
|
||||||
|
|
||||||
|
修改 `app/question_gen/strategy.py` 中的 `get_strategy` 函数,在首次调用时触发特化策略注册(避免循环导入):
|
||||||
|
|
||||||
|
```python
|
||||||
|
_BUILTIN_REGISTERED = False
|
||||||
|
|
||||||
|
def get_strategy(task_type: str) -> TaskTypeStrategy:
|
||||||
|
"""获取题型策略。未注册的自动创建 BaseTaskTypeStrategy。
|
||||||
|
|
||||||
|
首次调用时延迟注册内建特化策略(避免循环导入)。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
task_type: 题型名。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
TaskTypeStrategy 实例。
|
||||||
|
|
||||||
|
异常:
|
||||||
|
KeyError: task_type 不在消歧绑定表和注册表中。
|
||||||
|
"""
|
||||||
|
global _BUILTIN_REGISTERED # noqa: PLW0603
|
||||||
|
if not _BUILTIN_REGISTERED:
|
||||||
|
_BUILTIN_REGISTERED = True
|
||||||
|
_register_builtin_strategies()
|
||||||
|
|
||||||
|
if task_type in _STRATEGY_REGISTRY:
|
||||||
|
return _STRATEGY_REGISTRY[task_type]
|
||||||
|
return _build_default_strategy(task_type)
|
||||||
|
|
||||||
|
|
||||||
|
def _register_builtin_strategies() -> None:
|
||||||
|
"""注册内建的特化策略。由 get_strategy 首次调用时延迟执行。"""
|
||||||
|
from app.question_gen.strategy_action_recognition import ActionRecognitionStrategy
|
||||||
|
register_strategy(ActionRecognitionStrategy())
|
||||||
|
```
|
||||||
|
|
||||||
|
同时更新 `_TASK_TYPE_TO_FAMILY` 中 AR 的注释:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 修改前:
|
||||||
|
"Action Recognition": VISUAL_FAMILY, # Plan A 临时绑定;Plan B 替换为特化策略
|
||||||
|
|
||||||
|
# 修改后:
|
||||||
|
"Action Recognition": VISUAL_FAMILY, # fallback — 注册表中已被 ActionRecognitionStrategy 替换
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: 运行测试验证通过**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM pytest tests/unit/test_strategy.py tests/unit/test_strategy_action_recognition.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:全部 PASS。
|
||||||
|
|
||||||
|
- [ ] **Step 5: 提交**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add app/question_gen/strategy.py tests/unit/test_strategy.py
|
||||||
|
git commit -m "feat(question_gen): register ActionRecognitionStrategy, replace temp VISUAL binding"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: 全量回归测试 + lint
|
||||||
|
|
||||||
|
- [ ] **Step 1: lint**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM ruff format app/question_gen/ tests/ && conda run -n Video-Tree-TRM ruff check app/question_gen/ --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: 全量测试**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
conda run -n Video-Tree-TRM pytest tests/unit/ tests/integration/ -v --tb=short
|
||||||
|
```
|
||||||
|
|
||||||
|
预期:1173+ 全部 PASS
|
||||||
|
|
||||||
|
- [ ] **Step 3: 提交(如有 lint 修复)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A && git commit -m "chore: lint and format Plan B changes"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 行为保真检查清单
|
||||||
|
|
||||||
|
| # | 行为 | 状态 | 说明 |
|
||||||
|
|---|------|------|------|
|
||||||
|
| 1 | 11 个非 AR 题型行为不变 | 保留 | get_strategy 对非 AR 类型仍返回 BaseTaskTypeStrategy |
|
||||||
|
| 2 | AR 从 VISUAL_FAMILY(L3) 变为 AR 特化(L2) | **有意变更** | 设计文档 §4 明确标注 |
|
||||||
|
| 3 | AR 采样约束加强 | **有意变更** | 设计文档 §4: min_subtitles=3, cross_l2_span=True |
|
||||||
|
| 4 | AR prompt 从 visual.md 变为 action_recognition.md | **有意变更** | 专属 prompt 靶向动作识别 |
|
||||||
|
| 5 | AR strategy_name 从 "VISUAL" 变为 "ACTION_RECOGNITION" | **有意变更** | store 中新记录可区分 |
|
||||||
|
| 6 | AR skill_target 从 "M4" 变为 "M1_AR" | **有意变更** | 设计文档 §4 |
|
||||||
|
| 7 | select_sub_pattern 返回 SubPattern(非 None) | **有意变更** | AR 始终有 sub_pattern |
|
||||||
|
| 8 | sub_pattern.instruction 注入到 prompt | 保留 | Plan A 已接线(generator_v2.py:176-177) |
|
||||||
|
| 9 | sub_pattern.sampling_level_override 覆盖 level | 保留 | Plan A 已接线(pipeline_v2.py:359-360) |
|
||||||
|
| 10 | sub_pattern.name 写入 store | 保留 | Plan A 已接线(pipeline_v2.py:425) |
|
||||||
|
| 11 | pipeline 重出循环/后处理/四门 gate 不变 | 保留 | Plan B 不改 pipeline |
|
||||||
|
| 12 | 断点续跑 | 保留 | pipeline 的 progress 机制不变 |
|
||||||
|
|
||||||
|
## 核心算法保真校验
|
||||||
|
|
||||||
|
本计划不涉及核心算法迁移,保真校验不适用。
|
||||||
|
|
||||||
|
## 非功能性需求
|
||||||
|
|
||||||
|
| 维度 | 设计 |
|
||||||
|
|------|------|
|
||||||
|
| 持久化 | 不变 — on_accept 逐题回调。sub_pattern 名已在 Plan A 中接入 store |
|
||||||
|
| 幂等性 | 不变 — strategy 查找确定性,sub_pattern 选择由 rng 控制 |
|
||||||
|
| 断点续跑 | 不变 — progress 机制在 pipeline 层,strategy 无状态 |
|
||||||
|
| 原子性 | 不变 — 逐题落库 |
|
||||||
Reference in New Issue
Block a user