闭环:从 ERP 到持续变好的应用
这一页以一个车间的生产进度看板为例(示例公司 Demo Company),把 Semantic(数据平台)的各部分和自进化串成一条线:数据流(ERP 只读推上来)→ Ontology(对象、Action)→ 数据源(流接到哪个类型,写在定义里)→ 应用(读对象集、实时订阅、用 Action 改)→ 访问(谁能看、谁能改、分享)→ 留痕(每次修改、应用日志)→ 自提升(下一个版本)。车缝产量、库存、订单流程这类看板是同一套做法。
SAP / MES(只读)
│ 发布端:aidc semantic streams pipe + 适配器(客户箱上的 systemd 服务,不是 cron)
▼
Semantic ── 数据流 production-progress
│ └─ Object Type 定义里的 datasources:哪一列对哪个属性
▼
Ontology ── 工单线体 / 线体、链接、Action「登记异常」「解决异常」「维护线体」
▼
Nexus 应用 · 智能体 ── 访问:成员可改、公开链接只读 ── 留痕:每次修改、打开、反馈、版本
▲ │
└──────────────── 自进化 SDK:证据 → 提案 → 新语义版本 / 新应用版本 ◀──┘
1. 数据流:数据源只读地推上来
发布端装在客户箱上,读 SAP 的报工确认(AFRU)与生产进度报表,有变化才推一批到数据流 production-progress(见数据流与数据源)。它只有一把只能往这条流发布的 Key,永远不会写 SAP。
2. Ontology:先定义「这是什么」
aidc semantic define ontology/ # production.issue_status(枚举)、production.line、production.order_line、三个 Action
aidc semantic publish --notes "生产进度首版"
production.order_line 的属性分两类:工单、线体、计划、累计合格、实际 JPH……来自 SAP(只读);异常状态、异常说明、登记人、处理说明……只在语义层维护(writeback,Palantir 的 editOnly)。Action 定义「登记异常」要哪些参数、改哪些属性、谁能做(见 Semantic)。
3. 数据源:流接到哪个类型,写在定义里
数据流的哪一列对哪个属性,是 Object Type 定义的一部分(照 Palantir 的 backing datasource)。production.order_line 的定义里写:
"datasources": [
{ "type": "stream", "stream": "production-progress", "mode": "mirror",
"propertyMapping": { "order_no": "order", "line_code": "line", "material": "material", "product": "product", "shift": "shift", "plan": "plan",
"ok": "ok", "gap": "gap", "jph_actual": "jph_actual", "jph_std": "jph_std", "last_op": "last_op", "day": "day" } }
]
线体由工单行汇成:production.line 接同一条流,只映射 line_code ← line,mode 用 upsert。不改文件也行,命令改的同样是定义:
aidc semantic datasource set production.line --stream production-progress --map line_code=line --mode upsert
aidc semantic datasource list # 每个类型的数据源与同步进度
aidc semantic objects production.order_line --order-by gap:desc --page-size 5
定义落了之后,平台用流的当前全量同步一次;从这一刻起,SAP 每一次变化都进 Semantic:来自源头的属性更新,人改过的值不动。应用和智能体不再碰数据流,更不碰 SAP。智能体要改数据源,和改别的定义一样:在分支上改、开提案,人审核合并。
4. 应用:读对象集、实时订阅、用 Action 改
import { semantic } from "/developer/sdk/v1/aidc.js";
const client = semantic.ontology();
const lines = client.objects("production.order_line");
render((await lines.fetchPage({ $orderBy: { gap: "desc" } })).data);
lines.subscribe({ onChange: ({ object, state }) => patch(object, state), onOutOfDate: reload }); // 实时
const me = await semantic.admin.getCurrentUser(); // 我能做什么
await client.action("production.flag_issue").applyAction({ __object: row.__primaryKey, issue: "缺料", severity: "异常" });
semantic.observability.feedback({ topic: "看板", message: "希望按班次筛选" });
清单登记用到的 SDK 与语义资源(部署时会核对 import,用了没登记的直接拒收):
{
"sdk": ["semantic"],
"semantic": { "types": ["production.order_line", "production.line"], "actions": ["production.flag_issue", "production.resolve_issue", "production.update_line"] }
}
aidc app deploy app/ # → Developer 预览(test),版本号 = 清单 version
aidc app publish production-live --notes "语义层 + 异常登记" # 测过的版本 → Nexus
aidc app registry # 登记表:这个应用用了哪些 SDK、读写哪些类型 / Action
5. 访问:给谁用
- 本公司成员打开
/nexus/cell-demo/apps/production-live就能看、能执行「登记异常」(Action 的 roles 含 member)。 - 班组长在别的公司账号下?
aidc share production-live --user 他的邮箱 --role editor --days 30。 - 给客户或领导一个只读大屏链接:
aidc share production-live --public(真实数据,发之前确认;随时aidc share revoke)。 - 类型、Ontology 本身谁能看:Private / Group / Public / Open to Internet,见访问与账号。
6. 留痕:用得怎么样
aidc semantic observability summary production-live --days 7
aidc semantic edits-history production.order_line --pk <主键>
打开几次、谁在用、登记了多少次异常、哪些反馈还没处理、每个版本号的状态(已上线 / 已被替换…)、语义版本——都在第一条里。第二条看一个对象的每次修改(谁、何时、改前改后);开了 actionLog 的 Action 每次提交还会写一个 Action Log 对象。
7. 自进化:下一个版本
aidc evolve suggest production-live --file 生产日报口径.md --conversation 班组长群.txt
aidc evolve proposals --status open
aidc evolve accept <id> && aidc evolve apply <id> # 语义类:改说明 / 同义词 / 加属性 → 自动发 v2
语义类提案由开发者直接应用;智能体作者要在分支上改、开 Ontology 提案,由人审核合并。应用类提案(「加按班次筛选」)由开发者或智能体改代码,aidc app deploy → 测试 → aidc app publish,最后 aidc evolve apply <id> --version 1.2.0;提案关联的反馈自动标记为已处理,反馈人下次打开就能看到改进。
8. 自动化:把各部门的应用串起来
每个部门的应用发布后,就是公司能力目录里的一组能力(清单 exports 显式导出的,和从登记的类型 / Action 自动提取的)。跨部门的事——比如报价要用营业的询价、设计的 BOM、采购的行情、制造的工艺、财务的核价口径——写成一个工作流应用:
aidc semantic automate capabilities # 看有哪些能力可以用
aidc app deploy quote-workflow --dry-run # 部署前对照能力目录校验
aidc semantic automate run quote-workflow --param rfq_no=RFQ-2609-002 --preview
照 Palantir Automate:trigger.change 是条件(对象新建 / 修改时,登记询价 → 自动出报价草稿),步骤是效果;画布上看得到每一步用了谁的能力、产出了什么。它写回的结果照样进 Semantic、有留痕、进应用日志——闭环里多了一条「部门之间」的线。见自动化。
数据放在哪里
- Semantic 的对象、变化记录、日志、分享、提案都在 AIDC 中枢(Supabase Postgres),按公司隔离;只存看板与协作需要的业务字段,身份证、银行卡、密码之类的字段在定义层就被拒收。
- ERP / MES 只被发布端读;发布 Key 只能往一条流发。
- 还是某个类型数据源的流删不掉,先从定义里去掉数据源(同步就停,对象保留);删掉对象类型的定义会归档它(对象保留,直到开发者清理)。
7. 不写 cron:Loop 从 Semantic 读、由 Automate 触发(标准写法)
客户箱上的定时任务(每 5 分钟查一遍 ERP、和快照比、有新行就发钉钉)换成 Semantic 的三件东西:TableImport(ERP 只被读一次)、Object Type(数据的业务名字)、Automation(数据一变 / 到点就做事)。照 Palantir 的 Data Connection 与 Automate,名字不改;设计见 docs/semantic-data-connection.md。
ERP(只对客户箱开白名单)──▶ agent(装在客户箱上,不常驻:Semantic 要数据时经 SSM 叫醒一次,只回传变了的行)
──▶ Object Type(Semantic)──▶ Automation(Objects added / modified / removed · 到点)──▶ 钉钉 / 企业微信 · Loop 脚本
① 连接与 TableImport(一次,开发者):Connection 只写主机、端口、库名和箱上的凭证名;口令留在箱上。查询只能是一条 SELECT,带窗口(例:近 45 天),只选 Loop 用得到的列。
aidc semantic connectivity connection --ontology cell-demo --file stock-connection.json
aidc semantic connectivity import <connectionRid> --file inbound-lines.json # SNAPSHOT 窗口;target = Object Type 与列 → 属性
aidc semantic connectivity execute <connectionRid> <tableImportRid> --wait # 第一次全量,之后只传变化
② 读:自动连接。读由 TableImport 供数的类型时,比 freshness.maxAgeSeconds 旧就按需同步一次(先给当前值;?fresh=true / fresh=True 等结果)。没人读 = 不同步 = 不花钱。
③ 触发:Automation。「这个合同的线类物料一入库就私发质检」:
{
"apiName": "po-0001-inbound", "displayName": "ACME-0001 线类入库 → 私发质检员", "status": "active",
"condition": { "type": "objectsAdded", "evaluation": { "everyMinutes": 10, "workHours": "07:00-21:00" },
"objectSet": { "type": "filter", "objectSet": { "type": "base", "objectType": "stock.inboundLine" },
"where": { "type": "and", "value": [ { "type": "startsWith", "field": "orderNo", "value": "ACME-0001" }, { "type": "containsAnyTerm", "field": "materialName", "value": "涤纶线 弹力线 高弹" } ] } } },
"effects": [ { "type": "notification", "channel": "dingtalk", "via": { "agent": "demo-box", "profile": "purchasing" },
"recipients": [ { "type": "user", "id": "000000001", "name": "质检员" } ], "title": "辅料到货入库", "quietHours": "21:00-07:00",
"template": "### 📦 到货入库,请做辅料质检\n{{#objects}}- {{materialName}} {{materialRule}} **{{amount}} {{unitName}}**(入库单 {{billId}})\n{{/objects}}" } ],
"replaces": [ { "box": "demo", "profile": "purchasing", "jobId": "a1b2c3d4e5f6", "name": "ACME-0001 到货入库", "runsPerDay": 144 } ]
}
aidc semantic automations upsert --ontology cell-demo --file liya.json --dry-run # 编译对象集、看当前成员
aidc semantic automations upsert --ontology cell-demo --file liya.json # 从「现在」开始,不回放历史
aidc semantic automations show <automationRid> # 最近 20 次运行、每个收件人的结果
④ 还要写代码的 Loop(日报、渲染看板):脚本改成从 Semantic 读,触发写成 Automation 的 agentScript 效果(到点、或数据变了之后跑一次)。箱上脚本用 aidc_semantic(只用标准库,随 agent 装在 /opt/aidc-semantic/lib;运行时自带一次性只读令牌):
from aidc_semantic import sql, objects
rows = sql('SELECT "orderNo", "materialName", amount FROM "stock.inboundLine" WHERE "inputDate" >= now() - interval \'1 day\'', fresh=True)
迁移一个 cron 的定式:写 Automation(带 replaces)→ --dry-run 看对象集 → 建好后与原 cron 并行一轮、对上 → hermes cron pause <jobId>(暂停不删,保留两周)。/semantic/<组织>/connections 能看到每个 Automation 替掉了哪些 cron、原来每天跑多少次。
本页由 developer/docs/loop.md 生成 · Markdown 原文 · llms.txt