最近,我在学习 Palantir 的 Ontology,也对照看了 IBM 关于语义和经营模型的思路。一个疑问逐渐变得具体:它们都在给数据加上业务含义、描述关系、沉淀规则,本质上是不是在做同一件事?
这个疑问很适合作为学习本体的起点。
如果懂一点面向对象编程,看到“对象、属性、关系、动作”,很容易产生熟悉感。设备是一个类,某台水泵是一个实例,温度是属性,维修是方法。照这样理解,好像已经掌握了大半。
这个类比确实有用。接下来真正需要弄清楚的是:当多个系统、不同岗位和 AI 都要使用这些对象时,大家如何确认自己说的是同一件事,并按照同一套规则操作它。
本体的学习,可以从这里开始。
先交代一下范围。知识工程里的本体,关注一个领域中有哪些概念、概念之间有什么关系,以及哪些陈述成立。它可以用形式化语言表达,让软件进一步处理和推理。本文主要讨论企业软件中的本体建模,再以 Palantir 为例,解释模型怎样接入数据、支持查询和业务操作。哲学意义上的本体论,不是这里的学习主线。 来源W3C:OWL 2 入门说明[1]
先从设备、工单和工程师开始
假设我们要做一个设备维修系统。
最初的需求很简单:找出异常设备,创建维修工单,分配工程师,完成维修。先别急着选数据库,也不用打开 SDK,拿纸写下三个名词就够了:
- 设备 Equipment
- 工单 WorkOrder
- 工程师 Engineer
如果用面向对象的方式设计,我们可能给设备加上编号、名称和运行状态,给工单加上故障描述、创建时间和处理状态,给工程师加上姓名与专业。
这些都是理解本体的现成基础。
- 类 → 对象类型(Object Type):例如设备。
- 实例 → 对象(Object):例如编号为 P-003 的水泵。
- 字段 → 属性(Property):例如运行状态、安装位置。
- 对象之间的引用 → 关系(Link):例如工单维修某台设备。
- 一组实例 → 对象集合(Object Set):例如所有待维修设备。
Palantir 对对象类型、对象和对象集合的区分,也大体沿着这个思路:类型描述共同结构,对象对应具体实体或事件,集合则代表一组对象。 来源对象类型官方说明[2]
不过,名词认熟以后,还需要问得细一点。
“设备”究竟指一种产品型号,还是现场安装的某一台机器?水泵更换电机以后,是否还是原来那台设备?同一张工单能否处理多台设备?一个工程师能不能同时负责几张工单?
这些问题会改变模型。
例如“某型号水泵”和“现场的 P-003 水泵”最好区分开。前者描述一类产品的规格,后者有自己的安装时间、维修记录和运行状态。把它们混在一个对象里,后面就容易出现“这个型号修过三次”之类让人摸不着头脑的数据。
本体建模的第一步,是确定我们究竟在描述什么,以及描述到多细。
名词听起来简单,边界往往藏在细节里。
有了对象,再把关系写出来:
- 工单 W-017 → 维修对象 → 设备 P-003
- 工单 W-017 → 指派给 → 工程师 E-008
- 设备 P-003 → 安装于 → A 厂房
这里的箭头都有具体含义。“维修对象”和“安装位置”不能因为都连着两个节点,就被当成同一种关系。还要约定方向、数量,以及关系是否可以暂时不存在。例如一张刚创建的工单,可以尚未指派工程师。
这也是为什么画出一张关系图,只完成了一部分工作。连线容易,解释每一条线究竟允许什么,需要回到业务本身。
让对象对应真实世界里的那件事
模型放到真实数据里,下一层问题就出现了。
继续用这个假设案例。设备台账把那台水泵记为 P-003,监测系统使用 sensor_17,维修记录里写的是“三号泵”。
人可能知道它们指向同一台设备。程序需要明确的对应依据。
因此,要为设备确定稳定的身份,再把不同来源的记录映射过来。随后还要确认:名称来自哪里,运行状态由谁维护,传感器读数是什么时候采集的,两个来源冲突时怎样处理。
这时,OOP 的类比就需要补充了。程序里创建一个实例,只解决了程序内部的对象表达。企业本体里的对象,还需要持续对应业务世界中的那件事物。
对象相同,不代表关于它的每条信息都同样新、同样可靠。
例如监测系统最后一次上报的温度是 85℃,但采集时间在昨天。界面只显示“85℃”,很容易让使用者把历史读数理解成当前状态。
初学时,可以先把最新温度和采集时间作为设备属性。等需求变成“分析过去一周的振动变化”,再引入时间序列或独立的观测记录。模型跟着需要回答的问题扩展。
本体不会自动修复这些数据问题。它提供了一套组织和使用数据的方式,而对象识别、数据质量与更新规则,仍然需要认真设计。
这部分看起来没有“智能”那么吸引人,却直接决定上面的分析是否可信。
从修改字段,到完成一次业务操作
接下来,设备需要维修了。
在简单的程序里,我们可能直接写:
work_order.status = "closed"
这行代码很好懂,但业务上还有几个问题没回答:谁可以关闭工单?维修结果是否已经填写?是否需要验收?关闭以后,还要修改哪些关联信息?
Palantir 的 Action 可以用来定义一次业务操作所涉及的对象、属性和关系变更,并配置相应的参数、逻辑与校验。 来源Action 官方说明[3]
例如,我们为这个练习约定一个“完成维修”动作:
- 输入:工单、处理结果。
- 条件:工单处于处理中;操作者具有对应权限;处理结果不能为空。
- 变更:保存处理结果,记录完成时间,将工单状态改为待验收。
这里特意保留了“待验收”。它意味着工程师完成操作与业务确认完成,是两个不同的状态。如果实际流程不需要验收,就可以简化;如果需要,模型里就应该表达出来。
- 工单处于“处理中”
- 操作者具有对应权限
- 处理结果不能为空
Function 和 Action 也可以在这里分清。
Function 用于实现计算或业务逻辑,例如计算设备风险、选择候选工程师,也可以在适用的机制下支持本体编辑。Action 则把一次业务变更组织成可调用的操作,复杂的 Action 可以由 Function 支撑。因此,把 Function 一概理解成“只能读”,或者把 Action 理解成对象上的普通方法,都不够准确。 来源Functions 官方说明[4]
还有一个容易漏掉的事实:把工单状态更新成“已完成”,并不证明现场设备已经修好。若操作还要写回外部维修系统,也必须检查那个系统是否真正接收成功。
软件记录、跨系统同步和现实结果,各自需要证据。
本体的通用含义与产品实现
走到这里,我们已经接触到两层东西:一层描述业务世界,一层规定怎样改变系统中的业务状态。
Palantir 把对象、属性、关系,以及 Actions、Functions、动态安全等能力一起纳入 Ontology,形成组织的业务操作层。 来源Palantir 本体概览[5]
但不要把这个产品定义直接推广到所有本体。
通用的本体建模不必自带工作流、写回能力和权限引擎。Palantir 把这些能力组合到同一套产品体系里,是它的工程实现和产品选择。
同样,面向对象也能够构建复杂的共享业务系统。本体并没有让原来做不到的所有事情突然变得可能。比较它们时,更有价值的问题是:业务定义放在哪里,多少应用可以复用,修改怎样传播,谁负责维护,以及出错后能否追溯。
如果只是一个小工具,几个类、一套数据库和明确的业务服务,可能已经够用。随着参与者和应用增加,把共同使用的业务定义显式管理起来,价值才会越来越具体。
IBM 的语义与经营模型,和本体有什么共同点
这也解释了我最初接触 IBM 相关思路时的熟悉感。
IBM 的相关思路同时涉及自然语言的语义识别、指标口径、维度、计算规则和计划模型,也包括数据写入与预算回写等能力。
所以,如果把它理解成一个“将问题翻译成查询语句”的工具,就低估了它所描述的范围。它还在将经营分析与计划所需要的业务规则整理成可以反复使用的模型。
来源IBM
用设备维修这个例子看,两种建模视角可以这样区分:
经营模型可能关注某厂房、本月、某预算版本下的维修费用,怎样按设备或部门分摊,以及增加维修投入会怎样影响经营结果。
对象模型则可能从 P-003 这台设备出发,关联它的工单、人员、备件和状态,再定义相应操作。
这是对建模重心的比较,并不是能力边界。多维模型可以接入明细,对象模型也可以支持聚合和测算。实际系统里,两种视角还可以配合。
因此,我更愿意把两者的共同点理解为:将企业已经知道、但散落在系统和人员经验中的业务含义,整理成软件可以稳定使用的模型。
至于它们的权限、版本、变更一致性和跨系统执行是否相当,需要继续看实现。架构图能说明设计意图,不能替代运行结果。
语义解析、本体与知识图谱各自做什么
“语义解析”和“本体”之间的关系,也就容易解释了。
有人问:“这个月哪些设备反复维修?”
语义解析要把这句话转成明确的查询意图:时间范围是什么,“反复”指两次以上还是三次以上,统计创建工单的次数还是实际维修次数。
本体与相关业务规则则要事先说明:什么是设备,什么是维修工单,一张工单是否对应一次维修,以及哪些状态进入统计。
查询程序再根据这些定义取数。
如果公司还没约定“反复维修”的含义,模型就应当说明采用了哪种口径,必要时追问。让 AI 自己挑一个答案,并不会让口径分歧消失。
知识图谱也容易在这里与本体混淆。入门时,可以把本体理解为偏重概念、关系及其含义,把知识图谱理解为将具体实体和事实连接起来的知识表示。但这只是便于理解的分工;实际系统可以把模型和事实放在一起,本体也可以包含对具体个体的陈述。 来源W3C:本体、类与个体[1]
至于图数据库,它是一种存储和查询技术。选好了数据库,设备、工单和维修次数的业务定义仍然需要有人说清楚。
AI 能使用这些定义,也仍然需要证据
AI 加进来以后,这些定义变得更有用,也更容易被过度期待。
在这个维修系统里,可以让 AI 根据用户问题查询设备、沿关系寻找工单、调用风险计算,再提出派工建议。允许执行时,还要通过相应的操作接口和权限检查。
这会减少模型临时猜测表结构、拼接业务口径的需要。不过,提供了本体,并不等于 AI 已经理解企业全部业务。
例如 P-003 最近维修次数增加,附近产线也发生过停机。模型可以帮助我们找到这两组事实,但不能仅凭关联就断言“水泵导致了停机”。因果判断还需要故障记录、时间顺序和其他证据。
同样,配置“温度超过阈值则进入检查名单”,是一条明确的业务规则;根据历史数据预测故障,是另一个模型任务;用语言解释结果,又是另一项能力。把它们分别说明,才能知道某个结论究竟从哪里来。
我觉得这是学习本体时很值得保留的习惯:每遇到一个看起来很聪明的结果,都往下问一层,究竟是已有事实、人工规则、计算结果,还是模型推断。
用一个小练习,把概念连起来
如果准备系统学习,我建议把前面的维修案例做成一个小练习,按以下顺序推进。每一步都留下一个能检查的结果。
- 先写问题,再定义对象。 只选三个问题,例如哪些设备需要维修、哪些工单尚未分配、哪些设备在一个月内维修超过两次。围绕它们定义设备、工单、工程师及其关系。暂时不相关的概念先留在外面。
- 准备少量数据,验证身份和口径。 三台设备、五张工单、两名工程师就足够。故意加入一条设备别名、一张未分配工单和一条过期读数。检查模型能否明确表达它们。此时可以对照阅读官方的对象类型[2]与关系类型[6]说明。
- 定义一次完整操作。 选择“分配工程师”,写清输入、权限、前置条件和结果。再列出应该失败的情况:工程师不存在、工单已关闭、操作者无权限。读 Actions 文档[3]时,把这些问题逐项对应过去。
- 接入应用,完成查询与修改。 有 Foundry 环境,就用熟悉的语言,通过 OSDK 查询设备、读取关联工单,再调用一个 Action。没有环境,可以先在本地模拟同样的接口,但要明确:模拟验证的是自己的模型和逻辑,平台的运行机制仍需另外学习。
- 让模型经历一次变化。 例如规定一张工单可以由多名工程师协作,或者给“完成维修”增加验收环节。观察数据、查询和操作需要怎样调整。能处理这样的变化,往往比把最初那张关系图画得漂亮更能检验理解。
OSDK 文档,适合放在第四步阅读。它提供基于本体生成的类型和接口,让应用访问本体能力。有了前面的对象和操作定义,SDK 中的每个名字才有具体含义。 来源Ontology SDK 概览[7]
完成这个小练习以后,再决定向哪里深入。
如果目标是开发企业应用,可以继续学接口与多态、对象集合查询、权限、数据更新和模型版本管理。如果对知识表示与自动推理更感兴趣,则可以沿 RDF、RDFS、OWL 这条路线继续。
两条路线有交集,但不必在第一次创建维修工单之前,先把形式逻辑全部学完。进入 OWL 时,还会遇到一个需要专门理解的差别:未记录某件事,不直接等于这件事为假。这和很多业务程序的默认处理方式不同,不能把它自动套用到所有平台上。 来源W3C:OWL 的开放世界假设[1]
学习到这里,可以回头检查一下最初的面向对象类比。
“设备是类,水泵是实例”仍然成立,至少作为入门理解很有帮助。后来补上的,是这台水泵怎样被不同系统识别,状态来自哪里,工单与它是什么关系,以及谁能在什么条件下改变这些记录。
我会把自己的第一个学习成果定得很小:找到一台异常设备,说明判断依据,为它创建一张符合规则的工单,再确认操作结果。
这个过程跑通以后,“对象、关系、规则、动作”就不再只是几组熟悉的词。下一次再看到“企业本体”四个字,也就有了可以逐项追问的具体内容。