chore: 清理生成视频和 AI 临时文件
|
|
@ -57,3 +57,21 @@ artifacts/
|
|||
apps/*.dxf
|
||||
tests/golden/_*.json
|
||||
beihai-shipyard-aps-data/
|
||||
|
||||
# ---- Generated presentation and media drafts (do not commit) ----
|
||||
/video/
|
||||
/_refs/
|
||||
*.mp4
|
||||
*.mov
|
||||
*.avi
|
||||
*.mkv
|
||||
*.webm
|
||||
*.wmv
|
||||
*.m4v
|
||||
*.mp3
|
||||
*.wav
|
||||
/APS智能体演讲稿*.md
|
||||
/APS智能体演示讲解稿.md
|
||||
/Pi-Agent兜底能力详细方案.md
|
||||
/Pi-Agent接入计划.md
|
||||
/Pi-Agent接入详细计划.md
|
||||
|
|
|
|||
BIN
APS智能体演示视频.mp4
131
APS智能体演示讲解稿.md
|
|
@ -1,131 +0,0 @@
|
|||
# 从"人排产"到"智能体排产"
|
||||
## —— APS 计划排产智能体 演示讲解稿(边讲边演,约 15–18 分钟)
|
||||
|
||||
> 使用说明:【讲】为面向领导的讲解词,【演】为系统实际操作。演示口令均已在系统中验证可用;建议演示前完成数据导入并确认服务已启动(Web 端 http://localhost:5173)。
|
||||
|
||||
---
|
||||
|
||||
## 开场(只讲不演,约 2 分钟)
|
||||
|
||||
【讲】各位领导,大家好。今天我不放 PPT,直接让系统自己说话。接下来十五分钟,我将用我们真实的工厂数据,现场演示 APS 计划排产智能体的完整工作过程。
|
||||
|
||||
先交代背景。排产是制造业数字化最后一块硬骨头:约束复杂、变化频繁、决策高度依赖老师傅的个人经验。传统排产软件把成百上千个参数推给用户,最后往往沦为摆设。
|
||||
|
||||
而大模型的成熟给了我们一条新路——**让机器理解人的意图,让算法完成繁重的计算,让人专注于判断与决策**。这就是各位现在看到的这套系统:用自然语言驱动、用可视化确认、用门禁审计约束的计划排产智能体。
|
||||
|
||||
下面开始演示。
|
||||
|
||||
---
|
||||
|
||||
## 第一幕:数据准备——把工厂"搬"进系统(约 2 分钟)
|
||||
|
||||
【讲】一切智能的前提是数据。各位请看,这是我们真实的工厂数据目录——订单、物料、BOM、工艺路线、设备台账,就是最常见的 Excel 表格。
|
||||
|
||||
【演】打开左侧「新工厂排产项目」,展示导入结果卡片(订单 5 行、物料 45 行、工艺路线 15 行、设备 15 行),点击「根据这些数据排产」。
|
||||
|
||||
【讲】请注意刚才发生了什么:系统自动识别了每一张表的角色——哪张是订单、哪张是 BOM、哪张是设备——完成表头映射与校验,写入主数据。传统 APS 实施中最耗时的"数据初始化",在这里是一次导入完成的。
|
||||
|
||||
---
|
||||
|
||||
## 第二幕:一句话排产——听得懂(约 2 分钟)
|
||||
|
||||
【讲】数据就绪。现在,我不点任何菜单,只跟它说一句话。
|
||||
|
||||
【演】在对话输入框输入:**「试排一版交期优先」**,回车。等待右侧甘特图刷新,切换到负荷、交期两个视图各看一眼。
|
||||
|
||||
【讲】各位看到的是完整的智能体闭环:系统理解我的意图,调用排产引擎真实求解,几秒钟产出一个排产版本,右侧沙盘同步呈现——这是甘特图,每个订单在哪台设备、什么时间、哪道工序,一目了然;这是设备负荷,哪台设备超载一眼可见;这是交期看板,哪张订单有延期风险清清楚楚。
|
||||
|
||||
特别强调一点:**这些数字全部来自运筹学引擎的确定性计算,大模型只负责听懂我的话,制度上不允许它编造任何一个数字。**
|
||||
|
||||
---
|
||||
|
||||
## 第三幕:多策略对比——算得全(约 2 分钟)
|
||||
|
||||
【讲】排产从来没有唯一解,只有适合当下经营目标的解。我让系统把几种思路同时算一遍。
|
||||
|
||||
【演】输入:**「对比几种策略」**。等待方案卡片出现,指着 KPI 逐项差异讲,然后点击最优方案的「采用此方案」。
|
||||
|
||||
【讲】系统在我们看不到的地方,把同一份订单用交期优先、产能均衡、换型最小化等不同策略并行试排——这叫沙盒对比,试排期间正式数据不受影响。每张卡片上的准时率、换型次数、设备利用率逐项对照,最优项高亮。我看中哪个,一键采用,右侧沙盘立即刷新。
|
||||
|
||||
过去计划员凭经验只能想一种排法,现在是**机器穷举、人来拍板**。
|
||||
|
||||
---
|
||||
|
||||
## 第四幕:紧急插单与动态调度——应变得快(约 2 分钟)
|
||||
|
||||
【讲】计划永远赶不上变化。现在模拟最常见的突发:客户来电话,一张急单要插进来。
|
||||
|
||||
【演】输入:**「插单快评」**(或在订单面板操作插单向导),展示影响评估结果;再演示:**「设备故障怎么办」→ 展示 L1 池内换机建议**。
|
||||
|
||||
【讲】请注意系统的处理方式:它不是把急单硬塞进去引发连锁延期,而是先做局部修复、评估影响面——影响小,池内秒级换机;影响大,逐级升级为窗口重排、日重排乃至全局重排。这就是我们的 **L1 到 L4 分级动态调度**。
|
||||
|
||||
而且每一步重排建议都带着影响评估和确认卡——**重排是智能体的建议,拍板权永远在人**。
|
||||
|
||||
---
|
||||
|
||||
## 第五幕:柔性排产——我们的差异化能力(约 2 分钟)
|
||||
|
||||
【讲】多品种、小批量的工厂,设备未必永远属于某条产线。这是我们与市面上产品最大的不同。
|
||||
|
||||
【演】打开「柔性工作台」,输入:**「三模式对比」**,展示正排、倒排、瓶颈锚定三种模式的对比结果与产能池仪表盘。
|
||||
|
||||
【讲】系统建立了**工序能力池和虚拟产线**机制:排产时按订单需求,从能力池里动态组合设备、预占资源、用完释放,连设备移动耗时、模具换型时间都精确计算。正排保开工、倒排保交期、瓶颈锚定保产能利用率,三种模式自由切换。
|
||||
|
||||
瓶颈工序的产能是实时重算的——设备一停机,全线产能预测即刻更新,四小时、一天、一周的负载预警自动色标。
|
||||
|
||||
---
|
||||
|
||||
## 第六幕:图纸智能解析——AI 的另一只手(约 2 分钟)
|
||||
|
||||
【讲】排产的上游是技术资料。工程图纸里的物料和工艺信息,过去要靠人一个个抄进系统。
|
||||
|
||||
【演】打开右侧「工程图纸」工作区,输入一张 DXF 图纸路径(例如 `%RUIYANG_DEMO_DIR%\5060102101-001-e(1).dxf`),点击「解析图纸」,展示图号版本识别结果、SVG 预览与物料/BOM/工艺候选清单。
|
||||
|
||||
【讲】系统直接读懂了这张 CAD 图纸:自动识别图号和版本,九千多个图元逐一解析,把图纸里的物料、BOM 引用、工艺信息提取成结构化的候选清单。请注意"候选"两个字——**图纸是证据,不是命令**,这些信息必须经过人工确认才会写入主数据。这就是我们的原则:AI 负责提取,人负责批准。
|
||||
|
||||
---
|
||||
|
||||
## 第七幕:发布与门禁——管得住(约 2 分钟)
|
||||
|
||||
【讲】方案满意了,能不能一键生效?能,但要过一道门。
|
||||
|
||||
【演】输入:**「发布这个版本」**。展示弹出的 P2 确认卡,点击批准。然后输入:**「清空数据重新初始化」**(仅展示确认卡,不批准,点驳回或取消)。
|
||||
|
||||
【讲】各位刚才看到的是系统的**四级门禁**:只读查询随便看,试排对比轻提示,但发布、回滚这类关键动作,必须经确认卡人工点头;涉及 MES 下发等外部系统的动作,要二次确认。刚才那个清空数据的危险操作,我不批准,它就永远执行不了。
|
||||
|
||||
同时,每一次操作都记入哈希链式审计台账——谁决定的、依据是什么、系统当时看到了什么,随时可查、不可篡改。**智能体的每一步"想动",都要经过人的"放行"。**
|
||||
|
||||
---
|
||||
|
||||
## 第八幕:存档、回放与报告——经验沉淀为资产(约 2 分钟)
|
||||
|
||||
【演】输入:**「存个档」**,展示时间线检查点;点击某个历史检查点演示回滚(展示确认卡即可)。然后输入:**「打开仪表盘」**展示 KPI 汇总;最后输入:**「生成日报」**或导出 Word 排产报告。
|
||||
|
||||
【讲】最后三样东西,送给管理者。其一,**时间线**:每个决策节点自动存档,随时回滚到任何一个"如果当初"。其二,**仪表盘**:利用率、准时率、在制、延误,一屏汇总。其三,**报告**:一键生成排产日报和正式的 Word 排产报告——订单交付明细、瓶颈工序、冲突清单、MES 下发状态全部在案,数字直接来自冻结快照,不经过任何 AI 改写。
|
||||
|
||||
---
|
||||
|
||||
## 收尾(只讲不演,约 1 分钟)
|
||||
|
||||
【讲】各位领导,刚才十五分钟,我们从一份 Excel 开始,走完了**数据导入、智能排产、多策略对比、插单应变、柔性组线、图纸解析、门禁发布、存档报告**的完整闭环。
|
||||
|
||||
这套系统的价值,可以归结为三句话:
|
||||
|
||||
**第一,让排产听得懂人话**——计划员从深夜的 Excel 中解放出来;
|
||||
**第二,让决策算得清利害**——机器穷举、人来拍板,每个决定都有计算作底气;
|
||||
**第三,让经验沉淀为资产**——老师傅的智慧变成组织的系统能力,越用越聪明。
|
||||
|
||||
它对标西门子 Opcenter 完成了主体能力覆盖,行业适配不靠定制开发、换一套数据即可运转——不仅能解决我们自己的问题,更具备产品化输出的潜力。
|
||||
|
||||
我的演示到此结束,恳请各位领导批评指正,谢谢大家。
|
||||
|
||||
---
|
||||
|
||||
### 演示前检查清单(不给领导看)
|
||||
|
||||
- [ ] 后端 API(:8000)与前端(:5173)均已启动,浏览器已登录
|
||||
- [ ] 当前项目为「新工厂排产项目」,数据已导入(订单/物料/工艺/设备行数正常)
|
||||
- [ ] 已设置 `RUIYANG_DEMO_DIR`,其中 DXF 图纸路径可复制粘贴
|
||||
- [ ] 演示口令依次试跑一遍:试排一版交期优先 → 对比几种策略 → 插单快评 → 三模式对比 → 发布这个版本 → 存个档 → 打开仪表盘 → 生成日报
|
||||
- [ ] 提前存一个"干净"检查点,演示中翻车可一键回滚
|
||||
- [ ] 「清空数据重新初始化」仅用于展示门禁,**切勿批准**
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
# 让排产听懂人话(功能对照版)
|
||||
## —— APS 计划排产智能体产品演讲稿(约 10 分钟)
|
||||
|
||||
---
|
||||
|
||||
各位领导、各位同仁:
|
||||
|
||||
大家好。今天我向大家介绍的产品,是 **APS 计划排产智能体**——一款用自然语言驱动、用可视化确认的高级计划排产系统。
|
||||
|
||||
今天我不讲概念,而是对照系统的真实功能,一个模块一个模块地向大家汇报:它到底能做什么,以及每一项能力在工厂里意味着什么。
|
||||
|
||||
整款产品可以用一句话概括:**左手说意图,右手出结果,关键操作过门禁。** 下面,我们沿着生产计划的真实工作流,从数据到订单、从计划到排产、从发布到执行,完整走一遍。
|
||||
|
||||
## 一、主数据:先把工厂搬进系统
|
||||
|
||||
一切排产的前提是数据真实。系统的主数据模块覆盖了工厂建模的全部要素。
|
||||
|
||||
**第一,资源建模。** 从工厂、车间、产线到工位、设备,一棵通用资源树完整承载;产线可以编辑、可以停用,停用的产线自动退出排产,不留人为疏漏。
|
||||
|
||||
**第二,物料与工艺。** 物料库存、BOM 明细用量、关键物料标记、工艺步骤工时、外协工序标记,全部可视化维护。
|
||||
|
||||
**第三,日历与维保。** 班次、日历、设备维保计划进入排产计算,维保时段自动避让,设备不会在保养时被排上任务。
|
||||
|
||||
**第四,数据导入与集成。** Excel、CSV 一键导入,表头映射、校验、确认三步落库;与 ERP 的订单库存同步、与 MES 的开工完工回写,都已打通标准流程。
|
||||
|
||||
特别值得一提的是两项行业级能力:一是**换型矩阵**——产品族之间的切换时间精确到矩阵级管理,排产时自动叠加换型耗时;二是**柔性资源档案**——设备的能力集合、可移动属性、移动耗时、模具适配清单全部建档,这是后面柔性排产的地基。
|
||||
|
||||
## 二、订单:从一张订单到一套制造方案
|
||||
|
||||
订单模块回答三个问题:接什么、谁先谁后、如何落地。
|
||||
|
||||
**订单全生命周期管理**——新建、编辑、取消、完成,状态过滤后自动进入排产范围。**订单池与审核**——订单须经过提交、批准的状态机流转,只有已批准订单才能进排产,从制度上杜绝"先干后批"。**优先级管理**——客户等级权重直接参与排产排序,一句话"提高 VIP 权重",全局排序即刻调整。
|
||||
|
||||
针对制造业最头疼的两个场景,系统给出了专门答案:**紧急插单**,有快评与局部修复机制,先评估影响再决定是否采用,而不是硬塞进去引发连锁延期;**预测订单**,单独建账、默认不进正式排产,需要时可以纳入试排、可以一键转正。
|
||||
|
||||
还有两项能力值得单独说明。**订单钉扎溯源**:从销售订单到工单、到物料、到设备负荷,一条链条正查反查都畅通。**订单分解(MRP)**:一张订单按 BOM 与工艺自动展开,自制部分进排产、采购部分给出净需求与前置期倒排建议、外协工序单独标记——从商务订单到制造需求,语义清晰、各司其职。
|
||||
|
||||
## 三、计划层:把答案给在问题发生之前
|
||||
|
||||
传统排产软件解决"怎么排",我们向前多走一步,先回答"能不能"。
|
||||
|
||||
**时间分桶计划**,把近期按日、中期按周、远期按月混合建模;**粗能力评估**,有限产能与无限产能双模式对照;**可行性分析**,在正式排产之前明确告知:哪些订单能按期、缺口在哪一周、缺口有多大。**库存投影**则画出未来库存曲线,断料风险与安全库存告警提前浮出水面。
|
||||
|
||||
发现产能超载之后,**产能平衡**给出削峰建议——哪些任务可以提前、哪些可以挪到空档;挪不动怎么办?**产供决策**给出结构化的三级路径:先加班、再扩线、最后外协,每一条建议都有数据支撑。**交期承诺模拟**更是销售部门的利器:一张询单插进来,乐观、中值、悲观三个交期区间连同资源缺口一并呈现,让每一次对外承诺都经得起推敲。
|
||||
|
||||
## 四、排产引擎:多引擎、多策略、多约束
|
||||
|
||||
这是系统的心脏。
|
||||
|
||||
**引擎层面**,规则引擎、约束规划引擎、遗传算法、混合求解、NSGA-II 多目标优化全部内置,按问题规模与精度要求自动适配。
|
||||
|
||||
**策略层面**,交期优先、先进先出、产能均衡、换型最小化、成本优先、综合评分六大模板开箱即用;多方案沙盒并行计算,方案卡片逐项对比 KPI,最优项自动高亮。
|
||||
|
||||
**约束层面**,十三类约束全部进入注册表:物料齐套三态校验、模具寿命到限锁定、班组技能并发上限、顺序相关换型叠加——每一项都可以在配置中心启停、可以设定软硬。硬约束守住发布底线,任何人都无法把一张违反硬约束的计划发布出去。
|
||||
|
||||
针对高级场景,系统还提供:**战役合并排产**,同产品交期窗口自动合并,减少换型损耗;**滚动时域排产**,从实时一小时到七天长期,多级窗口逐级细化;**正排、倒排、瓶颈锚定**三种模式,配合能力池动态组建虚拟产线——设备从池中选取、预占、用完释放,模具换型与移动耗时分毫必较。
|
||||
|
||||
## 五、动态调度:异常发生时的从容应对
|
||||
|
||||
工厂里没有一成不变的计划。系统把异常处置分为四级:**L1 池内换机**——设备故障,秒级切换到备用设备;**L2 短窗重排**——局部扰动局部消化;**L3 日窗重排**——影响扩大时重排当日;**L4 全局重排**——重大变化时整体优化。每一级都出确认卡,重排不是系统的自作主张,而是人的知情决策。
|
||||
|
||||
## 六、结果与执行:从沙盘到车间
|
||||
|
||||
排产版本经确认后**一键发布**,下发 MES 执行;**报工数据实时回流**,进度偏差在订单上自动呈现,形成完整闭环。
|
||||
|
||||
在执行监控上,系统提供:甘特图支持**拖拽调程**,边拖边校验、十五分钟吸附,拖动即生成新版本;**冲突解决中心**,按冲突类型给出修复建议,一键应用;**方案对比表**,固定策略与柔性三模式矩阵式对照;**KPI 仪表盘**,利用率、准时率、在制、延误一屏汇总;**产能池仪表盘**,四小时、一天、一周的负载预测,瓶颈自动色标预警。
|
||||
|
||||
## 七、对话与治理:智能的边界,信任的基石
|
||||
|
||||
最后讲这套系统与众不同的地方——它如何驾驭 AI,又如何约束 AI。
|
||||
|
||||
**对话层**,意图识别采用"正则快路 + 大模型精解"两级管线,断网时自动降级,永不失语;**知识问答**基于企业 SOP 与制度文档检索作答,引用必附出处,查不到就明说查不到,绝不编造。
|
||||
|
||||
**治理层**,三道防线缺一不可:其一,**数字不经大模型**——所有排产结果与 KPI 全部来自引擎的确定性计算,AI 只负责理解与表达;其二,**P0 至 P3 四级门禁**——只读自由、试排轻提示、关键写操作必须确认、外部系统动作二次确认,智能体的每一步动作都要经过人的放行;其三,**审计哈希链**——全程留痕、防篡改、可校验、可回放,任何时候都能回答:谁决定的、依据是什么、系统当时看到了什么。
|
||||
|
||||
## 结语
|
||||
|
||||
各位同仁,从主数据到订单、从计划层到排产引擎、从动态调度到执行闭环,这套系统的每一项功能,都对应着工厂里一个真实的痛点。它的行业适配不靠定制代码,靠的是主数据与知识库的配置;它的智能不取代人的判断,而是让人的每一个决定,都有计算作底气、有图形作印证、有记录作凭据。
|
||||
|
||||
**当排产听得懂人话,当变化能够被从容应对,计划员将从深夜的 Excel 中解放出来。** 这,就是 APS 智能体交付给中国制造的答卷。
|
||||
|
||||
我的汇报到此结束,谢谢大家。
|
||||
|
||||
---
|
||||
|
||||
*(全文约 2600 字,正常语速演讲约 9–10 分钟;各模块时长可按听众侧重灵活裁剪)*
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
# 从"人排产"到"智能体排产"
|
||||
## —— APS 计划排产智能体 系统功能与流程架构汇报(领导汇报版,约 20–30 分钟)
|
||||
|
||||
> 使用说明:本稿面向领导汇报,主讲**系统功能与整体流程架构**,全程可纯讲不演;标注【可插演示】处如时间允许可现场操作(口令均经系统验证)。全文约 6500 字,正常汇报语速 22–25 分钟;每节标注时长与压缩点,压到 20 分钟或加演示拉到 30 分钟均可。
|
||||
|
||||
---
|
||||
|
||||
## 〇、开场(约 2 分钟)
|
||||
|
||||
各位领导:
|
||||
|
||||
大家好。今天向各位汇报的,是我们自主研发的 **APS 计划排产智能体**。我的汇报分四个部分:**第一,为什么做;第二,系统的总体架构——它是怎么运转的;第三,业务功能全流程——从一张订单到车间执行,系统完整走一遍;第四,它为什么可信、目前验证到什么程度。**
|
||||
|
||||
先说为什么。这些年我们在 ERP、MES 上的投入不小,但有一个环节始终依赖"老师傅"——计划排产。原因有三:约束太复杂,物料齐套、设备产能、模具寿命、班组技能、换型耗时,牵一发而动全身;变化太频繁,插单、故障、物料延期,计划永远赶不上变化;决策太依赖人,一个资深计划员要培养五年以上,经验却无法沉淀、无法复制。传统 APS 软件把成百上千个参数原样推给用户,最后软件沦为摆设,计划员重新回到 Excel。
|
||||
|
||||
而大语言模型的成熟给了我们一条新路:**让机器理解人的意图,让运筹学引擎完成繁重的计算,让人专注于判断与决策。** 这套系统用一句话概括——**用自然语言驱动、用可视化确认、用门禁审计约束的计划排产智能体。**
|
||||
|
||||
---
|
||||
|
||||
## 一、总体架构:一句话如何从"说"变成"排产结果"(约 4 分钟)
|
||||
|
||||
先向各位领导交代系统的整体架构。系统分五层,我用一次真实请求把五层串起来。
|
||||
|
||||
**第一层,表现层。** Web 浏览器与 Electron 桌面端共用同一套界面:左边是对话窗,右边是排产沙盘,我们称之为**"左说右动"**。桌面端数据落本地,无需服务器托管界面,可以发安装包独立运行。
|
||||
|
||||
**第二层,接入与智能体核心。** 所有请求先经网关,进入**意图识别两级管线**:常用指令走"规则快路",毫秒级响应;复杂表达走大模型精解;断网时自动降级、永不失语。意图被翻译成结构化命令后,必须先过一道**权力判定(Harness)**——这是架构的铁律:**任何写操作都必须经过权力判定,没有例外。**
|
||||
|
||||
**第三层,业务域。** 工作流编排、沙盒试排、视图投影、报告生成都在这里。特别说明"沙盒":试排和方案对比全部在沙盒里进行,**试排期间正式数据不受任何影响**,架构上写死了"沙盒不得写主干"。
|
||||
|
||||
**第四层,引擎层。** 排产引擎、知识库、世界状态。这里要特别强调:**所有排产结果、所有 KPI 数字,全部来自运筹学引擎的确定性计算,大模型只负责理解与表达,制度上不允许它碰任何一个数字。**
|
||||
|
||||
**第五层,数据与契约层。** 前后端共用一套 JSON Schema 契约,接口版本严格校验;版本不兼容,系统在挂载前显式阻断,不会出现"前端新、后端旧"的脏状态。
|
||||
|
||||
现在,请各位随我看一句话的完整旅程——这就是系统的**请求主链路**:
|
||||
|
||||
> 计划员输入"试排一版交期优先" → 网关接收 → 意图管线理解成结构化命令 → 工作流编排 → **权力判定**:只读和试排直接放行(P0/P1),发布、回滚这类关键动作挂起,弹出确认卡等人点头(P2),涉及 MES 下发等外部系统动作要二次确认(P3)→ 执行器调用引擎真实求解 → 同时写入**审计哈希链** → 结果投影成甘特图、负荷图、交期看板,回到右侧沙盘。
|
||||
|
||||
这条链路里有三道闸门是架构级焊死的:**写主干必过权力判定;沙盒不得写主干;报告数字只能来自冻结快照。** 后面讲功能时大家会发现,每一个功能都跑在这条链路上,没有旁路。
|
||||
|
||||
---
|
||||
|
||||
## 二、业务功能全流程:从一张订单到车间执行(约 11 分钟,汇报主体)
|
||||
|
||||
下面沿着生产计划的真实工作流,把功能完整走一遍:**数据 → 订单 → 计划 → 排产 → 调度 → 执行 → 回流**,七个环节环环相扣。
|
||||
|
||||
### 2.1 数据:先把工厂"搬"进系统(约 1.5 分钟)
|
||||
|
||||
一切智能的前提是数据。系统支持订单、物料、BOM、工艺路线、设备、模具、工序的 **Excel/CSV 一键导入**——表头自动映射、校验、确认三步落库,传统 APS 实施中最耗时的数据初始化,在这里一次完成。与 ERP 的订单库存同步、与 MES 的开工完工回写,也已打通标准集成流程。
|
||||
|
||||
主数据建模覆盖工厂全要素:**资源树**(工厂—车间—产线—工位—设备)、物料 BOM 与工艺工时、**班次日历与设备维保**(维保时段自动避让)、**换型矩阵**(产品族之间切换时间精确到矩阵级)、模具寿命与班组技能档案。还有一项地基性能力——**柔性资源档案**:每台设备的能力集合、可移动属性、移动耗时、模具适配清单全部建档,这是后面柔性排产的前提。
|
||||
|
||||
【可插演示:展示真实工厂数据目录,输入「分析一下数据文件」,系统自动识别表角色并完成导入——订单 5、物料 45、工艺 15、设备 15、BOM 42。】
|
||||
|
||||
### 2.2 订单:从商务订单到制造需求(约 1.5 分钟)
|
||||
|
||||
订单进入系统后,先过**订单池审核**:提交、批准、驳回的状态机流转,**只有已批准的订单才能进入排产**,制度上杜绝"先干后批"。客户等级权重直接参与排产排序,一句"提高 VIP 权重",全局排序即刻调整。
|
||||
|
||||
接着是 **MRP 订单分解**:一张订单按 BOM 和工艺自动展开——自制部分进排产、采购部分给出净需求与前置期倒排建议、委外工序单独标记,商务订单与制造需求语义分离、各司其职。分解建议经人工确认后下达,采购单自动补全预计到料日。
|
||||
|
||||
针对两个高频痛点有专门机制:**紧急插单**走"快评 + 局部修复",先评估影响面再决定是否采用,而不是硬塞进去引发连锁延期;**预测订单**单独建账、默认不进正式排产,需要时可纳入试排、一键转正。此外**订单钉扎溯源**打通从销售订单到工单、物料、设备负荷的完整链条,正查反查都畅通。
|
||||
|
||||
【可插演示:输入「执行MRP分解」→ 展示自制建议与采购建议;输入「下达MRP建议单」→ 展示确认卡批准过程。】
|
||||
|
||||
### 2.3 计划层:把答案给在问题发生之前(约 2 分钟)
|
||||
|
||||
传统排产软件只解决"怎么排",我们向前多走一步,先回答"**能不能**"。
|
||||
|
||||
- **时间分桶计划**:近期按日、中期按周、远期按月混合建模;
|
||||
- **粗能力评估**:有限产能与无限产能双模式对照;
|
||||
- **可行性分析**:正式排产之前明确告知哪些订单能按期、缺口在哪一周、缺多少;
|
||||
- **库存投影**:画出未来库存曲线,断料风险与安全库存告警提前浮出水面;
|
||||
- **产能平衡**:超载时给出削峰建议,哪些任务提前、哪些挪到空档,前后负荷对照呈现;
|
||||
- **产供决策**:缺口挪不动时给出结构化三级路径——先加班、再扩线、最后外协,每条建议都有数据支撑;
|
||||
- **交期承诺模拟**:销售询单进来,系统给出乐观、中值、悲观三个交期区间连同资源缺口——**让每一次对外承诺都有计算依据**,这是销售部门的利器。
|
||||
|
||||
### 2.4 排产引擎:系统的心脏(约 3 分钟)
|
||||
|
||||
这是技术含量最高的部分,从三个维度汇报。
|
||||
|
||||
**引擎维度:多引擎真实求解。** 内置规则引擎、约束规划引擎(CP)、遗传算法(GA)、混合求解(规则出初解、CP 求精)、NSGA-II 多目标优化,按问题规模与精度自动适配。注意——是**真正的数学求解**,不是让大模型"猜"一张排产表。算不出来怎么办?系统会给出**最小冲突集与中文归因**,明确告诉计划员"卡在哪、为什么",而不是报一个看不懂的错误。
|
||||
|
||||
**策略维度:六大策略模板 + 沙盒对比。** 交期优先、先进先出、产能均衡、换型最小化、成本优先、综合评分开箱即用,另有战役合并策略把同产品交期窗口自动合并、减少换型损耗。同一份订单多种策略**沙盒并行试排**,方案卡片上准时率、换型次数、设备利用率逐项对照、最优项高亮,一键采用。过去计划员凭经验只能想一种排法,现在是**机器穷举、人来拍板**。系统还会从计划员的采用记录中归纳偏好,越用越懂这家工厂。
|
||||
|
||||
**约束维度:十三类约束全部进注册表。** 物料三态齐套、模具寿命到限锁定、班组技能并发上限、顺序相关换型叠加、设备日历维保避让、工艺先后硬约束……每一项都可在配置中心启停、设定软硬:**软约束服务优化,硬约束守住底线——违反硬约束的计划,任何人都发布不出去。** 企业自己的 SOP 制度文件,也能编译成排产约束沉淀进系统。
|
||||
|
||||
**还有一项最突出的差异化能力——柔性排产。** 多品种小批量的工厂,设备未必永远属于某条产线。系统打破"设备固定属于产线"的传统假设,建立**工序能力池 + 虚拟产线**机制:排产时按订单需求从能力池动态组合设备、预占资源、用完释放,连设备移动耗时、模具换型时间都精确计算。**正排、倒排、瓶颈锚定**三种模式自由切换;**滚动时域**从实时一小时到七天长期逐级细化;瓶颈工序产能实时重算——设备一停机,全线产能预测即刻更新。
|
||||
|
||||
【可插演示:输入「对比几种策略」→ 方案卡逐项讲 KPI 差异 → 一键采用;柔性工作台输入「三模式对比」→ 展示正排/倒排/瓶颈锚定与产能池仪表盘。】
|
||||
|
||||
### 2.5 动态调度:异常发生时的分级响应(约 1.5 分钟)
|
||||
|
||||
工厂里没有一成不变的计划。系统把异常处置分为四级:**L1 池内换机**——设备故障秒级切换备用设备;**L2 短窗重排**——局部扰动局部消化;**L3 日窗重排**——影响扩大重排当日;**L4 全局重排**——重大变化整体优化。缺料事件也打通了端到端闭环:WMS 缺料信号进来,自动触发重排方案、确认、下发、回执。
|
||||
|
||||
每一级重排都带着影响评估和确认卡——**重排是智能体的建议,拍板权永远在人。**
|
||||
|
||||
### 2.6 执行与回流:计划不止于纸面(约 1.5 分钟)
|
||||
|
||||
排产版本经确认后**一键发布**,下发 MES 执行——外部系统动作走最高等级二次确认;**报工数据实时回流**,进度偏差在订单上自动呈现,计划—执行—反馈形成完整闭环。
|
||||
|
||||
执行监控四件利器:**甘特图拖拽调程**(边拖边校验、十五分钟吸附,拖动即生成新版本)、**冲突解决中心**(按冲突类型给出修复建议,一键应用)、**方案对比表**(固定策略与柔性三模式矩阵式对照)、**KPI 仪表盘与产能池仪表盘**(利用率、准时率、在制、延误一屏汇总,四小时/一天/一周负载预测自动色标预警)。
|
||||
|
||||
【可插演示:输入「发布这个版本」→ P2 确认卡;输入「打开仪表盘」→ KPI 汇总;输入「存个档」→ 时间线检查点与回滚。】
|
||||
|
||||
---
|
||||
|
||||
## 三、智能体治理与多智能体编排:智能的边界,信任的基石(约 3 分钟)
|
||||
|
||||
让机器参与生产决策,信任是前提。系统设计了三道防线,这也是我们与市面上"AI+排产"概念产品的本质区别。
|
||||
|
||||
**第一道,数字不经大模型。** 所有排产结果与 KPI 全部来自引擎确定性计算,AI 只负责理解与表达,从制度上杜绝编造。知识问答基于企业 SOP 检索作答,**引用必附出处,查不到就明说查不到**。
|
||||
|
||||
**第二道,P0 到 P3 四级门禁。** 只读查询自由、常规试排轻提示、发布回滚必须人工确认、外部系统动作二次确认。**智能体的每一步"想动",都要经过人的"放行"。**
|
||||
|
||||
**第三道,全程留痕可审计。** 从一句指令到一次发布,全部记入哈希链式审计台账,防篡改、可校验、可回放,并有归档密封与篡改检测。任何时候都能回答三个问题:**谁决定的、依据是什么、系统当时看到了什么。**
|
||||
|
||||
在此之上,系统还具备**多智能体编排**能力:可以按需创建不同角色的智能体——数据解析、MRP 分解、柔性排产、报告生成——挂上目标后,看门狗按能力边界自动分发任务、监控执行,智能体之间通过消息总线接力协作;任务超期自动收回重排,**失败时诚实上报、绝不假装成功**,全部完成自动结案。这为多车间、多工厂协同排产预留了架构空间。
|
||||
|
||||
---
|
||||
|
||||
## 四、工程底座与验证情况(约 2 分钟)
|
||||
|
||||
**工程底座三句话:** Web 与桌面双形态,同一套代码;前后端契约严格版本对齐,杜绝接口漂移;全量黄金回归测试**一千零四十二个用例全部通过**,每次改动都有自动化测试守住底线。
|
||||
|
||||
**验证情况三件事:** 其一,已用真实工厂数据完成全流程验证——Excel 导入、订单池审核、MRP 分解、柔性排产、MES 下发、报工回流完整闭环跑通;其二,工程图纸 DXF 文件可直接解析,自动识别图号版本、提取物料与工艺候选,经人工确认后写入主数据——**图纸是证据不是命令,AI 负责提取,人负责批准**;其三,以西门子 Opcenter APS 为基准逐项对标,排产引擎、柔性资源模型、计划层能力已实现主体覆盖,自然语言交互与图纸智能解析是我们的独有优势。
|
||||
|
||||
**可复制性:** 行业适配不靠定制开发,靠主数据与知识库配置——重工、轻工、电子、装备制造,同一套引擎换一套数据即可运转;小厂单线开箱试排,大厂可扩展多工厂多级排程。这意味着它不仅能解决我们自己的问题,更具备**产品化输出**的潜力。
|
||||
|
||||
---
|
||||
|
||||
## 五、收尾(约 1 分钟)
|
||||
|
||||
各位领导,回顾刚才的汇报:一套五层架构、一条焊死三道闸门的请求主链路、一段从数据到回流的七环节业务闭环、三道信任防线——这就是 APS 计划排产智能体的完整图景。
|
||||
|
||||
它的价值归结为三句话:
|
||||
|
||||
**第一,让排产听得懂人话**——计划员从深夜的 Excel 中解放出来;
|
||||
**第二,让决策算得清利害**——机器穷举、人来拍板,每个决定都有计算作底气;
|
||||
**第三,让经验沉淀为资产**——老师傅的智慧变成组织的系统能力,越用越聪明。
|
||||
|
||||
**让排产听得懂人话,让决策算得清利害,让过程经得起审计。** 这是 APS 智能体已经交出的答卷,也是我们对智能制造下一程的承诺。
|
||||
|
||||
汇报完毕,恳请各位领导批评指正,谢谢大家!
|
||||
|
||||
---
|
||||
|
||||
## 附一:时长控制表
|
||||
|
||||
| 章节 | 标准时长 | 压到 20 分钟 | 拉到 30 分钟 |
|
||||
| --- | --- | --- | --- |
|
||||
| 〇 开场 | 2 min | 1.5 min | 2 min |
|
||||
| 一 总体架构 | 4 min | 3 min(链路举例讲快) | 4 min |
|
||||
| 二 业务全流程 | 11 min | 8 min(计划层、执行节压缩一半) | 15 min(插入全部 4 段演示) |
|
||||
| 三 治理与多智能体 | 3 min | 2.5 min | 4 min(多智能体现场演示) |
|
||||
| 四 底座与验证 | 2 min | 1.5 min | 2 min |
|
||||
| 五 收尾 | 1 min | 1 min | 1 min |
|
||||
| 合计 | ~23 min | ~18–20 min | ~28–30 min |
|
||||
|
||||
## 附二:演示口令速查(如现场加演示)
|
||||
|
||||
依次试跑:`分析一下数据文件` → `执行MRP分解` → `下达MRP建议单` → `试排一版交期优先` → `对比几种策略` → `插单快评` → `三模式对比` → `发布这个版本` → `存个档` → `打开仪表盘` → `生成日报`。
|
||||
|
||||
演示前检查:后端(:8000)与前端(:5173)已启动;项目数据已导入且行数正常;提前存一个"干净"检查点,演示翻车可一键回滚;「清空数据重新初始化」仅用于展示门禁,**切勿批准**。
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
# 从"人排产"到"智能体排产"
|
||||
## —— APS 计划排产智能体汇报演讲稿(领导汇报版,约 12 分钟)
|
||||
|
||||
---
|
||||
|
||||
各位领导:
|
||||
|
||||
大家好。今天向各位汇报的,是我们在智能排产方向上的核心成果——**APS 计划排产智能体**。
|
||||
|
||||
这不是对传统排产软件的界面改良,而是排产工作方式的一次范式升级。我的汇报分四个部分:为什么做、做成了什么、能力有多深、价值在哪里。
|
||||
|
||||
## 一、为什么做:排产是制造业数字化最后一块硬骨头
|
||||
|
||||
各位领导都清楚,这些年我们在 ERP、MES 上的投入不可谓不大,但有一个环节始终依赖"老师傅"——**计划排产**。
|
||||
|
||||
原因有三。其一,**约束太复杂**:物料齐套、设备产能、模具寿命、班组技能、换型耗时、工艺先后,任何一个因素变化都会牵一发而动全身。其二,**变化太频繁**:紧急插单、设备故障、物料延期,计划永远赶不上变化。其三,**决策太依赖人**:一个资深计划员的培养需要五年以上,而他的经验无法沉淀、无法复制、更无法传承。
|
||||
|
||||
传统 APS 软件为什么没能解决?因为它们把复杂性原封不动地推给了用户——成百上千个参数、层层嵌套的菜单,最后软件沦为摆设,计划员重新回到 Excel。
|
||||
|
||||
**而大语言模型的成熟,给了我们一条全新的路:让机器理解人的意图,让算法完成繁重的计算,让人专注于判断与决策。** 这就是 APS 智能体的出发点。
|
||||
|
||||
## 二、做成了什么:一个"听得懂、算得准、管得住"的排产智能体
|
||||
|
||||
我用一句话定义这款产品:**用自然语言驱动、用可视化确认、用门禁审计约束的计划排产智能体。**
|
||||
|
||||
它具备智能体的完整闭环——**感知、决策、执行、留痕**。
|
||||
|
||||
**感知层**,计划员用母语直接下达指令:"试排一版交期优先""对比几种策略,哪个换型最少""这张急单插进来影响多大"。系统采用"规则快路 + 大模型精解"的双级意图管线,毫秒级响应,断网时自动降级,永不失语。
|
||||
|
||||
**决策层**,意图被翻译成结构化命令,驱动真正的运筹学引擎计算——注意,是真正的数学求解,不是让大模型"猜"一个排产表。
|
||||
|
||||
**执行层**,结果以甘特图、设备负荷图、交期看板三视图实时呈现;多方案并排对比,准时率、换型次数、产能利用率逐项对照,最优项自动高亮。我们称之为**"左说右动"**——左边对话表达意图,右边沙盘验证结果。
|
||||
|
||||
**留痕层**,每一次试排、每一次发布、每一次回滚,全部进入哈希链式审计台账,可校验、可回放、防篡改。
|
||||
|
||||
## 三、能力有多深:六大能力体系
|
||||
|
||||
下面向各位领导重点汇报能力深度,这也是我们与市面上"AI+排产"概念产品的本质区别。
|
||||
|
||||
**第一,多引擎求解体系。** 系统内置五大引擎:规则引擎、约束规划引擎(CP)、遗传算法(GA)、混合求解(规则出初解、CP 求精)、NSGA-II 多目标优化。六大策略模板开箱即用——交期优先、先进先出、产能均衡、换型最小化、成本优先、综合评分。同一份订单,多种策略沙盒并行试排,方案卡片逐项对比,一键采用。不可行时,系统还能给出最小冲突集与中文归因,明确告诉计划员"卡在哪、为什么"。
|
||||
|
||||
**第二,全要素约束体系。** 十三类约束全部进入注册表、可配置可启停:物料三态齐套、模具寿命到限锁定、班组技能并发上限、顺序相关换型矩阵、设备日历维保避让、工艺先后硬约束……软约束服务优化,硬约束守住底线——违反硬约束的计划,任何人都无法发布。企业自己的 SOP 制度文件,也能编译成排产约束沉淀进系统。
|
||||
|
||||
**第三,柔性排产体系——这是我们最突出的差异化能力。** 面向多品种、小批量,系统打破"设备固定属于某条产线"的传统假设,建立**工序能力池 + 虚拟产线**机制:排产时按订单需求从能力池动态组合设备,预占资源、用完释放,连设备移动耗时、模具换型时间都精确计算。正排、倒排、瓶颈锚定三种模式自由切换,滚动时域从实时一小时到七天长期逐级细化。
|
||||
|
||||
**第四,计划层与交期承诺体系。** 把答案给在问题发生之前:时间分桶计划、有限/无限产能双模式粗评估、可行性分析、库存投影、产能削峰建议、加班—扩线—外协三级产供决策。尤其值得一提的是**交期承诺模拟**——销售询单进来,系统给出乐观、中值、悲观三个交期区间和资源缺口,让每一次对外承诺都有计算依据。
|
||||
|
||||
**第五,动态调度体系。** 异常处置分级响应:L1 设备故障秒级池内换机,L2 短窗口局部重排,L3 日窗重排,L4 全局重排。每一级都生成影响评估和确认卡——**重排是智能体的建议,决策权永远在人**。
|
||||
|
||||
**第六,可信治理体系。** 三道防线:其一,**数字不经大模型**——所有排产结果与 KPI 全部来自引擎确定性计算,AI 只负责理解与表达,制度上杜绝编造;其二,**P0 到 P3 四级门禁**——只读自由、试排轻提示、关键写操作人工确认、外部系统动作二次确认;其三,**全程审计哈希链**——随时能回答三个问题:谁决定的、依据是什么、系统当时看到了什么。
|
||||
|
||||
## 四、价值在哪里:已验证、可对标、可复制
|
||||
|
||||
**已验证。** 系统已完成真实工厂数据的全流程验证:主数据 Excel 一键导入,订单池审核、MRP 自动分解、柔性排产、MES 下发、报工回流完整闭环;工程图纸 DXF 文件可直接解析,自动识别图号版本、提取物料与工艺候选,经确认后写入主数据。
|
||||
|
||||
**可对标。** 我们以西门子 Opcenter APS 为基准做了逐项功能对标,排产引擎、柔性资源模型、计划层能力已实现主体覆盖,部分能力——如自然语言交互、图纸智能解析——是我们的独有优势。
|
||||
|
||||
**可复制。** 行业适配不依赖定制开发,靠主数据与知识库配置实现:重工、轻工、电子、装备制造,同一套引擎,换一套数据即可运转。小厂单线开箱试排,大厂可扩展至多工厂多级排程。这意味着它不仅能解决我们自己的问题,更具备产品化输出的潜力。
|
||||
|
||||
各位领导,排产智能体的意义,不止于效率提升。它把计划员从深夜的 Excel 中解放出来,把个人经验沉淀为组织能力,把"老师傅退休就断层"的风险,变成"系统越用越聪明"的资产。
|
||||
|
||||
**让排产听得懂人话,让决策算得清利害,让过程经得起审计。** 这是 APS 智能体已经交出的答卷,也是我们对智能制造下一程的承诺。
|
||||
|
||||
汇报完毕,恳请各位领导批评指正,谢谢大家。
|
||||
|
||||
---
|
||||
|
||||
*(全文约 2700 字,正常语速汇报约 11–12 分钟;第三部分是能力主体,可按领导关注点取舍压缩至 10 分钟)*
|
||||
66
APS智能体演讲稿.md
|
|
@ -1,66 +0,0 @@
|
|||
# 让排产听懂人话
|
||||
## —— APS 计划排产智能体产品演讲稿(约 10 分钟)
|
||||
|
||||
---
|
||||
|
||||
各位领导、各位同仁:
|
||||
|
||||
大家好。今天,我向大家介绍的,不是一款普通的软件,而是一种全新的生产计划工作方式——**APS 计划排产智能体**。
|
||||
|
||||
在正式开始之前,请允许我先描述一个几乎所有制造企业都熟悉的场景。
|
||||
|
||||
## 一、从一个真实困境说起
|
||||
|
||||
清晨七点,计划员走进办公室,等待他的是这样一幅图景:销售部昨夜临时追加了一张紧急订单,要求三天内交付;三号线的一台关键设备凌晨报警停机;而仓库刚刚反馈,某个关键物料的到货时间比预期晚了两天。桌面上摊着 Excel 表格,屏幕上开着三四个系统,电话此起彼伏。他必须在几小时内回答三个问题:这张急单能不能接?接了以后哪些订单会延期?设备停了,今天的生产怎么重新安排?
|
||||
|
||||
这不是某一位计划员的困境,而是整个离散制造业的集体困境。订单越来越碎,交期越来越短,变化越来越快,而排产决策所依赖的,仍然是人的经验、人的记忆力,以及深夜里一次次的推翻重来。
|
||||
|
||||
**APS 智能体要解决的,正是这个问题。**
|
||||
|
||||
## 二、它是什么:左手对话,右手沙盘
|
||||
|
||||
如果用一句话概括这款产品——**它是一个用自然语言驱动、用可视化确认的计划排产智能体**。
|
||||
|
||||
这句话包含两个关键词。
|
||||
|
||||
第一个关键词是"自然语言驱动"。计划员不需要学习复杂的菜单和参数,只需要像对一位资深同事说话那样下达指令:"试排一版交期优先的方案""对比几种策略,看看哪个换型最少""这张急单插进来,影响有多大"。系统理解意图之后,立即调用排产引擎进行真实计算。
|
||||
|
||||
第二个关键词是"可视化确认"。系统从不让一个黑箱结果直接生效。每一个方案都以甘特图、设备负荷图、交期达成看板三种视图完整呈现;每一次多策略对比,都生成并列的方案卡片,准时率、换型次数、产能利用率逐项对照,最优项一目了然。计划员看懂之后,一键采用,右侧的排产沙盘即刻刷新。
|
||||
|
||||
我们称之为**"左说右动"**:左边是对话,右边是沙盘;语言负责表达意图,图形负责验证结果。人始终站在决策的中心。
|
||||
|
||||
## 三、它能做什么:从订单到执行的完整闭环
|
||||
|
||||
这款产品的能力,覆盖了生产计划的全价值链,我用四个层次向大家说明。
|
||||
|
||||
**第一层,排产引擎——把"排得出来"变成"排得最优"。** 系统内置规则引擎、约束规划引擎、遗传算法与多目标优化引擎,支持交期优先、产能均衡、换型最小化、成本优先等多种策略模板。物料齐套、模具寿命、班组技能、设备日历、换型矩阵——凡是真实工厂里存在的约束,都在引擎的考量之内。十三类约束全部可配置、可启停,硬约束守住底线,软约束服务优化。
|
||||
|
||||
**第二层,柔性排产——让产能摆脱固定产线的束缚。** 在多品种、小批量的生产模式下,设备未必永远属于某条产线。系统为此建立了"工序能力池"与"虚拟产线"机制:排产时按订单需求,从能力池中动态组合设备、预占资源、用完释放,连设备移动耗时、模具换型时间都纳入计算。正排、倒排、瓶颈锚定三种模式自由切换,瓶颈工序的产能实时重算。
|
||||
|
||||
**第三层,计划与承诺——把答案给在问题发生之前。** 在正式排产之前,系统已经可以完成粗能力评估、可行性分析与库存投影:未来几周产能够不够?缺口在哪一周、缺多少?能否按期交付?对于销售询价,系统能给出乐观、中值、悲观三个交期区间,让每一次承诺都有依据。插单快评、分级重排则让异常处置有章可循——设备故障时,系统自动建议池内换机;影响扩大时,逐级升级为窗口重排、日重排乃至全局重排,每一步都留下决策痕迹。
|
||||
|
||||
**第四层,执行与闭环——计划不止于纸面。** 排产版本经确认后一键发布,下发 MES 执行;报工数据实时回流,进度偏差自动呈现;检查点时间线支持随时存档、随时回滚,每一次"如果当初那样排"的假设,都可以安全地验证。
|
||||
|
||||
## 四、它为何可信:三道安全防线
|
||||
|
||||
让机器参与生产决策,信任是前提。为此,产品设计了三道防线。
|
||||
|
||||
**第一道,数字不经大模型。** 大语言模型在这套系统中只负责理解意图与组织语言,所有排产结果、所有 KPI 数字,全部来自运筹学引擎的确定性计算。AI 可以翻译,但绝不允许编造。
|
||||
|
||||
**第二道,操作分级门禁。** 系统将所有操作按风险分为四级:只读查询自由进行;常规试排轻量提示;发布、回滚等关键动作必须经确认卡人工点头;涉及外部系统的动作需要二次确认。智能体的每一步"想动",都要经过人的"放行"。
|
||||
|
||||
**第三道,全程留痕可审计。** 从一句指令到一次发布,每个环节都记入哈希链式审计台账,防篡改、可校验、可回放。出了问题,能精确回答三个问题:谁决定的、依据是什么、系统当时看到了什么。
|
||||
|
||||
## 五、它的边界与诚意
|
||||
|
||||
最后,我想坦率地说明这款产品的定位边界。它不是要取代 MES 的执行管理,也不是要取代计划员的专业判断;它的行业适配不依赖定制代码,而是通过主数据与知识库的差异配置实现——重工、轻工、电子、装备制造,同一套引擎,换一套数据即可运转。小厂可以单线开箱试排,大厂可以走向多工厂的多级排程。
|
||||
|
||||
我们始终相信:**技术的价值,不在于替人做决定,而在于让人的每一个决定,都有计算作底气、有图形作印证、有记录作凭据。**
|
||||
|
||||
当排产听得懂人话,当变化能够被从容应对,计划员将从深夜的 Excel 中解放出来,把经验用于真正的判断。这,就是 APS 智能体想要交付给中国制造的一份答卷。
|
||||
|
||||
我的介绍到此结束,谢谢大家。
|
||||
|
||||
---
|
||||
|
||||
*(全文约 2450 字,正常语速演讲约 9–10 分钟)*
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
# Pi Agent 兜底能力 · 详细实施方案
|
||||
|
||||
> 版本 v2.0 · 2026-09-02 · 取代:`Pi-Agent接入计划.md` / `Pi-Agent接入详细计划.md`(那两份是"接入通道"定位,本方案是"**全系统兜底能力**"定位,范围显著扩大)
|
||||
> 依据:`plan.md` §2.1/§2.2/§3、`PROJECT_OPERATING_RULES.md`、`docs/architecture/harness.md`、`docs/architecture/skills.md`、`docs/architecture/overview.md`
|
||||
> 现状代码锚点:`server/aps_domain/workflow.py:2875`(当前 unknown 意图兜底 = 纯话术回复,**无能力**)、`server/agent_core/harness.py`(`_POWER_MAP` 62 项登记 + 未登记默认 P3 拒绝)、`server/agent_core/tool_runtime.py`(唯一执行入口)、`server/agent_core/mcp_bus.py`、`server/agent_core/feature_flags.py`(FF-01 开关机制)、`apps/desktop/sidecar.cjs`(子进程环境清洗/看门狗,Pi runtime 可直接复用这套模式)
|
||||
|
||||
---
|
||||
|
||||
## 1. 定位重述:什么是"兜底能力"
|
||||
|
||||
**现状**:用户说一句系统听不懂的话,走到 `workflow.py:2875` 的 `assistant.reply/unknown` 分支——LLM 回一段话术,**事情没办成**。已登记意图执行失败(求解器 fatal、数据缺字段、接口超时)也只有报错,没有自救。
|
||||
|
||||
**目标态**:Pi Agent 成为 APS 的**通用能力后备层**——产品化路径"不能办"或"办砸了"时,由 Pi 这个具备读/写/执行能力的通用智能体,在 Harness 划定的围墙内把事办成,并且全程可审计、可回滚、可熔断。
|
||||
|
||||
```
|
||||
用户请求 → 意图管线
|
||||
├─ 命中已登记意图 → 产品化路径(现状,快/稳/确定性)
|
||||
│ └─ 执行失败 ──┐
|
||||
└─ 未识别/未登记 ───┤
|
||||
▼
|
||||
【受治理的兜底车道 Governed Fallback Lane】
|
||||
Pi 分析任务 → 产出《执行计划草稿》(P1,只读可直通)
|
||||
→ 确认卡呈人类审批 (P2 起)
|
||||
→ 批准后 Pi 在沙箱内执行(工具桥只暴露登记过的能力)
|
||||
→ 执行后世界状态 diff 验证 + 报告
|
||||
→ 全程审计链 + 证据链 + 可回滚 checkpoint
|
||||
```
|
||||
|
||||
**一句话:Pi 是被 Harness 雇佣的临时工——有手艺,但进厂要登记、干活要批条、动设备要有人在场、出活要验收。**
|
||||
|
||||
## 2. 与产品宪法的冲突分析与消解
|
||||
|
||||
这是本方案最关键的一节。兜底能力天然想"什么都能干",宪法要求"未经授权什么都不能干"。逐条消解:
|
||||
|
||||
| 宪法红线(PROJECT_OPERATING_RULES 原文) | 表面冲突 | 消解设计 |
|
||||
|---|---|---|
|
||||
| 「动作必须经 `_POWER_MAP` 白名单登记,未登记默认 P3 拒绝」 | 兜底场景恰恰是"未登记意图" | 新增 3 个**元意图**登记进 `_POWER_MAP`:`agent.fallback.propose`=P1(产出计划草稿,沙盒语义)、`agent.fallback.execute`=P2(执行已批准计划)、`agent.fallback.execute.highrisk`=P3(涉主干写/外部系统,逐字段人工确认或默认拒绝)。Pi 从未"直接做事",它做的事都被这三个登记动作包裹 |
|
||||
| 「LLM 只有提议权」(tool_runtime) | Pi 是 LLM 驱动的执行体 | Pi 的**计划**是提议;**执行**走 `/api/actions/confirm` 唯一通道。Pi 能调用的工具本身就是经过登记的意图封装(见 §4.3 工具桥),物理上无法直写 store/DB |
|
||||
| 「不得引入未设计的隐式副作用」 | Pi 自由执行副作用不可枚举 | 沙箱围墙(§4.2):文件系统圈禁在 run 专属目录、网络只通 APS loopback、shell 白名单、环境变量清洗(复用 sidecar.cjs 的 allowlist 模式)。墙内副作用显式枚举,墙外物理不可达 |
|
||||
| 「写前必须建 checkpoints 成对快照」 | Pi 执行前后状态未知 | 兜底车道**强制**执行前 checkpoint、执行后 world diff 验证报告,diff 摘要进确认卡和审计 |
|
||||
| 「失败必须显式报告」 | LLM 倾向"圆场" | Pi 输出契约强制 `status: success|partial|failed|blocked`;`partial/failed/blocked` 必须附未竟事项清单;gateway 侧校验缺失字段即判 failed |
|
||||
| 「mock/stub 不得进入产品路径」 | Pi 可能"假装"调用了工具 | 工具桥每次调用返回真实调用凭证(callId),Pi 报告中引用 callId 可被审计对账;无 callId 支撑的成果声明判无效 |
|
||||
|
||||
## 3. 场景矩阵(10 类兜底场景 × 治理策略)
|
||||
|
||||
| # | 场景 | 触发条件 | 权力 | 治理策略 | 验证方式 | Pi 干不了时的降级 |
|
||||
|---|------|---------|------|---------|---------|------------------|
|
||||
| S1 | **意图未识别**(新说法/新需求口令) | 意图管线产出 `unknown` | propose=P1 / execute=P2 | 计划草稿确认卡必出 | 执行后 diff + 用户确认回执 | 退回话术 + "已记录需求"工单 |
|
||||
| S2 | **已登记意图执行失败**(求解器 fatal、数据缺字段) | handler 抛错/返回失败 | P1 诊断只读 / 修复=P2 | 诊断报告直通;修复动作出卡 | 重跑原意图成功即为验证 | 显式报错原文 + 诊断附件 |
|
||||
| S3 | **新数据格式接入**(客户给了没人写过 importer 的 Excel/CSV/JSON) | data.import 解析失败或用户直接给文件 | P2(导入写主干) | 计划含字段映射表,确认卡呈现映射供审 | 导入后行数/金额对账 + 抽样比对 | 输出《手工整理指引》 |
|
||||
| S4 | **缺算法/策略**(某工艺无现成排产策略) | flex.schedule 无匹配 skill 或用户明示"试个新策略" | P1(沙盒试排) | 仅沙盒语义,产物为草稿版本 | 沙盒 KPI 对比基线版本 | 明确告知"超出兜底能力" |
|
||||
| S5 | **ad-hoc 分析/报告**("帮我看看哪条线最容易拖期") | report.generate/data.analyze 覆盖不了的自由分析 | P1 | 只读工具桥 + 沙盒计算 | 报告数字必须引用冻结快照字段(宪法既有规则) | 返回原始数据 + 分析失败说明 |
|
||||
| S6 | **外部集成故障**(MES/WMS 接口挂了,要手工补录/对数) | integrations 调用失败告警 | P2 | 补录动作逐笔出卡 | 与外部系统恢复后对账 | 生成待补录清单(Excel)交人工 |
|
||||
| S7 | **现场运维诊断**(support 工程师查日志/修配置) | 运维人员在运维入口显式发起 | P2;改配置 P3 | 仅运维角色可见入口;全程录屏级审计 | 修复后健康检查绿 | 输出诊断报告 + 建议人工操作 |
|
||||
| S8 | **演示/售前救场** | 演示中任何上述场景 | 同对应场景 | 无特殊豁免(宪法) | 同对应场景 | 话术降级 |
|
||||
| S9 | **批量数据处理**(一次性清洗/转换 5000 行工单) | 用户发起且无对应产品功能 | P2 | 计划含抽样预览(前 20 行变换结果)出卡 | 全量校验规则 + 抽样人工确认 | 分批+断点,失败批次显式列出 |
|
||||
| S10 | **Pi 自身失败**(模型不可用/超时/超预算/死循环/部分写入) | 熔断器触发 | — | 超时(默认 10min)/步数(50)/token 预算三重熔断;部分写入由 checkpoint 回滚 | 回滚后 diff 为空即验证 | 显式失败报告 + 已回滚声明 |
|
||||
|
||||
**矩阵结论**:10 类场景中 S1/S2/S3/S5/S9 是价值主干(覆盖 80% 真实需求),S4/S6/S7 价值高但风险也高(放后期),S10 是必须设计的元场景。
|
||||
|
||||
## 4. 详细设计
|
||||
|
||||
### 4.1 组件清单(新增 4 个可重生模块 + 1 个外部进程)
|
||||
|
||||
| 组件 | 位置 | moduleId | 职责 |
|
||||
|------|------|----------|------|
|
||||
| FallbackLane 编排器 | `server/agent_core/fallback_lane.py`(新增,~600 行) | `core-fallback-lane` | 触发判定 → 任务简报 → 调 Pi → 收计划 → 出卡 → 执行 → 验证 → 审计 |
|
||||
| Pi 工具桥 | `server/integrations/pi_bridge.py`(新增,~400 行) | `integ-pi-bridge` | 向 Pi 暴露围墙内工具集(§4.3),每次调用发 callId 凭证 |
|
||||
| 兜底验证器 | `server/agent_core/fallback_verify.py`(新增,~300 行) | `core-fallback-verify` | 执行后 world diff、规则校验、报告生成(数字只许来自冻结快照) |
|
||||
| 熔断与预算 | 并入 fallback_lane(~150 行) | 同上 | 超时/步数/token 三重熔断 + audit_alerts 联动 |
|
||||
| Pi runtime 进程 | Node 进程(`pi-agent-core` headless 模式) | — | 被编排器以子进程拉起,生命周期管理**复用 sidecar.cjs 的 SidecarManager 模式**(端口/nonce/环境清洗/看门狗/日志轮转全套照搬) |
|
||||
|
||||
### 4.2 沙箱围墙(自内向外四层)
|
||||
|
||||
```
|
||||
L1 工具层:Pi 只能看见工具桥暴露的工具(§4.3),没有裸 fs/shell/net
|
||||
L2 文件层:cwd 圈禁 ~/.aps/fallback/<runId>/(Web 态 server/data/fallback/<runId>/);
|
||||
可读注入区(用户上传文件副本)、可写工作区、产物出口目录三区分离
|
||||
L3 网络层:仅允许 127.0.0.1:<gateway port>;模型 API 出口走 gateway 代理(可关)
|
||||
L4 进程层:环境变量清洗(CONDA/Python 变量剥离,照搬 buildChildEnv)、
|
||||
父进程看门狗、taskkill 进程树回收、10MiB 日志轮转
|
||||
```
|
||||
|
||||
> 说明:Pi 官方支持 Gondolin/Docker 沙箱,但工业现场 Windows 离线机器上 Docker 不可靠,故以 L1-L4 进程级围墙为主,Docker 沙箱作为 Web/服务器部署的可选加强项。
|
||||
|
||||
### 4.3 工具桥暴露面(围墙内 Pi 的全部"手艺")
|
||||
|
||||
| 工具 | 包装自 | 权力 | 说明 |
|
||||
|------|--------|------|------|
|
||||
| `aps_invoke(intent, params)` | `/api/agent/invoke`(即 handle_intent) | 随意图 | **Pi 写世界的唯一方式**,内部仍过 _POWER_MAP/确认卡 |
|
||||
| `aps_query(sql_like)` | master.query / data.analyze 只读集 | P0 | 世界状态只读视图 |
|
||||
| `knowledge_query(q)` | `/api/rag/query`(ragScopes 鉴权) | P0 | 知识库 |
|
||||
| `fs_read/fs_write(path)` | 沙箱 L2 三区 | — | 物理圈禁,越界即 EACCES |
|
||||
| `shell_run(cmd)` | 白名单(python 脚本、xlsx 处理等显式登记命令) | — | 每条命令正则白名单 + 参数审查 |
|
||||
| `checkpoint_create()` | state checkpoints | — | Pi 可主动建回滚锚点 |
|
||||
| `report_emit(md)` | fallback_verify | — | 产物唯一出口,强制走验证器 |
|
||||
|
||||
### 4.4 意图与权力登记(harness 变更)
|
||||
|
||||
```python
|
||||
# _POWER_MAP 新增 3 项(harness.md 权力矩阵同轮更新)
|
||||
"agent.fallback.propose": "P1", # 产出执行计划草稿(沙盒语义,不写主干)
|
||||
"agent.fallback.execute": "P2", # 执行已批准计划 → 确认卡
|
||||
"agent.fallback.execute.highrisk": "P3", # 涉外部系统/主干批量写 → 默认拒绝,白名单放行
|
||||
```
|
||||
|
||||
确认卡内容(P2 出卡时必须冻结):计划步骤清单、每步工具与权力、预计影响面(目标实体清单)、`evidenceRefs`、执行前 checkpoint id、回滚方式。**卡片上的承诺即执行上限**——执行时逐步比对,Pi 偏离计划即熔断(计划外工具调用 → blocked)。
|
||||
|
||||
### 4.5 证据链与审计
|
||||
|
||||
- 每次兜底运行:`runId` 贯穿 propose→confirm→execute→verify 全链;
|
||||
- Pi 每步工具调用:TOOL 审计(actor=`pi-fallback:<runId>`、callId、入参摘要、结果摘要);
|
||||
- 确认卡批准/拒绝:GATE 审计(既有机制);
|
||||
- 验证报告:REPORT 审计 + 产物落 `~/.aps/fallback/<runId>/report.md`;
|
||||
- 全链可通过既有 `/api/gov/audit` 按 runId 过滤回放。
|
||||
|
||||
### 4.6 开关与熔断(复用 FF-01)
|
||||
|
||||
- `features.json` 新增 `"fallback": false`——**默认全关**,现场按需开;开关本身 P2 确认卡管理;
|
||||
- 熔断三闸:单次运行超时 10min / 步数 50 / token 预算(可配);日维度累计预算;
|
||||
- 触发熔断 → 显式失败 + checkpoint 回滚 + audit_alerts 通知。
|
||||
|
||||
## 5. 部署形态(两个大坑,提前说)
|
||||
|
||||
| 形态 | 方案 | 坑 |
|
||||
|------|------|-----|
|
||||
| **Web/服务器部署** | docker-compose 增加 `pi-runtime` 服务(Node 22 + pi-agent-core) | 小,标准做法 |
|
||||
| **桌面端打包** | PyInstaller sidecar 之外再加 Node runtime(~60-80MB)打进安装包,或做成**可选组件**首次使用时下载 | ① 体积恶化(与 Tauri 瘦身诉求矛盾,两事更该串行决策);② **离线工厂没有模型 API 出口**——兜底重度依赖 LLM,断网即瘫。对策:模型出口走 gateway 代理可配内网模型网关;无模型时 fallback 开关强制关闭且 UI 明示原因(失败显式,不装死) |
|
||||
|
||||
## 6. 阶段计划(修订版,替代 v1.0 计划)
|
||||
|
||||
| 阶段 | 内容 | 工期 | 出口标准 |
|
||||
|------|------|------|---------|
|
||||
| **P0 PoC** | 单场景 e2e 打穿:S5(ad-hoc 分析)。Python 编排器拉起 Pi headless → 计划 → 假确认 → 沙箱执行 → 报告。**不碰产品路径**,全部在 `poc/` | 4-5 人日 | 一个真实分析任务从发起到报告全链跑通;四层围墙验证有效(故意越狱测试被拒) |
|
||||
| **P1 只读兜底** | S1(只读类)/S5/S9-只读部分 进产品路径;fallback_lane + pi_bridge 转正;`agent.fallback.propose` 登记;FF-01 开关接入 | 7 人日 | 意图未识别时用户能拿到"办成的事"而非话术;越狱/注入黄金测试 10 例全拦 |
|
||||
| **P2 沙盒写兜底** | S2/S3/S9 写路径;`agent.fallback.execute`=P2 出卡;checkpoint 强制 + diff 验证器;熔断三闸 | 10-12 人日 | 新格式 Excel 导入从"给文件"到"对账通过"全链路演示绿;计划偏离熔断测试通过 |
|
||||
| **P3 高风险与运维** | S4/S6/S7;`execute.highrisk`=P3;运维入口与角色门禁;集成故障对账流 | 7-10 人日 | MES 断连补录场景验收;运维全程审计可回放 |
|
||||
| **P4 评估与硬化** | 兜底质量 golden 集(30+ 场景用例:成功率/误写率/确认轮次/token 成本四指标);prompt 注入防护集(工单备注藏指令等 20 例);离线降级演练 | 8 人日 | golden 集成功率 ≥85% 且误写率 0;注入集 100% 拦截 |
|
||||
| **P5 验收发布** | 全量黄金(1071+ 基线)、桌面打包冒烟(含可选组件)、文档同轮、现场 runbook | 5 人日 | 发布门禁全绿;康尼数据集真实验收 |
|
||||
| **合计** | | **41-47 人日(1 人约 8-10 周)** | |
|
||||
|
||||
### 里程碑视图
|
||||
|
||||
```
|
||||
W1 W2-3 W4-6 W7-8 W9-10 W11
|
||||
[P0] → [P1 只读] → [P2 写兜底] → [P3 高风险] → [P4 硬化] → [P5 发布]
|
||||
↑go/no-go ↑已可演示价值 ↑核心能力闭环 ↑按需可裁剪 ↑质量门禁
|
||||
```
|
||||
|
||||
## 7. 风险登记册(兜底定位特有)
|
||||
|
||||
| # | 风险 | 等级 | 对策 |
|
||||
|---|------|------|------|
|
||||
| F1 | **非确定性**:同一请求两次兜底结果不同 | 🔴 | 计划审批制(人看的是计划不是黑盒)+ golden 集回归 + 产物必须经验证器,不靠 Pi 自述 |
|
||||
| F2 | **Prompt 注入**:订单备注/导入文件里藏"忽略之前指令" | 🔴 | 注入防护 golden 集(P4);用户数据进 Pi 前包裹隔离标记;工具桥不认 Pi 的"用户已确认"自述——确认只信 gateway 会话内的真实确认卡 |
|
||||
| F3 | **部分写入**:执行到一半熔断 | 🟡 | checkpoint 强制前置 + 回滚验证(diff 为空才算回滚成功) |
|
||||
| F4 | **成本失控**:LLM token 烧穿预算 | 🟡 | 三闸熔断 + 日预算 + audit_alerts |
|
||||
| F5 | **离线工厂无模型出口**,兜底变废铁还误导用户 | 🟡 | 无模型时开关强制关 + UI 明示原因;支持内网模型网关地址配置 |
|
||||
| F6 | **Node runtime 进桌面包** | 🟡 | 可选组件化;与 Tauri 决策串行 |
|
||||
| F7 | **"兜底兜不住还装兜住"**(LLM 圆场) | 🔴 | 输出契约强制 status 字段 + callId 对账(§2 最后一行),圆场在网关层被物理判失败 |
|
||||
| F8 | 团队对"治理下通用智能体"的调试经验不足,问题定位难 | 🟡 | 全程 runId 可回放 + Pi trace 落盘;P0 即建立调试工具链 |
|
||||
| F9 | 范围蔓延:兜底太好用 → 产品化路径荒废 | 🟢 | 治理指标:兜底触发率应随产品化下降;触发率周报,高的场景反哺产品化立项 |
|
||||
|
||||
## 8. 与 v1.0 接入计划的关系
|
||||
|
||||
v1.0 的 `/api/agent/` 适配层、Agent Token、MCP 总线登记**全部保留**——它们在本方案中变成工具桥的基础设施(`aps_invoke` 就是走那层面)。外向接入(人在 Pi 终端里用 APS)成为 P1 完成后的副产品,不再单独排期。
|
||||
|
||||
## 9. 三条决策建议
|
||||
|
||||
1. **先 P0 后承诺**:4-5 人日的 PoC 直接验证最危险的两个未知数(围墙有效性、计划审批可用性),PoC 不过则退回 v1.0 纯接入定位;
|
||||
2. **S 场景分批上线**:P2 之后每批场景单独灰度(FF-01 开关粒度到场景),不一锅端;
|
||||
3. **与 Tauri 串行已定**,再强调一次:F6 意味着如果未来迁 Tauri,Node runtime 的打包方案要一起重设计。
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
# Pi Agent 接入集成计划(结合现有架构与产品规范)
|
||||
|
||||
> 2026-09-02 · 依据:`plan.md` §2.1/§2.2(Gateway 层"Pi Agent 接入"职责)、`PROJECT_OPERATING_RULES.md`、`docs/architecture/harness.md`、`skills.md`、`overview.md`、现状代码(`server/agent_core/`:tool_runtime / mcp_bus / skills / harness / audit)
|
||||
>
|
||||
> **对象界定**:Pi Agent = badlogic 开源 Pi(`pi-coding-agent` CLI + `pi-agent-core` runtime + npm 技能包扩展生态)。若实际指内部自研 Agent 或其它产品,P0-P2 阶段不变,仅 P1 的接插件形态替换。
|
||||
|
||||
---
|
||||
|
||||
## 1. 接入方向决策(先定方向,再谈工期)
|
||||
|
||||
| | 方向 A:**外向接入**(推荐) | 方向 B:内向嵌入 |
|
||||
|---|---|---|
|
||||
| 含义 | APS 暴露稳定 API/MCP 面,Pi 作为**外部客户端智能体**通过技能包调用 APS 能力 | 把 `pi-agent-core` 嵌入 APS,作为通用执行 runtime |
|
||||
| 与宪法兼容性 | ✅ 完全符合:Gateway 是接入层本职;写操作仍过 Harness,「LLM 只有提议权」不破 | 🔴 高风险:引入第二个工具执行通道,与 `tool_runtime`(唯一执行入口)、`_POWER_MAP`(未登记默认 P3 拒绝)直接冲突 |
|
||||
| 技术栈 | 现有 FastAPI 面 + 一个 npm 技能包(TypeScript) | 需内嵌 Node runtime 或 IPC 桥,桌面 sidecar 复杂度大增 |
|
||||
| 工期量级 | **5-7 周全量,2-3 天见 PoC** | 8 周以上且要重审门禁体系 |
|
||||
|
||||
**结论:选方向 A。** plan.md 把 Pi Agent 接入放在 Gateway 而非 Agent Core,本身就说明意图是"接入通道"而非"换引擎"。
|
||||
|
||||
## 2. 架构落位(与现有层一一对应)
|
||||
|
||||
```
|
||||
Pi CLI(用户终端)
|
||||
└─ pi-aps 技能包(npm,新开发) ← 唯一新增的外部组件
|
||||
└─ HTTPS → Gateway (BFF) ← 既有面,加 /api/agent/* 适配
|
||||
├─ 认证:Agent Token(新,基于既有 JMS/租户体系签发)
|
||||
├─ 只读意图 → tool_runtime 只读白名单(已存在)✅ 零改动
|
||||
├─ 写意图 → _POWER_MAP 登记 → P2/P3 确认卡 ✅ 既有机制
|
||||
│ └─ Pi 侧权限钩子 ← 确认卡状态轮询/SSE
|
||||
└─ 审计:actor="pi-agent:<device>",全链路证据链 ✅ 既有机制
|
||||
治理面:Pi 接入在 mcp_bus 登记为插件(tool 级 allow/deny、健康探测、启停)✅ 总线已有
|
||||
```
|
||||
|
||||
**核心原则:不为 Pi 开任何后门。** 所有写路径复用 `/api/actions/confirm` 唯一执行通道;Pi 只是"另一个 UI 入口",和 Web 前端同权同级。
|
||||
|
||||
## 3. 分阶段计划与工期估算
|
||||
|
||||
### P0 · 验证性 PoC(2-3 天)
|
||||
- 跑通 Pi 扩展机制:开发最小技能包 `pi-aps`,调通 `GET /api/health`(校验 `interfaceVersion`)+ `GET /api/world/summary`
|
||||
- 验证三件事:① Pi 技能包的工具注册/权限钩子 API 形态;② 认证链路(先用开发态 token);③ SSE 会话流在终端的呈现方式
|
||||
- **产出**:PoC demo(终端里问"当前 KPI"→ 真实数据)+ go/no-go 报告
|
||||
- 人力:1 人 × 2-3 天
|
||||
|
||||
### P1 · 只读接入(1 周)
|
||||
- Gateway 新增 `/api/agent/` 适配层:把只读意图白名单(`order.pool`/`plan.buckets`/`conflict.list`/`knowledge.query` 等 19 个)封装为 agent 友好的 JSON-RPC 风格端点
|
||||
- Agent Token 签发与吊销(P2 确认卡管理,落 `~/.aps` 或租户库;scope 到只读)
|
||||
- `pi-aps` v0.1:查询类命令全集 + 错误透传(遵守规范:失败显式报告,不泛化确认)
|
||||
- 黄金测试:agent 端点契约 + token 越权 fail-closed
|
||||
- 人力:1 人 × 1 周
|
||||
|
||||
### P2 · 写操作过门禁(1-2 周)
|
||||
- P1/P2 意图(如 `flex.schedule` 试排草稿、`skill.enable`)接入:确认卡在终端呈现为 Pi 权限确认钩子,批准后走 `/api/actions/confirm`
|
||||
- 证据链贯穿:Pi 发起的 P2/P3 写同样冻结 `evidenceRefs`/`beforeSnapshot`,审计 `actor=pi-agent` 可独立过滤
|
||||
- **关键约束**(来自 PROJECT_OPERATING_RULES):不得引入隐式副作用;DRAFT/未批准状态不得当事实返回给 Pi
|
||||
- 人力:1 人 × 1-2 周(确认卡异步交互在 CLI 的 UX 是主要变数)
|
||||
|
||||
### P3 · MCP 总线治理化(1-2 周)
|
||||
- Pi 接入面在 `mcp_bus` 登记为正式插件:manifest + 工具契约(input/output JSON Schema + P0-P3 权力标注)+ tool 级 allow/deny + 健康探测 + 启停
|
||||
- 三方契约同步:`shared/schemas/` ↔ `contracts.py` ↔ 技能包类型定义,纳入 `test_contract_sync.py` 门禁
|
||||
- 管理台:SkillConsole 同款 UI 呈现 Pi 插件(概览/健康/审计/日志)
|
||||
- 人力:1 人 × 1-2 周
|
||||
|
||||
### P4 · 验收与发布门禁(1 周)
|
||||
- 全量黄金测试(当前基线 1071 项)+ agent 专项;文档同轮(harness.md 端点备案、skills.md、CHANGELOG)
|
||||
- 安全评审:token 泄漏面、桌面态 nonce 与 agent token 的并存策略
|
||||
- 桌面端打包冒烟(sidecar 不变,风险低)
|
||||
- 人力:1 人 × 1 周
|
||||
|
||||
**合计:1 人约 5-7 周;P0+P1(只读可用版)2 周内可演示。**
|
||||
|
||||
## 4. 风险与规范映射
|
||||
|
||||
| 风险 | 等级 | 规范依据与对策 |
|
||||
|------|------|---------------|
|
||||
| 第二个执行通道绕过 Harness | 🔴 | 铁律:所有写走 `tool_runtime`/`/api/actions/confirm`;加黄金测试断言"agent 端点无直写 store" |
|
||||
| 确认卡在 CLI 的异步 UX | 🟡 | P2 阶段先做同步轮询版;超时自动拒绝(fail closed) |
|
||||
| Agent token 权限蔓延 | 🟡 | scope 最小化(先只读);签发/吊销走 P2 确认卡;审计独立 actor |
|
||||
| Pi 上游版本漂移 | 🟡 | 技能包锁定 Pi 版本范围;`min_bus_version` 同款兼容声明 |
|
||||
| 与 Tauri 迁移抢人力 | 🟡 | 两者都动 Gateway/sidecar 周边——**建议串行**:先 Pi 接入 P0-P1(不动壳),Tauri 决策等 WebView2 调查 |
|
||||
|
||||
## 5. 建议的下一步
|
||||
|
||||
先跑 **P0(2-3 天)**:成本最低,直接验证"Pi 技能包 ↔ 现有 Gateway"的匹配度,产出 go/no-go。P0 不过,后面全部不用谈;P0 过了,P1 的估算就有实测依据了。
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
# Pi Agent 接入 · 详细实施计划
|
||||
|
||||
> 版本 v1.0 · 2026-09-02 · 配套摘要文档:`Pi-Agent接入计划.md`
|
||||
> 依据:`plan.md` §2.1/§2.2、`PROJECT_OPERATING_RULES.md`、`docs/architecture/harness.md`、`docs/architecture/skills.md`
|
||||
> 现状代码基线:`server/agent_core/`(harness `_POWER_MAP` 62 项登记、tool_runtime 只读白名单 19 项、mcp_bus、skills、audit)、`server/auth/`(JMS provider + 许可证 token + 租户)、`server/gateway/app.py`
|
||||
>
|
||||
> **对象界定**:Pi Agent = badlogic 开源 Pi(pi-coding-agent CLI + pi-agent-core + npm 技能包生态)。方向 A:外向接入,Pi 作为外部客户端智能体经 Gateway 调用 APS 能力,不开第二个执行通道。
|
||||
|
||||
---
|
||||
|
||||
## 0. 总览
|
||||
|
||||
| 阶段 | 名称 | 工期(人日) | 出口标准(Go/No-Go 门禁) |
|
||||
|------|------|------------|--------------------------|
|
||||
| P0 | 验证性 PoC | 2-3 | 终端内完成真实查询往返;Pi 扩展 API 三个未知数全部有答案 |
|
||||
| P1 | 只读接入 | 5 | 只读意图 19 项全部可经 agent 端点调用;token 越权测试 fail-closed |
|
||||
| P2 | 写操作过门禁 | 5-10 | P1/P2 意图经确认卡执行;CLI 侧确认/拒绝/超时三态可演示 |
|
||||
| P3 | MCP 总线治理化 | 5-10 | Pi 插件入总线清单;契约三方同步门禁通过;管理台可见 |
|
||||
| P4 | 验收与发布门禁 | 5 | 全量黄金测试绿;文档同轮完成;安全评审签字 |
|
||||
| **合计** | | **22-33 人日(约 5-7 周/1 人)** | |
|
||||
|
||||
**串行前提**:与 Tauri 迁移不并行(都动 Gateway/sidecar 周边);FF-01 基线已提交(8b7063f)。
|
||||
|
||||
---
|
||||
|
||||
## P0 · 验证性 PoC(2-3 人日)
|
||||
|
||||
### 目标
|
||||
用最小成本验证"Pi 技能包 ↔ 现有 FastAPI Gateway"匹配度,产出 go/no-go。
|
||||
|
||||
### 任务分解
|
||||
|
||||
| # | 任务 | 产出 | 工时 |
|
||||
|---|------|------|------|
|
||||
| P0-1 | 安装 Pi(`npm i -g` pi-coding-agent),跑通官方 hello 技能包,确认扩展 API 形态(工具注册签名、权限钩子、配置落点 `~/.pi/`) | 笔记 + 截图 | 0.5d |
|
||||
| P0-2 | 起本地 APS server(`.venv` 固定 CPython,`python -m uvicorn server.main:app --port 8000`),确认 `/api/health` 返回 `interfaceVersion=1.0` | 环境就绪 | 0.5d |
|
||||
| P0-3 | 写最小技能包 `pi-aps`(单文件):注册 2 个工具 `aps_health` / `aps_summary`,调 `/api/health` 与 `/api/world/summary`,结果原样透传 | PoC 技能包 | 1d |
|
||||
| P0-4 | 验证 SSE:终端订阅 `/api/chat` 会话流或等价端点,确认流式事件在 CLI 可读(决定 P2 确认卡用轮询还是 SSE) | 技术结论 | 0.5d |
|
||||
| P0-5 | go/no-go 报告:三个未知数(扩展 API 形态 / 认证链路 / SSE 呈现)+ P1 估算修正 | 报告 | 0.5d |
|
||||
|
||||
### PoC 技术约束(防止 PoC 污染产品路径)
|
||||
- PoC 技能包只读、不进仓库 `apps/` 或 `server/`;放 `poc/pi-aps/`;
|
||||
- 认证用开发态临时方案(环境变量 token),**不写** token 签发产品代码——那是 P1 的事;
|
||||
- 遵守规范:工具失败显式报错,不包装成泛化成功回复。
|
||||
|
||||
### 出口标准(全部满足才进 P1)
|
||||
1. 在 Pi 终端输入自然语言/命令 → 返回真实 APS 数据(非 mock);
|
||||
2. Pi 权限钩子能在工具调用前拦截(P2 确认卡的技术前提);
|
||||
3. 无明显阻塞性限制(如技能包无法持久化配置、无法发 HTTPS 到自签证书内网服务器等)。
|
||||
|
||||
---
|
||||
|
||||
## P1 · 只读接入(5 人日)
|
||||
|
||||
### 目标
|
||||
Pi 用户可完成全部只读场景:查订单池、KPI、分桶计划、冲突、知识库。
|
||||
|
||||
### API 设计(新增 `/api/agent/` 适配层)
|
||||
|
||||
设计原则:**薄适配,零业务逻辑**(Gateway 职责边界:不含排产算法/LLM 决策)。复用 `handle_intent`,不复制逻辑。
|
||||
|
||||
```
|
||||
POST /api/agent/invoke
|
||||
请求:{ "intent": "order.pool", "params": {...}, "requestId": "uuid" }
|
||||
响应:{ "ok": true, "intent": "...", "power": "P0", "data": {...},
|
||||
"evidenceRefs": [...], "interfaceVersion": "1.0" }
|
||||
错误:{ "ok": false, "error": { "code": "INTENT_NOT_REGISTERED" |
|
||||
"POWER_DENIED" | "CONFIRM_REQUIRED" | "UPSTREAM_FAILED", ... } }
|
||||
|
||||
GET /api/agent/intents # 列出该 token scope 可调用的意图目录(从白名单/_POWER_MAP 派生)
|
||||
GET /api/agent/intents/{name} # 单意图参数 schema(供 Pi 动态生成工具签名)
|
||||
```
|
||||
|
||||
行为规则:
|
||||
- 只读意图(tool_runtime 白名单 19 项 + `_POWER_MAP` 中 P0 项)→ 直通执行;
|
||||
- P1/P2/P3 → P1 阶段一律返回 `CONFIRM_REQUIRED`/`POWER_DENIED`(P2 阶段才接通);
|
||||
- **未登记意图 → 拒绝 + 审计**(与 tool_runtime 同语义,fail closed)。
|
||||
|
||||
### 任务分解
|
||||
|
||||
| # | 任务 | 涉及文件 | 工时 |
|
||||
|---|------|---------|------|
|
||||
| P1-1 | `/api/agent/*` 三个端点:参数校验(Pydantic)、intent 登记检查、委托 handle_intent、统一错误码 | `server/gateway/app.py`(新增路由段,<150 行) | 1d |
|
||||
| P1-2 | Agent Token:基于 `server/auth/` 既有体系签发长期 token(type="agent",scope=["read"]),绑定租户 + device;签发/吊销登记 P2 意图 `agent.token.issue` / `agent.token.revoke` 入 `_POWER_MAP` | `server/auth/`(新增 `agent_tokens.py`)、`harness.py` 登记 2 项 | 1.5d |
|
||||
| P1-3 | 审计:`actor="pi-agent:<deviceId前8位>"`,全部调用落 TOOL/AGENT 审计事件,可按 actor 过滤 | `server/agent_core/audit.py`(复用,仅扩展 actor 约定) | 0.5d |
|
||||
| P1-4 | `pi-aps` v0.1:从 `/api/agent/intents` 动态生成工具集;配置项(server URL、token、超时)落 `~/.pi/aps.json`;错误码 → 人类可读终端输出 | `poc/pi-aps/` → 转正为独立 npm 包 | 1.5d |
|
||||
| P1-5 | 黄金测试:端点契约、未登记意图拒绝、token 无效/越权/吊销 fail-closed、审计落链断言 | `tests/golden/test_agent_gateway.py`(新增) | 0.5d |
|
||||
|
||||
### 出口标准
|
||||
- 只读意图 100% 可调;非只读一律显式拒绝;
|
||||
- token 六种异常(缺失/伪造/过期/吊销/scope 越界/跨租户)全部 fail-closed 且有审计;
|
||||
- `pytest tests/golden/test_agent_gateway.py` 全绿;`test_contract_sync.py` 不受影响。
|
||||
|
||||
---
|
||||
|
||||
## P2 · 写操作过门禁(5-10 人日)
|
||||
|
||||
### 目标
|
||||
Pi 可发起 P1/P2 意图(试排、登记 skill 等),确认卡在终端完成人机确认。
|
||||
|
||||
### 确认卡交互设计(CLI 三态)
|
||||
|
||||
```
|
||||
Pi 发起 flex.schedule(P1 草稿类)→ 直通执行,返回 evidenceRefs(含 schedule-version)
|
||||
Pi 发起 schedule.publish(P2)→ /api/agent/invoke 返回 CONFIRM_REQUIRED + cardId
|
||||
→ Pi 权限钩子向用户呈现确认卡摘要(动作/影响/evidenceRefs 指纹)
|
||||
→ 用户批准:POST /api/actions/confirm { cardId, approved: true }(既有唯一执行通道 ✅)
|
||||
→ 用户拒绝/超时(默认 5min):fail closed,审计留痕
|
||||
```
|
||||
|
||||
### 任务分解
|
||||
|
||||
| # | 任务 | 工时 |
|
||||
|---|------|------|
|
||||
| P2-1 | invoke 端点接通 P1 意图(沙盒/草稿语义直通,返回 evidenceRefs) | 1d |
|
||||
| P2-2 | invoke 端点接通 P2:生成确认卡(复用 harness 出卡逻辑,冻结 evidenceRefs/beforeSnapshot),返回 cardId + 摘要 payload | 1.5d |
|
||||
| P2-3 | token scope 升级:`read` → `read+write`(签发改 P2 确认卡;scope 与意图权力交叉校验:P2 意图必须 write scope) | 1d |
|
||||
| P2-4 | pi-aps v0.2:确认卡终端 UI(摘要渲染 + y/n + 超时倒计时);批准后轮询/SSE 拿执行结果;失败显式呈现 | 1.5-3d |
|
||||
| P2-5 | 证据链黄金测试:Pi 发起的 P2 写,审计含 beforeSnapshot + evidenceRefs + `verify_pending_evidence` 缺项拒绝 | 1d |
|
||||
| P2-6 | 超时/并发边界:一 token 同时仅一张 pending 卡;卡过期自动拒绝 | 1d(含测试) |
|
||||
|
||||
### 出口标准
|
||||
- 演示脚本全绿:试排→发布→回滚三链路在 Pi 终端闭环;
|
||||
- 安全测试:无卡直调 confirm、伪造 cardId、过期卡、跨 token 用卡——全部拒绝 + 审计;
|
||||
- 变数说明:P2-4 的 CLI 交互若 Pi 权限钩子能力受限(P0-4 结论),可能退化为"Web 确认 + CLI 只读结果",工期取下限。
|
||||
|
||||
---
|
||||
|
||||
## P3 · MCP 总线治理化(5-10 人日)
|
||||
|
||||
### 目标
|
||||
Pi 接入面成为 `mcp_bus` 正式插件,享受统一治理(契约、权限、健康、启停、审计、管理台)。
|
||||
|
||||
### 插件 manifest(落 `server/data/mcp_plugins/plugins.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin_id": "pi-agent-gateway",
|
||||
"name": "Pi Agent 接入面",
|
||||
"version": "1.0.0",
|
||||
"min_bus_version": "1.0",
|
||||
"endpoint": "self:///api/agent",
|
||||
"tools": [
|
||||
{"name": "order.pool", "power": "P0", "input_schema_ref": "shared/schemas/..."},
|
||||
{"name": "flex.schedule", "power": "P1", "input_schema_ref": "shared/schemas/..."},
|
||||
{"name": "schedule.publish", "power": "P2", "input_schema_ref": "shared/schemas/..."}
|
||||
],
|
||||
"ragScopes": []
|
||||
}
|
||||
```
|
||||
|
||||
### 任务分解
|
||||
|
||||
| # | 任务 | 工时 |
|
||||
|---|------|------|
|
||||
| P3-1 | 把 `/api/agent/intents` 目录生成为 MCP manifest(自动生成 + 版本化),注册进 mcp_bus | 1.5d |
|
||||
| P3-2 | tool 级 allow/deny 配置面:按现场可裁剪 Pi 可用意图(deny 优先,fail closed) | 1d |
|
||||
| P3-3 | 三方契约同步:`shared/schemas/agent_invoke.schema.json` ↔ `server/contracts.py` ↔ pi-aps 类型定义;入 `test_contract_sync.py` 门禁 | 1.5d |
|
||||
| P3-4 | 管理台:SkillConsole 复用双面板模式呈现 Pi 插件(概览/健康/审计/日志页签) | 2d |
|
||||
| P3-5 | 健康探测:agent 端点纳入总线探测历史(最近 20 次) | 0.5d |
|
||||
| P3-6 | 文档同轮:harness.md 端点备案、skills.md 增补、CHANGELOG | 0.5d |
|
||||
|
||||
### 出口标准
|
||||
- 总线清单可见、可启停(P2 确认卡)、审计可按插件过滤;
|
||||
- 契约漂移测试阻断生效(故意改一端 → CI 红)。
|
||||
|
||||
---
|
||||
|
||||
## P4 · 验收与发布门禁(5 人日)
|
||||
|
||||
| # | 任务 | 工时 |
|
||||
|---|------|------|
|
||||
| P4-1 | 全量黄金测试(基线 1071 项 + 新增 agent 专项)固定 CPython 运行时全绿 | 1d |
|
||||
| P4-2 | 安全评审:token 存储(`~/.pi/aps.json` 权限 600)、传输(内网 HTTP → 建议 HTTPS 或 SSH 隧道指引)、桌面态 nonce 与 agent token 并存策略 | 1.5d |
|
||||
| P4-3 | 真实场景验收:康尼数据集上跑"查询→试排→确认发布"全链路 5 轮 | 1d |
|
||||
| P4-4 | 发布物料:pi-aps npm 包版本化 + 安装文档 + 现场部署 runbook | 1d |
|
||||
| P4-5 | 回顾:估算偏差分析,更新本计划为 v1.1 | 0.5d |
|
||||
|
||||
---
|
||||
|
||||
## 6. 横切约束(每阶段都必须遵守,来自 PROJECT_OPERATING_RULES)
|
||||
|
||||
1. **无后门**:任何写路径不得绕过 `tool_runtime`/`/api/actions/confirm`;P1 起加黄金测试断言"agent 端点代码无直接 store 写调用"(import 扫描级)。
|
||||
2. **失败显式**:工具失败/为空/中止 → 结构化错误码透传到终端,禁止泛化确认。
|
||||
3. **状态诚实**:DRAFT/未批准/失败状态在 agent 响应中显式标注 `status` 字段,不得当完成事实。
|
||||
4. **证据链**:P2/P3 写全部携带 `beforeSnapshot` + `evidenceRefs`;审计 append-only。
|
||||
5. **契约三方同步**:改契约必须三端同改 + `test_contract_sync.py`。
|
||||
6. **文档同轮**:每阶段收尾同步 harness.md / CHANGELOG;`docs/README.md` 铁律。
|
||||
7. **运行时**:所有验证用 `.venv` 固定 CPython,禁用 PATH 上的 Anaconda python(WinError 127 前科)。
|
||||
8. **提交纪律**:未经用户授权不提交/不推送;每阶段一个独立 commit,conventional 中文提交信息。
|
||||
|
||||
## 7. 风险登记册
|
||||
|
||||
| # | 风险 | 概率 | 影响 | 触发阶段 | 对策 |
|
||||
|---|------|------|------|---------|------|
|
||||
| R1 | Pi 权限钩子不支持异步确认交互 | 中 | P2 降级为"CLI 发起 + Web 确认" | P0-4 暴露 | PoC 即验证;降级方案可接受 |
|
||||
| R2 | token 长期持有泄漏 | 低 | 数据外泄 | P1 后 | scope 最小化 + 吊销通道 + 审计告警(audit_alerts 既有) |
|
||||
| R3 | Pi 上游 API breaking change | 中 | 技能包失效 | 长期 | 技能包锁版本范围;manifest `min_bus_version` 同款声明 |
|
||||
| R4 | 与现场交付(康尼/徐工)抢人力 | 高 | 双方延期 | 全程 | P0/P1 先行(可演示价值),P2+ 按交付间隙排 |
|
||||
| R5 | 内网无 npm registry,技能包分发难 | 中 | 现场装不上 | P4 | 离线 tarball 分发 + runbook 写明 |
|
||||
| R6 | 与 Tauri 迁移冲突 | 低 | 返工 | — | 已约定串行 |
|
||||
|
||||
## 8. 关键依赖与前置
|
||||
|
||||
- ✅ FF-01 基线已提交(8b7063f)
|
||||
- ⬜ P0 需要:本机可装 Pi(npm 网络)、APS server 本地可起
|
||||
- ⬜ P1 需要:确认 agent token 在桌面态(sidecar nonce 门禁)与 Web 态(JMS 登录)两种部署下的统一策略——**建议 P0 期间出结论**
|
||||
- ⬜ P4 需要:康尼数据集可用
|
||||
|
||||
## 9. 里程碑视图
|
||||
|
||||
```
|
||||
W1 W2 W3-4 W5-6 W7
|
||||
[P0 PoC]→[P1 只读]→[P2 写门禁]→[P3 治理化]→[P4 验收]
|
||||
↑go/no-go ↑可演示 ↑安全评审预备 ↑发布门禁
|
||||
```
|
||||
BIN
_refs/ref1.png
|
Before Width: | Height: | Size: 159 KiB |
BIN
_refs/ref2.png
|
Before Width: | Height: | Size: 280 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
# Pi Agent 兜底能力发布与现场运行手册
|
||||
|
||||
> 角色:Agent-D(P5 发布实现)· 成文日期:2026-09-04
|
||||
> 依据:`Pi-Agent兜底能力详细方案.md` §5/§6/§7、`poc/pi-fallback/P4-P5-DESIGN.md` §5、`poc/pi-fallback/P4-P5-AUDIT.md`、`docs/architecture/fallback.md` 与当前代码。
|
||||
> 依据:`poc/pi-fallback/P4-P5-DESIGN.md` §5、`poc/pi-fallback/P4-P5-AUDIT.md`、`docs/architecture/fallback.md` 与当前代码。
|
||||
> 本文只写运行与发布准备边界,不替代 `CHANGELOG.md`/`fallback.md`;那两份由主管统一更新。
|
||||
|
||||
## 1. 启用前提与 fail-closed 开关
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# pi-aps:Pi Agent 访问 APS Gateway 的 PoC 包
|
||||
|
||||
本目录对应 `Pi-Agent接入详细计划.md` 的**方向 A(外向接入)**:Pi CLI 作为外部
|
||||
本目录实现 **方向 A(外向接入)**:Pi CLI 作为外部
|
||||
客户端智能体,通过新增的 `/api/agent/*` 适配层调用 APS 业务能力,不在 Pi 侧另开
|
||||
排产执行通道。
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# GOAL:Pi Agent 兜底能力 · P4/P5 收口(多 agent 协同 · 第五轮)
|
||||
|
||||
> 本文件是本轮协同的协调板。每个 sub agent 开工前必读;完工后在最终报告里给交接物。
|
||||
> 目标文档:根目录 `Pi-Agent兜底能力详细方案.md`。
|
||||
> 目标文档:`P4-P5-DESIGN.md` 与 `P4-P5-AUDIT.md`。
|
||||
|
||||
## 主管已核实基线(2026-09-04)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
## 目标(Go/No-Go 判据)
|
||||
|
||||
按 `../../Pi-Agent兜底能力详细方案.md` §P0:在 `poc/pi-fallback/` 内(**不碰任何产品代码**):
|
||||
本轮 P0 在 `poc/pi-fallback/` 内完成(**不碰任何产品代码**):
|
||||
|
||||
1. Python 编排器能拉起 Pi headless 进程并下发一个真实 ad-hoc 分析任务;
|
||||
2. 四层围墙骨架生效:工具白名单 / 文件圈禁 / 网络限制 / 进程回收;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# NOTES-architecture — Pi 兜底能力 P0 PoC 骨架说明(Agent-B)
|
||||
|
||||
> 日期:2026-09-02。作者:Agent-B(架构师)。
|
||||
> 前置阅读:`GOAL.md`、`NOTES-pi-runtime.md`(Agent-A)、《Pi-Agent兜底能力详细方案.md》§4.1–4.4。
|
||||
> 前置阅读:`GOAL.md`、`NOTES-pi-runtime.md`(Agent-A)、`docs/architecture/fallback.md`。
|
||||
> 状态:mock 模式全流程跑通,3 项围墙自检 PASS;`--real` 路径冒烟通过(无网关时 stopReason=error 显式失败)。
|
||||
|
||||
## 1. 骨架结构
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> 设计员:Agent-D · 日期:2026-09-02 · 协调板:`GOAL-P1.md`
|
||||
> 施工员(Agent-E)照本文件施工;测试文档员(Agent-F)按 §6 测试矩阵与 §1 文档清单执行。
|
||||
> 前置已读:GOAL-P1.md、《Pi-Agent兜底能力详细方案.md》§4/§6、P0 三份 NOTES、
|
||||
> 前置已读:GOAL-P1.md、docs/architecture/fallback.md、P0 三份 NOTES、
|
||||
> harness.py / workflow.py / tool_runtime.py / feature_flags.py / audit.py / aps_home.py /
|
||||
> gateway/app.py 聊天段 / contracts.py / intent.py / assistant.py / dialog.py / poc 骨架。
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> 设计员:Agent-I · 日期:2026-09-03 · 协调板:`GOAL-P2.md`
|
||||
> 实施员(Agent-J)照本文件施工;验证员(Agent-K)按 §8 测试矩阵与 §7 冒烟规格执行。
|
||||
> 前置已读并源码核实:GOAL-P2.md、《Pi-Agent兜底能力详细方案.md》§2/§3/§4.4/§4.5、
|
||||
> 前置已读并源码核实:GOAL-P2.md、docs/architecture/fallback.md、
|
||||
> P1-DESIGN.md / P1-IMPL-NOTES.md / P1-SMOKE.md、fallback_lane.py(823 行)/ pi_bridge.py(261 行)、
|
||||
> harness.py(852 行)/ state/checkpoints.py(201 行)/ state/store.py / tool_runtime.py /
|
||||
> async_jobs.py(204 行)/ workflow.py execute_confirmed(499 起)与 import.commit 分支(836 起)/
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> 设计员:Agent-L · 日期:2026-09-03 · 协调板:`GOAL-P3.md`
|
||||
> 实施员(Agent-M)照本文件施工;验证员(Agent-N)按 §8 测试矩阵与 §9 冒烟规格执行。
|
||||
> 前置已读并源码核实:GOAL-P3.md、《Pi-Agent兜底能力详细方案.md》§3(S4/S6/S7 行)/§6 P3 段、
|
||||
> 前置已读并源码核实:GOAL-P3.md、docs/architecture/fallback.md、
|
||||
> P2-DESIGN.md / P2-IMPL-NOTES.md / P2-VALIDATION.md、
|
||||
> fallback_lane.py(1735 行:propose_reply 745 / _PLAN_SCENARIOS 1013 / validate_plan 1075 /
|
||||
> check_step_request 1218 / execute_plan 1514 / _stage_plan_confirmation 1686)、
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# P4-P5-DESIGN(Agent-A 最小可用版)
|
||||
|
||||
> 设计员:Agent-A | 日期:2026-09-04 | 协调板:poc/pi-fallback/GOAL-P4.md
|
||||
> 依据:Pi-Agent兜底能力详细方案.md、docs/architecture/fallback.md、P1/P2/P3 设计与验证、P4-P5-AUDIT.md、fallback_lane/pi_bridge/fallback_verify 与 tests/golden/test_fallback_*.py。
|
||||
> 依据:docs/architecture/fallback.md、P1/P2/P3 设计与验证、P4-P5-AUDIT.md、fallback_lane/pi_bridge/fallback_verify 与 tests/golden/test_fallback_*.py。
|
||||
> 本轮只新增本文件;未 commit/push;未跑全量测试。
|
||||
|
||||
## 1. 现状缺口
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
orchestrator.py — Pi Agent 兜底能力 P0 PoC:Python 编排器
|
||||
=========================================================
|
||||
|
||||
职责(对应《Pi-Agent兜底能力详细方案.md》§4.1 FallbackLane 编排器 + §4.6 熔断):
|
||||
职责(对应 `docs/architecture/fallback.md` 的 FallbackLane 编排与熔断设计):
|
||||
|
||||
1. 以子进程拉起 Pi headless(`node .../cli.js -p --mode json`),逐行解析 JSONL 事件流;
|
||||
2. 三重熔断:超时 / 步数上限 / 输出体量上限,触发即杀进程树(Windows taskkill /T /F)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
sandbox.py — Pi Agent 兜底能力 P0 PoC:四层围墙骨架
|
||||
====================================================
|
||||
|
||||
对应《Pi-Agent兜底能力详细方案.md》§4.2「沙箱围墙(自内向外四层)」:
|
||||
对应 `docs/architecture/fallback.md` 的沙箱围墙设计:
|
||||
|
||||
- L1 工具层:由 tool_bridge.py 的工具白名单 + orchestrator 启动参数 `--tools read,grep,find,ls`
|
||||
实现(pi 只看得见白名单工具,且本 PoC **不装 bash/edit 给真实路径**,见下);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
tool_bridge.py — Pi Agent 兜底能力 P0 PoC:工具桥与 callId 凭证
|
||||
================================================================
|
||||
|
||||
对应《Pi-Agent兜底能力详细方案.md》:
|
||||
对应 `docs/architecture/fallback.md` 与 `P1-DESIGN.md`:
|
||||
|
||||
- §4.3 工具桥暴露面:定义围墙内工具白名单注册表(名称 / 权力等级 P0-P2 /
|
||||
参数 schema / 是否需确认)。产品态里这些工具经由 HTTP 桥暴露给 Pi;
|
||||
|
|
|
|||
|
|
@ -1,202 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import random
|
||||
from typing import Any, Callable
|
||||
|
||||
from server.aps_domain.constraints import hard_blocking_conflicts
|
||||
from server.contracts import ScheduleResult
|
||||
from server.engines import get_engine
|
||||
from server.engines.base import EngineParams
|
||||
from server.timeutil import add_minutes, fmt_date, today0
|
||||
|
||||
World = dict[str, Any]
|
||||
|
||||
DEFAULT_MONTE_CARLO_SEED = 20260731
|
||||
DEFAULT_MONTE_CARLO_TRIALS = 24
|
||||
|
||||
|
||||
def _counter() -> Callable[[str], int]:
|
||||
values: dict[str, int] = {}
|
||||
|
||||
def next_id(kind: str) -> int:
|
||||
values[kind] = values.get(kind, 3000000) + 1
|
||||
return values[kind]
|
||||
|
||||
return next_id
|
||||
|
||||
|
||||
def _bounded_normal(rng: random.Random, mean: float, sigma: float, low: float, high: float) -> float:
|
||||
return max(low, min(high, rng.gauss(mean, sigma)))
|
||||
|
||||
|
||||
def _perturb_world(
|
||||
world: World,
|
||||
rng: random.Random,
|
||||
*,
|
||||
reset_schedule_products: bool,
|
||||
) -> tuple[World, dict[str, Any]]:
|
||||
sandbox = copy.deepcopy(world)
|
||||
if reset_schedule_products:
|
||||
sandbox["scheduleVersions"] = []
|
||||
sandbox["productionOrders"] = []
|
||||
sandbox["workOrders"] = []
|
||||
sandbox["conflicts"] = []
|
||||
quantity_scale = _bounded_normal(rng, 1.0, 0.10, 0.80, 1.20)
|
||||
efficiency_scale = _bounded_normal(rng, 1.0, 0.08, 0.75, 1.25)
|
||||
|
||||
for order in sandbox.get("salesOrders") or []:
|
||||
for item in order.get("items") or []:
|
||||
quantity = float(item.get("quantity") or 0.0)
|
||||
if quantity > 0:
|
||||
item["quantity"] = max(1, int(round(quantity * quantity_scale)))
|
||||
for line in sandbox.get("lines") or []:
|
||||
base = float(line.get("efficiencyFactor") or 1.0)
|
||||
line["efficiencyFactor"] = round(base * efficiency_scale, 6)
|
||||
|
||||
capacity_shock_line = None
|
||||
lines = sandbox.get("lines") or []
|
||||
if lines and rng.random() < 0.15:
|
||||
shocked = lines[rng.randrange(len(lines))]
|
||||
shocked["efficiencyFactor"] = round(float(shocked.get("efficiencyFactor") or 1.0) * 0.55, 6)
|
||||
capacity_shock_line = shocked.get("id")
|
||||
|
||||
return sandbox, {
|
||||
"quantityScale": round(quantity_scale, 6),
|
||||
"efficiencyScale": round(efficiency_scale, 6),
|
||||
"capacityShockLineId": capacity_shock_line,
|
||||
}
|
||||
|
||||
|
||||
def _percentile(values: list[float], percentile: float) -> float:
|
||||
if not values:
|
||||
return 0.0
|
||||
ordered = sorted(values)
|
||||
position = (len(ordered) - 1) * percentile
|
||||
lower = int(position)
|
||||
upper = min(lower + 1, len(ordered) - 1)
|
||||
fraction = position - lower
|
||||
return round(ordered[lower] * (1.0 - fraction) + ordered[upper] * fraction, 4)
|
||||
|
||||
|
||||
def run_monte_carlo(
|
||||
world: World,
|
||||
*,
|
||||
strategy: str = "COMPREHENSIVE",
|
||||
engine_type: str = "RULE",
|
||||
trials: int = DEFAULT_MONTE_CARLO_TRIALS,
|
||||
seed: int = DEFAULT_MONTE_CARLO_SEED,
|
||||
baseline_kpi: dict[str, Any] | None = None,
|
||||
planning_horizon_days: int = 14,
|
||||
start_date: str | None = None,
|
||||
delivery_buffer_ratio: float | None = None,
|
||||
freeze_window_hours: float | None = None,
|
||||
constraints: dict[str, bool] | None = None,
|
||||
reset_schedule_products: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""Re-solve fixed-seed demand/capacity perturbations in isolated sandboxes.
|
||||
|
||||
经统一 Explore 通道执行(矩阵 55 行):fn 只拿深拷贝沙盒,主干永不外泄写引用;
|
||||
每 trial 的 _perturb_world 再在沙盒上做独立扰动,互不污染。
|
||||
"""
|
||||
from server.aps_domain.explore_boundary import run_explore
|
||||
return run_explore(world, lambda sandbox: _monte_carlo_impl(
|
||||
sandbox,
|
||||
strategy=strategy, engine_type=engine_type, trials=trials, seed=seed,
|
||||
baseline_kpi=baseline_kpi, planning_horizon_days=planning_horizon_days,
|
||||
start_date=start_date, delivery_buffer_ratio=delivery_buffer_ratio,
|
||||
freeze_window_hours=freeze_window_hours, constraints=constraints,
|
||||
reset_schedule_products=reset_schedule_products,
|
||||
))
|
||||
|
||||
|
||||
def _monte_carlo_impl(
|
||||
world: World,
|
||||
*,
|
||||
strategy: str,
|
||||
engine_type: str,
|
||||
trials: int,
|
||||
seed: int,
|
||||
baseline_kpi: dict[str, Any] | None,
|
||||
planning_horizon_days: int,
|
||||
start_date: str | None,
|
||||
delivery_buffer_ratio: float | None,
|
||||
freeze_window_hours: float | None,
|
||||
constraints: dict[str, bool] | None,
|
||||
reset_schedule_products: bool,
|
||||
) -> dict[str, Any]:
|
||||
"""Monte Carlo 核心实现(在统一通道沙盒内运行)。"""
|
||||
sample_count = max(1, min(500, int(trials)))
|
||||
baseline = baseline_kpi or {}
|
||||
baseline_tardiness = max(0.0, float(baseline.get("totalTardiness") or baseline.get("tardiness") or 0.0))
|
||||
baseline_conflicts = max(0, int(baseline.get("conflictCount") or baseline.get("conflicts") or 0))
|
||||
criteria = {
|
||||
"maxTotalTardiness": round(baseline_tardiness + max(1.0, baseline_tardiness * 0.10), 4),
|
||||
"maxConflictCount": baseline_conflicts,
|
||||
"requireNoHardViolations": True,
|
||||
}
|
||||
|
||||
rng = random.Random(int(seed))
|
||||
start = start_date or fmt_date(add_minutes(today0(), 24 * 60))
|
||||
outcomes: list[dict[str, Any]] = []
|
||||
for trial in range(sample_count):
|
||||
sandbox, perturbation = _perturb_world(
|
||||
world,
|
||||
rng,
|
||||
reset_schedule_products=reset_schedule_products,
|
||||
)
|
||||
params = EngineParams(
|
||||
orderIds=[],
|
||||
engineType=engine_type,
|
||||
strategyTemplate=strategy,
|
||||
planningHorizonDays=planning_horizon_days,
|
||||
startDate=start,
|
||||
deliveryBufferRatio=delivery_buffer_ratio,
|
||||
freezeWindowHours=freeze_window_hours,
|
||||
name=f"mc-{seed}-{trial + 1}",
|
||||
constraints=constraints or EngineParams().constraints,
|
||||
)
|
||||
result: ScheduleResult = get_engine(engine_type).solve(sandbox, params, _counter())
|
||||
hard_rows = hard_blocking_conflicts(sandbox, result.versionId, track="fixed")
|
||||
hard_ids = {row.get("id") for row in hard_rows}
|
||||
critical_unmapped = [
|
||||
row for row in sandbox.get("conflicts") or []
|
||||
if row.get("versionId") == result.versionId
|
||||
and row.get("severity") == "CRITICAL"
|
||||
and row.get("id") not in hard_ids
|
||||
]
|
||||
hard_count = len(hard_rows) + len(critical_unmapped)
|
||||
accepted = (
|
||||
hard_count == 0
|
||||
and float(result.totalTardiness) <= criteria["maxTotalTardiness"] + 1e-9
|
||||
and int(result.conflictCount) <= criteria["maxConflictCount"]
|
||||
)
|
||||
outcomes.append({
|
||||
"trial": trial + 1,
|
||||
**perturbation,
|
||||
"totalTardiness": round(float(result.totalTardiness), 4),
|
||||
"conflictCount": int(result.conflictCount),
|
||||
"hardViolationCount": hard_count,
|
||||
"accepted": accepted,
|
||||
})
|
||||
|
||||
accepted_count = sum(1 for outcome in outcomes if outcome["accepted"])
|
||||
tardiness = [float(outcome["totalTardiness"]) for outcome in outcomes]
|
||||
return {
|
||||
"method": "fixed-seed-monte-carlo",
|
||||
"seed": int(seed),
|
||||
"trials": sample_count,
|
||||
"acceptanceCriteria": criteria,
|
||||
"acceptedTrials": accepted_count,
|
||||
"robustness": round(accepted_count / sample_count, 6),
|
||||
"distribution": {
|
||||
"tardinessP50": _percentile(tardiness, 0.50),
|
||||
"tardinessP90": _percentile(tardiness, 0.90),
|
||||
"tardinessP95": _percentile(tardiness, 0.95),
|
||||
"tardinessMax": round(max(tardiness, default=0.0), 4),
|
||||
"meanConflicts": round(
|
||||
sum(outcome["conflictCount"] for outcome in outcomes) / sample_count, 4
|
||||
),
|
||||
},
|
||||
"outcomes": outcomes,
|
||||
}
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
# ============================================================
|
||||
# 主控参数敏感性分析(moduleId: domain-sensitivity, SC-06,可重生 ✅)
|
||||
# 沙盒 one-at-a-time 扰动 + 固定种子蒙特卡洛;永不写主干
|
||||
# ============================================================
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from server.aps_domain.params import get_schedule_params
|
||||
from server.aps_domain.robustness import run_monte_carlo
|
||||
from server.contracts import UIBlock
|
||||
from server.engines import get_engine
|
||||
from server.engines.base import EngineParams
|
||||
from server.timeutil import add_minutes, fmt_date, today0
|
||||
|
||||
World = dict[str, Any]
|
||||
|
||||
|
||||
def _sandbox_counter():
|
||||
counters: dict[str, int] = {}
|
||||
|
||||
def next_id(kind: str) -> int:
|
||||
counters[kind] = counters.get(kind, 0) + 2000000
|
||||
return counters[kind]
|
||||
|
||||
return next_id
|
||||
|
||||
|
||||
def _kpi_from_result(result, sandbox: World) -> dict[str, float]:
|
||||
ver = sandbox["scheduleVersions"][-1] if sandbox.get("scheduleVersions") else {}
|
||||
return {
|
||||
"tardiness": round(float(result.totalTardiness), 2),
|
||||
"conflicts": float(result.conflictCount),
|
||||
"utilization": round(float(result.avgUtilization), 4),
|
||||
"changeoverMin": float(ver.get("totalChangeoverMin") or 0),
|
||||
"poCount": float(result.poCount),
|
||||
"woCount": float(result.woCount),
|
||||
}
|
||||
|
||||
|
||||
def _run_sandbox(
|
||||
world: World,
|
||||
*,
|
||||
strategy: str,
|
||||
horizon: int,
|
||||
start: str,
|
||||
vip_weight: float | None = None,
|
||||
delivery_buffer: float | None = None,
|
||||
freeze_hours: float | None = None,
|
||||
efficiency_scale: float | None = None,
|
||||
) -> dict[str, float]:
|
||||
sandbox = copy.deepcopy(world)
|
||||
sandbox["scheduleVersions"] = []
|
||||
sandbox["productionOrders"] = [p for p in sandbox.get("productionOrders", []) if p.get("status") == "PUBLISHED"]
|
||||
sandbox["workOrders"] = [w for w in sandbox.get("workOrders", []) if w.get("status") not in ("PENDING", "DRAFT", None)]
|
||||
# 清空草稿工单/PO,避免干扰;简化:只保留非本沙盒相关——种子通常无已发布,直接清空排产结果
|
||||
sandbox["productionOrders"] = []
|
||||
sandbox["workOrders"] = []
|
||||
sandbox["conflicts"] = []
|
||||
|
||||
sp = sandbox.setdefault("scheduleParams", {})
|
||||
if vip_weight is not None:
|
||||
levels = dict(sp.get("customerLevelWeights") or {})
|
||||
levels["VIP"] = float(vip_weight)
|
||||
sp["customerLevelWeights"] = levels
|
||||
if efficiency_scale is not None and efficiency_scale > 0:
|
||||
for ln in sandbox.get("lines") or []:
|
||||
base = float(ln.get("efficiencyFactor") or 1.0)
|
||||
ln["efficiencyFactor"] = round(base * float(efficiency_scale), 4)
|
||||
|
||||
params = EngineParams(
|
||||
orderIds=[],
|
||||
engineType="RULE",
|
||||
strategyTemplate=strategy,
|
||||
planningHorizonDays=horizon,
|
||||
startDate=start,
|
||||
deliveryBufferRatio=delivery_buffer,
|
||||
freezeWindowHours=freeze_hours,
|
||||
name=f"sensitivity-{uuid.uuid4().hex[:6]}",
|
||||
constraints={
|
||||
"materialKit": False, "equipment": True, "personnel": True, "changeover": True,
|
||||
"capacity": True, "dueDate": True, "tooling": True, "freeze": True,
|
||||
},
|
||||
)
|
||||
result = get_engine("RULE").solve(sandbox, params, _sandbox_counter())
|
||||
return _kpi_from_result(result, sandbox)
|
||||
|
||||
|
||||
def run_sensitivity(
|
||||
world: World,
|
||||
*,
|
||||
strategy: str = "COMPREHENSIVE",
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
SC-06:Tornado 单因子排序 + 固定种子蒙特卡洛鲁棒性。
|
||||
|
||||
经统一 Explore 通道执行(矩阵 55 行):fn 只拿深拷贝沙盒,主干永不外泄写引用;
|
||||
_run_sandbox 内部再做子沙盒扰动。
|
||||
"""
|
||||
from server.aps_domain.explore_boundary import run_explore
|
||||
return run_explore(world, lambda sandbox: _sensitivity_impl(
|
||||
sandbox, strategy=strategy,
|
||||
))
|
||||
|
||||
|
||||
def _sensitivity_impl(world: World, *, strategy: str) -> dict[str, Any]:
|
||||
"""Tornado/蒙特卡洛核心实现(在统一通道沙盒内运行)。"""
|
||||
sp = get_schedule_params(world)
|
||||
base_horizon = int(sp.get("planningHorizonDays") or 14)
|
||||
base_vip = float((sp.get("customerLevelWeights") or {}).get("VIP") or 3.0)
|
||||
base_buffer = float(sp.get("deliveryBufferRatio") or 0.95)
|
||||
base_freeze = float(sp.get("freezeWindowHours") or 24)
|
||||
start = fmt_date(add_minutes(today0(), 24 * 60))
|
||||
|
||||
baseline = _run_sandbox(
|
||||
world, strategy=strategy, horizon=base_horizon, start=start,
|
||||
vip_weight=base_vip, delivery_buffer=base_buffer, freeze_hours=base_freeze,
|
||||
efficiency_scale=1.0,
|
||||
)
|
||||
|
||||
# 每因子:低/高 两档(相对基线)
|
||||
factors: list[dict[str, Any]] = [
|
||||
{
|
||||
"id": "planningHorizonDays", "label": "展望期(天)",
|
||||
"baseline": base_horizon,
|
||||
"low": {"label": f"{max(3, base_horizon // 2)} 天", "kwargs": {"horizon": max(3, base_horizon // 2)}},
|
||||
"high": {"label": f"{min(60, base_horizon * 2)} 天", "kwargs": {"horizon": min(60, base_horizon * 2)}},
|
||||
},
|
||||
{
|
||||
"id": "vipWeight", "label": "VIP 等级权重",
|
||||
"baseline": base_vip,
|
||||
"low": {"label": "VIP=1", "kwargs": {"vip_weight": 1.0}},
|
||||
"high": {"label": "VIP=10", "kwargs": {"vip_weight": 10.0}},
|
||||
},
|
||||
{
|
||||
"id": "deliveryBufferRatio", "label": "交期缓冲比",
|
||||
"baseline": base_buffer,
|
||||
"low": {"label": "缓冲 0.85", "kwargs": {"delivery_buffer": 0.85}},
|
||||
"high": {"label": "缓冲 1.00", "kwargs": {"delivery_buffer": 1.0}},
|
||||
},
|
||||
{
|
||||
"id": "freezeWindowHours", "label": "冻结窗口(时)",
|
||||
"baseline": base_freeze,
|
||||
"low": {"label": "冻结 0h", "kwargs": {"freeze_hours": 0.0}},
|
||||
"high": {"label": "冻结 48h", "kwargs": {"freeze_hours": 48.0}},
|
||||
},
|
||||
{
|
||||
"id": "lineEfficiency", "label": "产线效率系数",
|
||||
"baseline": 1.0,
|
||||
"low": {"label": "效率×0.8", "kwargs": {"efficiency_scale": 0.8}},
|
||||
"high": {"label": "效率×1.2", "kwargs": {"efficiency_scale": 1.2}},
|
||||
},
|
||||
]
|
||||
|
||||
rows: list[dict[str, Any]] = []
|
||||
for fac in factors:
|
||||
common = {
|
||||
"strategy": strategy, "horizon": base_horizon, "start": start,
|
||||
"vip_weight": base_vip, "delivery_buffer": base_buffer,
|
||||
"freeze_hours": base_freeze, "efficiency_scale": 1.0,
|
||||
}
|
||||
low_kw = {**common, **fac["low"]["kwargs"]}
|
||||
high_kw = {**common, **fac["high"]["kwargs"]}
|
||||
# kwargs 用 horizon 键
|
||||
def _call(kw: dict) -> dict[str, float]:
|
||||
return _run_sandbox(
|
||||
world,
|
||||
strategy=kw["strategy"],
|
||||
horizon=int(kw["horizon"]),
|
||||
start=kw["start"],
|
||||
vip_weight=kw.get("vip_weight"),
|
||||
delivery_buffer=kw.get("delivery_buffer"),
|
||||
freeze_hours=kw.get("freeze_hours"),
|
||||
efficiency_scale=kw.get("efficiency_scale"),
|
||||
)
|
||||
|
||||
low_kpi = _call(low_kw)
|
||||
high_kpi = _call(high_kw)
|
||||
d_low = round(low_kpi["tardiness"] - baseline["tardiness"], 2)
|
||||
d_high = round(high_kpi["tardiness"] - baseline["tardiness"], 2)
|
||||
rows.append({
|
||||
"factorId": fac["id"],
|
||||
"label": fac["label"],
|
||||
"baselineValue": fac["baseline"],
|
||||
"lowLabel": fac["low"]["label"],
|
||||
"highLabel": fac["high"]["label"],
|
||||
"low": {
|
||||
"tardiness": low_kpi["tardiness"],
|
||||
"conflicts": low_kpi["conflicts"],
|
||||
"utilization": low_kpi["utilization"],
|
||||
"deltaTardiness": d_low,
|
||||
"deltaConflicts": round(low_kpi["conflicts"] - baseline["conflicts"], 1),
|
||||
},
|
||||
"high": {
|
||||
"tardiness": high_kpi["tardiness"],
|
||||
"conflicts": high_kpi["conflicts"],
|
||||
"utilization": high_kpi["utilization"],
|
||||
"deltaTardiness": d_high,
|
||||
"deltaConflicts": round(high_kpi["conflicts"] - baseline["conflicts"], 1),
|
||||
},
|
||||
"swing": round(abs(d_low) + abs(d_high), 2),
|
||||
"impactMetric": "tardiness",
|
||||
})
|
||||
|
||||
rows.sort(key=lambda r: r["swing"], reverse=True)
|
||||
|
||||
monte_carlo = run_monte_carlo(
|
||||
world,
|
||||
strategy=strategy,
|
||||
engine_type="RULE",
|
||||
baseline_kpi=baseline,
|
||||
planning_horizon_days=base_horizon,
|
||||
start_date=start,
|
||||
delivery_buffer_ratio=base_buffer,
|
||||
freeze_window_hours=base_freeze,
|
||||
constraints={
|
||||
"materialKit": False, "equipment": True, "personnel": True, "changeover": True,
|
||||
"capacity": True, "dueDate": True, "tooling": True, "freeze": True,
|
||||
},
|
||||
reset_schedule_products=True,
|
||||
)
|
||||
|
||||
md_lines = [
|
||||
"# 敏感性分析(Tornado)",
|
||||
"",
|
||||
f"- 策略基线:`{strategy}`",
|
||||
f"- 基线 KPI:延期 **{baseline['tardiness']}** h · 冲突 **{int(baseline['conflicts'])}** · "
|
||||
f"利用率 **{round(baseline['utilization'] * 100, 1)}%** · 换型 **{baseline['changeoverMin']}** 分",
|
||||
"- 说明:沙盒 one-at-a-time,不写主干;超时秒数对 RULE 无意义,未纳入。",
|
||||
"",
|
||||
"| 因子 | 低档 Δ延期 | 高档 Δ延期 | 摆幅 |",
|
||||
"| --- | ---: | ---: | ---: |",
|
||||
]
|
||||
for r in rows:
|
||||
md_lines.append(
|
||||
f"| {r['label']}({r['lowLabel']} / {r['highLabel']}) | "
|
||||
f"{r['low']['deltaTardiness']:+} | {r['high']['deltaTardiness']:+} | {r['swing']} |"
|
||||
)
|
||||
md_lines.append("")
|
||||
md_lines.append("摆幅 = |低档Δ延期| + |高档Δ延期|;越大表示该参数对延期越敏感。")
|
||||
md_lines.extend([
|
||||
"",
|
||||
"## 固定种子蒙特卡洛鲁棒性",
|
||||
"",
|
||||
f"- 种子:`{monte_carlo['seed']}` · 样本:**{monte_carlo['trials']}** 次",
|
||||
f"- 鲁棒性:**{round(monte_carlo['robustness'] * 100, 1)}%**",
|
||||
f"- 延期分布:P50 **{monte_carlo['distribution']['tardinessP50']}h** · "
|
||||
f"P90 **{monte_carlo['distribution']['tardinessP90']}h**",
|
||||
])
|
||||
|
||||
return {
|
||||
"strategy": strategy,
|
||||
"baseline": baseline,
|
||||
"rows": rows,
|
||||
"monteCarlo": monte_carlo,
|
||||
"markdown": "\n".join(md_lines),
|
||||
"hint": "敏感性只跑沙盒。若要固化参数,请到设置 → 排产参数 改权重/展望期并确认(P2)。",
|
||||
}
|
||||
|
||||
|
||||
def sensitivity_as_block(report: dict[str, Any]) -> UIBlock:
|
||||
"""产出 report UI 块(可预览/下载)。"""
|
||||
return UIBlock(
|
||||
blockId=f"sensitivity-{uuid.uuid4().hex[:8]}",
|
||||
type="report",
|
||||
props={
|
||||
"reportId": uuid.uuid4().hex[:10],
|
||||
"title": f"敏感性分析 Tornado({report.get('strategy')})",
|
||||
"markdown": report.get("markdown") or "",
|
||||
"reportType": "sensitivity-tornado",
|
||||
"baseline": report.get("baseline"),
|
||||
"rows": report.get("rows"),
|
||||
"monteCarlo": report.get("monteCarlo"),
|
||||
},
|
||||
)
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
"""将幻灯片与配音逐段合成为 MP4,再拼接为完整视频。"""
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import imageio_ffmpeg
|
||||
|
||||
FFMPEG = imageio_ffmpeg.get_ffmpeg_exe()
|
||||
WS = Path(__file__).resolve().parent
|
||||
REPO_ROOT = WS.parent
|
||||
PARTS = WS / "parts"
|
||||
PARTS.mkdir(exist_ok=True)
|
||||
|
||||
N = 12
|
||||
part_files = []
|
||||
for i in range(1, N + 1):
|
||||
slide = WS / "slides" / f"slide{i:02d}.png"
|
||||
audio = WS / "audio" / f"seg{i:02d}.mp3"
|
||||
part = PARTS / f"part{i:02d}.mp4"
|
||||
cmd = [
|
||||
FFMPEG, "-y",
|
||||
"-loop", "1", "-framerate", "30", "-i", str(slide),
|
||||
"-i", str(audio),
|
||||
"-c:v", "libx264", "-preset", "medium", "-tune", "stillimage",
|
||||
"-c:a", "aac", "-b:a", "192k",
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-shortest", "-movflags", "+faststart",
|
||||
str(part),
|
||||
]
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
|
||||
if r.returncode != 0 or not part.exists():
|
||||
print(f"part{i:02d} 合成失败:\n{r.stderr[-800:]}")
|
||||
sys.exit(1)
|
||||
part_files.append(part)
|
||||
print(f"part{i:02d}.mp4 ✓ ({part.stat().st_size // 1024} KB)")
|
||||
|
||||
lst = WS / "concat.txt"
|
||||
lst.write_text("".join(f"file 'parts/{p.name}'\n" for p in part_files), encoding="utf-8")
|
||||
|
||||
final = REPO_ROOT / "APS智能体演示视频.mp4"
|
||||
r = subprocess.run(
|
||||
[FFMPEG, "-y", "-f", "concat", "-safe", "0", "-i", str(lst),
|
||||
"-c", "copy", "-movflags", "+faststart", str(final)],
|
||||
capture_output=True, text=True, timeout=600,
|
||||
)
|
||||
if r.returncode != 0 or not final.exists():
|
||||
print("拼接失败:\n", r.stderr[-800:])
|
||||
sys.exit(1)
|
||||
print(f"\n最终视频: {final} ({final.stat().st_size / 1024 / 1024:.1f} MB)")
|
||||
|
Before Width: | Height: | Size: 220 KiB |
|
|
@ -1,12 +0,0 @@
|
|||
file 'parts/part01.mp4'
|
||||
file 'parts/part02.mp4'
|
||||
file 'parts/part03.mp4'
|
||||
file 'parts/part04.mp4'
|
||||
file 'parts/part05.mp4'
|
||||
file 'parts/part06.mp4'
|
||||
file 'parts/part07.mp4'
|
||||
file 'parts/part08.mp4'
|
||||
file 'parts/part09.mp4'
|
||||
file 'parts/part10.mp4'
|
||||
file 'parts/part11.mp4'
|
||||
file 'parts/part12.mp4'
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
"""从 narration.md 解析 SEG 分段,逐段调用 TTS 生成 MP3。"""
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
WS = Path(__file__).resolve().parent
|
||||
plugin_dir = (os.environ.get("APS_AUDIO_GENERATION_PLUGIN") or "").strip()
|
||||
voice_id = (os.environ.get("APS_TTS_VOICE_ID") or "").strip()
|
||||
if not plugin_dir or not voice_id:
|
||||
raise SystemExit("请配置 APS_AUDIO_GENERATION_PLUGIN 和 APS_TTS_VOICE_ID 后再生成配音")
|
||||
PLUGIN = Path(plugin_dir).expanduser().resolve()
|
||||
VOICE = voice_id
|
||||
|
||||
text = (WS / "narration.md").read_text(encoding="utf-8")
|
||||
segments = re.findall(r"SEG (\d+)([^)]*)\s*\n(.*?)(?=\n\nSEG |\Z)", text, re.S)
|
||||
print(f"共解析 {len(segments)} 段")
|
||||
|
||||
for num, body in segments:
|
||||
out = WS / "audio" / f"seg{num}.mp3"
|
||||
if out.exists() and out.stat().st_size > 10_000:
|
||||
print(f"seg{num} 已存在,跳过")
|
||||
continue
|
||||
body = " ".join(body.split())
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(PLUGIN / "scripts" / "audio_generation_tool.py"), "speech",
|
||||
"--text", body, "--voice-id", VOICE, "--output", str(out)],
|
||||
cwd=PLUGIN, capture_output=True, text=True, timeout=600,
|
||||
)
|
||||
ok = out.exists() and out.stat().st_size > 10_000
|
||||
print(f"seg{num}: {'OK' if ok else 'FAIL'} ({len(body)} 字)")
|
||||
if not ok:
|
||||
print(result.stdout[-500:], result.stderr[-500:])
|
||||
sys.exit(1)
|
||||
print("全部配音生成完成")
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
"""绘制演示视频用 1080p 幻灯片(深色科技风 + 品牌橙)。"""
|
||||
import os
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from pathlib import Path
|
||||
|
||||
WS = Path(__file__).resolve().parent
|
||||
W, H = 1920, 1080
|
||||
BG = (13, 25, 42) # 深藏青
|
||||
BG2 = (21, 37, 60) # 卡片底色
|
||||
ORANGE = (232, 107, 32) # 品牌橙(与应用主题一致)
|
||||
WHITE = (240, 244, 248)
|
||||
GREY = (150, 165, 185)
|
||||
|
||||
FONT = os.environ.get("APS_VIDEO_FONT_REGULAR") or "msyh.ttc"
|
||||
FONT_B = os.environ.get("APS_VIDEO_FONT_BOLD") or "msyhbd.ttc"
|
||||
|
||||
def font(size, bold=False):
|
||||
return ImageFont.truetype(FONT_B if bold else FONT, size)
|
||||
|
||||
SLIDES = [
|
||||
dict(kind="cover", title="从“人排产”到“智能体排产”",
|
||||
sub="工业智核 APS · 计划排产智能体", note="产品汇报演示"),
|
||||
dict(kicker="01 · 为什么做", title="排产:制造业数字化最后一块硬骨头",
|
||||
bullets=["约束复杂 —— 物料齐套、设备产能、模具寿命、班组技能、换型耗时,牵一发动全身",
|
||||
"变化频繁 —— 紧急插单、设备故障、物料延期,计划永远赶不上变化",
|
||||
"经验依赖 —— 老师傅的判断无法沉淀、无法复制、无法传承",
|
||||
"大语言模型的成熟,给出了全新解法"]),
|
||||
dict(kicker="02 · 智能体闭环", title="听得懂 · 算得准 · 管得住",
|
||||
bullets=["感知 —— 自然语言下达指令:「试排一版交期优先」",
|
||||
"决策 —— 意图翻译成命令,驱动运筹学引擎真实求解",
|
||||
"执行 —— 甘特 / 负荷 / 交期三视图实时呈现,左说右动",
|
||||
"留痕 —— 每次操作进入哈希链式审计台账,可校验可回放"]),
|
||||
dict(kicker="03 · 数据准备", title="把工厂“搬”进系统,只需一次导入",
|
||||
bullets=["订单、物料、BOM、工艺路线、设备台账 —— 普通 Excel 即可",
|
||||
"自动识别表角色、表头映射、数据校验",
|
||||
"传统 APS 最耗时的数据初始化,在这里一次完成"]),
|
||||
dict(kicker="04 · 一句话排产", title="「试排一版交期优先」",
|
||||
bullets=["几秒钟产出排产版本:订单 × 设备 × 工序 × 时间一目了然",
|
||||
"甘特图 / 设备负荷 / 交期看板三视图联动",
|
||||
"数字全部来自引擎确定性计算 —— 大模型不得编造任何数字"]),
|
||||
dict(kicker="05 · 多策略对比", title="机器穷举,人来拍板",
|
||||
bullets=["交期优先 / 产能均衡 / 换型最小化 —— 沙盒并行试排",
|
||||
"准时率、换型次数、设备利用率逐项对照,最优项高亮",
|
||||
"一键采用,右侧沙盘即刻刷新,正式数据零风险"]),
|
||||
dict(kicker="06 · 插单与动态调度", title="L1 → L4 分级动态调度",
|
||||
bullets=["紧急插单:先局部修复、评估影响面,而非硬塞引发连锁延期",
|
||||
"设备故障:秒级池内换机 → 短窗重排 → 日重排 → 全局重排",
|
||||
"每级重排附带影响评估与确认卡 —— 拍板权永远在人"]),
|
||||
dict(kicker="07 · 柔性排产", title="能力池 + 虚拟产线(差异化能力)",
|
||||
bullets=["打破“设备固定属于产线”假设,按订单动态组线、用完释放",
|
||||
"正排保开工 / 倒排保交期 / 瓶颈锚定保利用率",
|
||||
"设备停机即刻重算瓶颈产能,负载预警自动色标"]),
|
||||
dict(kicker="08 · 图纸智能解析", title="让 CAD 图纸自己“开口说话”",
|
||||
bullets=["DXF 图纸导入:自动识别图号与版本,逐图元解析",
|
||||
"提取物料 / BOM 引用 / 工艺信息为结构化候选清单",
|
||||
"图纸是证据不是命令 —— AI 负责提取,人负责批准"]),
|
||||
dict(kicker="09 · 门禁与审计", title="智能体的每一步“想动”,都要人“放行”",
|
||||
bullets=["P0–P3 四级门禁:只读自由 / 试排轻提示 / 关键写确认 / 外部二次确认",
|
||||
"违反硬约束的计划,任何人都无法发布",
|
||||
"哈希链审计:谁决定的、依据是什么、当时看到了什么,随时可查"]),
|
||||
dict(kicker="10 · 沉淀与报告", title="把经验沉淀为组织资产",
|
||||
bullets=["检查点时间线:每个决策节点自动存档,随时回滚",
|
||||
"KPI 仪表盘:利用率 / 准时率 / 在制 / 延误一屏汇总",
|
||||
"一键生成 Word 排产报告,数字来自冻结快照,不经 AI 改写"]),
|
||||
dict(kind="cover", title="让排产听得懂人话,让决策算得清利害",
|
||||
sub="工业智核 APS · 计划排产智能体", note="汇报完毕 · 谢谢大家"),
|
||||
]
|
||||
|
||||
def draw_cover(img, d, s):
|
||||
d.rectangle([0, H - 18, W, H], fill=ORANGE)
|
||||
d.rectangle([0, 0, W, 14], fill=ORANGE)
|
||||
tw = d.textlength(s["title"], font=font(72, True))
|
||||
d.text(((W - tw) / 2, H / 2 - 130), s["title"], font=font(72, True), fill=WHITE)
|
||||
sw = d.textlength(s["sub"], font=font(40))
|
||||
d.text(((W - sw) / 2, H / 2 + 10), s["sub"], font=font(40), fill=ORANGE)
|
||||
nw = d.textlength(s["note"], font=font(30))
|
||||
d.text(((W - nw) / 2, H / 2 + 110), s["note"], font=font(30), fill=GREY)
|
||||
|
||||
def draw_content(img, d, s, idx):
|
||||
d.rectangle([0, 0, W, 14], fill=ORANGE)
|
||||
d.rectangle([96, 120, 106, 260], fill=ORANGE)
|
||||
d.text((136, 118), s["kicker"], font=font(34, True), fill=ORANGE)
|
||||
d.text((136, 172), s["title"], font=font(56, True), fill=WHITE)
|
||||
y = 340
|
||||
for b in s["bullets"]:
|
||||
d.rounded_rectangle([96, y - 18, W - 96, y + 78], radius=16, fill=BG2)
|
||||
d.ellipse([132, y + 18, 156, y + 42], fill=ORANGE)
|
||||
d.text((190, y), b, font=font(34), fill=WHITE)
|
||||
y += 128
|
||||
footer = "工业智核 APS · 计划排产智能体"
|
||||
d.text((96, H - 72), footer, font=font(24), fill=GREY)
|
||||
num = f"{idx:02d} / {len(SLIDES):02d}"
|
||||
d.text((W - 96 - d.textlength(num, font=font(24)), H - 72), num, font=font(24), fill=GREY)
|
||||
|
||||
for i, s in enumerate(SLIDES, 1):
|
||||
img = Image.new("RGB", (W, H), BG)
|
||||
d = ImageDraw.Draw(img)
|
||||
if s.get("kind") == "cover":
|
||||
draw_cover(img, d, s)
|
||||
else:
|
||||
draw_content(img, d, s, i)
|
||||
img.save(WS / "slides" / f"slide{i:02d}.png")
|
||||
print(f"slide{i:02d}.png ✓")
|
||||
print("全部幻灯片绘制完成")
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# 视频解说词分段(配合幻灯片,总时长约 8 分钟)
|
||||
|
||||
SEG 01(封面)
|
||||
各位领导,大家好。今天向大家汇报的,是工业智核 APS 计划排产智能体。它不是对传统排产软件的界面改良,而是排产工作方式的一次范式升级:让机器理解人的意图,让算法完成繁重的计算,让人专注于判断与决策。
|
||||
|
||||
SEG 02(为什么做)
|
||||
排产,是制造业数字化最后一块硬骨头。约束复杂:物料齐套、设备产能、模具寿命、班组技能、换型耗时,牵一发而动全身;变化频繁:紧急插单、设备故障、物料延期,计划永远赶不上变化;决策又高度依赖老师傅的个人经验,无法沉淀、无法复制、更无法传承。而大语言模型的成熟,给了我们一条全新的路。
|
||||
|
||||
SEG 03(智能体闭环)
|
||||
这套系统,是用自然语言驱动、用可视化确认、用门禁审计约束的计划排产智能体,具备感知、决策、执行、留痕的完整闭环。计划员用母语直接下达指令:试排一版交期优先;系统理解意图,驱动运筹学引擎真实求解;结果以甘特图、设备负荷、交期看板三视图实时呈现;每一次操作,全部留痕可审计。
|
||||
|
||||
SEG 04(数据准备)
|
||||
一切智能的前提是数据。订单、物料、BOM、工艺路线、设备台账,就是最普通的 Excel 表格,一键导入。系统自动识别每张表的角色,完成表头映射与校验。传统排产软件实施中最耗时的数据初始化,在这里一次完成。
|
||||
|
||||
SEG 05(一句话排产)
|
||||
数据就绪,我们只对系统说一句话:试排一版交期优先。几秒钟,一个排产版本呈现眼前:每个订单在哪台设备、什么时间、哪道工序,一目了然;哪台设备超载、哪张订单有延期风险,清清楚楚。特别强调:这些数字全部来自运筹学引擎的确定性计算,大模型只负责理解意图,制度上不允许它编造任何一个数字。
|
||||
|
||||
SEG 06(多策略对比)
|
||||
排产没有唯一解,只有适合当下经营目标的解。一句"对比几种策略",系统在沙盒中把交期优先、产能均衡、换型最小化等策略并行试排,准时率、换型次数、设备利用率逐项对照,最优项高亮。看中哪个,一键采用。过去计划员凭经验只能想一种排法,现在是机器穷举、人来拍板。
|
||||
|
||||
SEG 07(插单与动态调度)
|
||||
计划永远赶不上变化。客户急单插进来,系统先做局部修复、评估影响面,而不是硬塞进去引发连锁延期;设备故障,秒级给出池内换机建议。影响小,局部消化;影响大,逐级升级为窗口重排、日重排乃至全局重排。这就是 L1 到 L4 分级动态调度,每一步重排都带着影响评估和确认卡,拍板权永远在人。
|
||||
|
||||
SEG 08(柔性排产)
|
||||
多品种、小批量的工厂,设备未必永远属于某条产线。系统建立工序能力池与虚拟产线机制:按订单需求动态组合设备,预占资源、用完释放,连设备移动耗时、模具换型时间都精确计算。正排保开工、倒排保交期、瓶颈锚定保利用率,三种模式自由切换。设备一停机,瓶颈产能即刻重算,负载预警自动色标。这是我们与市面产品最大的不同。
|
||||
|
||||
SEG 09(图纸解析)
|
||||
排产的上游是技术资料。一张 CAD 工程图纸导入系统,自动识别图号和版本,九千多个图元逐一解析,把图纸里的物料、BOM 引用、工艺信息提取成结构化的候选清单。请注意"候选"两个字:图纸是证据,不是命令,这些信息必须经过人工确认才会写入主数据。AI 负责提取,人负责批准。
|
||||
|
||||
SEG 10(门禁与审计)
|
||||
方案满意,能不能一键生效?能,但要过一道门。系统实行四级门禁:只读查询自由进行,试排对比轻量提示,发布、回滚等关键动作必须经确认卡人工点头,涉及外部系统的动作二次确认。每一次操作记入哈希链式审计台账:谁决定的、依据是什么、系统当时看到了什么,随时可查、不可篡改。智能体的每一步"想动",都要经过人的"放行"。
|
||||
|
||||
SEG 11(沉淀与报告)
|
||||
每个决策节点自动存档,随时回滚到任何一个"如果当初";利用率、准时率、在制、延误,一屏汇总;一键生成排产日报和正式的 Word 排产报告,数字直接来自冻结快照,不经过任何 AI 改写。老师傅的经验,从此沉淀为组织的系统能力,越用越聪明。
|
||||
|
||||
SEG 12(收尾)
|
||||
从一份 Excel 开始,到一份可下发的生产计划结束,这套系统走完了完整闭环。让排产听得懂人话,让决策算得清利害,让经验沉淀为资产。它对标国际主流排产产品完成主体能力覆盖,行业适配不靠定制开发,换一套数据即可运转。这,就是工业智核 APS 智能体交出的答卷。汇报完毕,谢谢大家。
|
||||
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 49 KiB |