叙事📖 故事版🎞 电影版🎬 ELI5文档🎯 蓝图📋 纪要⚙️ 引擎设计🏗 框架图🔁 时序图Demo🖱 交互v1▶️ 动画v1💥 场景v2📦 三阶段v3📅 日历v4
Tony He / 第一阶段蓝图 / 引擎设计
v1.0 · 三决策已锁定

排产引擎黑盒 · 设计文档

无状态纯函数 · CP-SAT · 引擎内零 LLM · 2026-09

0. 三个已锁定决策

决策①
机房预占 = F1 软冻结:进 MES 时机房分配默认跟随预排产,UI 上可单点解锁后参与重排。既尊重预排产的产能承诺,又保留排产经理的例外操作权。
决策②
无解诊断允许建议调休日加班:slack 选项集 = 延期 / 换人 / 加班日历扩展,全部明码标价(各方案对交期的影响并列给出),选择权在经理。
决策③
引擎只返回不写回;经理在 diff 审批卡上批复后由 MES 写入工单库,写入版本化可回溯。引擎永不直接碰生产数据库。

1. 进程边界:无状态服务

决策选择理由
排产状态归属引擎不持有。计划存 MES,引擎每次收「当前计划 + 操作」全量输入崩溃零影响;集成=HTTP 调用;可重放测试
部署形态Python + OR-Tools CP-SAT + FastAPI,Docker 单容器技术栈熟悉;CP-SAT Apache 2.0
LLM 位置引擎内零 LLM,只在外围(自然语言→操作、diff 话术)确定性可审计;排产正确性不赌模型输出

2. API:一个端点,八种操作

POST /solve
{ "op": "plan_month | change_duration | move_room | swap_crew | insert_order | cancel_order
       | mark_unavailable | what_if",
  "current_plan": {...},     // MES 当前计划(增量操作时必传)
  "orders": [...],           // 工单集(含 PO/物料/序列号/配置/出货日)
  "freeze_levels": {...},    // F0/F1/F2 档位映射(生产订单已下发 → F0)
  "config": { "buffer_days", "commit_window", "weights", "calendar" } }

→ { "plan": {...}, "diff": [...], "kpi": {...}, "diagnosis": "...", "quality": "optimal|within5pct|feasible" }

八种操作不是八个算法:全部 = 同一约束模型 + 冻结区 + 当前计划作为稳定性锚,只是输入参数不同。一条代码路径,bug 面最小。

操作语义对应扰动
mark_unavailable资源(人员或机房)在窗口内不可用:请假、机房检修④⑤——与节假日同一约束族(资源不可用窗口),提前排入则计划绕开
what_if不落库的预演:请假影响预览「我请这 3 天会顶飞哪几张单、谁可替」双向透明的引擎侧入口;同引擎 <1s
其余六种见蓝图①②③ + 生产订单重发(cancel+insert)

3. 冻结模型:三档,不是布尔

档含义建模
F0 硬冻结已开工 / 已通知客户 / 生产订单已下发start·room·crew 全锁死
F1 软冻结已通知人员未出发 / 机房预占(决策①)锁 room+crew,时间可小幅滑动;解锁=显式操作
F2 自由纯计划完全自由,受稳定性罚项保护

4. 目标函数:排序字典序 + 稳定性项

硬约束: 工作日历轴(周末/国庆/调休) · 资质证书 · 机房兼容 · 三阶段链(asm→dbg→field) · 物料齐套 ready
最小化: α·总延期 + β·偏离当前计划(稳定性) + γ·makespan

稳定性项是最小扰动的数学本体:每个 F2 单偏离输入计划一天罚 β 分——引擎天然倾向「少动」,不需要启发式模拟人的直觉。

5. 两段式求解(实战验证)

Phase 1: 纯可行性求解(秒级出可行解)
Phase 2: 以 Phase 1 为 hint 优化目标(限时 60-120s)

第一版直接优化会 UNKNOWN(对称性差、搜索慢)——两段式后实测:全月首排 <7s · 增量重排 <1s。超时返回当前最好解 + 质量标记(optimal / within 5% / feasible),不阻塞 UI。

6. 无解 → 诊断,不甩 INFEASIBLE

所有硬约束挂高价 slack 变量,求解永远「成功」,slack 取值即诊断(决策②:slack 选项含加班):

O026 无法按期:C 型调试 3 人×4 天,与 O014/O027 争抢 P18/P20/P23(仅 3 人持证)。
方案A:O027 交期 +3 天 → 全部可行
方案B:10/10 调休日加班 → 全部按期(需人事确认)

这是「demo 玩具」到「生产工具」的分水岭:经理遇到 INFEASIBLE = 直接弃用;遇到带选项的诊断 = 日常工具。

7. diff 输出带归因

O031 顺延 2 天 ← R5 被 O018(故障 +2 天)占用;备选 P22 无 C 证。

归因来源:求解时记录绑定变量的冲突约束,事后可校验。审批卡上每个变动都可点开看原因(决策③的审批依据)。

8. 配置与业务参数分离

{ "freeze_rules":  {"level0": ["started","customer_notified"], "level1": ["crew_notified"]},
  "buffer_days":   {"field_after_dbg": 1},
  "commit_window": {"field_weeks": 3, "roll_every": "week"},
  "weights":       {"lateness": 100, "stability": 1, "makespan": 10},
  "calendar":      "2026-10.json" }

全部为业务方定值(蓝图「开放决策」卡),改参数不发版。

9. 正确性防线

配套材料