D17 批 2:算法接缝(OCC payload 通道 + hints 透传到分模评分)—— 闭环通

让批 1 沉淀的老师傅经验 hints 真接入分模方案生成:
processing_service 拉同指纹 hints 装进 OCC worker payload,
planner 透传到 candidate_generator(axis 优先级加成)和
scheme_scorer(score_breakdown 新字段 + total_score 加成),
写入即消费闭环通。

变更内容:
- src/moldinsight/core/parting_candidate_generator.py
  generate_candidates(..., hints=None):_build_axis_metrics 末尾按 hints
  加成(priority_score += weight × 20 上限;sample_count ≥ 2 + weight ≥ 0.5
  → method 标签升级 "human_experience_primary")
- src/moldinsight/core/parting_scheme_scorer.py
  score_schemes(schemes, *, hints=None) keyword-only:_score_scheme 新增
  human_hint_bonus 字段(weight × 12 上限;sample_count < 2 时 ×0.5 折半
  防信号不足过度影响);_compute_human_hint_bonus 静态方法解析 axis
  (parting.axis → axis → Z);bonus 纳入 total_score
- src/moldinsight/core/multi_scheme_planner.py
  generate_plan(..., hints=None):透传 hints 到 candidate_generator 与
  scheme_scorer;global_summary.applied_hints 注入返回供前端 ResultView
  渲染经验角标
- src/moldinsight/services/processing_service.py
  _step_generate_cavity 加 db_session 形参;调用
  experience_feedback_service.resolve_for_process_params 拿同指纹 hints,
  装进 run_occ payload 顶层 experience_hints;解析失败回退空 list
  不阻塞主流程(旧任务不因 receives 闭包退化)
- src/moldinsight/core/occ_worker.py
  _op_generate_cavity:payload.get("experience_hints") or {} 透传给
  planner.generate_plan(..., hints=...);普通 dict 跨进程 pickle 安全
  (满足 occ_worker.py:7-8 硬规则)
- tests/test_experience_feedback_algorithm.py(new)11 例:
  - candidate_generator 3 例(无 hints 默认 / hints 加成 / sample_count < 2 不升级)
  - scheme_scorer 4 例(无 hints 无 bonus / bonus 加成 / sample_count 折半 /
    weight=0 不加成)
  - multi_scheme_planner 2 例 OCC-gated(透传 / applied_hints 默认空)
  - processing_service 2 例 OCC-gated(payload 含 experience_hints /
    解析失败回退空 list)

设计取舍:
- keyword-only hints:避免与位置参数混淆
- weight 仅正向上有效:max(0, (adopted-rejected)/total),老师傅拒绝
  的不扣分老算法,只让采纳的加分
- signal-noise 控制:sample_count < 2 时 bonus ×0.5,但 priority_score
  仍加成(候选方向仍偏向,避免完全无信号)
- graceful degradation:hints 解析失败回退空 list,主流程继续

- docs/STATUS.md 顶部加 2026-09-23 批 2 日志条目
- docs/TECH_DEBT.md D17 追加批 2 已完成描述 + 缩减剩余工作(仅剩批 3 / 4)

测试基线:192 passed, 13 skipped(净增 7 通过 + 4 OCC-gated skip)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-09-23 16:21:33 +08:00
parent 2c9ba9d6b3
commit 505f3591ab
8 changed files with 550 additions and 11 deletions
+42 -4
View File
@@ -223,8 +223,13 @@ class ProcessingService:
stage_started = time.perf_counter()
plan_result, export_artifacts = await self._step_generate_cavity(
file_path, selected_material, is_foam_material, process_params,
task_id, timeout=timeout_seconds,
db_session,
file_path,
selected_material,
is_foam_material,
process_params,
task_id,
timeout=timeout_seconds,
)
stage_timings["generate_cavity"] = round(time.perf_counter() - stage_started, 3)
# 方案 B:各方案形状的持久化 STEP 已由子进程导出并返回 manifest(export_artifacts),
@@ -529,14 +534,46 @@ class ProcessingService:
return mesh_result
async def _step_generate_cavity(
self, file_path: str, selected_material: dict, is_foam_material: bool,
process_params: Dict[str, Any], task_id: str, timeout: float = 600,
self,
db_session: AsyncSession,
file_path: str,
selected_material: dict,
is_foam_material: bool,
process_params: Dict[str, Any],
task_id: str,
timeout: float = 600,
) -> Tuple[Dict[str, Any], Optional[Dict[str, Any]]]:
"""生成多方案分模结果(方案 B:子进程内完成分模 + 方案形状 STEP 导出)。
D8:型腔是任务的核心产出,生成失败必须让任务 failed——
异常直接向编排层传播。返回 (plan_result, export_manifest)。
D17 Human-in-Loop 闭环:解析同指纹历史 hints(list of {scheme_axis, weight, sample_count, ...}),
装进 OCC worker payload,让子进程内的 planner/candidate_generator/scheme_scorer 加成。
hints 解析失败不阻塞主流程(logger.warning 后视为空),保证已有任务不退化。
"""
# D17:拉取同指纹老师傅经验(写入即消费)
experience_hints: List[Dict[str, Any]] = []
try:
from moldinsight.services.experience_feedback_service import (
experience_feedback_service,
)
experience_hints = await experience_feedback_service.resolve_for_process_params(
session=db_session,
task_id=task_id,
process_params=process_params or {},
)
if experience_hints:
logger.info(
f"D17 Human-in-Loop:注入 {len(experience_hints)} 条经验"
f"到 task={task_id} 的分模方案"
)
except Exception as hints_err:
logger.warning(
f"D17 hints 解析失败,回退到无 hints 模式: {hints_err}"
)
experience_hints = []
result = await self.run_occ(
"generate_cavity",
{
@@ -546,6 +583,7 @@ class ProcessingService:
"is_foam_material": is_foam_material,
"process_params": process_params,
"export_out_dir": os.path.abspath(self.cad_exporter.output_dir),
"experience_hints": experience_hints, # D17 payload 通道
},
timeout=timeout,
)