# P3 实施计划 — 执行策略接入 + 自适应闭环打通 + 调度统一 | 项 | 内容 | |---|---| | 文档版本 | V1.0 | | 日期 | 2026-08-29 | | 状态 | 已实施完成(2026-08-29,M1-M5 全部落地并提交) | | 依据 | `docs/PLATFORM_DESIGN_V2.md` 第 4 节(P3 批次)+ 短板 S7/S8 | | 前置 | P1(共享核心层 afmcore)✅、P2(拓扑注册表 + 适配器)✅ 已落地 | --- ## 1. 背景与目标 ### 1.1 P3 要解决什么 当前系统实际跑通的是 **"全因子扫描"** 一条链路:方案固定参数列表 → 任务下发 → 本地执行器逐点跑 Motor-CAD → 结果回传。而 Phase 3 承诺的 **"AI 自适应优化闭环"(feasibility-first 搜索)在 web 端算法已实现并通过验收,却从未真正驱动真实仿真**。 具体两个平台性短板(对应设计文档 S7 / S8): | # | 短板 | 现状 | 后果 | |---|---|---|---| | S7 | **执行策略硬编码全因子** | `FeasibilityFirstSearch` / `AdaptiveLoop` 只存在于 web 端内存;批次选出的点**没有通道下发到本地执行器**,结果也没回填驱动下一批 | 自适应闭环未真通,P3 优化能力是"摆设" | | S8 | **调度逻辑分裂** | web 端 `BatchScheduler`(内存优先级队列)与本地 `task_executor`(轮询认领)两套,契约不一致 | 平台化调度难扩展、难并行 | ### 1.2 目标 > 把"单策略(全因子)、单调度(串行轮询)"升级为 **"可插拔执行策略 + 自适应闭环真实跑通 + 多实例并行调度"**。 验收标准(做到什么算完成): 1. 方案可选择执行策略(full_factorial / adaptive / lhs),策略在共享核心层注册,新增策略只做注册。 2. adaptive 策略下,本地执行器真实跑 Motor-CAD 的每批结果回填搜索模型,自动选下一批,直至收敛/预算耗尽。 3. 本地执行器支持多实例并行,任务状态机与 web 端调度契约统一。 4. 全程可留痕、可断点恢复、可回归测试(延续 TEST-004/005 纪律)。 --- ## 2. 现状盘点(已探查,非假设) ### 2.1 已实现(P3 可复用的资产) | 模块 | 位置 | 能力 | 状态 | |---|---|---|---| | FeasibilityFirstSearch | `web/backend/app/services/feasibility_search.py` | LHS 初始化 / 主动学习选批 / 信任域 / 收敛判断 / `report_result(point_id, metrics, status)` / 状态导出 | ✅ 已实现+验收 | | AdaptiveLoop 编排器 | `web/backend/app/services/adaptive_loop.py` | generate_plan → initialize_search → get_next_batch → report_results → update_experience → check_completion | ✅ 已实现(执行环节占位) | | L0 预筛选 | `web/backend/app/services/l0_prescreening.py` | 排除不可行域 | ✅ | | AI 结果分析 | `web/backend/app/services/result_analyst.py` | 趋势/异常/置信度分级 | ✅ | | 经验库增强 | `web/backend/app/services/experience_enhancer.py` | 自动抽取设计规则入库 | ✅ | | 批量调度器 | `web/backend/app/services/batch_scheduler.py` | 优先级队列/并行上限/checkpoint | ✅(web 内存态) | | 本地执行器 | `scripts/task_executor.py` | 轮询认领 / 逐点执行(已接 `afmcore` 适配器)/ 进度回传 | ✅(P2 已适配器化) | | 任务管理 | `web/backend/app/services/task_manager.py` | 任务 CRUD / 进度 / 结果 / 心跳 | ✅ | | 搜索 API | `web/backend/app/routers/search.py` | create / next-batch / report / export / runs | ✅ | ### 2.2 关键缺口(P3 要做的) | # | 缺口 | 说明 | |---|---|---| | G1 | **无执行策略抽象** | 方案里的 `search_strategy.method`(full_factorial/lhs/active_learning)只是配置字符串,执行器只认"固定参数列表",没有策略层 | | G2 | **批次 ↔ 任务无桥** | `FeasibilityFirstSearch` 选出的 `SearchPoint[]` 与 `TaskManager.create_task(parameters=[...])` 之间没有转换通道;adaptive 批次是"动态追加"语义,现有任务模型是"一次性固定列表" | | G3 | **结果无回填驱动** | 执行器把结果回传到 task,但没有任何环节把结果喂回 `search.report_result()` 并触发下一批 `get_next_batch()` | | G4 | **执行器单实例串行** | `run_task_executor.py` 启动单个轮询线程,无并行;多实例需要许可证策略 | | G5 | **调度契约不一致** | batch_scheduler 的任务字段与 task_executor 认领的字段不同源;状态机语义未统一(queued/dispatched/running/completed 各说各话) | --- ## 3. 目标架构(数据流) ``` ┌──────────────────────── Web 端 ────────────────────────┐ │ 方案(Plan) │ │ ├─ search_strategy.method ∈ {full_factorial, adaptive, lhs} │ │ └─ 执行策略解析 → get_strategy(method) │ │ │ │ [adaptive 协调器 StrategyOrchestrator](新增) │ │ generate_plan → initialize_search → get_next_batch │ │ │ batch(N points) │ │ ▼ │ │ TaskManager.create_task(type="adaptive_batch", │ │ parameters=points, loop_id, batch_id) │ │ │ │ │ ┌────▼──── 调度契约(统一状态机 queued/running/…)────┐ │ │ │ BatchScheduler(可选队列) ←→ REST /api/tasks │ │ │ └──────────────────────────────────────────────────┘ │ └────────────────────┬────────────────────────────────────┘ │ HTTP 轮询认领 ┌────────────────────▼──────── 本地执行端 ─────────────────┐ │ TaskExecutor(多实例并行,每实例独立 Motor-CAD) │ │ ├─ 认领 → get_adapter(tool).run_point / 批量 │ │ ├─ 结果回传 /api/tasks/{id}/results │ │ └─ adaptive 任务:本批完成后不结束,等待下一批 │ └─────────────────────────────────────────────────────────┘ │ 结果 ▼ StrategyOrchestrator: report_results → search.report_result() → analysis → update_experience → 收敛? 否 → get_next_batch() → 是 → 闭环完成,方案标记 converged/预算耗尽 ``` 关键决策点: - **adaptive 循环的"心跳"放哪**:放 web 端 `StrategyOrchestrator`(新增服务),它负责"取批 → 建任务 → 等结果 → 回填 → 下批"。本地执行器保持无状态(只认领、执行、回传),避免执行器内嵌循环逻辑导致断连后状态丢失。 - **断点恢复**:循环状态落在 web 端(`search.export_state()` 已有 checkpoint 能力),任务级结果落在 task.json(已有)。 --- ## 4. 里程碑分解 ### P3-M1 执行策略抽象层(共享核心层) **任务**: 1. 新建 `src/afmcore/strategies/__init__.py`:`SimulationStrategy` ABC - `select_next(points_to_run) -> list[params]`(生成/选择下一批点) - `report(point_id, metrics, status)`(回填结果) - `next_batch_ready() -> bool` / `is_converged() -> bool` / `state() -> dict` - `kind`("full_factorial" / "adaptive" / "lhs") 2. 新建 `strategies/full_factorial.py`:把现有 `plan_schema.SimulationPlan.generate_points()`(笛卡尔积)包装为策略 3. 新建 `strategies/adaptive.py`:**包装 web 端 `FeasibilityFirstSearch`**——这是"算法已在 web、执行在本地"的桥接层。共享核心层不 import web,因此 adaptive 策略持有一个"搜索后端回调"(注入函数),或将该策略实现放在本地侧(见 P3-M2 说明) 4. 策略注册表:`register_strategy / get_strategy(method)` 5. `plan_schema.SearchStrategy.method` 增加校验(只允许已注册方法) **设计取舍(重要)**:`FeasibilityFirstSearch` 目前依赖 `l0_prescreening`(web 服务)。为不破坏现有验收资产,**第一版策略层做"双实现"**: - 共享核心层定义协议 + full_factorial/lhs 纯实现(可直接复用) - adaptive 通过 **StrategyOrchestrator(web 端)** 实现协议,内部调用现有 `FeasibilityFirstSearch`,本地执行器只认"批次的 points",不感知 adaptive 逻辑 **产出**:`src/afmcore/strategies/`(协议 + 注册表 + full_factorial + lhs) **验收**:单测——策略注册/选择/状态;full_factorial 与 `SimulationPlan.generate_points` 结果一致;未注册方法报错。 --- ### P3-M2 任务模型扩展 + adaptive 批次桥接 **任务**: 1. `task_manager.py` 任务模型扩展(Task 增加字段,向后兼容): - `task_type`: `"scan"`(默认,现有一致)| `"adaptive_batch"` - `loop_id` / `batch_id` / `point_ids[]`(adaptive 批次标识) - `dynamic`: `true`(表示任务完成后可能有后续批次,不触发"完成即终态"的误判) 2. `TaskManager.create_task` 支持 `parameters` 直接传 `SearchPoint[]`(自动转换 `{point_id, params}`) 3. 新增 `web/backend/app/services/strategy_orchestrator.py`(核心新增): - `start_adaptive(plan, loop_id)` → 初始化搜索 → 取首批 → 建 `adaptive_batch` 任务 - `on_batch_completed(task_id, results)` → 结果按 `point_id` 回填 `search.report_result()` → `result_analyst` 分析 → `update_experience` → 判断收敛/预算 → 未收敛则 `get_next_batch()` 建下一批 - `get_loop_status(loop_id)` → 供 monitor/前端轮询 4. `search.py` 路由增强:暴露 `POST /loops/{id}/start`、`POST /loops/{id}/resume`(断点恢复入口) **设计取舍**:adaptive 循环状态存 web 端(内存 + `export_state()` 落盘可选),执行器无状态。断连恢复:执行器重启后重新认领 `pending/dispatched` 任务,orchestrator 依据任务状态决定是续批还是重建。 **产出**:task 扩展 + `strategy_orchestrator.py` + 路由 **验收**:单测(fake 执行器)——任务字段向后兼容;orchestrator 完整跑通"建批→完成→回填→下批";断点恢复逻辑(模拟执行器中途退出)。 --- ### P3-M3 执行器 adaptive 批次执行模式 **任务**: 1. `task_executor.py` 支持 `adaptive_batch` 任务:认领后按 `point_ids` 顺序执行,每个 point 走 `get_adapter().run_point()`(P2 已就绪) 2. 结果回传扩展:`report_results` 携带 `point_id → params → metrics` 映射(现有 `point_index` 之外增加 `point_id`),供 orchestrator 回填 3. `run_task_executor.py` 支持多实例:`--instance` 参数(多进程各自独立轮询,天然多实例;实例心跳带 `instance_id` 区分) 4. 执行器对 `dynamic` 任务不误判终态:本批完成 → `completed`(batch 级),循环是否结束由 orchestrator 决定 **产出**:task_executor 扩展 + 多实例入口 **验收**:fake adapter 集成——一个 `adaptive_batch` 任务 3 点执行、结果带 point_id 回传;双实例并行认领不同任务不重复。 --- ### P3-M4 调度契约统一 + 并行控制 **任务**: 1. 定义**统一任务状态机**(文档 + 常量): `queued → dispatched → running → completed | failed | cancelled` (`task_manager` 为权威,`batch_scheduler` 与其对齐字段名;明确两者关系:batch_scheduler 是可选的上层优先级队列,本地执行器始终走 REST 认领,二者通过同一 `/api/tasks` 契约衔接,不重复实现调度语义) 2. `batch_scheduler` 字段对齐 `task_manager.Task`(task_id/task_name/priority/status/parameters/plan_data/wait_for),消除两套字段漂移 3. 并行控制策略文档化:`MAX_PARALLEL_TASKS`(web 队列)+ `NUM_EXECUTORS`(本地实例数)+ **Motor-CAD 许可证约束说明**(浮点许可池决定本地实例上限) 4. 心跳/监控完善:`executor_heartbeat` 支持 `instance_id`,monitor 展示多实例状态 **产出**:状态机常量 + batch_scheduler 对齐 + 并行配置文档 **验收**:状态机单测(非法迁移拒绝);batch_scheduler 字段与 Task 契约一致性断言。 --- ### P3-M5 端到端闭环验证 + 文档收尾 **任务**: 1. **集成测试(fake adapter)**:`plan(adaptive) → orchestrator → 批次 → 执行器 → 回填 → 收敛` 全闭环,断言搜索状态收敛、预算扣减正确、经验库有产出 2. **真实 Motor-CAD 烟雾测试**:单 adaptive 任务(1-2 批)真实跑通(环境允许时;不允许则记录为待办) 3. 回归测试扩展:`scripts/test_platform_registry.py` 增加策略层 + orchestrator(fake)用例 4. 文档:README(五期)、TEST_RECORDS(TEST-006)、PLATFORM_DESIGN_V2(P3 批次标记完成) 5. Git 提交 **验收**:闭环测试 PASS + 文档留痕 + 提交合规。 --- ## 5. 工作量与建议顺序 | 里程碑 | 预计工作量 | 依赖 | 建议 | |---|---|---|---| | P3-M1 策略抽象 | 1-2 天 | P2 适配器 ✅ | 先做,共享核心层独立可测 | | P3-M2 任务扩展+orchestrator | 2-3 天 | M1 | 核心难点,优先 | | P3-M3 执行器批次+多实例 | 1-2 天 | M2、P2 | 与 M2 可并行一部分 | | P3-M4 调度统一 | 1 天 | M3 | 低风险,文档为主 | | P3-M5 闭环验证+文档 | 1-2 天 | M2-M4 | 收尾 | **总计约 6-10 天**(含验证与文档)。建议一次性连续推进 M1→M5,每里程碑提交一次(延续项目纪律)。 --- ## 6. 风险与应对 | 风险 | 影响 | 应对 | |---|---|---| | adaptive 循环"等批"期间执行器空闲 | 利用率低 | 首批用满 batch_size;循环粒度=批次而非单点;或与普通扫描任务混排 | | 执行器断连导致循环悬空 | 闭环卡死 | orchestrator 心跳+超时重派;任务级 checkpoint(task.json 已有) | | 多实例并行许可证不足 | 启动失败 | 文档化 NUM_EXECUTORS ≤ 可用许可数;启动时预检许可证(robust_motorcad 已有 check_license_server) | | FeasibilityFirstSearch 依赖 web 服务(l0) | 策略层耦合 | M1 双实现方案:共享层协议 + web 端 orchestrator 实现;后续再把 l0 上提共享层 | | 前端仍是"全因子"展示 | UI 与 adaptive 语义不符 | 本批先做 API/后端闭环,前端 adaptive 视图列 P4 或单独 UI 批次 | | 大量结果回填拖慢搜索 | 性能 | report_result 批量接口(一次回填整批,而非逐点) | --- ## 7. 验证矩阵(本计划验收口径) | 层 | 验证方式 | 通过标准 | |---|---|---| | 单元 | strategies 单测 | 注册/选择/状态/未注册报错;full_factorial 与 generate_points 一致 | | 单元 | 任务模型扩展 | 旧任务无新字段可解析(向后兼容) | | 集成 | fake adapter 全闭环 | 收敛/预算/经验库断言全过 | | 集成 | 多实例并行 | 双实例不重复认领、心跳区分 instance_id | | 真实 | Motor-CAD 烟雾 | 1-2 批真实跑通(环境允许) | | 回归 | test_platform_registry.py 扩展 | 原有 36 项 + 新增全 PASS | | 纪律 | ASCII/编译/Git | 79+ 文件编译 0 失败、纯 ASCII、提交规范 | --- ## 8. 遗留/后续(不属于本计划范围) - 前端 adaptive 视图(批次可视化、收敛曲线)→ P4 / 独立 UI 批次 - 把 L0 预筛选从 web 上提共享核心层(消除 web 依赖)→ P4 重构项 - 多物理场(热/结构)策略适配 → 路线扩展 - Maxwell/JMAG 适配器 → 路线扩展 --- *本文档为计划稿,评审通过后按 M1→M5 实施,每里程碑更新 README / TEST_RECORDS / PLATFORM_DESIGN_V2 并提交。* --- ## 6. 实施记录(2026-08-29 完成) | 里程碑 | 提交 | 结果 | 备注 | |---|---|---|---| | M1 策略抽象层 | 2e9adfa | 通过 | strategies/ 抽象+注册表+full_factorial/lhs/adaptive;plan_schema 策略校验 | | M2 任务扩展+orchestrator | fa74834 | 通过 | Task 新字段+迁移;AdaptiveOrchestrator 闭环;修复 report_results plan_id bug | | M3 执行器批次+多实例 | d65c6fa | 通过 | point_id 回传+认领原子化+并行入口;修复 on_complete 参数个数 bug | | M4 调度契约统一 | 719023e | 通过 | task_contract.py 统一状态词+字段对齐 batch_scheduler | | M5 闭环验证+真实烟雾 | 2611c28 | 通过 | HTTP 全链路闭环(fake) + 真实 Motor-CAD 烟雾;修复 run_point 忽略 model_path bug | 测试记录:docs/TEST_RECORDS.md TEST-006~010;回归脚本 scripts/test_p3_orchestrator.py / test_executor_m3.py / test_p3_m4_contract.py / test_p3_closed_loop.py + test_platform_registry.py(36 项)。