当只看脸的 RAG 学会了顺藤摸瓜……
当RAG只会“看脸”时,多跳推理任务几乎成了Agent的噩梦。检索回来的结果要么不完整,要么完全跑偏,导致整个推理链路在错误中层层叠加。但最近来自Zleap AI团队的SAG(SQL-Retrieval Augmented Generation)给出了一套截然不同的解法——它把最难的MuSiQue基准测试上的Recall@2从49.5%直接拉到64.1%,Recall@5更是飙到了80.04%。更重要的是,这套方案已经在5亿级数据规模的生产环境里跑通了,论文、代码和在线Demo全部公开。
先说说老问题。你可能已经熟悉传统向量RAG的逻辑:把每段文本切成块,转成向量,然后问问题的时候找最“像”的几块。简单、快速、便宜,在单轮问答里够用。但一旦遇到需要跨文档推理的问题,它就抓瞎了。比如“A公司收购了B公司,B公司的CTO后来加入了C项目,C项目影响了哪个产品路线?”这个答案散在三篇完全不相关的文档里。单独拎出任何一篇,和问题的相似度都不高。向量搜索只知道“像不像”,不知道“谁和谁有关系”。
GraphRAG看到了这个短板,于是尝试用知识图谱来建模实体和关系。思路是对的,但代价太大。它需要把文本拆成三元组,每一步都得靠LLM抽取实体、归一化名称、合并重复、发现社区、生成摘要。跑一遍又慢又贵,而且增量更新更是噩梦——每加一个新文档,很可能需要重建全局图。HippoRAG 2是目前公认的结构化RAG强基线,但它依赖全局PageRank做图排序,数据量一上来,每次新增数据都得“把整个图书馆重新排一遍”,生产环境根本扛不住。
那SAG怎么破局?它干脆不建图谱、不做三元组、不搞全局图。而是给每个文本块加一张“索引卡”:一张卡上有一个完整的事项摘要(event),同时从原始文本中提取多个实体(entity),覆盖人物、组织、地点、时间、产品等11种类型。event保留完整上下文,entity负责索引和连接,两者之间通过SQL的关联查询建立多对多关系,形成一个超边结构。
这和三元组有本质区别。三元组拆得太碎——「头→关系→尾」,同一件事不同模型可能抽出的关系谓词千差万别,质量高度依赖每条关系的抽取精度。而SAG只让LLM做两件相对稳定的活儿:把文本块总结成一个完整事项,再从原文里尽可能把实体都抽出来。事项保持故事完整性,实体做桥梁。在图结构上,一个event同时连接多个entity,更像超图中的超边——一件事把所有相关的人、地点、组织串在一起。更轻,反而效果更好。原因很简单:RAG最终还是要回到原文证据,三元组太碎,容易丢上下文;event则保留了上下文,同时提供了可检索、可扩展的结构。
实现细节上,代码中还隐藏着一个关键设计:抽取event时会强制做代词消歧,把“他”、“该公司”、“这个产品”全部替换成完整名称。这样每个event就是一段独立可读的完整描述,不依赖上下文也能被理解。
整个检索流程分为离线写入和在线检索两步。离线阶段,文档切块后提取event和entity,写入MySQL,同时写入Elasticsearch的向量索引和全文索引。有趣的是,每条event-entity关系自身也带描述文本和embedding向量——同一个实体“OpenAI”在不同event里的角色描述可能是“发布GPT-5的公司”和“Sam Altman创立的公司”,在向量空间里是不同的点,这大大提升了实体召回的精准度。
在线检索时,LLM先从问题中识别关键实体,然后两路并行:一路用实体去向量索引里找相近实体,再通过SQL的JOIN查出关联的event和chunk;另一路直接用问题向量做语义匹配。从已找到的event出发,通过SQL反向查出相关entity,再用这些entity找新的event,每轮只引入新内容。最后映射回原始chunk,回答基于原文证据。两条路高度互补——消融实验显示,纯语义路径的Recall@5只有56.2%,加入少量结构化路径后就飙到了80.0%。多跳的核心实现其实只是SQL里的关系扩展,不需要全局PageRank,不需要LLM临时推理一张图。
效果有多猛?在HotpotQA、2WikiMultiHop、MuSiQue三个多跳基准上,使用同样的embedding模型(BGE-Large-EN-v1.5)和LLM(Qwen3.6-Flash),SAG的Recall@2平均79.3%,领先HippoRAG 2(68.2%)11.1个百分点。差距最大的MuSiQue上,Recall@2达到64.1% vs 49.5%,相当于每3次查询就多命中一次关键证据。注意,Recall@2比Recall@10更重要——Agent不希望每次拿回一大堆上下文再自己挑,那样成本高、延迟高、干扰多。能在更少的返回结果里更早拿到关键内容,才是真本事。
更关键的是,SAG对底层模型选择的鲁棒性很强。HippoRAG 2原论文用更强的NV-Embed-v2在MuSiQue上Recall@5达到74.6%,但换成BGE-Large-EN-v1.5后直接掉到65.1%,损失近10个百分点。而SAG在BGE下跑出80.0%,换NV后升到81.7%,几乎不受影响。增益主要来自算法结构本身,而不是依赖更贵的模型。
规模化能力也是生产级的关键。每个chunk的event/entity提取可以独立并行处理,不需要串行建图。实体去重只靠简单字符串归一加SQL查重,同名同类型的直接复用。新数据进来,切块、抽取、写入SQL,不需要重建全局图——更像数据库的增量写入,跟图谱的全局重建完全是两种思路。Zleap AI团队已经在实际生产中积累5亿级数据量,在线检索延迟保持在秒级以内。他们还做了一个Wikipedia Demo(wiki.zleap.com),可以直接测试多跳检索效果,支持快速模式和高精度模式。
最后,SAG特别适合做Agent的数据底座。Agent不是一次问答,而是连续查很多次,先查一个线索,再根据线索查下一个。第一次查错了,后面推理全都建立在错误材料上。SAG的高召回价值在于:用更少的查询次数找到正确内容,降低每一步错误叠加的概率。同时,Agent的记忆天然适合event/entity结构——同一个用户、项目、偏好可能反复出现,新记忆可能补充或推翻旧记忆。event保留完整事项,entity连接同一个人、项目、任务,加上时间和关联id就能区分新旧状态。这给出一个清晰的答案:RAG要解决的核心问题,是数据进入Agent系统时应该被组织成什么样子。用event/entity加一层轻量索引,用SQL做多跳检索,让数据可以增量写入、并发处理、持续增长——从文本召回走向结构化数据底座。
相关链接:
论文:https://arxiv.org/abs/2606.15971
GitHub:https://github.com/Zleap-AI/SAG-Benchmark
Demo:https://wiki.zleap.com