From 5d0caa06e16fd0a364615ff947d4d8096f48c300 Mon Sep 17 00:00:00 2001 From: iomgaa Date: Thu, 9 Jul 2026 08:41:22 -0400 Subject: [PATCH] =?UTF-8?q?docs(design):=20main.py=20=E6=8E=A8=E7=90=86?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=20+=20=E5=88=9D=E5=A7=8B=20Prompt=20?= =?UTF-8?q?=E9=9B=86=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-07-09-main-inference-entry-design.md | 246 ++++++++++++++++++ research-wiki/graph/edges.json | 5 + research-wiki/index.md | 6 +- research-wiki/log.md | 2 + 4 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 research-wiki/designs/2026-07-09-main-inference-entry-design.md diff --git a/research-wiki/designs/2026-07-09-main-inference-entry-design.md b/research-wiki/designs/2026-07-09-main-inference-entry-design.md new file mode 100644 index 0000000..e62604a --- /dev/null +++ b/research-wiki/designs/2026-07-09-main-inference-entry-design.md @@ -0,0 +1,246 @@ +--- +id: main-inference-entry +title: main.py 推理入口 + 初始 Prompt 集设计 +type: design +status: approved +created: 2026-07-09 +--- + +# main.py 推理入口 + 初始 Prompt 集设计 + +## 1. 目标 + +完成第一版 900 道题推理基线,具体交付: + +| 交付物 | 说明 | +|--------|------| +| `main.py` | CLI Composition Root,本次仅实现 infer 模式 | +| `app/harness/deps_router.py` | 按 video_id 懒加载 InferenceDeps 的路由器 | +| `app/ports.py` 扩展 | 新增 `ToolDispatchFactory` / `PromptBuilderFactory` Protocol | +| `app/harness/runner.py` 小改 | `__init__` 注入 factory,替换 noop 占位 | +| `store/skills/v1/` | 14 个 skill(从 TRM4 v1 精简 + 注入 TRM5 card 字段) | +| `store/prompts/v1/` | 目录重组(从 `store/prompts/` 扁平结构迁入) | +| 配置变更 | concurrency=24, max_steps=40, breaker_threshold=48 | + +## 2. 架构 + +### 2.1 依赖流(Clean Architecture Composition Root) + +``` +main.py (Composition Root — 最外层) + │ + ├─ 构建 adapters ──────────────────────────────┐ + │ CircuitBreaker │ + │ RedisResponseCache (可选,降级为 None) │ adapters/ + │ SQLiteTelemetryRecorder │ + │ GovernedLLMClient (search) │ + │ GovernedLLMClient (evolve, 本次传同一实例) │ + │ GovernedVLMClient │ + │ LocalEmbeddingProvider │ + │ MonkeyOCRClient (可选) │ + │ │ + ├─ 构建 InferenceDepsRouter ───────────────────┤ + │ 接收: store_dir, embed, llm, vlm, ocr │ app/harness/deps_router.py + │ 复用: factory.build_inference_deps() │ + │ │ + ├─ 构建 Runner ────────────────────────────────┤ + │ 注入: config, llm, evolve_llm, vlm, │ app/harness/runner.py + │ telemetry, │ + │ tool_dispatch_factory, │ + │ prompt_builder_factory │ + │ │ + └─ asyncio.run(runner.infer()) ────────────────┘ +``` + +依赖只向内:`main.py` → `adapters/` + `app/` → `core/`。 + +### 2.2 InferenceDepsRouter + +**位置**:`app/harness/deps_router.py` + +**职责**:将 Runner 的全局统一 dispatch/prompt_builder 接口路由到 per-video 的 `InferenceDeps`。 + +``` +prompt_builder(qa) ← 先调用,注册 qid→vid 映射 + ↓ +AgentLoop.run() + ↓ +dispatch(tool, args, ctx) ← 后调用,通过 ctx["session_id"] 查映射 +``` + +核心伪代码: + +```python +class InferenceDepsRouter: + _deps_cache: dict[tuple, InferenceDeps] # (vid, skills_dir, prompts_dir) → deps + _qid_to_vid: dict[str, str] # question_id → video_id + + def create_dispatch(self, *, skills_dir=None): + async def _dispatch(tool_name, args, *, context): + vid = self._qid_to_vid[context["session_id"]] + deps = self._ensure_deps(vid, skills_dir, ...) + return await deps.tool_dispatch_fn(tool_name, args, context=context) + return _dispatch + + def create_prompt_builder(self, *, skills_dir=None, prompts_dir=None): + def _builder(qa): + self._qid_to_vid[qa.question_id] = qa.video_id # 注册映射 + deps = self._ensure_deps(qa.video_id, skills_dir, prompts_dir) + return deps.prompt_builder(qa) + return _builder + + def _ensure_deps(self, video_id, skills_dir, prompts_dir): + key = (video_id, str(skills_dir or ""), str(prompts_dir or "")) + if key not in self._deps_cache: + self._deps_cache[key] = build_inference_deps(...) + return self._deps_cache[key] +``` + +**时序保证**:`run_inference()` 中每道题先调 `prompt_builder(qa)` 构建 prompt,再启动 AgentLoop(调 dispatch)。映射注册总先于使用。 + +### 2.3 Runner 改动 + +`__init__` 新增 2 个可选参数(向后兼容): + +```python +def __init__(self, config, *, llm, evolve_llm, vlm, telemetry, + tool_dispatch_factory=None, + prompt_builder_factory=None): +``` + +`_make_tool_dispatch_fn` / `_make_prompt_builder` 优先用注入值,缺省保留 noop fallback。 + +### 2.4 Protocol 定义 + +`app/ports.py` 新增: + +```python +class ToolDispatchFactory(Protocol): + def __call__(self, *, skills_dir: Path | None = None) -> Callable[..., Any]: ... + +class PromptBuilderFactory(Protocol): + def __call__(self, *, skills_dir: Path | None = None, + prompts_dir: Path | None = None + ) -> Callable[[GeneratedQuestion], tuple[str, str]]: ... +``` + +### 2.5 main.py 结构 + +使用 argparse(复用 `RunConfig` + `load_config()` 的 YAML/CLI 三层合并逻辑)。 + +```python +def _build_parser(): # CLI 参数定义,与 TRM4 main.py 保持一致 +def _build_adapters(): # 从 .env 构建全套 adapters,返回 NamedTuple +def _log_result(): # 输出推理结果摘要 +def main(): # Composition Root:load_config → adapters → router → runner +``` + +本次只实现 `mode == "infer"` 分支,其余模式 `raise SystemExit("尚未实现")`。 + +## 3. 初始 Prompt 集 + +### 3.1 设计原则 + +``` +进化能学到的 → v1 留框架、去细节(给进化留空间) +进化学不到的 → v1 用人类版(否则永远缺失) +``` + +依据 TRM4 进化历史(v1→v40):skills 进化 39 轮(主力),system prompt 仅 1 轮,tool prompts 未变。 + +### 3.2 三类 Prompt 处理 + +| 类别 | 是否进化 | v1 来源 | 处理 | +|------|---------|---------|------| +| system.md | 微量 | TRM5 现有版本 | 保留(已含 card 字段说明,是基础设施) | +| skills/v1/ (14个) | 主力 | TRM4 v1 精简 + TRM5 注入 | 见 §3.3 | +| extract/verify (8个) | 不变 | TRM5 现有版本 | 保留(已适配 card 结构) | + +### 3.3 Skills v1 内容策略 + +每个 skill 文件的改造规则: + +| 内容层次 | 进化能学到? | v1 处理 | +|----------|------------|---------| +| YAML frontmatter(task_type) | 否 | 保留原版 | +| Step 标题 + 一句话基本意图 | 否 | 保留原版 | +| reflect/plan/action JSON schema | 否 | 保留原版 | +| **TRM5 card 字段索引** | **否** | **新增**(注入各层字段名及适用场景) | +| 数据驱动统计 | 是 | 移除 | +| 步骤间精确转换条件 | 是 | 移除 | +| 详细操作性规则 | 是 | 移除 | +| 大多数自检信号 | 是 | 移除(保留最基本 1 条) | +| 特定失败模式陷阱 | 是 | 移除(保留 1-2 条通用警告) | + +**card 字段索引表**(注入每个 skill): + +| 层级 | 字段 | 适用场景 | +|------|------|---------| +| L1 | scene_summary | 整体概况 | +| L1 | key_entities | 查找人物/物体 | +| L1 | main_actions | 主要动作 | +| L1 | temporal_flow | 时间线概览 | +| L1 | topic_keywords | 主题定位 | +| L2 | event_description | 事件因果 | +| L2 | entities / actions | 实体和动作细节 | +| L2 | state_changes | 状态转变 | +| L2 | spatial_relations | 空间关系变化 | +| L3 | frame_summary | 精确视觉证据 | +| L3 | visible_entities | 具体物体确认 | +| L3 | ongoing_actions | 正在发生的动作 | +| L3 | spatial_layout | 精确空间位置 | +| L3 | visual_attributes | 光照、色调、机位 | +| 全层 | visible_text | 画面文字(OCR) | +| 全层 | subtitle | 字幕转写 | + +### 3.4 store/ 目录重组 + +``` +store/ + prompts/ + v1/ ← 新建(从 store/prompts/*.md 移入) + system.md + observe_frame_extract.md + observe_frame_verify.md + search_similar_extract.md + search_similar_verify.md + view_node_extract.md + view_node_verify.md + view_node_children_extract.md + view_node_children_verify.md + skills/ + v1/ ← 新建(14 个文件) + default-strategy.md + action-reasoning.md + action-recognition.md + attribute-perception.md + counting-problem.md + information-synopsis.md + object-reasoning.md + object-recognition.md + ocr-problems.md + spatial-perception.md + spatial-reasoning.md + temporal-perception.md + temporal-reasoning.md +``` + +## 4. 配置变更 + +| 参数 | 原值 | 新值 | 位置 | +|------|------|------|------| +| concurrency | 12 | 24 | config/default.yaml | +| max_steps | 15 | 40 | config/default.yaml | +| breaker_threshold | 5 | 48 | .env | + +熔断器行为:所有 24 并发 agent 共享同一 CircuitBreaker 实例,`record_success()` 归零计数。48 = 连续 2 波全失败才触发开路,间歇抖动不会误触。 + +## 5. 拒绝的方案 + +| 方案 | 拒绝原因 | +|------|---------| +| Runner 子类覆盖 `_make_*` | Template Method 反模式,违反依赖反转 | +| 绕过 Runner 直接调 `run_inference` | 不复用 workspace 管理、日志、报告逻辑 | +| 照搬 TRM4 v1 skills | 进化空间不足,且缺少 TRM5 card 字段知识 | +| 极简骨架 skills | 基线质量过低,可能不收敛 | +| typer CLI | 需重写 `RunConfig` 的 YAML/CLI 合并逻辑,ROI 不值 | diff --git a/research-wiki/graph/edges.json b/research-wiki/graph/edges.json index 4662ea2..d035403 100644 --- a/research-wiki/graph/edges.json +++ b/research-wiki/graph/edges.json @@ -70,6 +70,11 @@ "id": "plan:question-gen-synth", "label": "赛题生成工具实现计划", "type": "plan" + }, + { + "id": "design:main-inference-entry", + "label": "main.py 推理入口 + 初始 Prompt 集设计", + "type": "design" } ], "links": [ diff --git a/research-wiki/index.md b/research-wiki/index.md index 5edcdaf..7c8a73c 100644 --- a/research-wiki/index.md +++ b/research-wiki/index.md @@ -1,13 +1,15 @@ # Research Wiki 索引 -> 自动生成,更新时间:2026-07-09 09:05 UTC +> 自动生成,更新时间:2026-07-09 12:41 UTC -## design (13) +## design (15) - [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-07-app-harness-design](designs/2026-07-07-app-harness-design.md) `design:2026-07-07-app-harness-design` - [2026-07-07-core-evolution-design](designs/2026-07-07-core-evolution-design.md) `design:2026-07-07-core-evolution-design` - [2026-07-08-tree-repair-resilience-design](designs/2026-07-08-tree-repair-resilience-design.md) `design:2026-07-08-tree-repair-resilience-design` - [2026-07-09-paper-main-figure-design](designs/2026-07-09-paper-main-figure-design.md) `design:2026-07-09-paper-main-figure-design` +- [main.py 推理入口 + 初始 Prompt 集设计](designs/2026-07-09-main-inference-entry-design.md) `design:2026-07-09-main-inference-entry-design` +- [main.py 推理入口 + 初始 Prompt 集设计](designs/main-inference-entry.md) `design:main-inference-entry` - [出题模块迁移设计(question_gen)](designs/2026-07-07-question-gen-design.md) `design:2026-07-07-question-gen-design` - [建树修复管线:熔断根因修复 + 断点续跑 + 并发改造](designs/tree-repair-resilience.md) `design:tree-repair-resilience` - [建树模块竖切设计:数据结构 + 建树 + 修复 + 迁移](designs/2026-07-07-tree-module-design.md) `design:2026-07-07-tree-module-design` diff --git a/research-wiki/log.md b/research-wiki/log.md index 3201f2c..50b9ce9 100644 --- a/research-wiki/log.md +++ b/research-wiki/log.md @@ -33,3 +33,5 @@ - [2026-07-09 09:05 UTC] 新增 plan: 赛题生成工具实现计划 (plan:question-gen-synth) - [2026-07-09 09:05 UTC] 新增边: plan:question-gen-synth --implements--> design:question-gen-synth - [2026-07-09 09:05 UTC] 重建索引: 28 篇页面 +- [2026-07-09 12:41 UTC] 新增 design: main.py 推理入口 + 初始 Prompt 集设计 (design:main-inference-entry) +- [2026-07-09 12:41 UTC] 重建索引: 30 篇页面