问:31.5 兆帕的柱塞泵,能不能用 HM-46?
系统答:能。HM-46 是抗磨液压油,样本上写着适用于柱塞泵。
人工去核:翻两份公开的产品样本。一份写“适用于工作压力高于 28 兆帕的柱塞泵”,另一份写“建议工作压力不高于 14 兆帕”。同一个牌号,两个厂家,一个说 28 兆帕以上,一个说不高于 14 兆帕,两个区间根本不挨着。系统那个“能”字,靠的是把半句话从一个产品身上搬到整个牌号上,两份样本里都没有这个依据。
错的地方不在检索。这两句话在文档里都找得到,向量检索也确实把相关段落召回上来了。错在它把 HM-46 当成了一个东西,把“适用于柱塞泵”当成了这个东西的属性。
HM-46 是个牌号,也就是一类黏度等级。每个厂家都有自己的 HM-46,基础油不同,添加剂不同,台架试验不同,能覆盖的压力也不同。“适用于柱塞泵、28 兆帕以上”这句话,主语是某厂那一款具体产品,不是 HM-46 这个牌号。两者合成一个,声明就没了发布方,压力就变成一个可以随便搬运的数字。
这类错误,换一个更强的检索器也修不好。缺的不是文本,是结构:谁在说,说的是哪个个体,这句话在什么条件下成立。
补这三样东西的活儿叫本体。它不算新概念,Tom Gruber 给的定义是“对概念化的显式规范”,说白一点,是一份机器可读的说明:这个领域里有哪些东西,它们怎么相连,哪些说法不可能成立。
但本体不是非做不可。做的成本不低,做错的成本更高。所以先回答一个问题:手上这个制造业项目,到底该不该上。
先算这笔账,再谈上不上
如果应用只是按编号查一张表、返回几个字段,关系库或者一个 JSON 文件就够了,不必往这个方向走。
真要上,得付四笔账:设计、治理、验证、维护。最后一笔最重。没人维护的本体很快和现实脱节,一份过期的图纸比没有图纸更危险,因为有人会照着它干活。
这四笔账不被算错的场合很少,最常见的一种是把本体当成知识图谱的升级版,先建起来再想用途。建完发现答不上任何一个业务问题,于是又加一层,加到没人敢动。
判断的办法不是看技术先进不先进,是看有没有下面这几种毛病。
五个信号,出现一个可以谈,出现三个基本该做
同一个东西有三个名字。 销售叫“抗磨液压油”,仓库叫“HM 油”,二十年前的老系统里叫“H46”。名字不统一的时候,任何跨系统的统计都是错的,而且不会有人发现。
问题要跨类型走路径。 “满足国标、且能用在 25 兆帕以上柱塞泵上的油有哪些”,一句话里有一个产品、一个标准、一类设备、一个数值条件,靠关键词匹配拼不出来。
系统要能挡住明显不成立的断言。 数据里录进一条“某台设备满足 GB 11118.1”。设备可以符合某个设备标准,但没法满足一个油品标准,这条必须被拦下,理由还要能说给人听。
需要推出没有直接存的事实。 存了“华东某厂的 HM-46 是液压油”,本体里写了“液压油属于润滑产品”,那么它是润滑产品这件事不必再录一遍。
大模型需要一张可靠的地图。 模型很擅长把润滑产品、执行标准、设备型号混着说,因为它读的是语言。类型、路径、约束这三样给它,检查才有依据。
一个信号的时候,多半还有个便宜办法。名字不统一,先做一份对照表;只想拦几条明显的错,写几行校验规则也能顶一阵。这些办法的共同点是只管眼前这一处,换个系统、换个人来问,还得再补一遍。
一个信号是毛病,三个信号是结构问题。
三个信号同时出现的时候,它们指向同一个缺口:系统里没有“什么是同一类、什么是一个个体、什么话在什么条件下成立”这三层。这时补规则补不完,规则之间还会互相打架,今天加一条明天破一条。缺的是结构本身。
第五个信号最容易误判。“上了大模型,所以要做本体”,这句话不成立。模型混说产品、标准和设备型号,才需要给它一张地图;只让它写文案、做摘要,给它一份术语表就够了。
决定要做,先分清图纸和机器
一句话版本是:本体写规则,知识图谱存事实。这话对,但太粗,容易让人以为本体就是一张更正式的表结构。
换个更贴工业的说法。本体是产品图纸,知识图谱是已经装好的那台机器。图纸定零件清单、装配关系、公差范围;机器是具体的这一台,有序列号,有实际装配记录,也有装错的地方。图纸改了机器不会自己跟着变,机器装错了图纸也不会报警。后面大半麻烦,都从这个错位开始。
再往里一层,是类和个体没分开。类是“什么东西算一类”,个体是“这一台、这一桶、这一家”。图纸只画类,机器装出来才有个体。
拿润滑油业务落地看一眼,本体这一层定的是:
-
类:润滑产品、液压油、齿轮油、执行标准、设备、生产厂 -
关系:满足标准、适用于、由谁生产、替代哪个旧牌号 -
约束:一个东西不能同时是油品和标准;液压油至少要挂一个执行标准
知识图谱这一层存的是具体事实:
-
华东某厂的 HM-46 是一款液压油 -
它满足 GB 11118.1 -
它由华东某厂生产
本体能表达的东西比数据库结构多。表结构管字段类型和必填,本体管的是另一头:这条关系的两头必须是什么类,两个类能不能重叠,反过来能不能推。这三件事,关系表都做不到。
分工一乱,开头那个“能”字就有了来源:把某款产品的一条声明,当成牌号的属性存进图里,图和检索都没觉得不对。
五层技术,一层管一段
信号回答的是该不该,这一节回答怎么做。语义网这套标准常被当成一个整体来谈,其实每一层回答的问题完全不同,混着讲必然乱。按依赖关系往下走,一共五层。这里的五层和前面那五个信号不是一回事,五个信号是判断题,五层是把题做出来的工序。
先有唯一的名字:IRI
HM-46 这个名字在行业里不唯一。不同厂都有 HM-46,同一个厂不同年份配方也变过。做统计的时候,“HM-46 的销量”这句话本身就有歧义;做判断的时候,“HM-46 能用到多少兆帕”同样有歧义。牌号是共用的名字,产品是具体的那一个。
IRI 解决这一层。它用的是网址那套写法,好处是能借域名所有权保证不撞名:别家可以有一模一样的路径,域名不同就是两个东西。
turtle@prefix lub: <https://data.data3oil.com/lub/> .
写好这行前缀,lub:HM46 就等价于 https://data.data3oil.com/lub/HM46。前缀只是缩写,不改变身份。常见的误解是以为这个名字必须能打开一个网页,能不能打开是另一件事,名字只要唯一就够了。
为了不占篇幅,后面几段只写 lub: 前缀,rdf、rdfs、owl、sh 这些标准前缀按 W3C 规范里的地址补上即可。
事实写成三元组:RDF
RDF 把每条事实拆成主语、谓语、宾语三个位置。这里的 lub:HM46 指某厂那一款具体的油,不是牌号本身。上面那三条事实写成 Turtle 是这样:
turtlelub:HM46 a lub:HydraulicOil ; lub:meetsStandard lub:GB11118_1 ; lub:producedBy lub:FactoryEast .
分号表示后面几条的主语还是 lub:HM46。三行就是三条边。
同一张图也能写成 JSON-LD,样子完全不同,描述的是同一张图。RDF 是结构,Turtle 和 JSON-LD 是这种结构的两种写法,像同一份图纸可以打印在纸上,也可以存成 CAD 文件。格式换来换去,不影响图里有什么。
给词汇加骨架:RDFS
有了事实还不够,还得能说“液压油是一种润滑产品”,能说“满足标准这个关系,左边应该是产品,右边应该是标准”。这是 RDFS 干的事。
turtlelub:Lubricant a rdfs:Class . lub:HydraulicOil a rdfs:Class ; rdfs:subClassOf lub:Lubricant . lub:meetsStandard a rdf:Property ; rdfs:domain lub:Lubricant ; rdfs:range lub:Standard .
这一层有个地方,第一次接触的人容易理解错:domain 和 range 不是录入校验。
meetsStandard 的定义域写了润滑产品。这时候有人往图里塞一条“某台设备满足 GB 11118.1”,RDFS 推理器不会报错,它会老老实实推出“这台设备是润滑产品”。它按你给的规则去理解世界,不负责拦住你。
这个行为和直觉相反,因为 RDFS 的设计目标是推理,不是验收。想要“不合规就报错”,得往下走,交给 SHACL。
让语义变厚:OWL
OWL 在 RDFS 之上补了几类真正有用的公理:逆属性、不相交、属性链、基数约束。
turtlelub:producedBy a owl:ObjectProperty ; owl:inverseOf lub:produces . lub:Lubricant owl:disjointWith lub:Standard .
逆属性是说,图上只存一个方向,推理器能补出另一个方向。存了“HM-46 由华东某厂生产”,就能得到“华东某厂生产 HM-46”。这不是冗余,是省录入。
不相交更值钱。润滑产品和执行标准互不相交。把这条和前面 RDFS 里那两个声明接上:producedBy 的定义域是润滑产品,它的逆属性 produces 的值域也就是润滑产品。
于是数据里出现“某厂生产了 GB 11118.1”的时候,推理器会先推出“GB 11118.1 是润滑产品”。它同时又是标准,而这两个类不相交。那个个体于是成了不可能存在的东西,一致性检查据此判整张图不一致,不会带着矛盾继续往下算。
不相交这条公理管的就是这件事:两个类不许重叠,一个个体不能两头都算。系统手里没有这条界限,“标准”和“产品”就会互相串。
OWL 还有一件事必须知道:它不是一个东西,是四个档位,选错档推不动。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
判断方法不复杂。本体主要是一棵很深的分类树,EL 就够,SNOMED CT 三十多万个类,靠的就是这一档。
但 EL 的取舍很明确:子类、等价类、不相交、存在量词、属性链都有,逆属性、基数约束、全称限制一个都没有。所以逆属性和“一个产品只能有一个主标准”这种基数约束,一旦进了模型,EL 就不够用,得换 RL,或者直接上 DL。
DL 的表达力最全,代价是最坏情况双指数。上了 DL,实例规模必须控制住,否则推理时间不可控。选档位是设计决定,不是越全越好。
补上“缺了就算错”:SHACL
前四层都在把话说清楚,没有人负责说错了怎么办。
OWL 建立在开放世界假设上:没写不等于假,可能只是还不知道。这个假设对推理是对的,对验收是灾难。
业务上要的是另一套:一条记录没填客户就是不合格,不许入库。没写等于不合规,这叫封闭世界假设。SHACL 干的是这件事。
turtlelub:HydraulicOilShape a sh:NodeShape ; sh:targetClass lub:HydraulicOil ; sh:property [ sh:path lub:meetsStandard ; sh:class lub:Standard ; sh:minCount 1 ; sh:message "液压油必须至少挂一个执行标准,取值必须是标准类的个体" ; ] ; sh:property [ sh:path lub:viscosityGrade ; sh:datatype xsd:string ; sh:minCount 1 ; ] .
拿一条不合格的数据去验,报告会直接指到节点上:某个产品的 meetsStandard 指到了一个油品而不是标准,某个产品没有黏度牌号。这是 OWL 不肯做的事。
这里有个坑,两个方向都会错。
SHACL 认子类:sh:targetClass 会自己顺着 rdfs:subClassOf 往下找,不用额外开推理。可它只认这一条链,别的推理一概不看。
一处是漏报。节点类型靠 domain、逆属性、属性链推出来的时候,形状选不中它,该抓的问题一个不抓,报告全绿。
另一处是误报。sh:class 看不到靠 range 推出来的取值类型,数据明明合格,却被判成不合格。
两个方向都不会报错,只会给出一个看起来正常的结论。
用 pyshacl 时要把推理显式打开:
pythonfrom pyshacl import validate conforms, report_graph, report_text = validate( data_graph="graph.ttl", shacl_graph="shapes.ttl", inference="rdfs", )
inference 的默认值是 none,改成 rdfs,上面两处才对得上。顺序也必须是先推理、再验证。
推理能多出什么,以及它的代价
把几条公理摆在一起看效果。
turtlelub:HydraulicOil rdfs:subClassOf lub:Lubricant . lub:Lubricant rdfs:subClassOf lub:ChemicalProduct . lub:producedBy rdfs:range lub:Manufacturer . lub:producedBy owl:inverseOf lub:produces .
图上只存两条事实:
turtlelub:HM46 a lub:HydraulicOil ; lub:producedBy lub:FactoryEast .
推理器能给出四条新的:HM-46 是润滑产品,HM-46 是化工产品,华东某厂是生产厂,华东某厂生产 HM-46。两条进,图上多出四条。
这是本体最实在的收益:规则写对了,机器自己就能推出可解释的结论,不必靠文本相似度去猜。
代价也在同一个地方。推出来的东西,可靠性不会超过你亲手写的那几条规则。一条写错的领域规则会沿着子类关系一路传下去,最后整张图都在用错的分类,而且看起来一切正常。本体设计因此归到治理里,规则改动要走评审,光画图不够。
把信号变成能测的题
五个信号是判断,判断得落到能检验的题上,否则做完没人知道对不对。
最常见的失败起手是:“先把领域里所有的概念画出来。”最后得到一棵很大的分类树,层级漂亮,但答不上任何一个具体问题。
另一种起手是先写问题。这套做法叫能力问题,Grüninger 和 Fox 在做企业建模时提出,后来 Noy 和 McGuinness 的《Ontology Development 101》把它写成了标准入门步骤。规则只有一条:问题要具体到能用数据检验。
润滑油领域能写出来的问题长这样:
-
满足 GB 11118.1、且适用于 25 兆帕以上柱塞泵的液压油有哪些 -
某个停产牌号被哪些新产品替代,替代关系是厂家声明的还是现场验证的 -
某台设备当前用的油,有没有超出它的压力适用范围 -
哪些在售产品只挂了一个标准
写问题的过程会暴露语言的模糊。“适用”是指厂家样本上声明的范围,还是现场跑出来的范围?这两种范围在业务上不是一回事,在模型里必须是两条不同的边。不写问题,这个区别永远发现不了。
更进一步,是把能力问题做成回归测试。每条配三类样本:
正例:数据齐全,应该给出确定答案。
反例:看起来像,但不该被采纳。比如一份培训稿里写着某款油“可用于高压系统”,而厂家样本没给压力参数。系统不该拿培训稿当依据。
未知例:证据缺位,系统应该明确说不知道,不能拿相似的历史记录补一个答案。
三类都过,这条问题才算过。只测正例的验收,测的是模型会不会顺着说话。
建本体这件事,大模型能替你干到哪一步
成熟方法论有好几套,TOVE、METHONTOLOGY、On-To-Knowledge,严谨程度不同。轻量项目可以借它们最实用的部分,压成九步。前半是想清楚:定范围和目标、写能力问题、抽概念和关系、搭初始本体。后半是让它活下来:推理验证、修订、发布、监控、维护。
大模型在前期能省很多力气。把领域文档、数据库表结构、真实用户提问交给它,它可以提出候选能力问题、抽候选概念、归并同义词、起草类和属性定义、建议逆关系、生成初始的 Turtle 和 SHACL 骨架。
它不能替你做的,是领域判断。模型会生成语法完全正确、业务上很微妙地错的本体。典型错误有三种:把执行标准当成可销售的产品,把牌号建成个体并给它挂上产品级的属性,把“适用”和“推荐”合成一条边。这三种错误不会让推理报错,只会让答案慢慢偏掉。
流程里必须留一步人工审查,而且要审得动。大项目里,这一审就是领域专家签字。一个能用的本体系统通常同时满足几条:概念有权威来源、尽量复用已有词表、能扩展而不必重写、为真实问题服务、推理和验证能被自动测、重大语义改动有人批。
本体在 GraphRAG 里改的是哪几处
GraphRAG 把检索和图上的关系结合起来,本来就能回答一部分多跳问题。加上本体,它变可靠的地方有五处。
查询分解。 用户问“满足国标、能用在 25 兆帕柱塞泵上的油”,本体告诉系统这是一条合法路径:产品到标准,产品到设备,设备到压力。翻译成图查询就是确定的:
sparqlPREFIX lub: <https://data.data3oil.com/lub/> SELECT ?oil ?grade WHERE { ?oil a lub:HydraulicOil ; lub:meetsStandard lub:GB11118_1 ; lub:viscosityGrade ?grade ; lub:suitableFor ?pump . ?pump a lub:PlungerPump ; lub:ratedPressure ?p . FILTER (?p >= 25) }
本体在这里起的是地图的作用。没有它,模型只能猜该往哪走,猜错了也看不出来。
实体消解。 同一家厂在语料里有三种写法:全称、简称、带“有限公司”的版本。本体的做法是把标签和强标识符分开,注册号这类权威键负责身份,skos:altLabel 负责保留别名给搜索用。消解本身还是要靠匹配算法加人工抽检,本体只负责把话说清:注册号算权威,简称不算。
检索控制。 问液压油的执行标准,本体能限定只走“满足标准”这条边,而不是把所有提到这款油的页面全捞上来。检索宽度这件事,规则比相似度可靠。跳数也要设上限,一般两跳最合适,三跳以上捞进来的多半是松散相关的实体,会把上下文稀释掉,答案反而变差。
抽取阶段的约束。 这一处最容易被忽略,也最影响成品质量。让大模型自由抽关系,它会为同一个意思造出十几个动词:适用于、可用于、推荐用于、适配。图被切碎,路径断开。正确做法是把本体的类和关系当白名单传给抽取器,只允许它在这份清单里选。清单外的,宁可留给人工。
答案验证。 模型说“GB 11118.1 由华东某厂生产”。本体知道 producedBy 的左边必须是产品,而 GB 11118.1 是标准,产品和标准又互不相交,于是这条能在到达用户之前被拦下,要求重新生成。这是本体在 RAG 链路里最直接的价值:它让一部分错误变成可检测的。
还有两件事不算本体的功劳,但和它一起决定成败。油品配方、执行标准、设备参数都有有效期,不带时间的图会把三年前的参数当现在用。出处同样要紧,每条边要能追到原文位置,否则答案无法核,也无法在源文件更新后重算。
出处不是可选项,它是判断的前提。样本上那句“适用柱塞泵 28 兆帕以上”,不是某个产品的一个数字,而是一条带主语、带发布方、带试验依据的声明。把它压成一个数字存进图里,图就再也回答不了“这是谁说的”。挂上发布日期和样本版本,才答得回来。
三种本体,别混着用
“本体”这个词现在至少指三种东西,成本差一个数量级。
逻辑本体,就是前面讲的那套:OWL 定义含义,推理机在背后演算。适合需要分类推理和一致性检查的场合。
可执行本体,代表是 Palantir 那类平台。它不只描述世界,还把数据、逻辑、动作、权限绑在一起,本体成了可以直接运行的操作平面。Palantir 自己的文档给了这个类比:对象类型相当于一个数据集,对象相当于一行,属性相当于一列,链接类型相当于一次 join。语义靠命名、元数据和文档承载,背后没有 OWL 那样的推理机在做分类推演。
词表,比如 SKOS,只做同义词、上下位、别名。它不做逻辑推理,但能把“抗磨液压油 / HM 油 / H46”统一到一个概念上,成本极低,收益立刻可见。
三种都叫本体,选之前先问清楚要的是推理、是操作,还是统一叫法。只有第一个信号、其余四个都没有的项目,要的多半是第三种。用逻辑本体的成本去做一件只需要统一叫法的事,是这个领域最常见的浪费。
只做非做不可的那部分
Gruber 那五条原则里,最后一条最容易被跳过:最小本体承诺。只做推理需求所要求的假设,不多做。
这条原则的现实含义很朴素:把整个行业都建进去,不如把十来个真问题答准。前者往往没人维护,后者改一处能看见一处。
这套东西真正要解决的不是模型大小,而是三件事:牌号和产品分成两个层级,产品级的声明挂上发布方,油品和执行标准分开。三件事做到了,一个“能”字站不站得住,系统自己就能判。
每层不做什么
层与层的分工记不住没关系,记每一层拒绝做什么更省事:IRI 只保证不重名,不负责解释;RDF 只把事实拆成三元组,不负责校验;RDFS 只加类层级,不负责拦数据;OWL 只推理,不负责验收;SHACL 只验收,不负责推理。
知道谁不干哪些事,才不会指望 domain 和 range 替你拦住脏数据,也不会以为在文档里写一句“请保证数据合规”就算验证过了。
五个信号的作用也一样,它最大的用处不是催人上项目,是让人知道什么时候不必上。一个项目的本体边界画清楚了,靠的不是建了多少类,是想明白了哪些东西不归它管。

