语义 SDK(Semantic)
Semantic 是 AIDC 的数据平台(照 Palantir Foundry:Data Connection + Ontology + Automate + Security)。企业数据的一切都在这里:数据从哪来、存成什么对象、谁能看、谁改了什么、变了之后自动做什么、花了多少钱。ERP / MES / OA 这些数据源永远只读;应用和智能体读对象集、用 Action 改(参数校验、谁能做、留痕)。
ERP / MES / OA ──(发布端,只读)──▶ 数据流 ──(Object Type 定义里的 datasources)──▶ Semantic(对象 · 链接 · Action)──▶ 应用 · 智能体 · 自动化 · SQL
import { semantic } from "/developer/sdk/v1/aidc.js";
Semantic 是数据平台
| 要做什么 | 用什么 | Palantir 里叫 |
|---|---|---|
| 读对象、沿链接走、聚合 | semantic.ontology().objects(t).where(…).fetchPage() / aggregate() / pivotTo() |
Ontology SDK(OSDK) |
| 实时 | objectSet.subscribe({ onChange, onOutOfDate }) |
Object set subscription |
| 改数据 | client.action(a).applyAction(…)(只有这一条写路径) |
Actions |
| 数据从哪来 | semantic.streams / semantic.stream() + Object Type 定义里的 datasources |
Data Connection · Streams · backing datasource |
| SQL | semantic.sql() / semantic.database() |
Ontology SQL |
| 谁能看 | semantic.filesystem(Private / Group / Public / Open to Internet)· semantic.admin(当前账号、成员) |
Filesystem ResourceRoles · Admin |
| 变了做什么 | semantic.automate(数据变化 / 定时 → Action、模型分析、通知) |
Automate |
| 留痕与用量 | Action Log、editsHistory、semantic.observability、semantic.usage,平台对象类型 aidcModelUsage / aidcAppEvent / aidcAutomationRun |
Action log · Observability · Resource Management |
| 建本体 | 分支与提案(智能体作者,人在网页上审核合并) | Global Branching · Ontology proposals |
原来的连接、数据、权限、工作流、日志、账单六个 SDK 就是上面这些部分,1.20.0 起都在 semantic 里。旧名照样能用、和新家是同一份实现:connect.stream === semantic.stream、auth.me === semantic.admin.getCurrentUser、workflow.run === semantic.automate.run、log.feedback === semantic.observability.feedback、billing.summary === semantic.usage.summary,connect.agent 搬到了 model.agent;应用清单 sdk 里写旧名也照收(归一成 semantic)。
数据从哪来:数据流与数据源
数据在源头一变,源头旁边的发布端(aidc semantic streams pipe + 适配器,只读)就把变化推上来,平台按序落账(数据流)。数据流接到哪个 Object Type、哪一列对哪个属性,写在 Object Type 的定义里(照 Palantir:Ontology Manager 的 Datasources 页选 backing datasource)——改数据源就是改本体:
{ "kind": "objectType", "apiName": "production.order_line", "title": "工单线体进度",
"schema": {
"columns": [ { "name": "order_no", "type": "string", "primaryKey": true }, { "name": "line_code", "type": "string", "primaryKey": true }, … ],
"datasources": [
{ "type": "stream", "stream": "production-progress", "propertyMapping": { "order_no": "aufnr", "line_code": "line", "ok": "gmnga" }, "mode": "mirror" }
] } }
- 规则(定义时就校验):流要在本组织存在;映射到的列要在流里;主键属性必须映射;只在语义层维护的属性(
writeback,Palantir 的 editOnly)和派生属性不映射;同一条流在一个类型里只出现一次。还是数据源的流删不掉(先从定义里去掉)。 - mode:
mirror= 流里没了的行在对象上标记「源头已消失」;upsert= 只增改(多行汇成一个对象、保留历史)。 - 谁能改:开发者直接定义(
aidc semantic define,或下面的快捷命令);智能体在分支上改、开提案,人审核合并(提案的 merge checks 多一项datasources)。 - 定义落了之后:平台按定义建好同步,用流的当前全量同步一次;之后流每落账一批就增量同步。定义里去掉数据源(或归档类型),同步就停,已有对象保留。
- 没写 = 沿用:重新定义时没写
datasources,沿用现有的数据源(返回一条警告);要去掉全部数据源,明确写"datasources": []。
aidc semantic streams create production-progress --title "生产进度" --key key --field key --field aufnr --field line --field gmnga:number
aidc semantic streams key production-progress --label "SAP 旁边的发布端" # aidc-pk-…,只显示一次
aidc semantic datasource set production.order_line --stream production-progress --map order_no=aufnr --map line_code=line --map ok=gmnga
aidc semantic datasource list # 每个类型的数据源与同步进度
aidc semantic datasource sync # 平台数据源立即同步(= /semantic 的「立即同步」)
await semantic.streams.create({ name: "orders", title: "订单", key: "order_no", fields: [{ name: "order_no" }, { name: "qty", type: "number" }] });
const pub = semantic.stream("orders").publisher(); // 发布端:只发与上次相比的差
await pub.rows(await readErpOrders());
实时:订阅对象集
const client = semantic.ontology();
const issues = client.objects("production.order_line").where({ status: "异常" });
const sub = issues.subscribe({
onChange({ object, state }) { state === "REMOVED" ? drop(object.__primaryKey) : upsert(object); },
onOutOfDate() { reload(); }, // 整个对象集要重读:刚订阅时来一次、断得太久、依赖的类型变了
onError({ subscriptionClosed, error }) { if (subscriptionClosed) showOffline(error); },
}, { properties: ["line_code", "gap", "status"] });
// sub.unsubscribe()
写法照 Palantir OSDK 的 objectSet.subscribe:对象进来或变了 → ADDED_OR_UPDATED(带属性),离开对象集(被过滤掉、删了、源头消失)→ REMOVED(只带主键)。同步、Action、别人的修改都会推过来;断线自动带着序号续传,不丢不重;页面隐藏超过 1 分钟断开、切回续上;应用里的连接时长计入应用的计算分钟。CLI:aidc semantic subscribe <类型> [--where '{…}']。官方走 WebSocket,AIDC 在同一路径(/api/v1/ontologySubscriptions/ontologies/{ns}/streamSubscriptions)走 SSE,消息一样。
访问与账号
const me = await semantic.admin.getCurrentUser(); // 我是谁、什么角色、能读哪些类型、能执行哪些 Action
if (!me.signedIn) semantic.admin.signIn();
await semantic.filesystem.setResourceAccess(rid, "public"); // Private / Group / Public / Open to Internet
await semantic.filesystem.shareResource(rid, { group: "cell-acme:dept:ops", role: "viewer" });
await semantic.filesystem.shareApplication({ audience: "company" }); // 应用的分享
开放程度四档、Owner / Editor / Viewer 三种角色、只有 Owner 改分享;资源是 Ontology、Object Type、数字员工、文件。详见访问与账号。
数据安全:Markings 与安全策略
财务、薪资、采购价、技术配方这类数据也进 Semantic,照 Palantir 用两种控制管住。上面的开放程度和角色决定「能不能打开这个资源」,下面这些再往里管到每一行、每一列:
| 控制 | 挂在哪 | 怎么判 |
|---|---|---|
| Markings(强制控制) | Ontology、Object Type、数据流、TableImport;或者写在行上(marking 类型的属性) |
挂着的 Marking 全都满足才看得见(同一个 DISJUNCTIVE 类别里满足任一即可)。不看角色,Owner、开发者也一样;只限制、不授予;沿层级(Object Type ← Ontology)和数据依赖(数据流 → 用它的类型的对象)传播 |
| 对象安全策略(行) | Object Type 定义里的 objectSecurityPolicy |
按对象的属性和读的人(组、账号、用户属性、行上的 Marking)判断每个对象看不看得见 |
| 属性安全策略(列) | Object Type 定义里的 propertySecurityGroups |
一组属性要另外满足的条件或 Marking;不通过的人读到 null,也不能拿它筛选、排序、求和 |
先建 Marking,再挂到资源上或写进定义:
aidc semantic admin marking-categories create --name 数据分级 # 类别:本组织开发者建
aidc semantic admin markings create --name 薪资 --category <类别 id> --member cell-demo:dept:hr
aidc semantic admin markings grant <薪资 id> USE <HR 负责人账号 id> # USE = 可以把它挂到资源上
aidc semantic filesystem mark <配方类型的 rid> <技术配方 id> # 整个类型挂 Marking(要 USE、是类型的 Owner)
aidc semantic filesystem markings <rid> # 直接挂的 + 继承来的
Marking 和类别建了不能删。角色:ADMINISTER 管成员与角色,USE 挂上,DECLASSIFY 去掉或停止继承;角色和成员互相独立(管 Marking 的人不一定看得见它保护的数据)。
行和列写在定义里(Demo Company 的员工薪酬;Marking 一律用 id 引用,aidc semantic admin markings list 查):
{
"kind": "objectType", "apiName": "employeeCompensation", "title": "员工薪酬",
"schema": {
"columns": [
{ "name": "employeeId", "type": "string", "primaryKey": true },
{ "name": "accountId", "type": "string" },
{ "name": "baseSalary", "type": "decimal" },
{ "name": "rowMarkings", "type": "array", "arraySubType": "marking", "notNull": true }
],
"objectSecurityPolicy": {
"name": "compensation-rows",
"granularPolicy": { "type": "and", "conditions": [
{ "type": "markingProperty", "property": "rowMarkings" },
{ "type": "or", "conditions": [
{ "type": "group", "name": "cell-demo:dept:hr" },
{ "type": "comparison", "comparison": { "operator": "EQUAL",
"left": { "type": "userProperty", "userProperty": { "type": "userId", "userId": {} } },
"right": { "type": "property", "property": "accountId" } } }
] }
] }
},
"propertySecurityGroups": [{ "name": "pay", "properties": ["baseSalary"], "appliedMarkings": { "<薪资 id>": "MANDATORY" } }],
"dataSecurity": { "markingConstraint": { "markingIds": ["<高管薪酬 id>"] } }
}
}
意思是:HR 部门或本人看得见这一行,行上带的 Marking(比如高管的行带「高管薪酬」)也要满足;金额另外要「薪资」。其他三类数据的常见配法:
| 数据 | 配法 |
|---|---|
| 财务 | Marking「财务」挂在 ERP 财务数据流上,用这条流的类型自动带上 |
| 采购价 | 采购订单行对采购员可见,unitPrice 放进属性安全策略,要「采购价」 |
| 技术配方 | 配方类型整个挂「技术配方」,成员只给研发负责人 |
规则(照 Palantir):
- 读:所有读路径都按读的人判定——Ontology API、对象集订阅、聚合、编辑历史、旧数据 API、/semantic 页面、自动化。Agent Key 是智能体身份,不是任何 Marking 的成员;Ontology SQL(Semantic 数据库)不含受保护的类型。
- Action:可以新建自己看不见的对象;改一个属性要看得见它现在的值;删要看得见整个对象;链接两端都要看得见;开了 Action Log 的,执行人要满足被改类型的全部 Marking。
- 自动化:条件和效果按拥有者(最后改条件或效果的人)的权限算;邮件通知按每个收件人的权限过滤。
- 只在读的时候判定:函数的结果、Action 写进去的值、导出的文件不带原数据的安全。
- 改安全策略:它是本体定义的一部分。改的人要满足改前改后涉及的全部 Marking,新加 Marking 要 USE,去掉或停止继承要 DECLASSIFY + USE。智能体在分支上改、开提案,由满足条件的人批准合并;
--dry-run自测时权限不够照样给出结果,「要谁来批」写在 warnings 里。分支预览(--branch)按 main 与分支里更严的那份判定。 - 上限:每个策略最多 10 个比较;权重是常量 1、集合 1,000、Marking 条件 3,000,总和小于 10,000(属性安全策略连同对象安全策略一起算);不能对组或 Marking 成员取反;策略用到的属性为空的行谁都看不见;
marking属性必须notNull,值要在dataSecurity.markingConstraint列出的 Marking 里。
试策略(照 Ontology Manager 的 Test security policies;只给开发者,结果不带属性值):
aidc semantic security test employeeCompensation --user <账号 id> --pk e1,e2
aidc semantic security test employeeCompensation --user <账号 id> --object '{"employeeId":"x","rowMarkings":[]}' --policy 新策略.json
SDK:semantic.admin.createMarking / addMarkingMembers / addMarkingRoleAssignments…、semantic.filesystem.addMarkings / removeMarkings / resourceMarkings、client.testSecurity(类型, {…});读对象时带 $loadPropertySecurityMetadata: true(照 OSDK),受属性安全策略保护的值会带上它的安全标记。
自动化(Automate)
数据一变(或到了时间)就做事:写在工作流应用的清单 workflow 里,照 Palantir Automate——条件(trigger.change = 对象新建 / 修改,when 过滤;trigger.schedule = 时间;手动)加效果(Action、模型分析、通知)。
const { run } = await semantic.automate.run({ rfq_no: "RFQ-001" }, { slug: "quote-workflow", mode: "preview" });
semantic.automate.watch(run.id, { onRun: draw, onDone: finish }, { slug: "quote-workflow" });
触发读的是 Semantic 的变化账(和对象集订阅同一条),不轮询、不写 cron。详见自动化。
留痕与用量
- 改数据的留痕:开了
actionLog的 Action 每次成功提交写一个 Action Log 对象;client.editsHistory(类型, { primaryKey })看一个对象的每次修改。 - 应用日志:
semantic.observability.track / feedback / error记使用、反馈、错误;summary / events看(应用日志)。 - 用量与账单:
semantic.usage.summary / records / check / prices / estimate(用量与账单)。 - AIDC 平台对象类型:平台替你的组织记下的应用、模型用量、应用日志、自动化运行,可以作为只读的 Object Type 进你的 Ontology——
aidcApplication、aidcModelUsage(按天 × 应用 / Key × 模型)、aidcAppEvent、aidcAutomationRun。本组织开发者打开 /semantic 时,智能体(数据库小艾)会开一个提案,你审核合并后才出现(不需要就关掉提案,同一批定义不会再提);之后按需同步(合并后、点「立即同步」、超过 1 小时有人看时)。用量、日志、自动化运行只给本组织开发者(可以在 Share 里开给别人),应用列表和 Nexus 里看到的一样。有了它们,看账单、查反馈就是查对象集,超支提醒就是一个自动化:
const byDay = await client.objects("aidcModelUsage").aggregate({ $select: { "costUsd:sum": "desc" }, $groupBy: { day: "exact" } });
const openFeedback = await client.objects("aidcAppEvent").where({ kind: "feedback", status: "open" }).fetchPage();
Ontology(照 Palantir)
语义层的建模语言、名字和 API 形状全部照 Palantir Ontology(设计:docs/semantic-ontology.md)。上面的写法(describe、objects、action().apply)继续可用;新写法是 semantic.ontology(),与 Palantir 的 OSDK 同形。示例取自 Demo Company 的示例本体(打开示例,要先登录 AIDC 账号;命名空间 cell-demo,全部是虚构数据;定义与数据在 developer/apps/ontology-demo-data/,应用在 developer/apps/ontology-demo/)。
语义部分(名词)
| Palantir 构件 | 是什么 | Demo 里的例子 |
|---|---|---|
| Object Type | 一类对象:主键、title、属性 | customer 客户公司、agent 智能体、application 应用、modelUsage 模型用量、cloudCost 云费用 |
| Property | 属性;base type 照官方(string、integer、long、double、decimal、boolean、date、timestamp、array、struct、geopoint、vector、timeseries…) | customer.location(geopoint)、customer.contact(struct)、modelUsage.dailyTokens(timeseries) |
| Derived Property | 沿链接读时计算(最多 3 跳;count、sum、avg、min、max、collectList、collectSet) | customer.agentCount = 智能体个数;customer.modelCostUsd = 模型费用合计 |
| Link Type | 两个 Object Type 的关系,两端各有名字;1:N 用外键,N:M 另存每一条链接 | customerAgents:customer.agents ↔ agent.customer;applicationAgents(N:M) |
| Interface | 多个 Object Type 共有的形状,可以继承 | Billable(继承 Monthly):modelUsage 和 cloudCost 都实现它,可以一起按月汇总成本 |
| Shared Property | 跨类型复用的属性定义 | costUsd、month |
| Value Type | 带约束的类型(enum、range、length、regex…),写入时校验 | cellId(cell- 开头)、yearMonth、customerStage(试点 / 付费 / 暂停) |
动力部分(动词、函数)
| Palantir 构件 | 是什么 | Demo 里的例子 |
|---|---|---|
| Action Type | 受控的写操作:参数 + 规则(createObject、modifyObject、createOrModifyObject、deleteObject、createLink、deleteLink)+ 提交条件(submission criteria) | adjust-seats:座位数不能少于成员数;assign-agent:给应用接入一个智能体(建一条 N:M 链接) |
| Action Log | 开了 actionLog 的 Action,每次成功执行都写一个 log.<action> 对象 |
log.adjust-seats:谁在什么时候把哪家的座位数改成多少 |
| Object Set | 对象的集合:过滤、并 / 交 / 差、沿链接走(searchAround)、按接口取、派生属性 | 付费客户的全部智能体 |
| Function | 代码写的逻辑,在隔离运行时里执行 | 要补(还没有隔离运行时);queryTypes 现在返回空列表 |
定义
定义还是 JSON,kind 用 Palantir 的名字(objectType、linkType、actionType、interfaceType、sharedPropertyType、valueType;旧的 object、link、action、enum 照旧可用)。
{
"kind": "linkType",
"apiName": "customerAgents",
"title": "公司的智能体",
"schema": {
"from": "customer", "to": "agent", "cardinality": "ONE_TO_MANY",
"apiNameAtoB": "agents", "apiNameBtoA": "customer",
"foreignKey": { "side": "to", "property": "customerId" }
}
}
{
"kind": "actionType",
"apiName": "adjust-seats",
"title": "调整座位数",
"schema": {
"parameters": [
{ "name": "customer", "type": "object", "objectType": "customer", "required": true },
{ "name": "seats", "type": "integer", "required": true, "min": 1, "max": 10000 }
],
"rules": [{ "type": "modifyObject", "objectType": "customer", "object": "$customer", "values": { "seats": "$seats" } }],
"submissionCriteria": [{
"condition": { "type": "comparison", "left": { "param": "seats" }, "operator": "gte", "right": { "param": "customer", "property": "members" } },
"failureMessage": "座位数不能少于成员数"
}],
"actionLog": true
}
}
名字照官方大小写:Object Type、Property、Link Type 两端、Value Type、Shared Property 用 camelCase,Action Type 用 kebab-case,Interface 用 UpperCamelCase。
从零做一个会执行的 Action(定义、只校验、执行、提交条件、命令行 / SDK / REST、做成应用、交给自动化):Academy 课程《动手:做一个会执行的 Action》,配套样板见样板应用的「座位申请」。新的 Object Type 只能有一个主键属性(旧的复合主键类型照旧可用,定义时给警告)。
定义里写了不认识的字段(多半是拼错了,比如把 submissionCriteria 写成 submissionCriterias)会直接被拒,错误信息给出路径——以前这类字段会被悄悄丢掉,Action 就少了提交条件。
Action 改源系统:writeback webhook
照 Palantir(Action 的 webhook):Action 可以配一个 writeback webhook——校验通过之后、规则之前调用源系统;源系统拒绝(或超时)就整个 Action 不生效,语义层一条都不改,原因原样返回给执行人(webhook_failed)。webhook 的输出在规则里用 $writeback.<输出名>。
{
"kind": "actionType",
"apiName": "stop-ec2-instance",
"title": "关机",
"schema": {
"parameters": [{ "name": "instance", "type": "object", "objectType": "ec2Instance", "required": true }, { "name": "reason", "type": "string" }],
"submissionCriteria": [{ "condition": { "type": "comparison", "left": { "param": "instance", "property": "state" }, "operator": "is", "right": { "literal": "running" } }, "failureMessage": "只有运行中的实例能关机" }],
"webhooks": { "writeback": { "webhook": "aws/ec2-stop-instances", "inputs": { "region": "$instance.region", "instanceId": "$instance.instanceId", "expectedLaunchTime": "$instance.launchTime" } } },
"rules": [{ "type": "modifyObject", "objectType": "ec2Instance", "object": "$instance", "values": { "lastAction": "stop", "lastActionAt": "$now", "lastActionResult": "$writeback.currentState" } }],
"roles": ["developer"],
"actionLog": true
}
}
- webhook 写成
<数据源>/<名字>,挂在 Data Connection 的数据源(Source)上,凭证在数据源里、不经过调用方。定义时校验:webhook 存在、必填输入都给了、没有多余的输入、$writeback.<输出>是它的输出、这个组织能用那个数据源。 - 规则只写只在语义层维护的属性(
writeback: true);状态这类从数据源来的属性等数据源同步回来——规则改它会一直盖住之后同步来的值(定义时会提醒)。 - 只校验(
$validateOnly)与预演不调用源系统;有 writeback 的 Action 一次只能提交一个请求(不收 applyBatch)。 - 现在的数据源只有 AIDC 平台提供的
aws(AIDC 自己的 AWS 账号:aws/ec2-stop-instances、aws/ec2-start-instances、aws/ec2-set-tag),客户自己的数据源在做。样板:developer/apps/aws-servers(EC2 实例、EBS 卷、账号费用的本体,开关机与自动关机)。
读与写(OSDK 写法)
const client = semantic.ontology(); // 应用里自动取应用所在公司;CLI / 智能体用 Key 所属公司
const paying = client.objects("customer").where({ stage: "付费", seats: { $gt: 30 } });
const page = await paying.fetchPage({ $orderBy: { seats: "desc" }, $pageSize: 20 });
// page.data[i]:{ __primaryKey, __apiName, __title, name, seats, location: { type: "Point", coordinates: [...] }, … }
const agents = await paying.pivotTo("agents").fetchPage(); // 沿链接走(searchAround)
const one = await client.objects("customer").fetchOne("cell-demo-a");
// 聚合(结果形状同 OSDK)
const byMonth = await client.interface("Billable").aggregate({ $select: { "costUsd:sum": "desc" }, $groupBy: { month: "exact" } });
// 派生属性
const withCost = client.objects("customer").withProperties({ apps: (b) => b.pivotTo("applications").aggregate("$count") });
// Action:先只校验,再执行
await client.action("adjust-seats").applyAction({ customer: "cell-demo-a", seats: 60 }, { $validateOnly: true });
const r = await client.action("adjust-seats").applyAction({ customer: "cell-demo-a", seats: 60 }, { $returnEdits: true });
// r.validation.result = VALID / INVALID(参数逐项、提交条件逐条);r.edits:新建 / 修改 / 删除了哪些对象和链接
where 写法:$eq $ne $gt $gte $lt $lte $isNull $in $contains $startsWith $containsAnyTerm $containsAllTerms $containsAllTermsInOrder $matchesRegex $within $and $or $not;聚合:$count、属性:sum|avg|min|max|exactDistinct|approximateDistinct,分组 exact、$fixedWidth、$ranges、$duration。
本体由智能体构建(唯一和 Palantir 不同的地方)
智能体不能直接改 main 上的本体。它在分支上改,开提案,由人在网页上审核、合并:
aidc semantic branch create add-department:开分支(基线 = 当前语义版本)。aidc semantic branch modify add-department ontology/:把定义放到分支上(一整份清单,--dry-run试跑,--expected-version防止并发覆盖)。aidc semantic objects agent --branch add-department:在分支上预览(读接口都收?branch=);branch validate看 merge checks,branch conflicts看和 main 冲突的地方,branch rebase跟上 main。aidc semantic branch propose add-department --title … --trigger "为什么要改":开提案。平台自动附上按资源的改动、校验结果、影响面(30 天的写入与活跃用户、依赖的应用)、破坏性改动。- 人在
/developer/<公司>/ontology/proposals/<id>逐项批准(破坏性改动要输入资源名确认),全部批准、merge checks 通过后合并:落到 main,发一个语义版本。
作者由凭证决定:Agent Key 一律是智能体;开发者 Key 在环境变量 AIDC_AGENT_ID 存在时,CLI 自动带 x-aidc-author: agent:<id>,作者也记为智能体。智能体作者直接定义 main 会得到 409 branch_required。批准、拒绝、合并只接受人的网页登录,任何 Key 都不行。
和 ERP、OA 的关系
ERP、MES、OA 缺省只读:发布端把数据推进数据流,按 Object Type 定义里的 datasources 同步进来。人和智能体的改动只走 Action,落在语义层(对象的 edits),数据源下一次同步不会冲掉它们。要真的改源系统(关一台服务器、回写一张单据),给 Action 配 writeback webhook(见上一节):源系统先接受,语义层才记一笔。
Semantic 平台(www.ai-dc.ai/semantic)
登录 ai-dc.ai/semantic/app 就进到自己组织的 Semantic;不属于任何组织的账号落到 Public。界面照 Palantir 的应用分工,只调这一页写的同一套 API:
| 页面 | 地址 | 做什么 |
|---|---|---|
| 概览 | /semantic/<cell> |
Object Type 一览(对象数、属性、链接、Public 标记)、最近的变化、待审核的提案、数据库状态 |
| Ontology 图 | /semantic/<cell>/graph |
画布:Object Type 是节点、Link Type 是边(多对多虚线);拖动、缩放、点开看属性与关系 |
| Object Types | /semantic/<cell>/object-types[/<apiName>] |
Ontology Manager:属性(base type、SQL 列、主键 / 标题 / Value Type / 派生 / 只在语义层)、链接、用到它的 Action、数据源、Share |
| Object Explorer | /semantic/<cell>/objects/<apiName>[/<主键>] |
表格:搜索、筛选、排序、按属性看分布;Object View:属性、每条链接上的对象、编辑历史、能执行的 Action |
| Actions | /semantic/<cell>/actions[/<apiName>] |
参数表单:先「只校验」(VALIDATE_ONLY)再提交;Action Log |
| SQL Console | /semantic/<cell>/sql |
Ontology SQL(见下一节);开发者在「连接」里轮换口令拿只读直连串 |
| Proposals | /semantic/<cell>/proposals |
智能体开的 Ontology proposal:逐项批准(可一次批准全部非破坏性的)、合并 |
| Access | /semantic/<cell>/access |
开放程度(Private / Group / Public / Open to Internet)、分享给谁、角色,见 访问与账号 |
| Public | /semantic/public |
所有登录的 AIDC 账号都看得见的 Ontology、Object Type、数字员工、文件,以及「分享给我」 |
网页会话调 /api/v1/ontologies/** 时,角色由统一的访问判定决定(Private / Group / Public):本组织开发者 = developer(与开发者 Key 同权);本组织成员(Ontology 对组织可见时)= member;别的组织的人按授予——Editor = editor、Viewer = viewer(只读);Ontology 与所有 Object Type 都没有角色 = 403。
Semantic 数据库(Ontology SQL)
每个组织一个 Postgres schema(ont_<组织>),第一次用时按需建好,定义变了下一次查询时自动重建。照 Palantir Ontology SQL:
- 表:每个 Object Type 一个视图,表名 = API name、列名 = 属性 API name(列类型:string → text、integer / long → bigint、double → double precision、decimal → numeric、date、timestamp → timestamptz,其余 jsonb)。每个多对多 Link Type 一个视图,两端的列名
<objectTypeApiName>_<relationApiName>(值是走这条链接到达的对象的主键);每个 Interface 一个视图(实现它的类型 UNION ALL,另有__objectType、__primaryKey)。一对多直接 join。派生属性是读时算的,不进 SQL。 - 数据:视图直接读当前值(数据源 ⊕ 语义层改动),不复制;删除的、源头已消失的不出现。
- 上限:只能一条 SELECT(可以 WITH / VALUES / TABLE 开头),最多 10,000 行、20 秒;位置参数
$1、$2…;dryRun= EXPLAIN。写入永远走 Action。 - 两个只读角色:
reader(本组织看得见的全部类型:本组织成员、开发者 Key、Agent Key、在 Ontology 上有 Viewer 以上授予的人)与public(只有授予了 Everyone 的类型:只看得见 Public 的外部账号)。应用票据不走 SQL——在应用里用semantic.ontology()。 - 直连:本组织开发者可以轮换口令,拿到 reader 的连接串,用 psql、BI 工具、Notebook 只读直连(只读事务、20 秒超时、最多 10 个连接、只看得见本组织的视图)。口令由服务端派生、不落库,库里只有 SCRAM 校验值;再轮换一次旧口令立即失效。
const r = await semantic.sql(`
SELECT o.name, count(a.*) AS agents
FROM organization o LEFT JOIN agent a ON a."organizationId" = o."organizationId"
GROUP BY 1 ORDER BY 2 DESC`);
const cost = await semantic.sql('SELECT month, sum("costUsd") FROM "modelUsage" WHERE "organizationId" = $1 GROUP BY 1', { parameters: ["cell-aidc"] });
const db = await semantic.database(); // 表与列、我用哪个角色
const conn = await semantic.rotateDatabaseCredentials(); // 开发者:psql "<conn.uri>"
aidc semantic sql 'SELECT stage, count(*) FROM organization GROUP BY 1' [--csv]
aidc semantic database --rotate
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/v1/sqlQueries/executeOntology |
执行(照官方 ExecuteOntologySqlQueryRequest:query、parameters、rowLimit、dryRun、ontologyIdentifier);响应是 JSON(官方是 Arrow) |
| GET | /api/v1/ontologies/{ns}/database |
数据库信息;开发者另有直连信息(不含口令) |
| POST | /api/v1/ontologies/{ns}/database/sync |
按当前定义重建视图(开发者) |
| POST | /api/v1/ontologies/{ns}/database/credentials |
轮换直连口令,新连接串只返回这一次(开发者) |
旧写法(1.2.x:describe / objects / action / define / publish)
1.2.x 起的写法照样能用(和上面同一份数据、同一套 Action 引擎),新代码请用上面的 semantic.ontology()。
三个概念
| 概念 | 是什么 | 例子(生产进度看板) |
|---|---|---|
| 对象类型 | 一类业务对象:主键 + 属性。属性要么来自数据源(同步进来,只读),要么只在语义层维护(writeback:备注、负责人、异常状态…) |
production.order_line(工单线体进度):工单、线体、计划、累计合格 ← SAP;异常状态、异常说明、登记人 ← 语义层 |
| 链接 | 对象之间的关系。最常见的是一个属性引用另一个类型的主键(references) |
工单线体 → 线体(line_code) |
| Action | 受控的写操作:参数(类型 / 必填 / 长度 / 枚举)+ 改哪些属性 + 谁能做 + 日志里的一句话 | production.flag_issue 登记异常:参数「异常说明」「级别」;写 issue、status、owner = 执行人 |
改数据只有两条路:成员用 Action(校验、权限、留痕);开发者用旧数据层直接改(管理用)。两条路的改动都落在语义层(对象的 edits),数据源下一次同步只更新它自己那一层,不会冲掉人改过的值。
读:说明书与对象
const space = await semantic.describe();
// space.types:看得见的对象类型(属性、单位、同义词、链接、对象数)
// space.actions:Action 与「我能不能执行」(allowed)
// space.markdown:给大模型读的整份说明书——智能体先读它再干活
// space.release:当前语义版本(v3…)
const hit = semantic.search(space, "合格数"); // 按业务说法定位:[{ kind: "property", type: "production.order_line", name: "ok" }]
const issues = await semantic.objects("production.order_line")
.where({ status: { in: ["关注", "异常"] }, day: "2026-09-26" })
.sort("-gap")
.list(); // { objects, total, seq }
const order = await semantic.objects("production.order_line").get("100000012345|L01-05");
const line = await semantic.objects("production.order_line").linked(order.pk, "production.order_line.line_code");
const byLine = await semantic.objects("production.order_line").aggregate({ groupBy: ["line_code"], metrics: { ok: ["ok", "sum"] } });
每个对象:props(当前值 = 数据源的值被语义层改动覆盖后)、rev(每改一次 +1)、edited(语义层改过的属性)、overridden(被改动盖住、数据源现在是另一个值的属性 → 数据源的值)、sourceGone(数据源里已经没有这一行)。
条件写法:{ 属性: 值 } 相等;{ 属性: { gt, gte, lt, lte, ne, in, nin, contains, startsWith, null } };多个属性之间是「且」;$or: [{…}, {…}] 任意一组成立。
实时
const view = semantic.objects("production.order_line").where({ day: today }).sort("-ok").live({
onUpdate(objects, change) { render(objects); }, // 先全量,之后数据一变就回调(同步、Action、别人的修改都算)
onStatus({ connection }) { badge(connection); },
});
// view.close()
底层是旧数据层的 watch(SSE,断线按序号续传,不丢不重)。
写:执行 Action
const r = await semantic.action("production.flag_issue").apply(
{ issue: "缺料:顶蓬面料未到", severity: "异常" },
{ object: "100000012345|L01-05", ifRev: order.rev },
);
// r.object:改后的对象;r.event.summary:「L01-05 登记异常:缺料…」(进操作记录)
- 参数按定义校验(不合法 422,信息里写明哪一项);
semantic.checkParams(actionInfo, params)可以在表单提交前本地预检。 - 谁能执行:应用清单
semantic.actions登记了它,且访客角色在 Action 的roles里(缺省 developer / member / editor)。只读访客(公开链接、只读分享)永远不能写;一律登录起没有匿名访客。 ifRev:对象当前 rev 不等于它就 409rev_mismatch(别人刚改过,刷新再改)。dryRun: true:只校验、返回计划,不落库。
定义与发布(开发者:CLI / 智能体)
定义就是 JSON。四种词条:enum、object、link、action。
{
"kind": "object",
"apiName": "production.order_line",
"title": "工单线体进度",
"description": "每个工单在每条线体上的当日进度(SAP 生产进度报表)",
"schema": {
"titleColumn": "line_code",
"synonyms": ["工单行", "生产任务"],
"columns": [
{ "name": "order_no", "type": "text", "primaryKey": true, "title": "工单" },
{ "name": "line_code", "type": "text", "primaryKey": true, "title": "线体", "references": { "entity": "production.line", "column": "line_code" } },
{ "name": "ok", "type": "integer", "title": "累计合格", "unit": "件", "synonyms": ["合格数", "良品数"] },
{ "name": "status", "type": "text", "enumRef": "production.issue_status", "writeback": true, "title": "异常状态" },
{ "name": "issue", "type": "text", "writeback": true, "title": "异常说明" }
]
}
}
{
"kind": "action",
"apiName": "production.flag_issue",
"title": "登记异常",
"schema": {
"objectType": "production.order_line",
"operation": "modify",
"parameters": [
{ "name": "issue", "type": "text", "title": "异常说明", "required": true, "maxLength": 200 },
{ "name": "severity", "type": "text", "title": "级别", "enumRef": "production.issue_status" }
],
"edits": { "issue": "$issue", "status": "$severity", "owner": "$userName", "flagged_at": "$now" },
"roles": ["developer", "member", "editor"],
"summary": "{line_code} 登记异常:{issue}"
}
}
取值表达式:$参数名、$now(当前时间)、$user(执行人账号)、$userName(执行人名字)、$uuid(新主键,create 用);其他是字面量(以 $ 开头的字面量写成 $$…)。operation:modify 改一个对象、create 新建(edits 要给出主键)、delete 删除(语义层墓碑)。
aidc semantic define ontology/ # 目录里的 *.json 整批提交:一起校验、按 枚举 → 对象 → 链接 → Action 落(有则改)
aidc semantic define ontology/ --dry-run # 只检查:整批引用是否闭合(批内互相引用算数)、相对上一个语义版本有哪些破坏性变更
aidc semantic publish --notes "加了异常登记" # 发一个语义版本 vN(只增;定义没变不占号)
aidc semantic describe --markdown # 给智能体读的说明书
aidc semantic act production.flag_issue --object "100000012345|L01-05" --param issue=缺料 --param severity=异常
- 引用闭合:Action 改的属性、引用的参数、外键目标、枚举都必须存在,否则定义直接 422。一个目录是一批(
semantic.defineAll(定义数组)/POST …/semantic/{命名空间}/types):在「整批改完之后」的全体定义上校验,批内互相引用算数,不闭合一条都不写。 - 破坏性变更(删类型 / 删属性 / 改类型 / 改主键 / Action 删参数或新增必填参数…)会在定义时返回、在发布时记档(
changeKind: breaking)。发布前先确认调用它的应用都改好了。 - 语义版本就是这家公司 Ontology 的版本号,与应用版本号一起出现在应用日志里;自进化 SDK 采纳的语义改进会自动发新版本。
权限一览
| 谁 | 读 | 执行 Action | 直接写(旧数据层) | 定义 / 发布 |
|---|---|---|---|---|
| 开发者 Key(CLI / 智能体) | 本公司全部 | 全部 | 全部 | ✓ |
| 应用里的 developer 访客 | 清单 semantic.types 登记的(含部门级) |
清单登记 + roles 允许 | 清单 semantic.write 登记的 |
— |
| 应用里的 member / editor | 清单登记、且对公司全员可见的 | 清单登记 + roles 允许 | — | — |
| viewer(只读分享 / 公开链接) | 同上 | — | — | — |
应用清单里这样登记:
{
"sdk": ["semantic", "ui"],
"semantic": {
"types": ["production.order_line", "production.line"],
"actions": ["production.flag_issue", "production.resolve_issue"],
"write": []
}
}
"*" 表示看得见的全部(数据浏览器这类通用应用)。
上表之外,数据安全(Markings、对象 / 属性安全策略)对所有人生效,包括开发者 Key:挂了 Marking 的数据,不是成员就读不到。
API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/developer/semantic/{命名空间} |
说明书(按凭证裁剪) |
| GET / POST | /api/v1/developer/semantic/{命名空间}/types |
全部定义(开发者)/ 一次定义一批({definitions: […]},整批校验) |
| GET / PUT / DELETE | /api/v1/developer/semantic/{命名空间}/types/{apiName} |
读 / 定义 / 归档 |
| POST | /api/v1/developer/semantic/{命名空间}/actions/{apiName} |
执行 Action |
| GET / POST | /api/v1/developer/semantic/{命名空间}/releases |
语义版本列表 / 发布 |
旧的数据层(/api/v1/developer/data/…:查询、聚合、订阅、直接写)照样能用;新代码用下面的 Ontology API 与对象集订阅。命名空间 = 公司 cellId(cell-…);应用里自动取应用所在公司。
Ontology API 照 Palantir REST API v2,前缀是 /api/v1/ontologies/{命名空间},响应体放在信封的 data 里、字段照官方:
| 方法 | 路径 | 官方操作 |
|---|---|---|
| GET | /ontologies、/ontologies/{ns}、/{ns}/fullMetadata |
List / Get Ontology、Full Metadata |
| GET | /{ns}/objectTypes[/{type}[/fullMetadata | /outgoingLinkTypes[/{link}]]] |
Object Type、Outgoing Link Types |
| GET | /{ns}/actionTypes、/interfaceTypes、/sharedPropertyTypes、/valueTypes、/queryTypes(各带 /{apiName}) |
各类型的 List / Get |
| GET | /{ns}/objects/{type}、/{type}/{pk}、/{type}/{pk}/links/{link}[/{pk2}] |
List Objects、Get Object、Linked Objects |
| POST | /{ns}/objects/{type}/search、/aggregate、/count |
Search、Aggregate、Count |
| GET / POST | /{ns}/objects/{type}/{pk}/timeseries/{property}/firstPoint、lastPoint、streamPoints |
Time Series |
| POST | /{ns}/objectSets/loadObjects、/aggregate、/createTemporary;GET /{ns}/objectSets[/{rid}] |
Object Set |
| POST | /{ns}/objectTypes/{type}/editsHistory |
Edits History |
| POST | /{ns}/actions/{action}/apply、/applyBatch(最多 20 个,一个事务) |
Apply Action |
| POST | /api/v1/ontologySubscriptions/ontologies/{ns}/streamSubscriptions(SSE) |
Object set subscription(官方走 WebSocket) |
| POST | /{ns}/datasources/platform/sync |
同步 AIDC 平台数据(平台对象类型;开发者) |
| GET / POST | /{ns}/branches[/{name}[/modify | validate | conflicts | discard | rebase | lock | fullMetadata | proposals]] |
Global Branching |
| GET / POST | /{ns}/proposals[/{id}[/tasks/{apiName}/review | merge | close]] |
Ontology proposal(review、merge 只收网页登录) |
| POST | /{ns}/objectTypes/{type}/security/test |
AIDC:Test security policies(Ontology Manager 的同名功能,官方没有公开 API) |
Markings 的管理照 Palantir AdminV2 / FilesystemV2:/api/v1/admin/markingCategories[/{id}]、/api/v1/admin/markings[/{id}[/markingMembers[/add \| /remove] \| /roleAssignments[/add \| /remove]]]、/api/v1/admin/markings/getBatch、/api/v1/admin/users/{userId}/getMarkings、/api/v1/filesystem/resources/{rid}/markings \| addMarkings \| removeMarkings。
完整字段见 OpenAPI。
本页由 developer/docs/semantic.md 生成 · Markdown 原文 · llms.txt