查看 Markdown

闭环:从 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. 访问:给谁用

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、有留痕、进应用日志——闭环里多了一条「部门之间」的线。见自动化。

数据放在哪里

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