| 决策 | 选择 | 理由 |
|---|---|---|
| 排产状态归属 | 引擎不持有。计划存 MES,引擎每次收「当前计划 + 操作」全量输入 | 崩溃零影响;集成=HTTP 调用;可重放测试 |
| 部署形态 | Python + OR-Tools CP-SAT + FastAPI,Docker 单容器 | 技术栈熟悉;CP-SAT Apache 2.0 |
| LLM 位置 | 引擎内零 LLM,只在外围(自然语言→操作、diff 话术) | 确定性可审计;排产正确性不赌模型输出 |
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) |
| 档 | 含义 | 建模 |
|---|---|---|
| F0 硬冻结 | 已开工 / 已通知客户 / 生产订单已下发 | start·room·crew 全锁死 |
| F1 软冻结 | 已通知人员未出发 / 机房预占(决策①) | 锁 room+crew,时间可小幅滑动;解锁=显式操作 |
| F2 自由 | 纯计划 | 完全自由,受稳定性罚项保护 |
硬约束: 工作日历轴(周末/国庆/调休) · 资质证书 · 机房兼容 · 三阶段链(asm→dbg→field) · 物料齐套 ready
最小化: α·总延期 + β·偏离当前计划(稳定性) + γ·makespan
稳定性项是最小扰动的数学本体:每个 F2 单偏离输入计划一天罚 β 分——引擎天然倾向「少动」,不需要启发式模拟人的直觉。
Phase 1: 纯可行性求解(秒级出可行解)
Phase 2: 以 Phase 1 为 hint 优化目标(限时 60-120s)
第一版直接优化会 UNKNOWN(对称性差、搜索慢)——两段式后实测:全月首排 <7s · 增量重排 <1s。超时返回当前最好解 + 质量标记(optimal / within 5% / feasible),不阻塞 UI。
所有硬约束挂高价 slack 变量,求解永远「成功」,slack 取值即诊断(决策②:slack 选项含加班):
这是「demo 玩具」到「生产工具」的分水岭:经理遇到 INFEASIBLE = 直接弃用;遇到带选项的诊断 = 日常工具。
归因来源:求解时记录绑定变量的冲突约束,事后可校验。审批卡上每个变动都可点开看原因(决策③的审批依据)。
{ "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" }
全部为业务方定值(蓝图「开放决策」卡),改参数不发版。