本体、RAG、Function Calling:三种技术是互斥的还是互补的?
有一个问题在企业 AI 项目里反复出现,表述不同但意思一样,我们已经在用 RAG 了,还需要本体吗?引入 MCP 之后,本体还有必要吗?选了 Function Calling,RAG 是不是就多余了?
这类问题背后有一个共同的假设,这几种技术在竞争同一个位置,选了一个就不需要另一个。这个假设是错的,而且错得很有代价。基于这个假设做技术选型的项目,通常会在某个维度上留下一个没人负责的空缺,等到问题暴露时,已经是生产环境里的故障。
先把问题说清楚
一个 Agent 接到任务,比如"帮我查上个月 A 仓库出库超过 500 件的商品,整理成表格",在得出结果之前要经历三件事。
- 搞清楚去哪里找数据,用什么操作,带什么参数。"A 仓库"在系统里是什么代码?"出库记录"存在哪张表?查这张表用哪个接口?接口需要传哪些参数,每个参数的格式是什么?这些信息用户没有提供,任务描述里也没有,Agent 需要自己找到。
- 真正地执行操作,调用接口,拿到数据。
- 判断拿到的数据对不对、任务算不算完成,然后决定是输出结果还是继续下一步。
三种技术分别作用于这三件事的不同环节。混用的根本原因,是把不同环节的问题当成了同一个问题。
RAG 在做什么
RAG 解决的是第一件事里的一个子集,AI 缺少某些背景知识,通过检索文档或其他外部材料来补充。
这类知识可以是业务规则(出库单审批需要哪个层级的经理签字),可以是数据字典(各仓库的编码和名称对照),可以是历史数据(A 仓库过去几个月的出库量均值)。这些信息可以写成文档,可以向量化存储,可以在推理时检索出来拼入上下文。
但注意 RAG 补充的知识的特点,它通常是陈述性的事实,是可以用文字描述的背景信息。它不是系统的结构关系。
“出库记录表的主键是 record_id,和商品表通过 item_id 关联,查询时需要传仓库代码和日期范围”——这类信息理论上可以写进文档,然后被 RAG 检索出来。但当系统里有几十张表、几十个服务端命令,表和命令之间有复杂的调用依赖时,把这些关系完整地写进文档,并保证文档随系统更新而同步,本身就是一个维护成本极高的工作。更关键的是,即便写进去了,切片之后的检索片段往往无法同时覆盖一次完整调用所需的全部上下文,AI 需要跨片段自己拼凑关系,这是 RAG 在操作场景下最容易出错的地方。
一句话描述 RAG 的能力边界,那就是主要补充知识,而不是承担系统结构建模。
Function Calling 在做什么
Function Calling 解决的是第二件事,给 AI 提供可以实际执行的操作能力。Tool、Skill、MCP 这些机制或封装,通常也是围绕这件事展开,但它们和 Function Calling 并不是完全同一层的概念。
这一层的职责单纯,它负责把 AI 生成的调用意图转换成真实的系统调用,把结果返回给 AI。没有这一层,AI 只能说"我应该调用这个接口",但说完什么都不会发生。问题在于 Function Calling 主要负责执行,不单独解决语义判断。AI 选择调用哪个函数,传什么参数,这个判断过程主要发生在 Function Calling 介入之前。如果 AI 在判断阶段选错了函数,或者参数传错了,Function Calling 通常会忠实地执行这个错误的调用。执行层本身不会替你完成语义纠错。
比如一个中型系统里有1400个服务端命令(WebAPI),全部注册为 Function,AI 在推理时要从1400个候选里选一个,依据是函数名和描述的语义匹配。命名规范、描述清晰,选对的概率高;命名混乱、描述缺失,选错的概率随之上升。Function Calling 本身对这件事没有任何保障机制。
本体在做什么
本体作用于第一件事和第三件事,但它补充的不是知识,而是结构。
在第一件事(搞清楚去哪里找数据、用什么操作)上,本体告诉 AI 这个系统里有哪些实体、实体之间是什么关系、每个实体上有哪些动作可以执行、每个动作的参数约束是什么。这通常是从系统元数据直接提炼出来的关系图,不是普通文档,它的优势也不主要来自向量检索,而来自结构本身。AI 拿到这个关系图,能把"查 A 仓库出库记录"这个意图更可靠地映射到正确的接口和参数,而不是主要凭文本相似度猜测。
在第三件事(判断结果对不对)上,本体提供了对返回数据的语义解释依据。系统返回的字段值是 2,本体里记录了这是枚举类型,2 对应"已审批",AI 才能向用户给出有意义的描述,而不是原样转述一个数字。
本体还能提供一个 RAG 和 Function Calling 都不直接提供的能力:为调用执行之前的权限判断提供语义依据。当前用户有没有权限调用这个接口?如果没有,系统可以拦截、记录审计日志、终止流程。这里复用的仍然是业务系统本身的鉴权体系,本体的作用是把"谁能对什么对象执行什么动作"这件事表达得更清楚,而不是替代鉴权系统本身。
函数签名和语义描述不是同一件事
这里有一个在工程实施里经常被忽视的细节,值得单独说。
本体里包含服务端命令的描述,这个描述有参数列表,看起来和 Function Calling 的函数签名很相似。但两者服务的对象不同:函数签名是给执行框架看的,告诉框架参数的类型和格式;本体里的描述是给 AI 看的,告诉 AI 这个操作在业务上是做什么的、什么情况下该调用它、每个参数的业务含义是什么。
很多团队在实施时把这两层合并,用一套 Function 定义同时承担两个职责。结果通常是:要么 Function 描述写得太短,AI 拿到的是机器接口格式,缺少业务语义,调用选择的准确率下降;要么 Function 描述写得很长,试图把业务说明都塞进去,但这些说明仍然是非结构化的文本,结构化的优势会明显减弱。
语义描述和执行接口是两层不同的东西,对应两类不同的职责,合并它们并不能减少工作量,只会让两边的职责都做得不彻底。
分工之后,拼图才完整
把三种技术放回 Agent 的执行过程里看,分工是这样的。
- 构建上下文的阶段,RAG 负责补充业务知识和背景信息,本体负责提供系统的结构化概念图,两者补充的是不同类型的信息,覆盖的是这个阶段里不同的空白。
- 执行动作的阶段,Function Calling 负责实际调用,但本体可以在调用发出之前为语义校验提供依据:接口选对了吗,参数的类型和范围符合约束吗,当前用户是否具备相应权限。通过校验才执行,不通过就拦截。
- 分析执行结果的阶段,AI 可以基于本体对返回数据做语义解释,判断任务完成情况,决定是输出结果还是进入下一轮。
三者各自解决一个维度的问题,缺掉任何一个,对应的维度就容易出现明显短板。没有 RAG,AI 的背景知识是不完整的。没有本体,AI 面对系统结构时会更盲目,选接口更容易靠运气,返回数据也更缺少稳定的解释依据,已有权限体系也更难被 Agent 正确理解和复用。没有 Function Calling,什么都理解了,但操作停留在意图层面,无法真正执行。
三件事不是同一件事,三种工具也不是在竞争同一个位置。
本文是"企业AI落地"系列的第11篇。从下一篇开始进入工程实现:为什么低代码平台的元数据是构建本体的天然矿藏,以及自动抽取是怎么做到的。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)