☰
AI Agent 记忆层升级:GraphRAG 与 Neo4j 实战指南
2026/11/2 9:50:29 网站建设 项目流程

1. 为什么 AI Agent 的记忆层最终都会落到图数据库上

做 AI Agent 的人迟早会撞上一堵墙:向量检索不够用了。

我最早做 Agent 的时候,记忆层就是一套朴素的 RAG——文档切块、embedding、丢进向量库、按余弦相似度召回。这套东西在"问答型"场景里跑得挺顺,但只要 Agent 开始做多跳推理,问题立刻暴露。举个我实际遇到的例子:用户问"我们上个季度负责支付模块的那个人,现在在哪个项目组?"向量库能召回"支付模块"相关的文档块,也能召回"人员调动"相关的文档块,但它没法把"人—负责—模块"和"人—调动—项目组"这两条关系串起来。它召回的是相似的文本,不是相连的事实。

这就是 GraphRAG 要解决的核心问题。GraphRAG 的本质是把知识从"一堆扁平的文本块"重构成"实体 + 关系"的图结构,让检索从"找相似"升级成"沿关系走"。而 Neo4j 作为目前最成熟的原生图数据库,几乎是 GraphRAG 落地时绕不开的存储层选择。

这篇内容我打算把"AI Agent + GraphRAG + Neo4j"这条链路从头到尾拆一遍。不是那种"三步搭建你的知识图谱"的营销文,而是把我在实际项目里踩过的坑、做过的取舍、以及那些文档里不会写的细节都摊开讲。适合两类人看:一是已经在做 Agent、想给记忆层升级的开发者;二是刚接触图数据库、想知道它在 AI 场景里到底怎么用的朋友。读完你应该能自己判断——你的 Agent 到底需不需要上图,以及如果要上,怎么上才不翻车。

2. GraphRAG 与朴素 RAG 的分水岭:检索范式的根本差异

2.1 向量检索的天花板在哪里

先把话说透。向量检索不是不好,它在"语义相似"这件事上非常强。你问"怎么退货",它能召回"如何申请退款",因为这两句话在语义空间里挨得近。但它的能力边界也很清晰:它只能表达"像不像",不能表达"连不连"。

我做过一个对比测试,同一个企业知识库,问"张工的直属领导负责哪条产品线"。向量方案召回的前 5 个块里,有 3 个提到了张工,2 个提到了产品线,但没有一个块同时包含"张工的直属领导是谁"和"这个领导负责什么产品线"这两跳信息。因为原始文档里这两条信息分散在不同段落,切块之后天然就断了。Agent 拿到这些块,只能靠 LLM 硬猜,猜错的概率相当高。

GraphRAG 的思路完全不同。它先把文档里的实体(人、部门、产品线、模块)和关系(负责、隶属、调用、依赖)抽出来,建成图。检索的时候,Agent 先定位到"张工"这个节点,然后沿着直属领导这条边走到领导节点,再沿负责这条边走到产品线节点。两跳查询,答案精确,不依赖 LLM 猜。

2.2 图结构给 Agent 带来的三种新能力

上了图之后,Agent 能做的事情明显变多了。我总结下来主要是三种:

  • 多跳推理:沿关系链走,回答"A 的 B 的 C 是什么"这类问题。这是向量方案最吃力的场景。
  • 全局摘要:GraphRAG 有个很关键的能力叫社区检测(community detection),能把图里关系紧密的节点聚成簇,然后对每个簇生成摘要。用户问"这个知识库主要讲了哪几个主题",向量方案基本答不了,图方案可以。
  • 可解释的检索路径:Agent 给出答案时,可以顺带把走过的路径吐出来——"我是从张工走到李总,再走到支付产品线的"。这在需要审计和溯源的场景里价值极高。

2.3 什么时候不该上图

但我必须泼一盆冷水:不是所有 Agent 都需要 GraphRAG。我见过太多项目,明明就是个 FAQ 问答,非要上知识图谱,结果抽取质量一塌糊涂,维护成本还高得离谱。

判断标准其实很简单,问自己三个问题:

判断维度适合向量 RAG适合 GraphRAG
查询类型单跳事实查询多跳关系推理
数据结构松散文本、FAQ实体关系密集
更新频率高频、碎片化中低频、结构化
答案要求语义相近即可需要精确路径

如果你的场景是"用户问产品参数,我返回说明书片段",老老实实用向量库,别折腾图。只有当"关系"本身是答案的一部分时,图才真正划算。

3. Neo4j 在 GraphRAG 架构里到底承担什么角色

3.1 存储层、检索层,还是推理层

很多人对 Neo4j 在 GraphRAG 里的定位是模糊的,以为它就是个"存图的数据库"。这个理解太浅了。在实际架构里,Neo4j 至少承担三个层次的职责:

第一层是持久化存储。实体、关系、属性、向量索引,全都落在 Neo4j 里。这里有个容易被忽略的点——Neo4j 从 5.x 开始原生支持向量索引(vector index),意味着你不需要再单独维护一个向量库,实体节点的 embedding 可以直接存在图里,用db.index.vector.queryNodes查询。这一下就省掉了一套组件的运维成本。

第二层是检索执行引擎。GraphRAG 的检索不是简单的"查节点",而是"混合检索"——先用向量索引找到入口节点,再用 Cypher 沿关系扩展。这个"向量 + 图遍历"的组合查询,Neo4j 能在一次查询里完成,不用在多个系统之间来回倒数据。

第三层是推理路径的载体。Agent 做多跳推理时,每一跳都是一次图遍历。Neo4j 的 Cypher 天然适合表达这种"从 A 出发,经过若干关系,到达 B"的逻辑,而且查询计划是编译执行的,比在应用层用代码一层层查要快得多。

3.2 为什么是 Neo4j 而不是别的图库

图数据库不止 Neo4j 一家,但 GraphRAG 场景里它出镜率最高,原因有几个:

  • Cypher 的表达力:声明式的图查询语言,写多跳查询非常直观。对比 Gremlin 那种命令式遍历,Cypher 的可读性对团队协作友好太多。
  • 向量索引原生支持:5.x 之后内置向量检索,省去组件拼装。
  • 生态成熟:官方 driver 覆盖主流语言,Python 侧的neo4j-driver和 LangChain 的Neo4jGraph、Neo4jVector集成都很顺。
  • APOC 和 GDS 库:图算法(社区检测、中心性、路径查找)开箱即用,GraphRAG 的社区摘要功能直接靠 GDS 实现。

提示:如果你只是做小规模实验,Neo4j 社区版完全够用。企业版主要多了多集群、细粒度权限这些运维特性,个人项目和中小团队用不上。

3.3 一个典型的 GraphRAG 数据流

把整个链路串起来看,数据流大概是这样:

  1. 抽取阶段:LLM 从原始文档里抽实体和关系,输出结构化的三元组。
  2. 入库阶段:通过neo4j-driver把三元组写进 Neo4j,同时给实体节点算 embedding 存进向量索引。
  3. 社区检测阶段:用 GDS 跑社区检测算法,把图切成若干簇,对每簇生成摘要。
  4. 检索阶段:Agent 收到问题,先向量检索定位入口节点,再 Cypher 多跳扩展,必要时叠加社区摘要。
  5. 生成阶段:把检索到的子图和路径喂给 LLM,生成最终答案。

Neo4j 在这条链路里是 2、3、4 三步的核心载体。下面我逐个拆。

4. 从零把 Neo4j 跑起来:安装、配置与连接

4.1 选哪种部署方式

Neo4j 的部署方式有好几种,选错了后面会很别扭。我按使用场景给你分一下:

  • Neo4j Desktop:图形化桌面应用,适合本地开发和调试。装完自带一个 Browser 界面,能可视化看图和写 Cypher,新手强烈建议从这里开始。
  • Docker 部署:适合需要可复现环境、或者要跑在服务器上的场景。一条docker run就能起来,配置通过环境变量注入。
  • 社区版直接安装:Linux 服务器上跑生产用,需要手动配 JVM 参数和内存。
  • AuraDB 云服务:官方托管,免运维,但数据在云上,敏感场景要评估。

我个人的习惯是:本地开发用 Docker,因为环境干净、删了重来毫无心理负担;需要可视化探索的时候开 Desktop。下面重点讲 Docker 方式,因为它最通用。

4.2 Docker 起一个 Neo4j 实例

docker run -d \ --name neo4j-graphrag \ -p 7474:7474 -p 7687:7687 \ -e NEO4J_AUTH=neo4j/your_password \ -e NEO4J_PLUGINS='["apoc", "graph-data-science"]' \ -v $HOME/neo4j/data:/data \ -v $HOME/neo4j/logs:/logs \ neo4j:5.26-community

几个参数值得说明:

  • 7474是 HTTP 端口,对应 Browser 界面;7687是 Bolt 协议端口,driver 连接走这个。
  • NEO4J_AUTH设置初始账号密码,第一次启动后一定要改掉默认密码,这是安全底线。
  • NEO4J_PLUGINS装 APOC 和 GDS,GraphRAG 的社区检测和批量导入都依赖它们。
  • 数据卷挂载到宿主机,容器删了数据还在,这点很重要。

注意:GDS 库对内存有要求,如果容器内存给小了,社区检测算法会直接报内存不足。建议至少给容器 4GB 内存。

4.3 内存配置:最容易被忽视的坑

Neo4j 默认的内存配置是给"玩具级"数据量准备的。一旦你导入几万个节点,查询就开始卡。核心是两个参数:

  • dbms.memory.heap.initial_size和dbms.memory.heap.max_size:JVM 堆内存,负责查询执行和事务处理。
  • dbms.memory.pagecache.size:页缓存,负责缓存磁盘上的图数据。

经验公式大致是:堆内存给总可用内存的 50%,页缓存给 30% 左右,剩下的留给操作系统。比如一台 16GB 的机器,堆给 8GB,页缓存给 5GB。页缓存尤其关键——它决定了图遍历时有多少数据能命中内存,配小了查询会频繁读盘,性能断崖式下跌。

在 Docker 里通过环境变量注入:

-e NEO4J_server_memory_heap_max__size=8G \ -e NEO4J_server_memory_pagecache_size=5G

注意环境变量里下划线是双写的,这是 Neo4j 配置项转环境变量的规则,_要写成__,容易写错。

4.4 用 neo4j-driver 建立连接

Python 侧连接 Neo4j 用官方 driver:

from neo4j import GraphDatabase driver = GraphDatabase.driver( "bolt://localhost:7687", auth=("neo4j", "your_password") ) def verify(): driver.verify_connectivity() print("连接成功") verify()

这里有个实操细节:driver 是线程安全的,应该全局复用一个实例,不要每次查询都新建。我见过有人在每个请求里GraphDatabase.driver(...),连接池直接被撑爆。正确做法是应用启动时建一个 driver,全局共享,关闭时统一driver.close()。

另外,verify_connectivity()在启动时调一次,能提前暴露网络或认证问题,比等到第一次查询才报错要好排查得多。

5. 用 Cypher 把知识图谱建起来:实体、关系与向量索引

5.1 三元组建模:从 LLM 输出到图结构

GraphRAG 的第一步是把非结构化文本变成三元组。LLM 抽取出来的东西通常是这样的:

{ "entities": [ {"name": "张工", "type": "Person"}, {"name": "支付模块", "type": "Module"} ], "relations": [ {"source": "张工", "target": "支付模块", "type": "负责"} ] }

入库的时候,关键是要先 MERGE 实体,再 MERGE 关系。用MERGE而不是CREATE,是因为同一个实体可能在多篇文档里反复出现,MERGE能保证不重复建节点。

MERGE (p:Person {name: $person_name}) MERGE (m:Module {name: $module_name}) MERGE (p)-[:负责]->(m)

MERGE的语义是"存在就匹配,不存在就创建",这是图数据去重的核心手段。但要注意,MERGE在高并发下可能产生重复节点,因为它是"先查后写"的。生产环境里通常会给实体名加唯一约束:

CREATE CONSTRAINT person_name_unique IF NOT EXISTS FOR (p:Person) REQUIRE p.name IS UNIQUE;

加了约束之后,重复插入会直接报错而不是静默产生脏数据,配合应用层的重试逻辑,能保证幂等。

5.2 批量导入的性能优化

一条条MERGE写数据,几万个节点能跑到天荒地老。批量导入有几个提速手段:

第一,用UNWIND批量处理。把一批三元组作为列表传进去,一次事务处理多条:

UNWIND $relations AS rel MERGE (s:Entity {name: rel.source}) MERGE (t:Entity {name: rel.target}) MERGE (s)-[:RELATED {type: rel.type}]->(t)

第二,控制事务大小。单事务别超过 1 万条操作,太大容易内存溢出,太小又浪费。我一般按 1000 到 5000 一批。

第三,导入前先建索引。在name字段上建索引,MERGE的查找速度会快一个数量级。这个顺序不能反——先导数据再建索引,等于白等。

第四,大批量场景用neo4j-admin import。这是离线导入工具,速度极快,但要求数据库是空的,适合初始化。增量更新还是得走 Cypher。

5.3 向量索引:让实体也能被语义检索

Neo4j 5.x 的向量索引是 GraphRAG 的关键拼图。建索引的语法:

CREATE VECTOR INDEX entity_embeddings IF NOT EXISTS FOR (n:Entity) ON (n.embedding) OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' } }

vector.dimensions必须和你用的 embedding 模型输出维度一致。用 OpenAI 的text-embedding-3-small就是 1536,用别的模型要对应改。维度写错了索引建不起来,或者查询结果完全不对。

查询的时候:

CALL db.index.vector.queryNodes('entity_embeddings', 5, $query_vector) YIELD node, score RETURN node.name, score

这返回的是和查询向量最相近的 5 个实体节点。这就是 GraphRAG 混合检索的入口——先用向量找到起点,再用图遍历扩展。

5.4 混合检索:向量入口 + 图扩展

把两步拼起来,就是一个完整的 GraphRAG 检索:

CALL db.index.vector.queryNodes('entity_embeddings', 3, $query_vector) YIELD node AS entry, score MATCH path = (entry)-[*1..2]-(related) RETURN entry.name, related.name, [r IN relationships(path) | type(r)] AS rel_types, score LIMIT 20

这段查询的意思是:先用向量索引找到 3 个最相关的入口实体,然后从这些实体出发,沿关系走 1 到 2 跳,把所有关联的节点和路径都捞出来。[*1..2]是变长路径,控制跳数很关键——跳数太多会爆炸式返回,太少又覆盖不到多跳信息。实践中 2 到 3 跳是比较平衡的选择。

提示:变长路径查询在稠密图上可能非常慢。如果你的图里某些节点度数特别高(比如"公司"这种超级节点),建议给路径加类型限制,比如-[:负责|隶属*1..2]-,避免走遍所有边。

6. 社区检测与全局摘要:GraphRAG 区别于普通图查询的地方

6.1 为什么要做社区检测

前面讲的都是"局部检索"——从某个入口出发走几跳。但有一类问题局部检索答不了,比如"这个知识库整体上讲了哪些主题"。这时候需要的是全局视角,而社区检测就是生成全局视角的手段。

社区检测的本质是把图里连接紧密的节点聚成簇。同一个簇里的节点之间关系密集,不同簇之间关系稀疏。每个簇代表一个"主题"或"领域"。对每个簇生成一段摘要,就得到了整个知识库的全局概览。

6.2 用 GDS 跑社区检测

Neo4j 的 GDS 库内置了多种社区检测算法,最常用的是 Louvain:

CALL gds.graph.project( 'knowledge_graph', 'Entity', {RELATED: {orientation: 'UNDIRECTED'}} ); CALL gds.louvain.write('knowledge_graph', { writeProperty: 'community' });

第一步把图投影到 GDS 的内存图里,第二步跑 Louvain 算法,把每个节点所属的社区 ID 写回节点的community属性。跑完之后,每个实体节点就多了一个"我属于哪个社区"的标签。

这里有个实操经验:投影图的时候一定要设orientation: 'UNDIRECTED'。社区检测关心的是"连接紧密程度",方向不重要,用有向图会漏掉大量反向关系,导致社区划分质量下降。

6.3 生成社区摘要

社区划分完之后,把每个社区的节点和关系捞出来,喂给 LLM 生成摘要:

MATCH (n:Entity) WHERE n.community = $community_id OPTIONAL MATCH (n)-[r:RELATED]->(m:Entity) WHERE m.community = $community_id RETURN n.name AS entity, collect({target: m.name, type: r.type}) AS relations

拿到这个社区的所有实体和内部关系,拼成一段文本,让 LLM 总结"这个社区主要涉及什么主题、有哪些关键实体、它们之间是什么关系"。生成的摘要存回图里,作为一个Community节点,和社区内的实体建立BELONGS_TO关系。

检索的时候,如果问题偏全局,就直接查社区摘要;如果偏局部,就走前面讲的向量 + 图扩展。两套检索路径配合使用,才是完整的 GraphRAG。

6.4 社区摘要的更新策略

社区不是一成不变的。新数据进来,图结构变了,社区划分也会变。但每次全量重跑社区检测成本很高,尤其是大图。

我的做法是分层更新:局部检索依赖的实体和关系实时更新,社区摘要按批次更新(比如每天或每周跑一次)。因为全局摘要对时效性要求本来就不高,用户问"整体主题"的时候,晚一天的数据完全可以接受。这样既保证了局部查询的实时性,又控制了全局计算的开销。

7. 把 Neo4j 接进 AI Agent:检索链路与工具封装

7.1 Agent 怎么调用图检索

Agent 调用 Neo4j 的方式,本质上是把图检索封装成一个工具(tool),让 LLM 决定什么时候调。用 LangChain 的话,可以这样封装:

from langchain_neo4j import Neo4jGraph from langchain.tools import tool graph = Neo4jGraph( url="bolt://localhost:7687", username="neo4j", password="your_password" ) @tool def graph_search(query: str) -> str: """根据问题检索知识图谱中的相关实体和关系""" # 先算 query 的 embedding query_vector = embed(query) cypher = """ CALL db.index.vector.queryNodes('entity_embeddings', 3, $vec) YIELD node AS entry, score MATCH path = (entry)-[*1..2]-(related) RETURN entry.name AS start, related.name AS end, [r IN relationships(path) | type(r)] AS rels LIMIT 15 """ result = graph.query(cypher, {"vec": query_vector}) return format_result(result)

关键点在于工具的 docstring 要写清楚它适合什么问题。LLM 是靠描述来决定调不调工具的。如果描述写成"查询数据库",LLM 根本不知道什么时候该用;写成"当问题涉及实体之间的多跳关系、需要沿关系链推理时使用",命中率会高很多。

7.2 检索结果怎么喂给 LLM

图检索返回的是一堆路径,直接丢给 LLM 效果不好,因为路径信息太碎。我的做法是把路径转成自然语言描述:

张工 --负责--> 支付模块 张工 --隶属--> 支付团队 支付团队 --隶属--> 技术中心

转成:"张工负责支付模块,隶属于支付团队,该团队隶属于技术中心。"

这样 LLM 读起来顺畅,推理也更准。另外,路径要按相关性排序,向量得分高的入口节点对应的路径排前面,让 LLM 优先看到最相关的内容。

7.3 多轮对话里的图上下文管理

Agent 做多轮对话时,图检索的结果会累积。如果每轮都把历史路径全塞进 prompt,token 很快爆炸。我的处理方式是只保留当前轮相关的子图,历史轮次只保留结论性的实体名,需要的时候再重新检索。

具体做法是维护一个"当前对话涉及的实体集合",每轮检索时把这个集合作为额外的入口节点,和向量检索的结果合并。这样既保持了对话的连贯性,又不会让上下文无限膨胀。

7.4 并发场景下的连接与查询管理

热词里有个"ai agent 怎么扛并发",这确实是 GraphRAG 落地时的真问题。Neo4j 的 driver 自带连接池,但默认配置不一定适合高并发 Agent。

几个调优点:

  • 连接池大小:max_connection_pool_size默认是 100,Agent 并发高的时候要适当调大,但别超过数据库的承载能力。
  • 查询超时:给每个查询设timeout,避免慢查询拖垮整个池子。变长路径查询尤其要设。
  • 读写分离:如果读多写少,可以用 Neo4j 的因果集群,读走从节点。社区版不支持集群,但可以用只读副本的思路做应用层分流。
  • 缓存热点子图:对于高频查询的实体,在应用层做一层缓存,减少数据库压力。

注意:并发调优的前提是先做查询优化。一个没建索引的 Cypher 查询,再怎么调连接池也扛不住。先把EXPLAIN和PROFILE用起来,确认查询走了索引,再谈并发。

8. 实测中那些文档不会告诉你的坑

8.1 实体抽取质量决定一切

GraphRAG 的效果,八成取决于实体抽取的质量。我踩过最惨的坑是:LLM 把"支付模块"和"支付系统"抽成了两个不同实体,导致图里同一个东西有两个节点,关系全断了。

解决办法有两个:一是在抽取 prompt 里明确要求归一化,让 LLM 对同一实体用统一名称;二是入库后跑实体消歧,用 embedding 相似度找出可能重复的实体,人工或自动合并。第二个方案更可靠,但成本高。

8.2 超级节点拖垮查询

图里总会有那么几个"超级节点"——连接了成百上千条边的实体,比如公司名、通用术语。从这些节点出发做变长路径查询,会瞬间返回海量结果,查询直接卡死。

我的应对策略是给超级节点打标记,检索时跳过或限制。具体做法是统计每个节点的度数,超过阈值的标记为:Hub,查询时加WHERE NOT related:Hub过滤掉。或者对超级节点的扩展单独限制跳数为 1。

8.3 embedding 模型换了要重建索引

这个坑很隐蔽。你一开始用某个 embedding 模型建了向量索引,后来换了个模型,维度或者语义空间变了,但索引还是旧的。查询结果会莫名其妙地差,而且不报错,极难排查。

换 embedding 模型必须重建向量索引,没有例外。重建的时候记得先把旧索引 drop 掉,否则会冲突。

8.4 Cypher 注入与参数化查询

Agent 生成的 Cypher 如果直接拼字符串,会有注入风险。所有用户输入必须走参数化查询,用$param占位,通过 driver 的参数字典传入。这一点和 SQL 注入的防护逻辑完全一样,但很多人写 Cypher 的时候会忘。

# 错误做法 graph.query(f"MATCH (n {{name: '{user_input}'}}) RETURN n") # 正确做法 graph.query("MATCH (n {name: $name}) RETURN n", {"name": user_input})

8.5 事务与幂等

Agent 可能会重试失败的写入操作。如果写入逻辑不是幂等的,重试会产生重复数据。前面提到的MERGE+ 唯一约束就是保证幂等的核心手段。另外,批量写入要包在显式事务里,要么全成功要么全回滚,避免图数据处于半更新状态。

9. 一个可复现的最小 GraphRAG 闭环

把前面的东西串起来,给你一个能跑通的最小实现。假设你已经有一个跑起来的 Neo4j 实例。

第一步,准备数据并抽取三元组。用 LLM 从文档里抽实体和关系,输出 JSON。

第二步,建约束和索引:

CREATE CONSTRAINT entity_name_unique IF NOT EXISTS FOR (e:Entity) REQUIRE e.name IS UNIQUE; CREATE VECTOR INDEX entity_embeddings IF NOT EXISTS FOR (e:Entity) ON (e.embedding) OPTIONS {indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' }};

第三步,批量写入实体和关系,同时给每个实体算 embedding 存进去。

第四步,跑社区检测,生成社区摘要。

第五步,封装检索工具,接入 Agent。

第六步,测试多跳查询,验证路径检索是否正确。

这个闭环跑通之后,你就有了一个能回答多跳问题的 Agent。剩下的就是不断优化抽取质量、调整检索跳数、补充社区摘要。

10. 关于成本、选型与后续演进的一些个人判断

最后聊点务实的。GraphRAG + Neo4j 这套方案,最大的成本不在数据库,而在实体抽取和社区摘要的 LLM 调用。一篇长文档抽三元组,token 消耗可能比直接做 RAG 高好几倍。所以我的建议是:先小范围验证价值,再决定要不要全量上图。挑一个关系密集、多跳查询频繁的子领域做试点,跑通了再推广。

选型上,Neo4j 社区版对绝大多数个人和中小团队够用,别一上来就上企业版。向量索引原生支持之后,也不需要再单独维护向量库,架构能简化不少。如果数据量真的很大,再考虑分片或者换分布式图库。

演进方向上,我比较看好的是图结构和向量检索的深度融合——不是简单的"向量找入口 + 图扩展",而是让图的结构信息反过来影响向量检索的排序。另外,增量式的社区更新也是个值得投入的方向,现在全量重跑社区检测的成本还是偏高。

我在实际项目里最深的一个体会是:GraphRAG 的价值不在于"更先进",而在于"更合适"。它解决的是关系推理问题,如果你的场景里关系不重要,它就是过度设计。反过来,如果你的 Agent 天天被"多跳问题"卡住,那上图带来的提升是质变级的。判断清楚自己的场景,比盲目追新技术重要得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询