给数据智能体装一个会自己长大的语义大脑:EvoOntology 论文解读

你有没有遇到过这种场景:让一个 AI 智能体去查公司的数据,问它"上个月成本为什么涨了",然后你就看着它开始瞎摸——先 SELECT * 几张表,发现列名是 cst_amt_mtd 这种天书,猜错了再换一张,来回十几轮,最后给你一个看起来挺像回事但其实张冠李戴的答案。

数据在智能体外面,智能体只能通过 SQL 接口、文件读取器这类通用工具去够它。中国人民大学数据工程实验室(ruc-datalab)刚挂出来的这篇 EvoOntology(arXiv:2609.15779),就是冲着这个痛点来的。说实话,读完我挺兴奋的——不是因为它涨了多少点,而是因为它把一个大家一直在凑合的事情,做成了一个正经的系统组件。

核心摘要:数据智能体处理异构数据(表格、CSV、数据库、文档)时面临一个结构性矛盾——数据在体外,语义在脑外,智能体只能盲目探索。EvoOntology 的思路是:在智能体和原始数据之间插入一个自进化本体层,封装成 MCP server,让智能体在运行时主动 browse/resolve 查询语义,而不是把整个语义层塞进 prompt。更关键的是,这个本体不是人工写好就完事的——它由 builder agent 自动构建,再通过"轨迹归因 → 类型化修补 → 配对验证门控"的循环持续进化,而且每个 LLM backbone 独立进化出自己的本体。结果相当能打:DDR-Bench 上 Trajectory-Wise 准确率平均提升 17.8 个点,BIRD 上 EX 平均提升 7.4 个点,同时每任务轮次从 14.6 降到 8.4,总 token 成本反而降了约 20%。这不是又一篇"加个知识库就变强"的论文,而是一套有完整消融支撑的方法论。


论文信息

  • 标题:EvoOntology: A Self-Evolving Ontology Layer for Data Agents
  • 作者:Meiduo Chong, Shaolei Zhang(通讯作者), Ju Fan, Xiaoyong Du
  • 机构:Renmin University of China(中国人民大学)
  • 链接:https://arxiv.org/abs/2609.15779 | 代码:https://github.com/ruc-datalab/EvoOntology

🎯 问题:智能体和数据之间隔着一条"语义鸿沟"

论文把这个痛点叫 agent-data gap(智能体-数据鸿沟)。你想想看,企业里的数据长什么样:关系数据库里几百张宽表,列名是 fact_cost_month_id 这种缩写;CSV 文件里字段含义全靠猜;文档里躺着业务规则(比如"GAAP 收入确认口径");图表和日志又是另一套格式。

智能体拿到一句"为什么上月成本涨了",它既不知道"成本"对应哪张表哪一列,也不知道"涨"该跟谁比、按什么口径算。现有的路子就两条,而且都不好走:

路线 做法 问题
原始查询(Raw querying) 让智能体直接探索 schema、发探测性 SQL 小数据还行,宽表+异构源直接爆炸,智能体陷入低效循环
静态语义层(Semantic layer) 人工构建元数据/指标层,塞进 prompt 上下文长度装不下;人工维护成本高;写死了,不随智能体行为适配

第二条路其实工业界一直在做——dbt 的 Semantic Layer、Cube、AtScale 这些,去年开始也纷纷推出 MCP server(dbt 的 MCP Server 在 2025 年底已经 GA)。但它们的共同点是:语义层是静态的、人工维护的,和智能体实际怎么使用这些语义完全脱节。智能体用着用着发现某个概念映射错了,语义层不会自己改。

这就是 EvoOntology 要补的位。

Figure 1:有无本体层的对比

Figure 1:左边是没有本体层的数据智能体——面对表格、CSV、文档、数据库、图表、日志等异构数据源,只能盲目探索(Blind Data Exploration),语义不确定性极高;右边是加上自进化本体层之后,智能体通过 ontology interaction 与本体层交互,本体层内部运行着 Diagnose(诊断轨迹)→ Attribute(归因到 Content/Tool/Schema 层)→ Patch(生成候选更新)→ Evaluate(父代 vs 候选对比评估)的进化循环,实现有语义接地的数据理解。


🧠 方法:一个三层本体 + 两个 MCP 工具 + 一条进化循环

EvoOntology 把演化第 \(t\) 轮的本体状态形式化为 \(\mathcal{L}_t = (\mathcal{S}_t, \Gamma_t, \mathcal{R}_t)\),三个字母对应三层:

  • Content Layer\(\mathcal{S}_t\),内容层):一个类型化语义图,装的是实际的语义内容
  • Schema Layer\(\Gamma_t\),模式层):定义内容层的"对象模型"——有哪些节点类型、允许哪些关系
  • Tool Layer\(\mathcal{R}_t\),工具层):运行时接口,决定智能体怎么访问这个本体

这个三层分离的设计挺讲究。部署时,智能体只检索当前步骤需要的那部分语义;进化时,演化智能体每次只改有界的一部分状态。不会出现"改了一个概念定义,整个语义层要重新灌进 prompt"的灾难。

Content Layer:四类节点、两类边

内容层是核心,节点分四族:Terms(领域概念,如 Cost、Revenue)、Mappings(把概念接地到具体的字段和链接路径,比如 fact_cost.cost_amount)、Constraints(约束概念的有效使用方式,比如"收入必须按 GAAP 口径")、Evidence(支撑语义声明的证据,比如数据采样)。

边有两类:Semantic Relations 连接概念之间(association、hierarchy、composition、equivalence、derivation 五种),Structural References 把概念链接到映射、把约束和证据挂到它们管辖的对象上。

为什么搞得这么重?后面的消融实验会告诉你答案——Mappings 和 Evidence 这两族拿掉之后性能直接崩掉。每个语义条目必须锚定在真实数据的探测结果上,而不是一句自然语言描述。这个设计决策是有代价的,但值。

Tool Layer:manifest 是唯一进 prompt 的东西

工具层通过 MCP server 暴露两个工具加一个会话清单:

接口 签名 干什么
browse \(f_{browse}(q, k, n)\) 按查询 \(q\) 和类别 \(k\) 检索 top-\(n\) 语义匹配
resolve \(f_{resolve}(\mathcal{I}, c)\) 返回请求的记录及其链接对象
manifest 会话初始化时给一份紧凑的来源和使用说明

注意第三点:manifest 是唯一被放进 prompt 的本体内容,其余全部按需检索。这就绕开了静态语义层"塞不下、塞多了干扰"的死结。说到 MCP,这个 Anthropic 2024 年底提出、2025 年 12 月捐给 Linux 基金会旗下 Agentic AI Foundation 的协议,现在已经是智能体接工具的事实标准了——EvoOntology 选 MCP 作为封装形态,所以任何兼容 MCP 的客户端都能即插即用,这个工程决策很聪明。

Figure 2:EvoOntology 总览

Figure 2:EvoOntology 全景。左侧是部署态:数据智能体一手拿着数据执行工具(Execute SQL、Execute Python),一手拿着本体交互工具(browse、resolve),在本体层的语义指导下与异构数据源交互。中间是构建态:builder agent 从工作负载查询中提取候选概念(如从"Why did cost rise last month?"提取 Cost 和 Time),在真实数据上探测接地(比如发现 cost 表的结构和值分布),然后构建出三层本体并暴露为工具。右侧是进化态:演化智能体从历史轨迹中诊断失败(比如"按渠道看成本"失败,归因到 Tools 层缺少 Add Filter 或 Content 层缺货币换算),生成候选补丁,经评估门控后才接受。

Builder Agent:不看答案,只看数据和工作负载

初始本体怎么来?builder agent 从训练工作负载 \(\mathcal{W}\) 和原始数据源 \(\mathcal{D}\) 出发,分两步:

一步是工作负载引导的探测:从反复出现的实体、指标、分析条件里提出候选概念集 \(\mathcal{C} = \text{propose}(\mathcal{W})\),然后对每个候选发探测查询 \(\text{probe}(c, \mathcal{D})\),去看候选字段的类型、值分布、语义一致性。

另一步是证据接地的提交:只有通过验证的候选才会进本体:

\[\mathcal{C}^+ = \{c \in \mathcal{C} \mid \text{verify}(\text{probe}(c, \mathcal{D})) = 1\}\]
\[\mathcal{S}_0 = \text{construct}(\mathcal{C}^+, \mathcal{D}; \Gamma_0)\]

这里有个细节我很喜欢:builder 不观察 gold answers。它只看"用户都在问什么"和"数据里到底有什么",不看正确答案。这避免了本体构建阶段就泄题。

Self-Evolution Loop:三步循环加一个硬门控

数据接地只保证本体"贴合数据",不保证"贴合这个智能体"。GPT 和 Claude 用同一个语义层,踩的坑可能完全不一样。所以进化循环用历史轨迹作为行为证据,分三步走:

一步:轨迹归因(Trajectory Attribution)。演化智能体分析历史轨迹 \(\mathcal{T}_t\),提取复发性失败签名 \(\Sigma_t = \text{analyze}(\mathcal{T}_t, \mathcal{L}_t)\),然后把每个签名归因到三个层级之一:\(\alpha: \Sigma_t \to \{C, T, S\}\)——是内容缺了、工具不好使、还是模式层表达力不够?

二步:局部干预(Localized Intervention)。对归因签名 \(\sigma\) 生成候选补丁 \(\mathcal{L}'_t = \text{patch}(\mathcal{L}_t, \sigma, \alpha(\sigma))\)。关键约束:每个候选只改一个层级。Content 干预增删改语义对象,Tool 干预改工具,Schema 干预改对象模型。

三步:骨干条件配对验证(Backbone-Conditional Paired Validation)。这是整个循环的承重墙。对 backbone 模型 \(m\),候选和父代在同一个验证集同样的解码配置和交互预算下对比评估,只有改进达到边际 \(\tau\) 才接受:

\[\mathcal{L}_{t+1} = \mathcal{L}'_t \quad \text{若} \quad \phi(\mathcal{L}'_t, \mathcal{V}; m) - \phi(\mathcal{L}_t, \mathcal{V}; m) \geq \tau\]

否则回滚,被拒的候选连同签名一起记录,防止反复踩同一个坑。而且所有 backbone 从同一个初始状态 \(\mathcal{L}_0\) 各自独立进化——这一点后面会看到,直接导致了不同 backbone 进化出相当不同的本体。

评估协议也值得一提:reciprocal two-fold,每个 benchmark 分成不相交的 A、B 两折,A 的 70% 用于构建和进化、30% 用于配对验证,冻结后在 B 上测试;然后反转两折再跑一遍取平均。held-out 折的答案绝不参与进化。这套流程在防止过拟合验证集上是认真的。


📊 实验:三个 benchmark、六个 backbone,提升全线为正

实验覆盖三个风格迥异的 benchmark:

Benchmark 任务 指标
DDR-Bench 跨异构源的开放式数据研究(10-K 财报场景) Message-Wise / Trajectory-Wise 准确率
InsightBench 商业分析洞察生成 Insight / Summary 分数
BIRD text-to-SQL(官方 Oracle Knowledge 设置) EX / VES

backbone 有六个:GPT-5.5、GPT-5.6-sol、Claude-Sonnet-5、Claude-Opus-4.8、DeepSeek-V4-Flash、Qwen3.5-Flash。所有条件用同一套 ReAct scaffold、同样的数据工具、解码配置和交互预算——对照做得干净。

DDR-Bench:主战场,提升最猛

DDR-Bench 是最能体现本体价值的场景——多源异构、长程研究。结果(Overall 列是相对 Baseline 的提升):

方法 Backbone Msg-Wise ↑ Traj-Wise ↑ Overall ↑
Baseline GPT-5.6-sol 64.0 68.5 66.3
Baseline + SL GPT-5.6-sol 62.5 65.5 64.0(−2.3)
EvoOntology GPT-5.6-sol 78.2 93.5 85.9(+19.6)
Baseline Claude-Opus-4.8 74.0 73.0 73.5
Baseline + SL Claude-Opus-4.8 65.9 71.4 68.6(−4.9)
EvoOntology Claude-Opus-4.8 78.0 92.3 85.2(+11.7)
Baseline DeepSeek-V4-Flash 26.2 30.3 28.2
EvoOntology DeepSeek-V4-Flash 37.5 52.3 44.9(+16.7)

全部六个 backbone 的 Trajectory-Wise 都提升,平均涨幅 17.8 个点,从 Qwen3.5-Flash 的 +4.8 到 GPT-5.5 的 +26.7。GPT-5.6-sol 的 Traj-Wise 干到 93.5,这个数相当能打。

但更值得说的是对照组的翻车:静态语义层(Baseline + SL)在多个强 backbone 上是负收益——Claude-Sonnet-5 的 Traj-Wise 直接掉 15.0 个点。这验证了我开头说的判断:把语义层当静态 prompt 片段硬塞,不但帮不上忙,还会分散注意力。EvoOntology 论文里最值钱的其实不是"本体有用",而是这个对比——同样的语义内容,静态塞和运行时按需查,效果天差地别

还有个对照很有意思:跟 memory 路线比(ReAct + Memory,把历史轨迹存成可检索的 episodes 注入 prompt),四个 backbone 平均 Traj-Wise 是 69.5(Baseline)→ 75.8(+Memory,+6.3)→ 89.5(EvoOntology,+20.0)。差距在哪?episodic memory 只能重放"上次怎么做的",不暴露类型化、可组合的语义结构。记忆是录像,本体是地图。

InsightBench 与 BIRD:增益小一些,但方向一致

InsightBench 上平均增益只有 1.9 个点(最大的 DeepSeek-V4-Flash +6.1)。论文的解释挺坦诚:Insight 按简短参考式发现评分,对齐参考后就饱和了,语义层能发挥的空间有限。我觉得这个结果是诚实的——不是每个任务都需要重语义,单 CSV 的商业分析本来就偏浅层。

BIRD(text-to-SQL)上 EX 平均涨 7.4 个点、VES 平均涨 8.6 个点,Claude-Opus-4.8 的 EX 从 67.5 到 78.3(+10.8)。对照组又翻车了:Baseline + SL 在 GPT-5.5 上 EX 掉了 5.6 个点,但 VES 全线上升——静态语义层让 SQL 写得更规范(VES 高),却干扰了生成正确查询(EX 低)。这个分裂现象本身就很说明问题。

消融:两个承重部件,两个承重对象族

消融实验做得相当扎实,三个维度都值得看。

进化循环四步消融(DDR-Bench,四 backbone 平均,完整循环 89.5):

变体 Traj-Wise ↑ Δ
完整循环 89.5
去掉 Gate(照单全收) 78.3 −11.2
去掉 Attribution(不归因层级) 83.2 −6.3
去掉 Diagnose(随机采样轨迹) 84.7 −4.8
去掉 Patch(自由形式重写) 87.8 −1.7

看到 w/o Gate 掉 11.2 个点 的时候我一点都不意外——没有门控的自动进化就是耍流氓,未过滤的坏补丁会引入后续轮次都撤不回的退化。这跟在线学习系统里"没有灰度验证的全量推送"一个道理。Attribution 掉 6.3 个点也说明:知道"该改哪一层"这件事本身就有信息量,乱改一气不行。

三层编辑消融:Content-only +8.7、Tool-only +13.2、Schema-only +3.6,全三层 +20.0。Tool 层是单层里最大的杠杆(跟附录里"Tool 级编辑只占总轮次的少数但贡献了 57% 的增益"一致),但三层互补、缺一不可。

对象族消融:去掉 Mappings 掉 13.4 个点,去掉 Evidence 掉 8.7 个点,而 Constraints 和 Relations 只掉 3.5 和 2.1。承重的是"概念接地到数据"和"证据支撑声明"这两族——这就是为什么这个本体必须重。

最反直觉的发现:每个 backbone 都该有自己的本体

Figure 5 这组分析是我个人觉得全文最有意思的部分。

Figure 5a:跨 backbone 的 Term 集合 Jaccard 重叠

Figure 5a:四个 backbone 从同一初始本体独立进化后,各自接受的 Term 标识符集合的成对 Jaccard 重叠。对角线为 1.00,非对角线全部不超过 0.62——两个 Claude 之间 0.55,两个 GPT 之间 0.61,跨家族更低至 0.56。同一家族的模型进化出的本体更相似,但即便如此也远未收敛到同一个。

Figure 5b:跨 backbone 迁移矩阵

Figure 5b:把某个 backbone 上进化好的本体直接拿给另一个 backbone 用的效果。行是本体在谁身上进化的,列是部署给谁用。对角线(自产自用)一律最高:GPT-5.5 90.9、GPT-5.6-sol 93.5、Sonnet-5 81.3、Opus-4.8 92.3;非对角线全面下跌,最少也掉 6.6 个点,GPT-5.5 进化出的本体给别人用平均掉 10.9 个点。

两组证据合起来说明一件事:不同 LLM 与数据的交互模式真的不一样,进化出的语义层也真的不一样,而且这个差异是有性能后果的。给 GPT 进化出的本体,Claude 用着就是不顺手。

这直接打脸了"构建一份通用语义层给所有模型用"的思路——包括 dbt Semantic Layer 这类工业方案的基本假设。当然反过来说,这也是 EvoOntology 落地时最大的成本:每换一个 backbone,就得重新跑一遍进化循环。

成本:更准,还更便宜

附录里的成本表值得单独拎出来:每任务轮次从 14.6 降到 8.4,总 token 从 52.6K 降到 42.0K(约省 20%),同时 Traj-Wise 从 69.5 涨到 89.5。输入 token 每轮其实涨了(3.2K → 4.6K,因为要查本体),但轮次砍了一半——智能体不再瞎摸,该查哪张表一上来就知道。这个 trade-off 非常划算。

一个具体的进化案例

Figure 8:card-legality 任务的本体进化

Figure 8:一个卡牌合法性查询任务的本体进化实例。初始本体 \(L_0\) 里有通用的 Card 和 Legality 概念及映射,但没有对"合法性状态码"的显式解释。进化后(\(L_4\),红框标注):新增了 Legality Status Code 这个 Term、它的 Mapping 和 Evidence,以及一条 Constraint——把状态值和请求的输出格式关联起来。补丁是 typed 的、局部的、带证据的,而不是整页重写。


🤔 我的判断

这篇论文最值钱的地方,在我看来不是那 17.8 个点,而是它把三件事同时做实了:

其一,把语义层从"prompt 素材"变成"运行时服务"。Baseline + SL 的负收益对照是全文最有说服力的实验——同样的语义内容,塞 prompt 里反而掉点,按需检索就大涨。这个结论对所有在做"把企业知识灌给 agent"的团队都有警示意义:上下文窗口不是越大越好用,语义消费的方式比语义本身更影响效果。

其二,backbone-conditional evolution 这个发现是真的反直觉。大家默认语义层应该是模型无关的——业务定义还能因为换个模型就变了吗?论文用 Jaccard 重叠和迁移矩阵告诉你:会。因为语义层服务的不只是"数据是什么",还有"这个智能体怎么用数据"。这个洞察往大了说,对所有 agent memory / context engineering 的工作都适用。

其三,Gate + Attribution 的方法论可以直接搬走。不管你是不是做数据智能体,只要你在做"让系统从历史轨迹中自动改进某个组件",这个"归因定位 → 类型化局部补丁 → 配对验证门控"的骨架都值得抄。消融数据告诉你哪根梁承重。

但问题也得说清楚:

评估的有效性依赖验证集质量。门控机制说到底是在验证集上做 A/B 测试,验证集和真实分布偏离多少,进化就可能跑偏多少。论文用 reciprocal two-fold 缓解了一部分,但 \(\tau\) 的选取、验证集规模的敏感性都没展开讨论。

每 backbone 独立进化是把双刃剑。性能上是对的,工程上等于 N 个 backbone 就要维护 N 份本体,加上每份的进化历史。对于一个频繁换模型的团队,这个维护成本不低。有没有可能进化出一份"主干本体 + backbone 特化的增量层"?论文没答。

弱 backbone 的天花板仍然明显。Qwen3.5-Flash 加了本体也只有 20.1 的 Overall。本体层能弥补语义探索的低效,但弥补不了推理能力本身的差距。这不是论文的问题,是提醒读者别误读增益的普适性。

另外有个地方我没完全看懂:论文摘要里说四个 backbone,实验设置里实际列了六个,分析章节又用四个(两个 GPT、两个 Claude)。可能是分析章节为了控制成本只跑了子集,但行文上这个小不一致让人读的时候愣了一下。

跟同期工作比,位置在哪?

语义层 + MCP 的组合,工业界(dbt、AtScale、ThoughtSpot、Looker)已经在做了;agent 自动构建语义层,也有一些 LLM 诱导 schema 描述的前置工作。EvoOntology 的真正增量在自进化——而且是带门控、带归因、backbone 条件化的进化。跟 memory 路线(Reflexion、Voyager)比,它存的是结构而不是轨迹。我认为它属于"工程整合 + 方法论创新"那一档:底层单点技术都不算全新,但组合出的系统形态和 backbone 特异性的实证发现,是有真实信息量的。


如果你正在做数据智能体、ChatBI 或者任何"让 agent 操作企业数据"的系统,这篇论文有三个可以直接拿走的东西:语义层做成 MCP 服务按需查,别塞 prompt;任何自动进化的组件,先配上门控和归因;别指望一份语义层伺候所有模型。开源代码在 GitHub(ruc-datalab/EvoOntology),值得拉下来跑一遍。

而那个更本质的问题还悬着:当本体可以自进化,"语义的真相"到底由谁裁决?验证集是今天的代理,但业务口径是会变的——本体的进化速度能不能跟上业务语义本身的漂移?这可能是下一篇论文的事。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我