AI 在机房设计中的分工:自然语言建模、22 条指令契约与工程化护栏
摘要:AI 在机房设计里最容易走偏的做法,是让模型凭空生成一张图。DCDesigner 把分工划清楚:理解意图、单位换算、可行性试算、参数填充交给模型;几何规则、编号、互斥推挤、校验、撤销全部由本地执行——AI 与手工操作共享同一套指令、同一个撤销栈。本文说明两条 AI 通路、契约与自纠错机制、工程化护栏与已知边界。
一、先谈分工:AI 该做什么,不该做什么
用大模型做机房设计,有两种思路:
- 思路 A:让模型生成图纸。模型直接输出几何布局,工具只负责画出来。问题是模型「画得好看」,但算不准间距、记不住领域规则、也无法保证对象不重叠;
- 思路 B:让模型生成指令。模型通过工具已有的建模指令逐步操作,几何与规则由工具的既有实现承担。
DCDesigner 选择了 B,并把这条原则写进了设计文档:「凡是判断都交给大模型,本地只做薄胶水」。具体到实现上:
- 复用既有22 条建模指令(同一
exec()、同一撤销栈、同一套参数校验); - AI 建的图与手工建的图同源——几何、编号、互斥推挤、通道宽联动一行未重写;
- 模型负责理解/单位换算/可行性试算/填参数/自我纠错;本地只保留三类边界:凭据与网络、进程保护、可逆性。
这样做的直接好处是可控:AI 的每一次操作都是一条可校验、可撤销、可复现的指令,而不是一段不可解释的图形输出。
二、通路一:内置 AI 建模面板(自然语言生成与改图)
编辑器内置「AI 建模(试验)」面板:顶栏 AI 按钮打开左侧面板,用中文描述即可生成机房——房间 / POD 通道 / 机柜排 / 桥架 / 空调 / UPS / 蓄电池 / 灭火器 / 门窗;之后可以继续对话改图(「热通道加宽到 1 米」「把 A 排复制一份」)。
使用要点:
- 填自己的 API Key:支持 DeepSeek 或任意 OpenAI 兼容网关,Key 只保存在本机浏览器 localStorage(
idc2d_ai_key_v1/idc2d_ai_cfg_v1),页面只以掩码回显;服务端既不读取也不落盘,只做无状态转发(POST /api/ai/chat); - 自动执行:模型给出的指令立即逐条下发,画布实时出图,不弹计划卡;执行结果以「本轮执行 N 条指令」折叠日志回报;
- 唯一的人工闸门:模型标了
destructive: true的不可逆调用(清空项目 / 批量删除 / 覆盖打开)会弹一条红色确认条,点「确认执行」才执行;未确认前画布零改动,发新消息即自动作废; - 撤销本轮:每个指令一步撤销,可按轮次整体回退;
- 输入支持附件:上传/粘贴/拖入文本与图片。文本类附件(txt/md/csv/json/log/yaml 等)整份读成文本拼进本轮消息(超 2 万字截断);图片在浏览器内先等比压缩(长边 1568px、JPEG q0.82、透明铺白底)再按 OpenAI 多模态格式随消息下发;单条消息 ≤4 个附件、文本文件 ≤2MB、单张原图 ≤8MB、压缩后总量 ≤6MB;本轮结束即释放图片 base64,不把图片带进后续每一轮;
- 进度可见:等待模型时三点跳动 + 「正在思考…」,自修重试与「正在执行第 i/N 条指令(工具名)」都有提示,等待超过 3 秒追加「已等待 N 秒」,行尾常驻「停止」。
面板与工勘向导互斥(同时只显示一个,都在左侧占位、展开时把画布往右挤而不遮挡),打开 AI 自动收起向导,反之亦然。
三、通路二:外部 Agent(如 WorkBuddy)指令中继
浏览器页面无法直接对外提供 HTTP 服务,因此由本地服务端做「信箱」中继:
| 端点 | 调用方 | 作用 |
|---|---|---|
POST /api/agent/cmd/:tool | AI Agent | 投递设计指令,挂起等待页面执行结果(默认 60s 超时,AGENT_CMD_TIMEOUT可调;页面未连接返回EDITOR_OFFLINE) |
GET /api/agent/status | AI Agent | 页面连接状态探活(connected=true且pages=1) |
GET /api/agent/next | 编辑器页面 | 长轮询领取指令 |
POST /api/agent/done | 编辑器页面 | 回传执行结果 |
GET /api/agent/openapi.json | Agent 平台 | OpenAPI 3.0 契约(按 URL 一键导入全部指令) |
22 条指令按用途分组:
- 项目:
project.new/project.open/project.list/project.save/project.export/project.undo/project.redo - 土建:
room.rect(矩形房间,支持偏移建子区域)、wall.add(自由墙段)、opening.add(门窗格栅开洞) - 布局:
pod.create(通道 POD,可整批下发柜级属性)、row.create(单排机柜)、obj.add(单台对象/桥架) - 修改:
obj.update、obj.updateBatch(批量改属性,整批一步撤销)、obj.move、obj.delete、obj.rotate - 查询/视图:
query.status(合规自检:重叠/越界/功率统计)、query.checks(完整 20 条规则问题清单,支持临时覆盖阈值)、query.objects、obj.get、view.shot(画布截图,可聚焦单对象)
每条指令 = 一步撤销;参数强校验(越界/越出房间拒绝且不留半成品);错误返回中文原因可直接转述;任何指令可附"shot":true随结果返回画布截图。
多页面路由也做了工程化处理:每个编辑器页面长轮询时携带持久clientId,服务端把指令粘性路由到单一活动页面(最近完成指令的页面,离线 8s 才故障转移,前台页面优先);页面切到前台会以bg=0重发轮询,若活动页为空/离线/也处于后台即自动接管——「看着哪个页面,指令就进哪个页面」;另有显式 claim 与页面内交互自动接管(节流 20s),防止 Agent 自开的无头页面抢走路由。
四、把「模型出错」变成「可纠正」
现实中模型会犯错,关键是错误是否可检测、可纠正。这里有三层设计:
4.1 单一输出协议
模型直接输出 JSON 计划:
{"reply":"给用户看的 1~3 句话","plan":["步骤说明"], "calls":[{"tool":"pod.create","args":{...},"why":"…","destructive":false}]}解析失败或协议不合规时,把错误原文回灌让模型自己修;输出协议放在提示词最末(利用 recency)。
4.2 指令名「领空」声明
合法 tool只有 22 个带点号的路径名。对象类型(ac/cabinet/pdu/ups/battery/extinguisher/vent/column/tray)是obj.add的type字段取值,不是工具名;除pod.create/row.create外不存在xxx.create/xxx.add形式的指令。
模型若按习惯编名(典型如ac.create),页面返回code:"UNKNOWN_TOOL",且message自带完整合法名单 + 照做即可的纠正建议(如「疑似想执行:obj.add { type:"ac", x, y, rotation }」)——回灌给模型即可一次自纠错,不必再翻契约。
4.3 契约取不到就不发
/api/agent/openapi.json是模型唯一的合法指令名来源。发送前面板确认契约已加载;取不到时先重试一次、仍失败则拦截发送并在对话区说明原因(输入内容保留,恢复后直接重发)——避免模型在没有名单的提示词里凭习惯编名字。
五、回灌实坐标:模型不靠猜
模型要改图,必须先知道图现在长什么样。每条指令执行后的回灌 = 固定字段(tool/ok/hint或code+message/added/warnings/stats)+ 结构化结果原样透传:
added[…].x/.y/.rotation(矩形对象)或.x1/.y1/.x2/.y2(墙、桥架);query.objects → objects[…]、obj.get → object、query.status → overlaps/outOfRoom、query.checks → issues。
只做体积护栏(列表 ≤200 条、单条 ≤24k 字符,截断时回"truncated":"objects,added"等字段名提示改用过滤),截图 dataURL 与导出正文不回灌。模型因此可以「先查实坐标再试算落位」——不改图中既有对象、不与桥架/空调重叠、不为已能查到的尺寸反问用户。
行为规则(单位归一、口径消歧「每排 12 台」vs「共 12 台」、缺参追问、可行性试算、规模取舍、破坏性标注、何时查画布、何时停止)统一写在public/js/ai/ai-rules.js的提示词里;契约送模型前机械裁剪(剥掉 HTTP 层与响应体,48.9KB → 约 25KB),前缀稳定以命中上下文缓存。
六、工程化护栏:凭据、进程、可逆性、隐私
| 护栏 | 具体机制 |
|---|---|
| 凭据与网络 | 无 Key 不发;服务端转发超时默认 120s;429/5xx/网络错误重试 2 次;随时可停止;模型不支持视觉时本地自动去掉图片重发一次并提示 |
| 进程保护 | 单轮 ≤40 次模型往返、单轮新增 ≤2000 对象;超限停止 |
| 可逆性 | 每条指令一步撤销;「撤销本轮」按撤销栈实际压栈统计(删除/修改/移动/旋转同样计入);破坏性调用弹一次确认条,取消时补一条「均未执行」回灌防模型误判已生效 |
| 隐私 | Key / 接口地址 / 模型只存本机浏览器;服务端不落盘、不记日志、不回显;只把对话文本、工具契约与执行结果(含对象 id 与坐标)发给模型;不上传项目 JSON,不发送甲方/园区/勘测人信息;未添加附件时一个字节也不外发 |
七、多人共用一套服务端的已知风险
需要明确的一条边界:中继为全局单队列 + 单活动页面。多人共用一套服务端并发使用 AI 时,指令仍会路由到同一活动页面(单人使用有前台接管与交互自动接管保障;多人同时用 AI 仍是先到先得的全局单队列)。同时data/*.json为共享命名空间(同名项目互相覆盖、无鉴权、非原子写)。
项目文档给出了完整的风险清单(含实测证据)、适用场景判定与三种隔离方案(每人一套 / 多实例+反向代理 / 多会话改造);仓库内tests/agent-multiuser.test.mjs用双页面模拟实证了串台行为(无需浏览器即可复现)。对有多人 AI 并发需求的团队,建议每人一套服务(单机 exe/node 零安装);服务器部署务必设NO_BROWSER=1,避免服务端自动弹开的浏览器页面成为「幻影页面」。
另外注意:EXEC_TIMEOUT表示页面可能已执行但结果丢失,指令非幂等,重试前应先用query.objects核实画布。
八、AI 提升的是什么,不是替代什么
提升:
- 出图效率:一句话生成房间、POD、机柜排、配套设备;改图时批量调整(改通道宽、复制整排、批量改属性);
- 自检闭环:
query.checks返回结构化问题清单 → 模型按对象 id 修正 → 再跑直至通过; - 录入减负:把现场手记、机柜清单(文本附件)直接变成上下文,减少手工录入。
不替代:
- 不替代设计与审核判断:制冷、供电、消防方案是否成立,责任仍在专业人;
- 不替代规范符合性结论:自检阈值是可配置的经验参考值;
- 不替代现场测量:AI 无法知道卷尺上的数字;
- 不解决多人协作:当前架构面向「单人多机/单人一套服务」。
附:事实来源与核验方式
- 内置 AI 面板:
README.md「AI 建模(试验)」;实现见public/js/ai/ai-panel.js、ai-orchestrator.js、ai-provider.js、ai-attach.js、ai-rules.js - 指令集与契约:
public/api/agent/openapi.json(22 条指令)、public/js/agent.js(页内执行器)、public/js/toolhints.js(UNKNOWN_TOOL 纠错文案) - 中继与多页面路由:
server.js/main.go(/api/agent/*);回归node tests/agent-relay.test.mjs、node tests/agent-e2e.cdp.mjs、node tests/agent-multiuser.test.mjs - 护栏与凭据:
node tests/ai-proxy.test.mjs、node tests/ai-feedback.test.mjs、node tests/ai-attach.test.mjs - 端到端(页内 mock 模型、不调真实 API):
node tests/ai-e2e.cdp.mjs
npm test # 含 ai-rules / ai-proxy / ai-feedback / ai-attach node tests/agent-relay.test.mjs node tests/ai-e2e.cdp.mjs # 需先启动服务与无头 Chrome 调试端口