二 · 本体工程方法论谱系
从 competency question 到 CI 的四件内核
本体工程不是一个新学科,它有三十年的方法论积累,也有三十年的失败记录。这一章按时代梳理主要方法论,指出它们各自解决了什么、留下了什么,然后收敛出四件去掉就会散架的内核,最后给一个两周能走完的最小流程。
五个阶段,各解决一个问题
| 年代 | 代表方法 | 关注点 | 留下的遗产 | 遗留的问题 |
|---|---|---|---|---|
| 1990s | 骨架法、TOVE、METHONTOLOGY | 把本体当知识获取工程 | competency question 这个起点仍然最好用 | 产出是文档与图,不可执行 |
| 2000s | NeOn、ONTO-CLEAN | 协作、复用、本体网络 | 复用的分类学(整包复用 / 摘用 / 对齐) | 本体复用在实践中几乎总是失败 |
| 2010s | OWL 2 与推理导向 | 形式化、可满足性、分类 | 可判定性的工程边界(EL/QL/RL) | 表达力与可用性之间的鸿沟 |
| 2015s | SHACL、JSON Schema、dbt 式约束 | 数据校验、放进写入路径 | 「约束优先」成为工业界默认 | 约束之间的一致性没人管 |
| 2020s | 本体进 git、进 CI | 版本、评审、影响面 | 本体被当代码管 | 影响面计算仍未标准化 |
| 2025s | LLM 诱导(从文本/表结构反推) | 冷启动成本 | 起草速度提升一个数量级 | 幻觉进入语义层,比文本幻觉更危险 |
几个具体的方法论简评:
- METHONTOLOGY 的贡献是把本体开发拆成规格、概念化、形式化、实现、维护五段,并且强调「规格」阶段要写清用途与使用者。它的毛病是重,一个中等规模项目光走流程就要几个月。今天还值得借用的只有一件事:在动手建模前,把「这个本体要能回答哪些问题」写成句子。
- NeOn 的贡献是承认「本体不都是自己建的」,因此把复用、重工程(re-engineering)、本地化当成一等公民。它的失败在于:复用别人本体的成本,通常高于自己重写一个够用的。
- ONTO-CLEAN 是这批方法里唯一把「清理」当核心的:它假设输入本体是脏的,任务是把脏东西识别出来、分类、再决定修还是删。这个视角在今天依然欠缺——大部分团队只有「建模」流程,没有「删除」流程。
- SHACL 之后的方法论其实还没写出来。 实践中已经形成共识(约束要可执行、要进 CI),但没有一份被广泛接受的方法文本。这份汇编的第二章后半部分,某种程度是在补这个缺口。
四件内核
不管用哪个时代的方法,有四件事缺了就会散架。它们不是步骤,是约束。
一、competency question:先写句子,再画图
做法:收集 15–25 条真实问题,必须是能被回答或不能被回答的句子,不是名词清单。
- 好:「某个客户在上个季度是否同时持有一个已到期和一个未到期的产品?」
- 坏:「客户、产品、持仓」。
好问题的两个特征:含时间或条件(逼出时态与状态建模),含「是否」「多少」「哪些」(逼出基数与聚合)。
常见错法:把业务方的需求文档改写成问句。需求文档写的是「要能查询客户持仓」,改写成问句还是同一个意思,仍然不产生建模约束。真正的问句来自曾经做错过的报表。
二、单一源:人可读、可 diff、可编译
做法:选一个文本格式(YAML / Turtle / 表格)当唯一真相,其余所有产物(JSON Schema、SQL DDL、OWL、SHACL、文档、ER 图)都是生成物,生成物不允许手改。
三个判据:
- 能不能在 code review 里看清这次改了什么?(这淘汰了二进制编辑器工程文件)
- 换一个目标格式,是不是改配置而不是改模型?
- 生成物与源不一致时,CI 会不会失败?
常见错法:把 Protégé 的工程文件当源。它在建模期很好用,但它是二进制的、不可 diff 的、且不能被别的工具消费。它可以当「分析工具」,不能当「源」。
三、可执行校验:必须是 CI job,必须有退出码
做法:把「必须为真」的规则写成可执行约束,挂在提交或写入路径上;校验失败必须让流程失败,而不是生成一份报告。
这里有一个非常实际的细节:退出码。一个校验器如果只在输出里打印「不通过」而退出码是 0,它在流水线里等于不存在。
常见错法:把校验做成定时任务 + 仪表盘。三个月后仪表盘没人看,坏数据已经流进下游七个系统。
四、变更影响面:先算爆炸半径
做法:任何一次语义变更,在合并前回答三个问题:哪些数据会变成不合规?哪些下游查询会变?哪些推论会新增或消失?
有一个很好的实证:某次变更只增加了一条 domain 声明,没有增删任何数据,却多出了 901 条推论。语义变更的爆炸半径与 diff 的行数无关。 这是它区别于普通代码变更的核心特征。
常见错法:只做语法 diff,不做语义 diff。两份 Turtle 文件按行比,差异几百行;按规范化后的三元组比,差异三条。
最小可行方法论(两周)
这套流程的目标不是「建一个好本体」,而是在两周内得到一个能失败的版本——如果它会失败,越早失败越便宜。
| 步骤 | 动作 | 产出 | 时间 |
|---|---|---|---|
| 1 | 收集 20 条真实问题,其中至少 5 条来自「曾经做错的报表」 | 问句清单 | 1 天 |
| 2 | 从问句反抽 12–18 个对象类型,每个类型不超过 8 个属性 | 类型清单 + 属性表 | 2 天 |
| 3 | 写 5 条「必须为真」的约束(不是「最好为真」) | 可执行约束 | 1 天 |
| 4 | 拿 100–500 条真实数据跑一遍,统计违规率 | 违规报告 | 1 天 |
| 5 | 把校验接进 CI,确保退出码非零 | 一个会红的流水线 | 1 天 |
| 6 | 冻结 v0.1,写下变更与弃用流程 | 版本记录 + 流程 | 1 天 |
第 4 步是分水岭。绝大多数本体项目从不拿真实数据跑自己的约束,因此永远不知道约束是太松(全部通过,等于没写)还是太紧(违规率 40%,无法上线)。违规率应该落在 2%–15% 之间:太低说明约束没有约束力,太高说明模型与数据现实脱节。这个区间是经验值。
三条反直觉的经验
建模会议不如校验报告有效。 让八个业务专家坐在一起讨论「客户到底是什么」,两小时能产出三页分歧。拿 500 条真实数据跑一份校验报告,二十分钟能产出二十条具体的、可裁决的错误。具体的错误比抽象的分歧容易收敛。
类多了不是问题,关系少了才是。 新手常担心类型爆炸,于是把十个概念压成一个再加一个 type 字段。这会让所有基于类型的约束失效——因为类型变成了数据,约束无法在 schema 层表达。真正的信号是关系数量:如果一个模型有 30 个类却只有 20 条链接,它大概率是一堆孤岛。
本体的寿命由「删除流程」决定,不由「建模质量」决定。 三年后还在用的本体,都是那些能安全删掉一个类的本体。做不到这一点的,会在两年内退化成「谁都不敢改」的遗留资产。所以第 6 步的弃用流程不是形式主义,它决定了这份资产会不会变成负债。