Files
geMoldInsight/docs/ARCHITECTURE.md
T
cjw 6baa6b0d0a docs:ARCHITECTURE / ROADMAP 同步 D17 Human-in-Loop 完成
更新两个权威文档与 D17 端到端闭环对齐:

- docs/ROADMAP.md §2.2 主线二"moldinsight 工程化增强"重点方向
  加一条 D17 已完成条目(2026-09-23~24,3 个 commit:数据 + 权限 +
  写入 API / 算法接缝 + OCC payload / 前端按钮 + Dialog + 经验角标;
  详见 TECH_DEBT.md D17),与既有 ~~XXX~~(YYYY-MM-DD 完成)格式一致

- docs/ARCHITECTURE.md 新增 §6.4 D17 Human-in-Loop 老师傅经验反馈闭环
  —— 已完成段:用 ASCII 数据流图展示老师傅点反馈按钮 → 路由层
  → service 写入 → 续期衰减 → 上传新 STP 触发 resolve_for_process_params
  → OCC payload 透传 → planner 算法加成 → ResultView 渲染的端到端链路

  段内列出"硬规则遵守"(跨模块 FK 守 §5.1、OCC payload 守
  occ_worker.py:7-8、D9 边界不破、init_db.py 幂等修复已落)和
  "重量级约束"(weight 仅正向、sample_count<2 时 ×0.5、graceful 退化、
  角色门控),最后给测试基线指针

  放在 §6.3"文档与结构尚未完全同步"之后作为"已完成端到端闭环"
  对照示例,便于新成员理解 D17 在系统中的位置

文档侧仅变更,无代码改动;按 AGENTS.md §4.1 映射表,模块边界
(ARCHITECTURE.md)/ 演进路线(ROADMAP.md)相关变更同步。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-24 10:15:36 +08:00

15 KiB
Raw Blame History

geMoldInsight 架构与边界(ARCHITECTURE)

文档定位:当前架构、模块边界与结构原则的权威文档。 本文描述“现在的系统结构是什么、边界如何划分、目标形态是什么”;不负责维护当前实现进度,当前状态见 STATUS.md,部署见 DEPLOYMENT.md,演进路线见 ROADMAP.md。 如需追溯模块化设计蓝图与扩展讨论,见 archive/BACKEND_MODULARIZATION_BLUEPRINT.md。


1. 架构目标

geMoldInsight 的目标架构不是微服务,也不是继续维持历史单体,而是:

单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith

这意味着:

  • 保持同一 Git 仓库
  • 保持同一 PostgreSQL 数据库
  • 按模块组织业务代码与部署入口
  • 在不拆库、不拆仓的前提下,明确业务边界与部署边界

2. 当前模块划分

2.1 moldinsight

目录:

职责:

  • STEP/STP 上传与任务管理
  • 几何分析与特征识别
  • 模具方案生成
  • 批量分析
  • 成本估算
  • 导出与结果查询
  • 结合 Celery 执行异步分析链路

2.2 inventory

目录:

职责:

  • 成品/物料管理
  • BOM 管理
  • 库存与库存流水
  • 采购订单 / 销售订单
  • 财务与对账
  • 采购建议推导

2.3 frontend

目录:

职责:

  • 模具分析页面
  • 进销存页面
  • 登录/用户管理
  • 统一路由与状态管理
  • 基于 OpenAPI 类型生成的前端调用

2.4 shared(当前平台层)

目录:

职责:

  • 配置
  • 数据库连接与 session
  • 认证与权限
  • 日志与 request_id
  • 应用工厂与共用中间件

说明:

  • shared 的定位已明确为平台层(跨模块基础能力);模块专属接线(RustFS 启动 / HTML 报告挂载 / 路由聚合)已收敛回模块层(见 §6.2),当前仓库结构仍以 shared 为事实名称
  • 剩余语义收敛(identity 平台表 vs 模块表的命名与注释口径)随实际重构继续推进

3. 当前代码结构

当前核心结构如下:

geMoldInsight/
├── src/
│   ├── entrypoints/
│   │   ├── moldinsight.py
│   │   └── inventory.py
│   ├── shared/
│   ├── moldinsight/
│   ├── inventory/
│   ├── celery_app.py
│   └── celery_tasks.py
├── frontend/
├── migrations/
├── deploy/
├── docs/
└── tests/

这反映的是当前实际代码组织,不是历史单体结构。


4. 部署边界

当前设计上支持三种部署模式:

4.1 unified

一个统一后端同时承载 moldinsight + inventory,并作为前端默认反代目标。

适合:

  • 本地开发
  • 集成环境
  • 小团队统一部署

4.2 moldinsight-only

只部署模具分析后端。

适合:

  • 单独开放分析能力
  • 异步任务与文件处理独立扩容

入口:

4.3 inventory-only

只部署进销存后端。

适合:

  • 独立使用 ERP / 库存能力
  • 与 moldinsight 分开部署节奏

入口:

部署操作与当前推荐方案见 DEPLOYMENT.md。


5. 关键架构原则

5.1 单数据库是刻意设计

项目不是把 moldinsight 与 inventory 强拆成两个数据库,而是保留共享数据库,以支撑完整业务闭环:

  • 分析结果
  • 创建成品
  • 成品 BOM
  • 销售 / 采购 / 库存

典型桥接关系示例:

  • STPFile.product_id -> Product.id

桥接只允许裸 FK 列(字符串表名),不允许跨模块 ORM relationship——单模块部署下另一模块的模型类可能未注册,跨模块 relationship 会让 mapper 配置直接失败(2026-09-17 批次 4 起为硬规则,原三条跨模块 relationship 均无使用方,已删除;对象化查询由使用方显式 select)。

5.2 模块边界优先于“临时方便”

新增逻辑时,应优先放入对应业务模块,而不是继续堆进 shared。

原则上:

  • moldinsight 业务进入 src/moldinsight/
  • inventory 业务进入 src/inventory/
  • 只有真正跨模块复用的基础能力才进入 src/shared/

5.3 前端是独立工程,不是后端静态附属

前端已是独立 Vite/Vue 工程,部署上可与后端组合,但在代码组织上应视为独立模块,而不是后端 static/ 的扩展。


6. 当前主要耦合点

虽然模块化已经成型,但仍有几个关键耦合点需要持续关注:

6.1 共享 ORM 模型 —— 已按模块拆分(2026-09-17,批次 4)

历史上的 shared/models/database.py(31 个模型类三类同居)已拆除,现为按归属分置:

跨模块只允许裸 FK(规则见 §5.1);全量模型注册点收敛为 migrations/env.py 与 tests/conftest.py;归属边界由 tests/test_model_ownership.py 锁定(含单模块独立 mapper 配置与旧模块无 facade 断言)。

6.2 app factory 组合职责 —— 已收敛(2026-09-18,D3 剩余)

平台层与模块专属接线的边界已明确(shared = 跨模块基础能力,模块专属接线归属模块层):

  • 平台工厂 src/shared/app_factory.py 只做纯平台引导:CORS / 请求日志 / 目录准备 / 静态托管 / 数据库与 Redis 启动 / auth 路由 / /health / SPA fallback。startup_hooks 参数承载模块专属启动接线——原 connect_rustfs 参数(平台工厂持有 moldinsight 依赖)已移除。
  • moldinsight 专属接线收敛回 moldinsight 层:
    • RustFS 启动 → init_storage.py 的 rustfs_startup_hook(moldinsight/unified 入口经 startup_hooks 注入)
    • /api 路由聚合 + HTML 报告根路径挂载 → moldinsight/api/__init__.py 的 register_moldinsight_routers(入口只做单点调用,不再重复 include html_report)
  • 入口 src/entrypoints/ 退化为纯组装:sys.path 修正 + 调 create_app + 传 startup_hooks / register_routers。

6.3 文档与结构尚未完全同步

代码结构已明显模块化,但历史文档中仍保留不少阶段性叙述、旧部署语义与重复说明,这也是本轮文档整理要解决的问题之一。

6.4 D17 Human-in-Loop 老师傅经验反馈闭环 —— 已完成(2026-09-23~24,3 个 commit)

算法演进由老师傅经验驱动:通过方案级整体反馈(采纳 / 建议调整 / 拒绝)按"产品指纹 + 工艺参数"为键跨任务匹配,下次同指纹产品分析自动消费老师傅沉淀的经验。这是少数"算法层由用户在线学习样本持续校准"的端到端闭环。

端到端数据流:

┌─────────────────────────────────────────────────────────────┐
│  老师傅在 ResultView 点 👍 老师傅反馈按钮                      │
│     → HumanFeedbackDialog 三选一(采纳 / 建议调整 / 拒绝)     │
└──────────────────────────────┬──────────────────────────────┘
                               │ POST /api/tasks/{id}/experience-feedback
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  experience_feedback_router (src/moldinsight/api/)             │
│    - ensure_task_access 归属校验                              │
│    - current_user.has_permission("feedback_experience_hint")  │
│    - service.record_feedback (flush; commit + invalidate)    │
└──────────────────────────────┬───────────────────────────────┘
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  experience_feedback_service.record_feedback                  │
│    - compute_fingerprint (bbox_aspect / volume_bucket /       │
│      face_bucket / undercut_class / material_family / is_foam) │
│    - 写 experience_feedback 表(D9 边界 / D17 衰减 90d TTL)  │
│    - 同 stp_file_id 整体续期 expires_at                       │
└──────────────────────────────┬───────────────────────────────┘
                               │  同 stp_file_id 上传新 STP 自动消费
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  processing_service._step_generate_cavity                     │
│    - experience_feedback_service.resolve_for_process_params   │
│      → hints (List[{scheme_axis, weight, sample_count, ...}]) │
│    - hints 装进 run_occ payload 顶层 experience_hints          │
└──────────────────────────────┬───────────────────────────────┘
                               │  OCC 子进程(spawn 隔离)
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  occ_worker._op_generate_cavity                               │
│    - payload.get("experience_hints") or {} → planner.generate_plan(hints=...) │
└──────────────────────────────┬───────────────────────────────┘
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  MultiSchemeMoldPlanner.generate_plan(..., hints=None)        │
│    - candidate_generator.generate_candidates(..., hints)      │
│        * priority_score += weight × 20                        │
│        * sample_count ≥ 2 + weight ≥ 0.5 → method="human_experience_primary" │
│    - scheme_scorer.score_schemes(schemes, *, hints)            │
│        * score_breakdown["human_hint_bonus"] = weight × 12    │
│          (sample_count < 2 时 ×0.5 折半)                    │
│    - global_summary.applied_hints 注入返回                   │
└──────────────────────────────┬───────────────────────────────┘
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  ResultView 渲染:                                            │
│    - summary-header 加 t-tag theme="success" 📚 历史经验 N 条  │
│    - 反馈提交后 onFeedbackSubmitted → loadExperienceHints 即刷  │
└──────────────────────────────────────────────────────────────┘

硬规则遵守:

  • 跨模块 FK 仍守 §5.1(experience_feedback.user_id / processing_task_id / stp_file_id 全用字符串表名,无 ORM relationship)
  • OCC 跨进程守 occ_worker.py:7-8 "杜绝 pickle OCC 对象"——payload 普通 dict 透传
  • D9 边界不破:service.flush + 路由 commit(无 service 内 commit)
  • 现有 init_db.py 幂等修复:按 code 补登权限/角色

重量级约束:

  • weight = max(0, (adopted-rejected)/total):仅正向有效,老师傅拒绝不"扣分"老算法
  • sample_count < 2 时 bonus ×0.5:信号不足折半,但 priority_score 仍加成(候选方向仍偏向)
  • 解析失败回退空 list:graceful,主流程不因下游错误退化
  • canGiveFeedback 角色门控:is_superuser || roles 含 process_engineer

测试基线:192 passed, 13 skipped(批 3 净增 +4 OCC-gated:candidate_generator 3 / scheme_scorer 4 / multi_scheme_planner 2 / processing_service 2);前端 vue-tsc + vite 通过。

详见 TECH_DEBT.md D17 + STATUS.md 2026-09-23~24 日志。


7. 专题文档与主骨架的关系

以下文档仍可作为专题补充参考,但不再承担默认入口职责:

AI、铝泡沫等更偏历史设计/规划性质的专题材料已迁入 archive/README.md。

阶段性任务清单、迁移计划、历史总结等文档会逐步迁入 archive/README.md。


8. 与相关文档的边界