AI时代的数据本体:从一张订单到Ontology

大模型读过很多数据,却未必认识你的业务。它知道“订单”这个词,却不知道你们公司的订单究竟承诺了什么。

前段时间重新梳理 RAG 和 Agent 的数据链路时,我碰到一个看起来很朴素的问题:供应商发来一封邮件,说某批轴承要延期三天,系统能不能顺着这条消息找出受影响的生产工单、产品、销售订单和客户,再给出下一步建议?

只做文档问答不难。按照之前整理的 RAG 混合检索 那套办法,把邮件放进向量库,问“哪个零件延期”,大概率可以答出来。难的是后半句:这批零件对应哪个物料编码,哪些工单依赖它,工单又在生产什么产品,哪些客户订单正等着这些产品?这些关系散落在采购系统、ERP、MES、CRM 和几张 Excel 里,模型不能靠“读起来像”把它们猜出来。

这正是 Ontology(本体) 重新被翻出来的背景。放在数据工程语境下,它也常被叫作“数据本体”——一套描述业务世界里有哪些对象、它们如何关联、哪些规则成立的显式模型。

名字听着有点哲学,做起来却很工程。这里不打算从定义背诵开始,直接搭一个小型制造业 Ontology,看看它到底比数据库 Schema 和普通知识图谱多了什么,又能为 AI Agent 补上哪块短板。

一封邮件找得到,影响链却找不到

假设一家制造企业同时运行着几套系统:

  • 采购系统记录供应商、采购单和预计到货时间;
  • ERP 保存物料、库存和销售订单;
  • MES 管生产工单、产线和工艺;
  • CRM 里有客户及交付承诺;
  • 邮件和群聊里还有大量尚未进入系统的变化。

每套系统的数据都可能是对的,放到一起却不一定能直接说话。采购系统里的 bearing_a、ERP 里的 MAT-0018 和邮件里的“A 型主轴轴承”,可能指的是同一种零件。销售口中的“订单”是客户承诺,生产部门口中的“订单”却常常是生产工单。

数据库可以保证 material_id 是字符串、delivery_date 是日期,也能靠外键连接两张设计良好的表。但它不会天然告诉另一个系统:

  • MAT-0018 和“A 型主轴轴承”是同一个现实对象;
  • 生产工单“需要”零件,销售订单“包含”产品,这两个关系语义不同;
  • 如果一个工单生产某产品,而订单包含这个产品,那么零件短缺可能沿这条链影响订单;
  • “建议调整排产”和“直接修改排产”是权限完全不同的动作。

这些知识当然可以写进 SQL、服务代码和操作手册。现实里也确实如此。麻烦在于,它们会被分别写很多遍,最后没有一处能完整回答“我们把这个业务世界理解成什么样”。

先画出制造企业的这个小世界

我们先不碰 RDF 和 OWL,只画出本次问题需要的对象:

graph LR S[供应商 Supplier] C[零件 Component] W[生产工单 WorkOrder] P[产品 Product] O[销售订单 SalesOrder] U[客户 Customer] F[工厂 Factory] S -->|供应 provides| C W -->|需要 requires| C W -->|生产 produces| P W -->|执行于 runsAt| F O -->|包含 contains| P U -->|提交 places| O

图很小,却已经暴露出几个有用的约定:供应商和客户都是组织,但扮演的业务角色不同;产品和零件可能都来自同一张物料表,在这个问题里却承担不同含义;工单与订单各自承担不同业务含义,光看中文名称相似就合并会出问题。

假设现在有下面几条具体事实:

  • “华东精密”供应“轴承 A”;
  • 生产工单 WO-0312 需要“轴承 A”;
  • 该工单生产“工业泵 P100”;
  • 销售订单 SO-8848 包含“工业泵 P100”;
  • 客户“远海能源”提交了这张销售订单。

当轴承 A 延期时,影响链就是:

轴承 A → WO-0312 → 工业泵 P100 → SO-8848 → 远海能源

这条链没有什么神秘算法。真正重要的是每条边都有稳定、明确的业务含义,系统不必临时让大模型猜“需要”“生产”“包含”是不是同一种关系。

这张图就是 Ontology 吗

还不能这么说。

Ontology 的经典解释是“对共享概念模型的形式化、显式说明”。翻成人话,可以拆成四个词:

  • 概念:这个领域里存在供应商、零件、工单、产品等对象;
  • 关系:工单需要零件,订单包含产品;
  • 规则requires 的起点应该是工单,终点应该是零件;
  • 共享:这些定义不是某个开发者脑中的临时理解,而是人和软件共同采用的约定。

有几个经常被混在一起的概念,可以先划一下边界:

概念主要回答的问题制造业例子
Taxonomy 分类体系谁属于哪一类轴承属于机械零件
Schema 数据模式一条数据长什么样工单必须有编号和状态
Knowledge Graph 知识图谱当前有哪些对象和关系WO-0312 需要轴承 A
Ontology 本体对象和关系意味着什么,哪些规则成立requires 连接工单与零件
Semantic Layer 语义层上层应用怎样用统一口径访问数据“准时交付率”的统一定义

边界并非绝对。实际项目中的知识图谱经常自带 Schema,语义层也可能使用 Ontology,轻量本体看起来甚至就是一棵分类树。这里不是为了争论术语,而是提醒自己:把节点和边存进图数据库,只说明数据成了图;业务含义有没有被认真建模,还得另说。

用三元组写下业务事实

语义 Web 体系常用 RDF 表达事实。RDF 的基本结构是三元组:

主语 Subject → 谓词 Predicate → 宾语 Object

例如:

WO-0312 → requires → 轴承 A

Turtle 是 RDF 的一种文本写法,比 RDF/XML 更适合人读。把前面的事实写出来,大概是这样:

@prefix mfg: <https://example.com/mfg/> .

mfg:eastPrecision
    a mfg:Supplier ;
    mfg:name "华东精密" ;
    mfg:provides mfg:bearingA .

mfg:bearingA
    a mfg:Component ;
    mfg:name "轴承 A" .

mfg:workOrder0312
    a mfg:WorkOrder ;
    mfg:orderNo "WO-0312" ;
    mfg:requires mfg:bearingA ;
    mfg:produces mfg:pumpP100 .

mfg:salesOrder8848
    a mfg:SalesOrder ;
    mfg:orderNo "SO-8848" ;
    mfg:contains mfg:pumpP100 ;
    mfg:placedBy mfg:oceanEnergy .

mfg:oceanEnergy
    a mfg:Customer ;
    mfg:name "远海能源" .

mfg:workOrder0312 是一个可唯一识别的资源,a mfg:WorkOrder 表示它属于生产工单类型,mfg:requires 则把它连接到轴承 A。这里的名称、编号和关系都可以追溯到原始系统,比只保存一段模型描述可靠得多。

三元组很灵活,但灵活也意味着容易失控。今天有人写 requires,明天有人写 needs,后天模型又生成 depend_on;“轴承 A”和 MAT-0018 被创建成两个节点,查出来的图很热闹,实际影响链却断了。

所以 RDF 负责表达事实,还需要 Ontology 规定这些词怎样使用。

用 OWL 给关系划出边界

OWL 是 W3C 定义的本体语言。一个最小版本可以先声明类和对象属性:

@prefix mfg: <https://example.com/mfg/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

mfg:Supplier   a owl:Class .
mfg:Component  a owl:Class .
mfg:WorkOrder  a owl:Class .
mfg:Product    a owl:Class .
mfg:SalesOrder a owl:Class .
mfg:Customer   a owl:Class .

mfg:provides
    a owl:ObjectProperty ;
    rdfs:domain mfg:Supplier ;
    rdfs:range mfg:Component .

mfg:requires
    a owl:ObjectProperty ;
    rdfs:domain mfg:WorkOrder ;
    rdfs:range mfg:Component .

mfg:produces
    a owl:ObjectProperty ;
    rdfs:domain mfg:WorkOrder ;
    rdfs:range mfg:Product .

mfg:contains
    a owl:ObjectProperty ;
    rdfs:domain mfg:SalesOrder ;
    rdfs:range mfg:Product .

这里的 domainrange 很容易被数据库经验带偏。它们在 OWL/RDFS 中首先承担推理语义,数据校验只是附带能力。

如果图中只有:

mfg:workOrder0312 mfg:requires mfg:bearingA .

结合上面的定义,推理器可以推出 workOrder0312WorkOrderbearingAComponent。如果错误地让一个客户 requires 某零件,系统也未必像数据库约束那样立刻拒绝;它可能推断这个客户同时还是一张生产工单。只有再声明两类互斥,才可能检测到逻辑不一致。

这是 Ontology 与传统 Schema 一个很关键的思维差异。OWL 通常采用开放世界假设:图里没有某个事实,只代表“目前不知道”,不能直接判定它为假。数据库业务校验更习惯封闭世界:必要字段没出现,就按不合格处理。

数据是否合格,交给 SHACL 来检查

如果我们真正想检查“每张生产工单至少需要一种零件”,SHACL 更直接:

@prefix mfg: <https://example.com/mfg/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

mfg:WorkOrderShape
    a sh:NodeShape ;
    sh:targetClass mfg:WorkOrder ;
    sh:property [
        sh:path mfg:requires ;
        sh:minCount 1 ;
        sh:class mfg:Component ;
        sh:message "生产工单至少需要一种有效零件"
    ] .

这段 Shape 会检查所有 WorkOrderrequires 至少出现一次,而且目标是 Component。工程上可以把它放进数据导入或发布流程,错误数据先进入隔离区,不要静悄悄污染整张图。

简单记一下分工:

  • RDF 负责写下事实;
  • RDFS/OWL 负责表达概念、关系及可推导语义;
  • SHACL 负责验证实际数据是否符合预期形状;
  • SPARQL 负责查询图中的事实和关系。

它们可以配合使用,但没有规定每个 Ontology 项目都必须把这套工具全上齐。很多业务只需要受控词汇、少量关系和数据校验,硬上复杂逻辑反而让团队没人敢改。

写一条查询,找出延期影响链

现在假设邮件解析模块已经把“轴承 A 延期”映射到统一资源 mfg:bearingA,接下来可以用 SPARQL 查询受影响对象:

PREFIX mfg: <https://example.com/mfg/>

SELECT ?workOrder ?product ?salesOrder ?customer
WHERE {
    ?workOrder mfg:requires mfg:bearingA ;
               mfg:produces ?product .

    ?salesOrder mfg:contains ?product ;
                mfg:placedBy ?customer .
}

查询路径完全显式:从需要轴承 A 的工单出发,找到工单生产的产品,再找到包含该产品的销售订单和下单客户。

这段代码可以用 Python 的 rdflib 跑起来:

from rdflib import Graph, Literal, Namespace, RDF

MFG = Namespace("https://example.com/mfg/")
graph = Graph()
graph.bind("mfg", MFG)

# 类型和名称
graph.add((MFG.workOrder0312, RDF.type, MFG.WorkOrder))
graph.add((MFG.workOrder0312, MFG.orderNo, Literal("WO-0312")))
graph.add((MFG.bearingA, RDF.type, MFG.Component))
graph.add((MFG.pumpP100, RDF.type, MFG.Product))
graph.add((MFG.salesOrder8848, RDF.type, MFG.SalesOrder))
graph.add((MFG.oceanEnergy, RDF.type, MFG.Customer))
graph.add((MFG.oceanEnergy, MFG.name, Literal("远海能源")))

# 对象之间的关系
graph.add((MFG.workOrder0312, MFG.requires, MFG.bearingA))
graph.add((MFG.workOrder0312, MFG.produces, MFG.pumpP100))
graph.add((MFG.salesOrder8848, MFG.contains, MFG.pumpP100))
graph.add((MFG.salesOrder8848, MFG.placedBy, MFG.oceanEnergy))

query = """
PREFIX mfg: <https://example.com/mfg/>
SELECT ?workOrder ?product ?salesOrder ?customer ?customerName
WHERE {
    ?workOrder mfg:requires mfg:bearingA ;
               mfg:produces ?product .
    ?salesOrder mfg:contains ?product ;
                mfg:placedBy ?customer .
    ?customer mfg:name ?customerName .
}
"""

for row in graph.query(query):
    print(
        row.workOrder.split("/")[-1],
        row.product.split("/")[-1],
        row.salesOrder.split("/")[-1],
        row.customerName,
    )

安装依赖后运行:

pip install rdflib
python ontology_demo.py

输出如下:

workOrder0312 pumpP100 salesOrder8848 远海能源

普通 SQL 当然也能完成这次查询。如果数据都在同一个关系模型里,关系稳定、维护团队一致,SQL 可能还是更省事的选择。Ontology 真正的价值,是把跨系统反复使用的对象、关系和规则从某条 SQL 里提出来,变成可共享、可治理、可被多种应用复用的语义资产。

LLM 和 Agent 在这条链路里做什么

有了 Ontology,大模型仍然得留着——两边擅长的问题不一样。

供应商可能在邮件里写:

A 型主轴轴承这周赶不上原计划,预计顺延三个工作日。

这段话没有物料编码,也不是规整表格。LLM 擅长从中提取候选实体、事件和时间:

{
  "event": "supplier_delay",
  "component_name": "A型主轴轴承",
  "delay_days": 3,
  "unit": "working_day"
}

但它不应该直接断言“A 型主轴轴承就是 bearingA”。更稳妥的链路是:

flowchart LR A[供应商邮件] --> B[LLM提取延期事件] B --> C[实体对齐与人工复核] C --> D[统一零件ID] D --> E[按Ontology查询影响链] E --> F[Agent生成处理建议] F --> G{权限与规则校验} G -->|通过| H[提交审批或执行动作] G -->|不通过| I[仅展示建议]

这条链路里每层各管什么:

  • LLM 处理自然语言和模糊表达;
  • 实体对齐把别名映射到统一业务对象;
  • 知识图谱保存可以追溯的实例和关系;
  • Ontology 约束允许使用的对象类型和关系;
  • 规则、权限与审批决定 Agent 能不能真的动手。

如果没有 Ontology,LLM 每次抽取都可能发明一套标签:part_ofPartOfbelongs_to 混在同一张图里。反过来,如果没有 LLM,非结构化邮件、维修记录和操作日志又要靠大量人工整理才能进入图中。

它们搭在一起比较合适:LLM 降低知识提取和本体维护的成本,Ontology 限制 LLM 自由发挥的范围。 一个擅长处理模糊,一个负责保留边界。

从“认识名词”走向“允许动作”

经典知识工程里的 Ontology 主要关心概念和逻辑语义。到了企业 Agent 场景,只让系统认识名词还不够,它迟早要面对动词:

对象:零件、工单、订单、客户
关系:工单需要零件,订单包含产品
状态:轴承预计延期三个工作日
动作:调整排产、切换供应商、通知客户
约束:谁能执行、谁来批准、结果写回哪个系统

Palantir 的 Foundry Ontology 就采用了这种更宽的产品化定义。除了对象、属性和链接,它还把 Action、Function、动态权限纳入同一个组织数字模型。用它的话说,语义元素是“名词”,动作和函数则提供“动词”。

这个思路对 Agent 很重要。前面在 Agent 的工具调用与任务规划 里重点处理的是“怎样调用”,Ontology 进一步追问“对什么对象调用、在什么约束下调用”。模型发现订单可能延期以后,可以生成三个方案,但“调整生产计划”“创建替代采购单”“通知客户”光有三个工具名称远远不够。系统还得知道:

  • 当前操作者有没有权限;
  • 动作需要哪些参数;
  • 哪些条件下必须审批;
  • 会修改哪些对象;
  • 最终写回 ERP、MES 还是 CRM;
  • 失败后如何回滚和审计。

不过需要分清语境:把数据、逻辑、动作和安全都称为 Ontology,是现代企业平台对概念的扩展,超出了 W3C OWL 对 Ontology 的原始定义范围。文章里可以借用这套思路设计 Agent,但没必要硬把所有工作流都塞进 OWL。

Ontology 解决不了哪些问题

Ontology 很容易被讲成企业数据的终极答案,真正做起来会发现,它先把许多原本藏着的问题暴露了出来。

最大的成本在达成共识,不在图数据库

销售认为“客户”是签合同的公司,售后认为实际使用设备的单位也是客户,财务只认可付款主体。它们未必有一个唯一正确的定义。

本体建模不是拍脑袋选词,得明确不同概念的边界、映射和适用场景。有时应该统一,有时应该保留 ContractPartyEndUserPayer 三种角色。过早把它们压成一个 Customer,反而会损失信息。

统一 ID 比画关系图更难

如果 MAT-0018bearing_a 和“A 型主轴轴承”没有可靠映射,再漂亮的 Ontology 也只能得到三个互不相识的节点。主数据、来源追踪、实体消歧和变更记录仍然要做,Ontology 不会自动修好脏数据。

本体也会过期

工艺变了,产品拆分了,组织调整了,原有关系就可能不再成立。本体需要版本、兼容策略、评审人和废弃流程。它更像一份持续演化的领域契约,设计完成那天也谈不上永久正确的"企业真理"。

推理能力越强,使用成本往往越高

OWL 可以表达比本文复杂得多的逻辑,但表达能力、可判定性和计算成本之间一直存在取舍。团队只需要类型继承和简单约束时,使用轻量词汇、SHACL 加普通查询往往更稳。不要因为工具支持某条逻辑公理,就把业务规则全翻译一遍。

LLM 生成本体只能作为草稿

让模型扫描文档并建议类、属性和关系很有用,直接把结果发布到生产图里则很危险。模型会把同义词拆成多个概念,也会把一段常见描述误当成永恒规则。领域专家仍要确认定义,数据工程师仍要核对来源,关键动作仍要保留人工审批。

什么场景值得做,什么场景先别做

Ontology 比较适合这些情况:

  • 多个系统对同一业务对象使用不同标识和定义;
  • 高频问题需要跨越多类对象和多跳关系;
  • 知识要被搜索、分析、规则引擎和多个 Agent 共同复用;
  • 结果必须可解释、可追溯,光给一个相似度远远不够;
  • Agent 将参与真实业务动作,需要统一的对象、权限和约束。

下面几种情况则可以先缓一缓:

  • 只是给一批文档做简单问答,向量检索已经够用;
  • 数据仍在频繁改表,连核心业务对象都没有稳定下来;
  • 没有领域专家参与,只准备让开发者或大模型猜定义;
  • 主数据和唯一标识尚未治理,却希望靠知识图谱自动消除重复;
  • 业务只是单库里的简单 CRUD,SQL 和数据字典完全可以覆盖。

判断标准跟数据量大小关系不大。真正要问的是:同一批业务含义是否正在被不同系统、团队和 Agent 反复解释,而且这些解释不一致已经产生了真实成本。

别从企业级大图开始

如果真要落地,我不建议第一天就开会设计“全公司的 Ontology”。这种项目很容易花几个月争论顶层分类,最后没有一个业务问题因此得到更好的答案。

更实际的路径是:

  1. 选一个高价值问题:例如零件延期会影响哪些客户订单;
  2. 只列核心对象:先控制在 5~10 种,覆盖整个制造业是后面的事;
  3. 定义少量稳定关系:每条关系都要能说清来源、方向和业务含义;
  4. 统一实例标识:保留各系统原始 ID,并建立可审计的映射;
  5. 写出一个可验证查询:结果由领域人员核对,不先谈“智能涌现”;
  6. 接入一个受控动作:先生成建议或审批单,再考虑自动执行;
  7. 用失败案例修订模型:记录缺失关系、错误映射和版本变化。

本例里甚至可以不用专门的图数据库。数据量不大时,rdflib、关系数据库或支持图查询的现有平台都能完成验证。等到关系遍历、跨域集成和图算法真的成为瓶颈,再做存储选型也不迟。

结语

回到开头那封供应商邮件。

LLM 可以读懂“轴承要晚三天”,RAG 可以把邮件找回来,数据库保存工单和订单,知识图谱把具体对象连起来,而 Ontology 负责说明这些对象为什么能这样连接、关系意味着什么、哪些推断和动作可以被接受。

它们更像一组分工不同的零件,各自解决不同环节的问题。少了 LLM,非结构化信息很难进入系统;少了可靠数据,Ontology 只剩一张空架子;少了明确语义,Agent 则可能拿着一堆正确数据,做出一个逻辑流畅的错误决定。

以前,系统只要把数据存对。现在,当 Agent 开始替人查数据、下判断甚至执行操作,我们还得把“这个业务世界究竟是怎样的”说清楚。

参考资料

版权声明: 本文首发于 指尖魔法屋-AI时代的数据本体:从一张订单到Ontologyhttps://blog.thinkmoon.cn/post/1037-ai-data-ontology-manufacturing-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!