做 Agent 记忆,别只会堆 RAG:知识图谱这一步,决定 AI 会不会“联想”

0 阅读12分钟

很多人在给 Agent 做记忆时,第一反应都是上向量库。

这没问题。向量检索确实是现在很好用、也相对省事的一套基础设施:你把聊天记录、文档片段、用户偏好、工具说明都切成 chunk,做 embedding,存进去,等模型要用的时候再召回。

但真把系统跑起来之后,你很快会遇到一个很别扭的现象:

它明明“记住了”,却还是“联想不到”。

这类问题,往往不是模型太笨,也不一定是上下文不够长,而是你的记忆结构本身只擅长“找相似”,不擅长“找关系”。

这时候,知识图谱就该上场了。

先看一个特别典型的误判场景

假设你的 Agent 记忆里已经有三条信息:

  • 小李精通 Python
  • 小李最近在用 n8n 搭自动化工作流
  • n8n 的 Code 节点支持 Python 和 JavaScript

现在小李来问一句:

帮我在 n8n 里写一段脚本,实现某个自动化逻辑。

如果你只靠向量检索,大概率会先命中这些和问题更接近的内容:

  • n8n
  • 写脚本
  • Code 节点
  • Python / JavaScript

但它不一定能稳定把“小李更擅长 Python”这条记忆也一起联想出来。

于是最后生成结果时,模型很可能随手给一段 JavaScript。语义上没错,工具也支持,但对这个用户来说并不是更合适的答案。

问题就出在这里:

向量库找的是“像不像”,不是“有没有关系”。

“n8n 写脚本”和“小李擅长 Python”这两件事,在字面上没那么像,但在决策上却强相关。人类很容易把它们串起来,系统却未必能。

这就是为什么很多 Agent 看起来已经接入了记忆,实际回答却还是差一口气。

RAG 不弱,它只是没负责“联想”这件事

先说清楚,RAG 本身没有问题。

如果你的需求是:

  • 从一堆文档里找相关片段
  • 从历史对话里找提过的事实
  • 给模型补上下文材料

那向量检索已经很好用了。

它的优势非常明确:

  • 接入快
  • 成本相对可控
  • 对模糊表达比较友好
  • 很适合处理长文本、说明文档、知识库这类内容

但它也有天然边界。

当你的系统开始需要下面这些能力时,只靠向量就会吃力:

  • 跨实体联想
  • 沿着关系追溯
  • 根据上下文判断哪条关系更重要
  • 做多跳推理
  • 把“用户—工具—技能—任务”这些关系串起来

一句话概括就是:

RAG 更像在一堆材料里找相关片段;知识图谱更像在一张关系网上找路径。

知识图谱到底补了哪一刀

知识图谱真正核心的价值,不是“能存更多信息”,而是能把信息之间的连接方式存下来

在图数据库里,世界不是一张张表,而是一堆“点”和“线”:

  • 点是实体,比如人、工具、公司、技术栈、任务
  • 线是关系,比如会用、依赖、属于、认识、负责、喜欢

如果把刚才的例子换成图结构,可能就是这样:

  • 小李 —— 擅长 —— Python
  • 小李 —— 使用 —— n8n
  • n8n —— 支持 —— Python
  • n8n —— 支持 —— JavaScript

这时候,当系统收到“帮我在 n8n 里写脚本”这个请求,它就不只是去搜相似文本,而是可以沿着关系往外扩:

  • 先锁定 n8n
  • 再看 n8n 支持哪些语言
  • 再看当前用户更擅长哪一种
  • 最后把结果交给主模型做回答

这就不是简单的召回,而是关系驱动的联想

对 Agent 来说,这一层很关键。因为很多真正有用的记忆,不是某一条孤立事实,而是:

  • 谁和谁有关
  • 谁依赖谁
  • 哪个工具和哪种工作流绑定
  • 哪个用户偏好和哪类答案更匹配

这些东西只靠 chunk 很难表达清楚。

图数据库不难理解,先记住两个词就够了

如果你以前没碰过图数据库,也别被名字吓住。

你先记两个概念就够:

1)节点(Node)

节点就是实体。

比如:

  • 人:小李
  • 工具:n8n
  • 语言:Python
  • 公司:OpenClaw 团队
  • 产品:某个 Agent

2)关系(Relationship)

关系就是实体之间的连接。

比如:

  • 小李 —— 擅长 —— Python
  • 小李 —— 使用 —— n8n
  • Agent —— 调用 —— MCP Server
  • 工作流 —— 依赖 —— 某个 Tool

如果你平时会在白板上画架构图,那你其实已经在用图的思维了。图数据库做的事,只是把这套“圆圈加箭头”的关系结构存进数据库里,并允许你高效查询。

Cypher 可以怎么理解

图数据库里很常见的一种查询语言是 Cypher。

你可以把它理解成:图数据库里的 SQL

SQL 更像是在表里筛行、连表、聚合;Cypher 更像是在描述一条路径应该长什么样。

比如你想查“小李认识的人的朋友”,Cypher 的心智模型不是“怎么一步步遍历”,而是“我需要一个这样的图案”:

MATCH (p1:Person {name: "小李"})-[:KNOWS]->(friend:Person)-[:KNOWS]->(fof:Person)
RETURN fof.name

它表达的意思其实很直白:

从小李出发,沿着“认识”这条线,先找到朋友,再找到朋友的朋友,最后把名字返回给我。

所以 Cypher 真正难的地方,从来不是语法,而是你有没有把实体和关系想清楚。

真要落到 Agent 里,重点不是“查图”,而是“怎么建图”

如果你准备把知识图谱接进 Agent,工程上更重要的不是先选 Neo4j 还是别的图库,而是先把下面三层设计清楚。

第一层:怎么从对话里抽实体和关系

图谱不会自己长出来。

你得先决定,系统到底要从对话和文档里抽什么。

比较常见的一批实体通常包括:

  • 用户
  • 公司
  • 项目
  • 工具
  • 编程语言
  • 平台
  • 任务
  • 偏好

关系也要提前限定:

  • 使用
  • 擅长
  • 负责
  • 隶属
  • 依赖
  • 喜欢
  • 学习中
  • 历史使用过

这一步尽量别贪多。因为一旦实体类型和关系类型定义得太散,后面就会非常乱。

更实际的做法是:

先围绕你的业务场景,定义一小套稳定、低歧义的实体和关系。

比如做 Agent 工作流,你可能最先需要的就是:

  • 用户
  • 工具
  • 技能
  • 项目
  • 平台
  • 任务

以及:

  • 使用
  • 擅长
  • 调用
  • 依赖
  • 属于
  • 负责

这套够跑起来之后,再慢慢扩。

第二层:怎么把实体和关系稳定写入图谱

这一步很容易踩坑。

因为图谱不是简单 append 文本。你要解决两个问题:

1)实体不能重复

比如同一个人、同一个工具、同一个技术名词,不能因为写法不同就进成两份。

比较常见的做法是用 MERGE 做防重:

MERGE (n:Person {name: $name})

它的意思很简单:

  • 有这个节点,就复用
  • 没有,就创建

2)关系不能乱长,还要能体现强弱

很多关系不是“一次发生就永远一样”。

比如用户反复提到某个工具,或者反复表达某个偏好,那这条关系就应该越来越强,而不是一直停留在同一层。

这时候你就可以在关系上挂一个 weight

MATCH (source:Person {name: $s_name}), (target:Tool {name: $t_name})
MERGE (source)-[r:USES]->(target)
ON CREATE SET r.weight = 1
ON MATCH SET r.weight = r.weight + 1

这样后面做检索时,你就不只是知道“有这条关系”,还知道“这条关系被确认过多少次”。

对 Agent 来说,这非常实用。

因为很多时候你不是想要“所有相关信息”,你想要的是:

更稳定、更强、也更可信的关系。

第三层:怎么让 Agent 真正用上图谱

很多人做到“能把图建起来”就停了,但真正让图谱发挥价值,还差最后一步:

要让它参与回答,而不是只做静态存档。

更稳的做法通常是双模型或多子任务结构:

角色 1:主模型

负责和用户对话、理解意图、生成最终答案。

角色 2:结构提取器

定期从聊天历史、任务记录、用户输入里抽实体和关系,写入图谱。

角色 3:图查询生成器

当主模型发现“这里需要查图谱”时,由另一个子模型把当前诉求翻译成 Cypher,再去图库里查。

最后,把查询结果返回给主模型,由主模型组织成自然语言答案。

这套结构的价值在于:

  • 主模型不必硬记所有图语法
  • 图谱查询可以独立演进
  • 抽取、存储、查询三层职责清楚
  • 后续更容易做调试和校验

对 Agent 工作流来说,这比“把所有事都塞给同一个模型”稳得多。

如果你今天就想把这套结构接进 Agent,可以按 4 步落地

第 1 步:先别急着建大图,先定一版基础 schema

先把实体类型和关系类型缩到能跑通的一版小范围结构。

例如做 OpenClaw、MCP、Agent workflow 这类系统时,第一版完全可以只保留:

  • 实体:用户、工具、平台、技能、项目、任务
  • 关系:使用、擅长、依赖、调用、负责、偏好

这样做的好处是,你能先把 schema、embedding 召回、Cypher 查询、工作流串起来,而不是一开始就把图库建成百科全书。

第 2 步:把“写入图谱”单独做成后台任务

不要让主对话链路一边响应用户,一边临时抽实体、归一化、写图库。

更稳的方式是:

  • 主链路先完成回答
  • 后台任务再把新对话送进结构提取器
  • 抽完三元组后统一写入 Neo4j、Memgraph 或其他图库

这样你的 Agent、OpenClaw skill、MCP 工具调用链路不会被图谱写入拖慢,整个 workflow 也更容易排错。

第 3 步:把“查图”做成单独的查询子链路

主模型不要直接拼所有查询语句。

更好的办法是加一个查询子链路:

  1. 先判断这次问题需不需要查图谱
  2. 需要的话,让子模型生成 Cypher
  3. 去图库查询节点、关系、多跳路径
  4. 把结果压缩成结构化上下文,再回喂主模型

这样做之后,图谱才真的会参与推理,而不是沦为一个冷冰冰的存档层。

第 4 步:让向量库和图谱分工,而不是互相替代

一套更稳的工程组合通常是:

  • 向量库:负责 chunk、embedding、语义召回
  • 图谱:负责实体关系、多跳联想、偏好与依赖建模
  • 主模型:负责最终生成

很多系统真正缺的不是“更多上下文”,而是“更对的结构化上下文”。把这三层分开之后,记忆质量会比继续单堆 RAG 稳很多。

什么场景更适合上知识图谱

不是所有项目都值得上图谱。

如果你的系统主要是:

  • 文档问答
  • FAQ 检索
  • 说明书召回
  • 搜一段相关上下文给模型看

那 RAG 已经够用了,没必要为了“看起来高级”硬塞图数据库。

但如果你的系统开始明显依赖下面这些能力,就要认真考虑图谱:

  • 用户长期偏好记忆
  • 工具、平台、技能之间的依赖关系
  • 多实体、多跳的推理链路
  • 复杂工作流里的上下游关系
  • 业务对象之间的稳定连接网络

比如:

  • 某个用户偏好哪种输出形式
  • 某个团队常用哪套技术栈
  • 某个项目绑定了哪些工具和服务
  • 某个 MCP Server 适合接在哪个 Agent 节点上
  • 某类问题应该优先走哪个工作流分支

这类问题本质上都不是“找一段像的文本”,而是“沿着关系找到正确路径”。

但知识图谱绝对不是银弹

这点必须说透。

知识图谱强,是强在关系推理;但它的工程代价也不低。

坑 1:入库很难,实体歧义非常烦

图谱比向量库更怕脏数据。

比如:

  • Python 和 python 算不算一个实体
  • Node、Node.js、nodejs 要不要合并
  • “龙虾”是不是 OpenClaw 的别名
  • 用户一句简称,能不能稳定归到正确节点

如果实体归一做不好,图谱很快就会长成一团乱麻。

而这一层又偏偏非常依赖 LLM 抽取质量,所以稳定性是个大问题。

坑 2:更新比向量库痛苦得多

向量库更新旧记忆,很多时候是删 chunk、补 chunk 就结束了。

图谱不是。

如果用户说:

我不用 Python 了,现在主要写 Node.js。

那你在图里要做的事情通常包括:

  • 找到用户节点
  • 找到它和 Python 之间的关系
  • 判断这条关系是删除、降权还是改成“历史使用过”
  • 新建或复用 Node.js 节点
  • 建立新的关系
  • 处理旧关系可能牵出的其他联动逻辑

一旦关系多起来,更新链路会非常容易出 bug。

所以图谱的门槛从来不只是“学一门查询语法”,而是你得有一套完整的实体治理和关系更新策略。

更稳的路线,不是“图谱替代向量”,而是两者配合

如果你现在正在做 Agent 记忆,我更推荐的不是二选一,而是分工:

向量库负责:

  • 模糊召回
  • 长文本语义检索
  • 文档片段补充
  • 从大量材料里先找到相关入口

知识图谱负责:

  • 实体关系存储
  • 多跳联想
  • 偏好与依赖建模
  • 关系级推理
  • 给主模型提供更结构化的上下文

更直白一点说:

向量负责“先找到大概相关的东西”,图谱负责“把真正有关联的东西串起来”。

这套混合结构,通常比纯图谱更稳,也比纯 RAG 更聪明。

最后收个口

很多 Agent 项目做到后面都会碰到一个瓶颈:

文档越喂越多,记忆越存越长,但回答质量并没有跟着明显变好。

原因往往不是“资料不够”,而是系统缺的不是更多文本,而是文本之间的关系结构

如果你的系统现在已经开始出现下面这些信号:

  • 能召回相关内容,但经常答不到更合适的点上
  • 记得住很多事实,却不会按关系联想
  • 一遇到多实体、多偏好、多工具依赖的场景就变钝

那就别只盯着向量库调参数了。

你真正该补上的,可能是知识图谱这一层。

因为让 Agent 看起来更像“真的理解了你”,很多时候靠的不是它记住了多少文本,而是它能不能顺着关系,把对的记忆在对的时刻调出来。