为何在当今的AI智能体架构中,简单方案更胜复杂设计
本文探讨了2024年针对向量数据库、超图内存以及调度复杂性的三种观点,表明更简单的系统往往能优于复杂的智能体架构。
阅读了今年关于AI智能体的诸多内容后,还未看到任何具体论点,一种模式就已显现。几乎所有提出的方案都是叠加式的:加上记忆层、加上图结构、加上编排框架、再加上包含三阶段重排的检索流程。还会增加更多智能体,负责监督你已经构建的那些智能体。在这一切的背后,都隐藏着同一个未明说的前提:复杂性即进步,如果你的系统没有比半年前更复杂,那就意味着你在落后。
某团队建设工具可能已经构建了类似架构的组件,当时或许也为某些选择找过理由。因此,当今年出现一些观点主张相反——认为那些复杂的添加其实并不值得大费周章时,它们理应得到比常见的“无需此功能”之类的标题更多的关注。大多数反对派科技文章不过是反向炒作,同样充满自信却同样缺乏证据。而这三个论点则有所不同:每一个都有可验证的依据——基准测试分数、结构分析,或是对工作实际进展的直接描述。这才是应当适用的标准,也是本文其余部分将遵循的标准。
以下是三个示例。在每个案例中,当实际问题远没有那么复杂时,相关领域却选择了更为复杂的架构方案。
案例一:你的代理程序很可能不需要向量数据库
选择基于向量存储的代理程序内存机制,往往是在几秒钟内做出的决定。有人提出“代理程序需要在不同会话之间记住信息”的需求,随之而来的自动回应就是:将数据嵌入并存储起来,再通过相似度进行检索。之所以采用这种方式,并非因为有人对比过其他方案,而只是因为所有教程都是这么做的。
今年的文章《Anubhav的“你的AI智能体无需向量数据库”》正是对这一假设进行了验证。值得铭记的结果来自LoCoMo基准测试:仅由纯文本文件目录构成、通过grep工具进行搜索的基准系统,就在其本身的测试环境中击败了多个获得资金支持、专为内存处理而设计的产品。这并非为了刻意取胜而设计的虚假对比。那些更为复杂的系统——有些甚至结合了嵌入技术、相似性搜索乃至图结构化内存——依然输给了仅需一个下午就能构建出来的方案。
一旦理解了这一原理,其解释就不再令人惊讶。向量相似度是一种检索技术,而非推理技术。它擅长找出在语义上与查询内容相近的文本,但在处理记忆真正需要的任务时表现不佳,比如识别三周前记录的事实已被昨天的更新所取代,或者两个存储的条目之间存在明显矛盾且必须确定哪个更具优先性。向量索引没有内置的时间概念,也没有修正机制,它只是返回嵌入空间中距离最近的条目,让模型自行去判断为何排名前五的条目中有两个存在分歧。
还存在第二种不匹配之处,这与原始能力关系不大,而更多关乎熟悉度。语言模型已经学习了大量以文件操作为核心的训练数据:读取文件、使用grep搜索内容、编辑文件、列出目录、追踪导入链等。这并非副作用,而是其训练数据的核心组成部分。基于grep和文件读取构建的流程正好利用了模型已有的这些熟练技能。相比之下,向量数据库的查询接口则是模型必须在特定场景中自行摸索如何有效使用的工具,它没有像处理文件那样深厚的先验经验。这样一来,你就用模型已具备的技能替代了它需要即时学习的技能,而为此也要承担嵌入和检索带来的延迟成本。
在经过实际推理而非依赖习惯之后,现在大致可以这样表述这个决策:
WHEN A FILESYSTEM + GREP BASELINE IS ENOUGH WHEN YOU ACTUALLY NEED A VECTOR STORE
------------------------------------------------ ------------------------------------------------
Single-agent or small-team memory Retrieval across a corpus too large to
fit or scan in context at all
Facts that change over time and need Cross-document semantic search where
correction, not just accumulation keyword overlap is genuinely weak
Memory the model itself writes, Centralized memory shared by many agents
manages, and re-reads in its own loop that needs access control and auditing
Debuggable state, plain text you can Multi-hop or relational reasoning across
open, diff, and edit by hand thousands of entities where similarity
search is doing real narrowing work
文中描述的写入、管理、读取流程需要具体化,因为“直接使用文件”这种说法在看到实际代码之前听起来只是笼统之谈。以下是一个无需任何托管服务即可立即运行的版本:
import os
import subprocess
from datetime import datetime
MEMORY_DIR = "agent_memory"
def write_memory(topic: str, content: str) -> str:
os.makedirs(MEMORY_DIR, exist_ok=True)
path = os.path.join(MEMORY_DIR, f"{topic}.md")
timestamp = datetime.utcnow().isoformat()
with open(path, "a", encoding="utf-8") as f:
f.write(f"\n## {timestamp}\n{content}\n")
return path
def recall(query: str) -> str:
# ripgrep if you have it, grep -r works fine too
result = subprocess.run(
["rg", "-i", "-C", "2", query, MEMORY_DIR],
capture_output=True, text=True
)
return result.stdout or "no matches"
def list_topics() -> list[str]:
if not os.path.isdir(MEMORY_DIR):
return []
return [f[:-3] for f in os.listdir(MEMORY_DIR) if f.endswith(".md")]
将那三个函数作为工具集成进去,让模型自行决定何时撰写笔记、何时进行搜索,以及何时直接将整个主题文件加载到上下文中——因为其长度足够短。这样就能实现一种无需嵌入成本、无需托管或支付向量数据库费用的内存系统,而且一旦出现问题,还可以直接在文本编辑器中查看状态。如果这种架构最终无法满足需求,原因会很明确:要么是因为语料库过大,普通文本工具无法快速搜索;要么是存在多跳问题,关键词搜索根本无法解答。这比仅仅跟随教程示例来引入向量存储要有充分的合理性。
并没有人说向量数据库在当今世界没有用武之地。问题其实更具体:在真正衡量那些较为基础的方案能带来多大的效果之前,不要就急着使用向量数据库。先尝试全上下文加载以及文件系统结合grep搜索的方法。只有当某种付费内存产品带来的提升幅度足够大,足以弥补其高昂的成本以及由此导致的调试难度增加时,才考虑使用它。大多数智能体内存相关的工作负载都达不到这一标准。
第二种情况:超图也无法拯救你的RAG系统
如果向量数据库是去年的自动选择,那么基于图的RAG则成了今年的趋势;而当团队认为普通的知识图谱仍不够表达能力时,超图便出现了。这一理念乍听之下似乎合理:普通图边仅连接两个节点,但现实中的许多事实涉及同时参与的多于两个的主体。试想这样一个场景:在某个预算周期内,一名员工代表整个部门为同事的差旅费签字批准——这一事实就牵涉到五个不同的参与者。若将其转化为成对的边,就会面临两难选择:要么失去其作为一个整体事件的特性,要么将其拆分成多条二元边,然后在查询时再把它们重新组合起来。而能够同时连接任意数量节点的超边似乎正是解决这一问题的方案。
一种更为精确的建模方式。因此,各团队致力于构建超图RAG系统,他们认为这种更高的精确度能带来更好的检索效果。今年,一位名叫Dustin的作者发表了一篇题为《超图并不会让你的RAG系统变得更好,它们实际上改变了什么》的文章,该文并未仅依据相关论文的摘要,而是通过实际实现情况来检验这一观点。结果几乎令人啼笑皆非:HyperGraphRAG这个以超边的重要性为核心理念的系统,实际上在内部是使用普通的二进制边将所有数据存储在标准图数据库中。更值得注意的是,论文的作者们亲自证明了这种转换方式——即将每条超边拆分成围绕代表该事件的实体节点的小型二进制边簇——并没有丢失任何信息,底层结构在转换过程中丝毫未损。所谓更真实的超图表示方式与“乏味”的二进制边版本,实际上可以完全从彼此中重建出来。
ly。那并非关于实现的无关细节——它从根本上动摇了整个论点。如果一个原生超边与由二元边构成的角色化簇能够表示相同的关联结构,且两者都可以轻易地从对方重建出来,那么选择其中一种其实并非会带来后续影响的建模决策,而仅仅是一种存储格式的选择。那篇文章的评论者费利克斯·安德森将相关数学原理表述得极为清晰:超边与角色化二元图描述的是相同的关联结构,而在元数受限的情况下,超树宽度仅会变化一个常数因子。超树宽度才是决定查询评估成本的实际复杂度指标——既不是跳数,也不是挤在一条边上的参与者数量。如果更换表示方式只会使该数值变化一个常数,而每一个事实都……
当参与者数量是有限的(这几乎适用于所有现实世界的情况——审批链中只有少数人,而非数千人),那么在切换机制上投入的所有工程努力,在决定查询成本的实际因素方面都毫无作用。有必要客观地解释为何人们容易陷入这种误解。跳数很直观:问题与答案之间存在的节点越多,似乎就意味着查询难度越大。而超树宽度则完全不直观——它源自约束满足理论与查询复杂性理论,其变化方式是跳数无法体现的,除非有人专门去验证。完全有可能通过增加结构复杂性,在精心挑选的示例查询中降低跳数,同时不改变其底层复杂度类别,甚至可能使其略有恶化。一篇论文中挑选的理想示例虽然看起来很出色,但对一般情况却无法提供任何有意义的说明。
在选择普通图、实体化图或原生超图存储方式之前,值得先查看以下并列对比:
REPRESENTATION WHAT IT ADDS WHAT IT ACTUALLY CHANGES
--------------------- ------------------------------- --------------------------------
Plain binary graph Simplest to build and query Baseline; loses atomicity of
with standard graph tooling multi-participant facts
Reified binary graph Recovers atomicity via an Same incidence structure as a
(event node + roles) explicit "event" node hyperedge; hypertree width
shifts by a constant only
Native hypergraph Hyperedges as first-class No reduction in query
store objects, arguably cleaner complexity class over a
to write against reified graph; new storage
engine to run and maintain
这些都不是认为图结构对RAG毫无用处的论据。与平面向量搜索相比,多跳关系检索确实能从图结构中获益——这一点毋庸置疑。有争议的是从普通图到超图的进一步转变;一旦深入研究实际证据,客观结论是:这种转变虽然能让数据模型看起来更简洁,但需要额外的基础设施来支持,而且并不会影响查询速度。如果问题出在检索质量上,有实际依据的解决方案通常是改进图构建流程或优化现有图的检索策略,而非引入更复杂的边类型。
案例三:真正的瓶颈从来都不是代码本身
前两个论点涉及检索架构,这属于大家熟悉的领域。第三个论点则有所不同,因为它并非关乎选择合适的工具——而是探讨高级工程师的工作实质,其现实意义比预期更为贴近实际。
帕特里克·科斯在一家拥有上千名员工的公司中担任技术主管,负责管理一个由五名工程师组成的团队。他将自己的文章命名为《AI无法完成我95%的工作(而我是一名软件工程师)》。文章开篇的论断看似是一种认输,但随后他开始阐述自己的观点:编写代码仅是他所用时间中极小的一部分。他的团队采用“谁开发,谁负责运行”的模式,这意味着系统维护的责任由这些工程师自行承担,而非交给另一个将生产问题视为他人事务的运维团队。他的早晨大约从8:30开始,先审查拉取请求,而这些请求中的代码——其中大部分是由AI工具负责初稿撰写的——明显比他几年前审查的代码要好得多。他并没有质疑AI是否能够生成优质的代码。
他完全承认这一点,随后指出这几乎不会改变他的工作实际要求。这正是值得仔细思考的细节,因为它动摇了许多代理堆栈推理中隐含的假设,也包括该领域诸多观点所依据的前提:即能力决定自动化程度。通常的逻辑是,一旦模型能够编写正确的代码,代码生成就不再属于人类工作,因此被自动化的“工作量”应与原本需要编写代码的那部分工作量保持一致。但科斯的观点是,早在人工智能出现之前,这一等式就已经不成立了——人工智能只是让这种错误更加显而易见。技术负责人的职责从来都不是主要负责编写代码,而是侧重于协调:决定要开发什么以及开发顺序,与优先级相互冲突的利益相关方协商范围,审查并支持他人的技术决策,承担沟通协调工作,指导经验较少的成员。
协调工程师们,同时理解利益相关方的需求与系统在不出现故障的情况下实际能够支持的功能之间的差异。这些都不是变相的编码工作,而是属于组织管理与人际协调范畴的工作,只不过在过程中会产出代码——而且还是高度可自动化的输出。这些工作嵌套在更广泛的职责体系之中,而这类职责恰恰难以自动化,因为它们的重点不在于生成具体成果,而在于促成人们之间的共识、权衡以及责任界定。在今年关于智能体的讨论中,这或许是最容易被忽视的观察结果,其重要性甚至超过任何单一的基准数据。因为它解释了为何对于许多高级工程师而言,“模型的编程能力大幅提升”与“我的工作变得轻松很多”这两者并未同步发生,即便他们正在积极使用这些工具并从中获得实际收益。在短短几年内,SWE-bench的分数从个位数上升至70多分,这确实代表了能力上的巨大提升。但这种提升并不会自动让工作量减少70%,因为从一开始,这份工作就并非70%的时间都在写代码——尤其是对于那些已经晋升为高级工程师的人来说,他们的职责还包括负责值班轮班和项目路线规划,而不仅仅是处理拉取请求。
需要诚实地指出的是,这一论点并不像前两种那样能够如此清晰地推广适用。关于向量数据库和超图的说法具有足够的技术性,人们可以通过基准测试或证明来验证它们,而之前的验证也正是如此进行的。至于高级工程师的工作中协调与编码各占多少比例,这一比例会因公司规模、团队成熟度、组织架构中的冗余部分究竟是真正起到作用还是仅造成效率低下,以及个人的技术层级而有所不同。在一家拥有千名员工的公司中,由五人组成的团队采用“谁开发谁维护”的模式只是一种特定的工作形式,并不能代表所有工程岗位的情况。即便如此,其背后的核心观点似乎仍然普遍适用:智能体的能力限制了工作中编码部分在理论上可被自动化的程度,但这恰恰说明了……
关于协调工作能占多大比例,你几乎一无所知,因为从一开始,这部分工作就从未受到打字速度或代码质量的限制。共同点
将这三种情况放在一起对比,就能发现真正的启示与向量数据库、超图或智能体能力并无直接关联。其关键在于各个领域所认为的难点所在与实际难点所在之间的偏差。
CASE WHERE COMPLEXITY WAS ADDED WHERE THE REAL BOTTLENECK WAS
------------------ ---------------------------------- --------------------------------
Agent memory Vector embeddings, similarity Whether the model can use a
search, sometimes a graph layer retrieval method it already
on top of that has deep fluency with
RAG structure Native hyperedges, a new The complexity class governing
storage engine, more query cost, which the fancier
elaborate graph modeling structure barely touches
"How much of the An assumption that model Whether the job was ever
job gets automated" capability alone predicts mostly about the thing the
the automatable fraction model is good at
那些较为复杂的方案本身并非坏主意。向量数据库在合适的应用场景中能够解决实际问题,超图或许能在本文未提及的某些情况下发挥作用,而人工智能代理确实能够减少工程工作中的繁琐任务,第三个案例的研究者也明确指出了这一点。错误并不在于追求复杂性,而在于没有验证这种复杂性是否针对真正的约束条件,而非仅仅是为了构建一个看似出色的解决方案而选择的最便捷的约束条件。
这种习惯不仅体现在代理工程领域。增加另一层功能几乎总比停下来思考那些简单、不起眼的基准方案是否经过过公平测试要容易得多。新的抽象层看起来像是明显的进步,是可以被指出来并称为升级的东西。而去检查grep是否已经能处理该情况、查询复杂度是否真的有所提升,或是耗费你一周时间的工作是否真如你所想的那样,这类工作进展更慢,带来的满足感也低得多,最终甚至可能得出应该停止开发而非继续下去的结论。
以下是在为任何技术栈添加新层之前值得参考的简化版检查清单:
1. Have I benchmarked the boring baseline, not just assumed it loses?
(full-context, grep, a plain graph, a human doing the coordination)
2. Does the new structure change the metric that actually governs cost
or quality, or does it just look more sophisticated on a diagram?
3. Am I reaching for this because a benchmark or proof told me to,
or because it's what the tutorials and the funded products default to?
4. If I strip this layer back out, what specifically breaks?
If I can't name it precisely, I probably don't need the layer yet.
5. Am I solving the bottleneck I actually have, or the bottleneck
that's most interesting to build a sophisticated solution for?
这些内容并非主张整体上减少工程工作量,而是建议在制定复杂的解决方案之前,先确定真正的瓶颈所在——因为那些方案往往基于“已经知道答案”的假设。此处列举的三个例子并非为了制造反差效果而刻意选择,它们之所以被如此归类,是因为有人付出了繁琐的验证工作,而验证结果与默认假设相悖。这比单纯抛出带有强烈观点的耸人听闻的标题要严格得多,也是未来在处理自身技术架构时应遵循的标准。
相关阅读
- 了解AI智能体:目标、工具、记忆与智能体循环 —— 以通俗易懂的方式讲解AI智能体与聊天机器人的区别,涵盖核心组件、决策循环、自主程度以及实际应用场景。
- 了解AI记忆机制:上下文、嵌入向量、RAG与模型权重解析 —— 本文详细阐述AI系统如何存储信息,涉及上下文窗口、嵌入向量、向量数据库、RAG以及模型参数等内容。