AI 为什么算不对你还剩几天年假:把本体真正用起来
上一篇概念篇讲了本体是什么:把一个团队对业务世界的共识,写成机器能读、能推理的说明书。这一篇讲怎么用起来。
这一篇拿 AWS 开源的 Context Ontology Accelerator(下称 COA)当教材,它把本体从建模到服务 agent 的整条链路都实现了。先交代清楚:文中的公司和人(安源科技的员工陈思远)是虚构的演示例子,数字也来自演示环境,用来说明机制,不是我的实测。例子是假的,机制是真的。
主线案例是员工年假。陈思远打开 HR 系统,看到剩余年假八天,他提交了五天的申请,被 HR 退了回来。原因写在员工手册里:可申请天数等于总额度,减去已用天数,再减去还在审批中的天数。总额度 12 天,已用 4 天,待审批 3 天,系统显示的「剩余」没扣待审批,所以是八天;按制度,他只能再请五天。我们要搭的,就是一个能把这五天算对的问答助手。
一、字段没错,数据没错,错在没人告诉它口径
如果让 AI 助手来回答「我还能请几天年假」,它很可能直接读数据库里叫 remaining_days 的那一列,然后很自信地告诉你:八天。
字段没错,数据也没错,错在没人告诉它这个字段的业务含义。企业数据里表结构看不出来的东西,可以归成三样:
| 看不见的东西 | 在这个案例里 |
|---|---|
| 口径 | 剩余天数到底扣没扣待审批 |
| 关系 | 审批人其实也是一名员工 |
| 边界 | 谁能看哪些数据 |
本体就是把这些写下来、让机器读得懂的那份说明书:像一本词典,统一「员工、同事、staff」这些叫法;像一张地图,标出概念之间的关系;也像一本规矩,写明约束和口径。
剩下的问题是成本。给几百张表手工写本体,这是很多团队望而却步的原因。COA 的思路分三步:AI 先起草,人来审核,审核过的本体再交给 AI agent 使用。
二、一张表怎么变成本体
COA 的工作流分三段:scan 接入,把数据库和文档接进来;model 建模,归纳出本体、定义指标;serve 服务,回答人和 agent 的问题。底层是几个 AWS 服务:Neptune 存本体和语义图,OpenSearch 做向量检索,Athena 直接用 SQL 查数据,Bedrock 提供模型推理,agent 通过 MCP 接入。
scan 阶段,COA 读取数据库的表结构,用大模型给每张表、每一列补上业务描述和同义词,还会推断表与表之间的外键;文档则被切成小块,抽取实体和事实,建成一张文档图谱。
到 model 阶段,一张表怎么变成一个类?转换规则是确定性的,不靠大模型发挥:
| 数据库里 | 本体里 |
|---|---|
| 一张表 | 一个类 |
| 普通列 | 数据属性 |
| 外键列 | 对象属性,指向另一个类 |
| 主键 | 唯一标识 |
| 不能为空的列 | 至少有一个值的约束 |
这里有个巧妙的设计:同一个关系写两份。本体里写它「是什么」,比如年假余额属于某位员工;映射文件里写它「怎么算」,比如用 employee_id 这一列去关联员工表。映射有 W3C 标准,叫 R2RML。
最反直觉的一点:本体里只有结构,数据不搬家。陈思远那一行记录始终留在原来的数据库里,查询时系统根据映射,把对本体的提问临时翻译成对原表的 SQL。这套机制叫虚拟知识图谱。模型先针对本体写查询,用的是 SPARQL,一种面向图数据的标准查询语言,好处是可以直接用「签约客户」这样的业务概念提问。翻译由一个叫 Ontop 的开源引擎完成:它拿到 SPARQL 查询后,按映射把每个类、每个属性换成对应的表和列,把条件拼成 join,得到一条意思完全相同的 SQL。COA 里有个值得注意的细节:Ontop 只翻译不执行,它连的是一个只有表结构、没有数据的空库,碰不到任何业务数据。
三、AI 起草,人来把关
scan 阶段最值得展开的,是 AI 补元数据时犯的错。
打开年假余额表,AI 已经给每一列写好了描述和同义词,推断的外键(employee_id 指向员工表)置信度 99%。仔细看 remaining_days 这一列,AI 写的口径是「总额度减已用再减待审批」。听起来非常合理,可是错了:这个系统的剩余天数只扣了已用,没扣待审批。这正是开头那个八天的来源。
这个细节我盯着看了很久。AI 猜口径的方式,和真实系统里口径 bug 的成因一模一样:从表名列名出发,猜一个最合理的业务含义,猜错了也不报错。所以「人审核」这道工序不能省,它是这条链路里唯一能纠正口径的环节。数据管理员把描述改成真实口径,注明出自手册哪一条,再加上「剩余天数」这样的中文同义词,保存并批准。
归纳本体时还有一步对齐:把新生成的类拿去和 schema.org 这类公共本体比对,看有没有现成的概念可以挂靠。以员工表为例:向量检索召回十个候选,employee role 以 0.72 分排第一,其余都在 0.44 上下,一眼就是噪音(有医学实验设计,有性别类型)。所以向量只负责召回,判断领域是否一致、给出理由的是大模型,拿不准的标成待确认交给人。年假余额这种 HR 特有的概念,公共本体里没有,就标成新概念。对齐不能只看名字:保险业里的 policy 是保单,schema.org 里的 policy 却是政策规范,同名不同义,要靠语义判断分开。
发布之前还有一道一致性检查,工具叫 HermiT,牛津大学开发的开源 OWL 推理机。可以把它理解成本体的编译器:它不看业务数据,只看类、属性和约束,按逻辑把所有推论走一遍,找出自相矛盾的定义。比如本体里既声明实习生是正式员工的一种,又声明实习生和正式员工互斥,那实习生这个类就不可能有任何成员,这叫不可满足的类,HermiT 会把它报出来。校验结果只做参考,是否接受提案仍然由人决定。
四、指标:把公式固定下来
本体说清了「有什么」,指标说清「怎么算」。
在 COA 里新建一个指标「可申请年假天数」,计算只差这一步:
1 | SELECT total_days - used_days - pending_days |
再填上同义词,比如「还能请几天年假」;写一句给 AI 的说明:不要直接用 remaining_days;最后把它关联到本体里的年假余额类。以后不管谁来问、用什么说法,只要命中这个指标,用的都是同一个口径。
五、一次提问的旅程
工具搭好了,看它回答真实问题的过程,包括怎么踩坑。
第一问:「研发中心有哪些员工的年假还在待审批?审批人是谁?」生成的 SQL 结构完全正确,三张表关联,审批人还专门又连了一次员工表。可结果是零行。问题出在一个小细节:数据库里年假存的是英文代码 ANNUAL,模型猜成了中文的「年假」。本体里缺了一样东西:这一列有哪些合法取值。补上很简单,在列的描述里写明取值,再归纳一次。
有意思的是第二次归纳:四张老表精确匹配到了上一版本体,只有新加的加班记录表被当成新概念。本体就是这样一板一板增量生长的。
再问一次,SQL 用上了 ANNUAL 和 PENDING,答案出来了。回到最初那个问题:「EMP3105 还能申请几天年假?」这次答案是五天,引用了手册里的计算公式,还解释了系统显示的剩余天数为什么偏大。打开执行轨迹能看到它的思路:先查本体,弄清有哪些概念和关系;判断这是个结构化的数值问题;转成 SQL 查到一行数据;再检索手册条款做印证;最后综合作答。
改写出来的 SQL 不会直接执行。先过权限检查,确认这个人能查这个空间;再过 SQL 防火墙,只允许只读查询,只放行白名单里的表,屏蔽黑名单里的列。
六、交给 Agent:指标先于模型
对 AI agent 来说,COA 是一个 MCP 服务器,提供六个工具:列出指标、描述本体、端到端问答、自然语言转 SPARQL、文档检索、图遍历。
接一个支持 MCP 的客户端(比如 Claude Code)到 COA 上,问同一个问题「EMP3105 还能申请几天年假」。agent 先调用 list_metrics,发现有一个现成的「可申请年假天数」指标;再调用 query,把员工编号作为维度参数传进去。这一次走的是第一层,直接执行治理指标,返回五天。执行轨迹只有四步:匹配指标、权限检查、SQL 防火墙、执行。大模型全程没有自己写 SQL。
同一个口径,playground 里问、agent 问、报表里取,拿到的都是同一个数。
再问一个要把数据和制度串起来的问题:「EMP3105 下周去北京出差,酒店每晚最多能报多少?」agent 先查到他是 P5、常驻上海,再检索差旅制度:北京是一类城市,P4 到 P6 每晚上限 600 元。它还顺带核对了一条前提:常驻上海,去北京才算出差。
值得注意的顺序:agent 拿到问题先查有没有现成的治理指标,命中就直接用。指标是人审核过、公式固定的答案,能命中就不该让模型现场发挥。权限方面,每次调用都以登录用户的身份做权限检查,agent 自己的身份只用来记审计日志,它能看到的不会超过它背后的人。
七、如果要落地,清单在这里
把这两篇里的机制合起来,我整理出六条实践清单:
- 从小处开始。不要一上来就想建全公司的本体,先挑一个高价值的领域,比如客户和收入,把它做深做准。过度建模是新手最常犯的错误之一。
- 准备一组展示问题。从真实业务里挑几十个有代表性的问题,写好标准答案。它既是验收标准,也是回归测试:每次修改本体、映射或指标都重新跑一遍,看准确率有没有下降。
- 增量接入数据。先用映射把现有数据源虚拟化,不急着搬进图数据库;只有推理或跨域整合真正需要时,再把那一部分物化下来。
- 治理从第一天开始。本体要有版本和审批流程,草稿和生产分开,随时可以回滚;大模型可以起草、可以建议映射,但每一次变更都要有人审核。
- 重视可观测和可解释。记录每次查询走了哪一层、用了哪些概念、耗时多少,回答里附上引用和推理链。用户看得到依据,才会信任结论。
- 尽量用开放标准。RDF、SPARQL、R2RML 这些 W3C 标准,避免被某个工具锁定。
回到开头。陈思远的五天能被算对,靠的不是更聪明的大模型,而是三件事:人把口径写进了本体,指标把公式固定了下来,查询时有确定性的闸门把关。
如果你的系统里也有一个「显示八天、实际只有五天」的字段,那就是你的本体该开始的地方。
参考
- 概念篇:面试官问什么是本体,我没答上来:补完课聊聊模型缺的那张地图
- AWS Context Ontology Accelerator:github.com/aws/context-ontology-accelerator




